Saturday, January 23, 2016

QuantLib : Simulating HW1F paths using PathGenerator

Monte Carlo is bread and butter for so many purposes. Calculating payoffs for complex path-dependent products or simulating future exposures for calculating CVA are two excellent examples. The big question is always how to do this efficiently. Designing, implementing and setting up any non-trivial in-house tool to do the job is everything but not a simple afternoon exercise with a cup of coffee and Excel. Fortunately, QuantLib is offering pretty impressive tools for simulating stochastic paths. This time, I wanted to share the results of my woodshedding with QL PathGenerator class. 


Parallel lives


In order to really appreciate the tools offered by QL, let us see the results first. Some simulated paths using Hull-White One-Factor model are shown in the picture below.






























If one really want to start from the scratch, there are a lot of things to do in order to produce these paths on a flexible manner and handling all the complexities of the task at the same time. Thanks for QL, those days are finally over.


Legoland

 

Setting up desired Stochastic Process and Gaussian Sequence Generator are two main components needed in order to get this thing up and running.

Along with required process parameters (reversion speed and rate volatility), HullWhiteProcess needs Handle to YieldTermStructure object, such as PiecewiseYieldCurve, as an input.

 // create Hull-White one-factor stochastic process
 Real reversionSpeed = 0.75;
 Real rateVolatility = 0.015;
 boost::shared_ptr<StochasticProcess1D> HW1F(
  new HullWhiteProcess(curveHandle, reversionSpeed, rateVolatility));

For this example, I have used my own PiecewiseCurveBuilder template class in order to make curve assembling a bit more easier. It should be noted, that the menu of one-dimensional stochastic processes in QL is covering pretty much all standard processes one needs for different asset classes.

Gaussian Sequence Generator (GSG) is assembled by using the following three classes : uniform random generator (MersenneTwisterUniformRng),  distributional transformer (CLGaussianRng) and RandomSequenceGenerator.

 // type definition for complex declaration
 typedef RandomSequenceGenerator<CLGaussianRng<MersenneTwisterUniformRng>> GSG;
 //
 // create mersenne twister uniform random generator
 unsigned long seed = 28749;
 MersenneTwisterUniformRng generator(seed);
 //
 // create gaussian generator by using central limit transformation method
 CLGaussianRng<MersenneTwisterUniformRng> gaussianGenerator(generator);
 //
 // define maturity, number of steps per path and create gaussian sequence generator
 Time maturity = 5.0;
 Size nSteps = 1250;
 GSG gaussianSequenceGenerator(nSteps, gaussianGenerator);
 //
 // create path generator using Hull-White process and gaussian sequence generator
 PathGenerator<GSG> pathGenerator(HW1F, maturity, nSteps, gaussianSequenceGenerator, false);

Finally, PathGenerator object is created by feeding desired process and generator objects in constructor method, along with the other required parameters (maturity, number of steps). After this, PathGenerator object is ready for producing stochastic paths for its client.

The program

 

Example program will first create relinkable handle to PiecewiseYieldCurve object. Remember to include required files into your project from here. After this, the program creates HW1F process object and Gaussian Sequence Generator object, which are feeded into PathGenerator object. Finally, the program creates 20 stochastic paths, which are saved into Matrix object and ultimately being printed into text file for further analysis (Excel chart).

#include "PiecewiseCurveBuilder.cpp"
#include <fstream>
#include <string>
//
// type definition for complex declaration
typedef RandomSequenceGenerator<CLGaussianRng<MersenneTwisterUniformRng>> GSG;
//
// function prototypes
RelinkableHandle<YieldTermStructure> CreateCurveHandle(Date settlementDate);
void PrintMatrix(const Matrix& matrix, std::string filePathName);
//
int main()
{
 // request handle for piecewise USD Libor curve
 Date tradeDate(22, January, 2016);
 Settings::instance().evaluationDate() = tradeDate;
 Date settlementDate = UnitedKingdom().advance(tradeDate, 2, Days);
 RelinkableHandle<YieldTermStructure> curveHandle = CreateCurveHandle(settlementDate);
 //
 // create Hull-White one-factor stochastic process
 Real reversionSpeed = 0.75;
 Real rateVolatility = 0.015;
 boost::shared_ptr<StochasticProcess1D> HW1F(
  new HullWhiteProcess(curveHandle, reversionSpeed, rateVolatility));
 //
 // create mersenne twister uniform random generator
 unsigned long seed = 28749;
 MersenneTwisterUniformRng generator(seed);
 //
 // create gaussian generator by using central limit transformation method
 CLGaussianRng<MersenneTwisterUniformRng> gaussianGenerator(generator);
 //
 // define maturity, number of steps per path and create gaussian sequence generator
 Time maturity = 5.0;
 Size nSteps = 1250;
 GSG gaussianSequenceGenerator(nSteps, gaussianGenerator);
 //
 // create path generator using Hull-White process and gaussian sequence generator
 PathGenerator<GSG> pathGenerator(HW1F, maturity, nSteps, gaussianSequenceGenerator, false);
 //
 // create matrix container for 20 generated paths
 Size nColumns = 20;
 Matrix paths(nSteps + 1, nColumns);
 for(unsigned int i = 0; i != paths.columns(); i++)
 {
  // request a new stochastic path from path generator
  QuantLib::Sample<Path> path = pathGenerator.next();
  //
  // save generated path into container
  for(unsigned int j = 0; j != path.value.length(); j++)
  {
   paths[j][i] = path.value.at(j);
  }
 }
 // finally, print matrix content into text file
 PrintMatrix(paths, "C:\\temp\\HW1F.txt");
 return 0;
}
//
void PrintMatrix(const Matrix& matrix, std::string filePathName)
{
 // open text file for input, loop through matrix rows
 std::ofstream file(filePathName);
 for(unsigned int i = 0; i != matrix.rows(); i++)
 {
  // concatenate column values into string separated by semicolon
  std::string stream;
  for(unsigned int j = 0; j != matrix.columns(); j++)
  {
   stream += (std::to_string(matrix[i][j]) + ";");
  }
  // print string into text file
  file << stream << std::endl;
 }
 // close text file
 file.close();
}
//
RelinkableHandle<YieldTermStructure> CreateCurveHandle(Date settlementDate)
{
 // create curve builder for piecewise USD Libor swap curve
 PiecewiseCurveBuilder<USDLibor> USDCurveBuilder(settlementDate, 
  UnitedKingdom(), Annual, Thirty360());
 //
 // add quotes directly into curve builder
 USDCurveBuilder.AddDeposit(0.0038975, 1 * Weeks);
 USDCurveBuilder.AddDeposit(0.004295, 1 * Months);
 USDCurveBuilder.AddDeposit(0.005149, 2 * Months);
 USDCurveBuilder.AddDeposit(0.006127, 3 * Months);
 USDCurveBuilder.AddFRA(0.008253, 3 * Months, 3 * Months);
 USDCurveBuilder.AddFRA(0.009065, 6 * Months, 3 * Months);
 USDCurveBuilder.AddFRA(0.01059, 9 * Months, 3 * Months);
 USDCurveBuilder.AddSwap(0.011459, 2 * Years);
 USDCurveBuilder.AddSwap(0.013745, 3 * Years);
 USDCurveBuilder.AddSwap(0.015475, 4 * Years);
 USDCurveBuilder.AddSwap(0.016895, 5 * Years);
 USDCurveBuilder.AddSwap(0.01813, 6 * Years);
 USDCurveBuilder.AddSwap(0.019195, 7 * Years);
 USDCurveBuilder.AddSwap(0.020115, 8 * Years);
 USDCurveBuilder.AddSwap(0.020905, 9 * Years);
 USDCurveBuilder.AddSwap(0.021595, 10 * Years);
 USDCurveBuilder.AddSwap(0.0222, 11 * Years);
 USDCurveBuilder.AddSwap(0.022766, 12 * Years);
 USDCurveBuilder.AddSwap(0.0239675, 15 * Years);
 USDCurveBuilder.AddSwap(0.025105, 20 * Years);
 USDCurveBuilder.AddSwap(0.025675, 25 * Years);
 USDCurveBuilder.AddSwap(0.026015, 30 * Years);
 USDCurveBuilder.AddSwap(0.026205, 40 * Years);
 USDCurveBuilder.AddSwap(0.026045, 50 * Years);
 //
 // return relinkable curve handle
 return USDCurveBuilder.GetCurveHandle();
}

Thanks for reading my blog.

-Mike

Thursday, January 7, 2016

QuantLib : Builder Class for PiecewiseYieldCurve

Selection of high-quality benchmark securities and bootstrapping of valuation curve is the bread and butter in valuing financial transactions. In one of my blog, I opened up one possible framework for this procedure. Needless to say, that program was still far away from being really easy-to-use and state-of-the-art implementation. For this reason, I wanted to take a look at some external analytics libraries I have been getting introduced last year.

This time, I wanted to share some fruits of woodshedding QuantLib way to build up piecewise term structure. As I was initially tackling through the example files found in QL downloadable package and the other relevant examples found with Google, there was one obvious issue : with all those rates, quotes and handles involved, a lot of administrative code writing needs to be done first, in order to get any piecewise curve up and running. Since we need valuation curves anyway for everything we do with QL, there should be a manageable way to handle this issue.


One template to rule them all



For the reason mentioned above, I came up with an idea of auxiliary piecewise curve builder class. The purpose of this class would be simple : it could give a client a chance to assemble piecewise curve by adding arbitrary amount of different types of quotes (deposit, FRA or swap) and finally a client could request handle for assembled curve. The resulting curve handle could then be directly used in other QL programs. Effectively, this class would be wrapping some of the required administrative code work away from a client.


Walkthrough


As an example of the usage of this PiecewiseCurveBuilder template class, let us go through some parts of the example program. In order to keep this example as simple as possible, we will operate only with one rate for each category (deposit, FRA, swap). First, we create stand-alone quotes from market data. Memory for a SimpleQuote (inherits from Quote base class) will be reserved by using Boost shared pointer :

  boost::shared_ptr<Quote> usd_quote_deposit_3M(new SimpleQuote(0.006127));
  boost::shared_ptr<Quote> usd_quote_fra_3M6M(new SimpleQuote(0.008253));
  boost::shared_ptr<Quote> usd_quote_swap_2Y(new SimpleQuote(0.011459));

Next, we create curve builder class instance for assembling USD Libor swap curve :

  Date settlementDate = UnitedKingdom().advance(tradeDate, 2, Days);
  PiecewiseCurveBuilder<USDLibor> USDCurveBuilder(settlementDate, UnitedKingdom(), Annual, Thirty360());

After this, we add quotes into USD curve builder :

  USDCurveBuilder.AddDeposit(usd_quote_deposit_3M, 3 * Months);
  USDCurveBuilder.AddFRA(usd_quote_fra_3M6M, 3 * Months, 3 * Months);
  USDCurveBuilder.AddSwap(usd_quote_swap_2Y, 2 * Years);

Finally, we request relinkable curve handle from USD curve builder :

  RelinkableHandle<YieldTermStructure> curveHandle = USDCurveBuilder.GetCurveHandle();
  DoSomethingWithCurveHandle(curveHandle);

Requested RelinkableHandle (inherits from Handle base class) can then be directly used in other QL programs. One should be aware, that all the changes we made in stand-alone quotes (SimpleQuotes) will have an effect on the curve. For an example, we could modify the existing quotes by shocking their rate up by 100 bps :

  boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_deposit_3M)->setValue(usd_quote_deposit_3M->value() + 0.01);
  boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_fra_3M6M)->setValue(usd_quote_fra_3M6M->value() + 0.01);
  boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_2Y)->setValue(usd_quote_swap_2Y->value() + 0.01);
  DoSomethingWithCurveHandle(curveHandle);

Additional add methods for different quote types are enabling even easier way to assemble a curve. Instead of giving a rate wrapped inside Quote object, it can be given directly into curve builder. First, we create curve builder for CHF Libor swap curve :

  settlementDate = UnitedKingdom().advance(tradeDate, 2, Days);
  PiecewiseCurveBuilder<CHFLibor> CHFCurveBuilder(settlementDate, UnitedKingdom(), Annual, Thirty360());

Next, we add market rates directly into CHF curve builder :

  CHFCurveBuilder.AddDeposit(-0.006896, 6 * Months);
  CHFCurveBuilder.AddFRA(-0.007103, 6 * Months, 6 * Months);
  CHFCurveBuilder.AddSwap(-0.0068355, 2 * Years);

Finally, we request relinkable curve handle from CHF curve builder :

  curveHandle = CHFCurveBuilder.GetCurveHandle();
  DoSomethingWithCurveHandle(curveHandle);

This last option would be suitable in situations, where a client has no need for any auxiliary rate
updating.

The complete example program has been presented below. The program will first create updateable USD Libor swap curve, print all the rates, modify quotes and re-prints the rates. After this, the program will create updateable CHF Libor swap curve and prints a set of discount factors. Finally, the program will create non-updateable CHF Libor swap curve by using another set of add methods and prints a set of discount factors.

Have a great start for the year 2016. Thanks for reading my blog.
-Mike


The program


// PiecewiseCurveBuilder.h
#pragma once
#include <ql/quantlib.hpp>
using namespace QuantLib;
//
template <class T>
class PiecewiseCurveBuilder
{
private:
 Date settlementDate;
 Calendar calendar;
 Frequency fixedLegFrequency;
 DayCounter dayCounter;
 DayCounter fixedLegDayCounter;
 BusinessDayConvention businessDayConvention;
 std::vector<boost::shared_ptr<RateHelper>> rateHelpers;
 boost::shared_ptr<YieldTermStructure> yieldTermStructure;
public:
 PiecewiseCurveBuilder(Date settlementDate, Calendar calendar, 
  Frequency fixedLegFrequency, DayCounter fixedLegDayCounter);
 void AddDeposit(boost::shared_ptr<Quote>& quote, Period periodLength);
 void AddDeposit(Rate quote, Period periodLength);
 void AddFRA(boost::shared_ptr<Quote>& quote, Period periodLengthToStart, Period periodLength);
 void AddFRA(Rate quote, Period periodLengthToStart, Period periodLength);
 void AddSwap(boost::shared_ptr<Quote>& quote, Period periodLength);
 void AddSwap(Rate quote, Period periodLength);
 RelinkableHandle<YieldTermStructure> GetCurveHandle();
};
//
//
//
// PiecewiseCurveBuilder.cpp
#pragma once
#include "PiecewiseCurveBuilder.h"
//
template <class T>
PiecewiseCurveBuilder<T>::PiecewiseCurveBuilder(Date settlementDate, 
 Calendar calendar, Frequency fixedLegFrequency, DayCounter fixedLegDayCounter)
{
 this->settlementDate = settlementDate;
 this->calendar = calendar;
 this->fixedLegFrequency = fixedLegFrequency;
 this->fixedLegDayCounter = fixedLegDayCounter;
 boost::shared_ptr<IborIndex> index(new T(3 * Months));
 dayCounter = index->dayCounter();
 businessDayConvention = index->businessDayConvention();
}
template <class T>
void PiecewiseCurveBuilder<T>::AddDeposit(boost::shared_ptr<Quote>& quote, Period periodLength)
{
 // using third DepositRateHelper constructor
 boost::shared_ptr<RateHelper> rateHelper(new DepositRateHelper(
  Handle<Quote>(quote), boost::shared_ptr<IborIndex>(new T(periodLength))));
 rateHelpers.push_back(rateHelper);
}
template <class T>
void PiecewiseCurveBuilder<T>::AddDeposit(Rate quote, Period periodLength)
{
 // using second DepositRateHelper constructor
 boost::shared_ptr<RateHelper> rateHelper(new DepositRateHelper(
  quote, boost::shared_ptr<IborIndex>(new T(periodLength))));
 rateHelpers.push_back(rateHelper);
}
template <class T>
void PiecewiseCurveBuilder<T>::AddFRA(boost::shared_ptr<Quote>& quote, 
 Period periodLengthToStart, Period periodLength)
{
 // using seventh FraRateHelper constructor
 boost::shared_ptr<RateHelper> rateHelper(new FraRateHelper(
  Handle<Quote>(quote), periodLengthToStart, 
  boost::shared_ptr<IborIndex>(new T(periodLength))));
 rateHelpers.push_back(rateHelper); 
}
template <class T>
void PiecewiseCurveBuilder<T>::AddFRA(Rate quote, 
 Period periodLengthToStart, Period periodLength)
{
 // using third FraRateHelper constructor
 boost::shared_ptr<RateHelper> rateHelper(new FraRateHelper(
  quote, periodLengthToStart, 
  boost::shared_ptr<IborIndex>(new T(periodLength))));
 rateHelpers.push_back(rateHelper); 
}
template <class T>
void PiecewiseCurveBuilder<T>::AddSwap(boost::shared_ptr<Quote>& quote, 
 Period periodLength)
{
 // using fifth SwapRateHelper constructor
 boost::shared_ptr<IborIndex> index(new T(periodLength));
 boost::shared_ptr<RateHelper> rateHelper(new SwapRateHelper(
  Handle<Quote>(quote), periodLength, calendar, fixedLegFrequency, 
  businessDayConvention, fixedLegDayCounter, index));
 rateHelpers.push_back(rateHelper);
}
template <class T>
void PiecewiseCurveBuilder<T>::AddSwap(Rate quote, 
 Period periodLength)
{
 // using fourth SwapRateHelper constructor
 boost::shared_ptr<IborIndex> index(new T(periodLength));
 boost::shared_ptr<RateHelper> rateHelper(new SwapRateHelper(
  quote, periodLength, calendar, fixedLegFrequency, 
  businessDayConvention, fixedLegDayCounter, index));
 rateHelpers.push_back(rateHelper);
}
template <class T>
RelinkableHandle<YieldTermStructure> PiecewiseCurveBuilder<T>::GetCurveHandle()
{
 if(yieldTermStructure == NULL)
 {
  yieldTermStructure = boost::shared_ptr<YieldTermStructure>(
   new PiecewiseYieldCurve<Discount, LogLinear>(
   settlementDate, rateHelpers, dayCounter));
 }
 return RelinkableHandle<YieldTermStructure>(yieldTermStructure);
}
//
//
//
// Tester.cpp
#include "PiecewiseCurveBuilder.cpp"
//
// prototype : template method for calculating a fair swap rate
template <typename T> Rate GetSwapRate(Period swapMaturity, Date settlementDate, Period floatingLegTenor, 
 Handle<YieldTermStructure>& curveHandle, Calendar calendar, DayCounter fixedLegDayCount, Period fixedLegTenor);
// prototype : hard-coded printer for USD rates
void PrintUSDRates(Date settlementDate, Handle<YieldTermStructure>& curveHandle);
// prototype : hard-coded printer for CHF discount factors
void PrintCHFDiscountFactors(Date settlementDate, Handle<YieldTermStructure>& curveHandle);
//
int main()
{
 // create trade date
 Date tradeDate(5, January, 2016);
 Settings::instance().evaluationDate() = tradeDate;
 //
 // create relinkable handle for curve
 RelinkableHandle<YieldTermStructure> curveHandle;
 //
 // create stand-alone quotes from USD market data
 boost::shared_ptr<Quote> usd_quote_deposit_1W(new SimpleQuote(0.0038975));
 boost::shared_ptr<Quote> usd_quote_deposit_1M(new SimpleQuote(0.004295));
 boost::shared_ptr<Quote> usd_quote_deposit_2M(new SimpleQuote(0.005149));
 boost::shared_ptr<Quote> usd_quote_deposit_3M(new SimpleQuote(0.006127));
 boost::shared_ptr<Quote> usd_quote_fra_3M6M(new SimpleQuote(0.008253));
 boost::shared_ptr<Quote> usd_quote_fra_6M9M(new SimpleQuote(0.009065));
 boost::shared_ptr<Quote> usd_quote_fra_9M12M(new SimpleQuote(0.01059));
 boost::shared_ptr<Quote> usd_quote_swap_2Y(new SimpleQuote(0.011459));
 boost::shared_ptr<Quote> usd_quote_swap_3Y(new SimpleQuote(0.013745));
 boost::shared_ptr<Quote> usd_quote_swap_4Y(new SimpleQuote(0.015475));
 boost::shared_ptr<Quote> usd_quote_swap_5Y(new SimpleQuote(0.016895));
 boost::shared_ptr<Quote> usd_quote_swap_6Y(new SimpleQuote(0.01813));
 boost::shared_ptr<Quote> usd_quote_swap_7Y(new SimpleQuote(0.019195));
 boost::shared_ptr<Quote> usd_quote_swap_8Y(new SimpleQuote(0.020115));
 boost::shared_ptr<Quote> usd_quote_swap_9Y(new SimpleQuote(0.020905));
 boost::shared_ptr<Quote> usd_quote_swap_10Y(new SimpleQuote(0.021595));
 boost::shared_ptr<Quote> usd_quote_swap_11Y(new SimpleQuote(0.0222));
 boost::shared_ptr<Quote> usd_quote_swap_12Y(new SimpleQuote(0.022766));
 boost::shared_ptr<Quote> usd_quote_swap_15Y(new SimpleQuote(0.0239675));
 boost::shared_ptr<Quote> usd_quote_swap_20Y(new SimpleQuote(0.025105));
 boost::shared_ptr<Quote> usd_quote_swap_25Y(new SimpleQuote(0.025675));
 boost::shared_ptr<Quote> usd_quote_swap_30Y(new SimpleQuote(0.026015));
 boost::shared_ptr<Quote> usd_quote_swap_40Y(new SimpleQuote(0.026205));
 boost::shared_ptr<Quote> usd_quote_swap_50Y(new SimpleQuote(0.026045));
 //
 // create curve builder for USD Libor swap curve
 Date settlementDate = UnitedKingdom().advance(tradeDate, 2, Days);
 PiecewiseCurveBuilder<USDLibor> USDCurveBuilder(settlementDate, 
  UnitedKingdom(), Annual, Thirty360());
 //
 // add quotes (reference to shared pointer) into USD curve builder
 USDCurveBuilder.AddDeposit(usd_quote_deposit_1W, 1 * Weeks);
 USDCurveBuilder.AddDeposit(usd_quote_deposit_1M, 1 * Months);
 USDCurveBuilder.AddDeposit(usd_quote_deposit_2M, 2 * Months);
 USDCurveBuilder.AddDeposit(usd_quote_deposit_3M, 3 * Months);
 USDCurveBuilder.AddFRA(usd_quote_fra_3M6M, 3 * Months, 3 * Months);
 USDCurveBuilder.AddFRA(usd_quote_fra_6M9M, 6 * Months, 3 * Months);
 USDCurveBuilder.AddFRA(usd_quote_fra_9M12M, 9 * Months, 3 * Months);
 USDCurveBuilder.AddSwap(usd_quote_swap_2Y, 2 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_3Y, 3 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_4Y, 4 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_5Y, 5 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_6Y, 6 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_7Y, 7 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_8Y, 8 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_9Y, 9 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_10Y, 10 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_11Y, 11 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_12Y, 12 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_15Y, 15 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_20Y, 20 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_25Y, 25 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_30Y, 30 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_40Y, 40 * Years);
 USDCurveBuilder.AddSwap(usd_quote_swap_50Y, 50 * Years);
 //
 // get relinkable curve handle from USD curve builder and print rates
 curveHandle = USDCurveBuilder.GetCurveHandle();
 PrintUSDRates(settlementDate, curveHandle);
 //
 // modify existing USD quotes by shocking rates up by 100 bps
 Real bump = 0.01;
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_deposit_1W)->setValue(usd_quote_deposit_1W->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_deposit_1M)->setValue(usd_quote_deposit_1M->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_deposit_2M)->setValue(usd_quote_deposit_2M->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_deposit_3M)->setValue(usd_quote_deposit_3M->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_fra_3M6M)->setValue(usd_quote_fra_3M6M->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_fra_6M9M)->setValue(usd_quote_fra_6M9M->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_fra_9M12M)->setValue(usd_quote_fra_9M12M->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_2Y)->setValue(usd_quote_swap_2Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_3Y)->setValue(usd_quote_swap_3Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_4Y)->setValue(usd_quote_swap_4Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_5Y)->setValue(usd_quote_swap_5Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_6Y)->setValue(usd_quote_swap_6Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_7Y)->setValue(usd_quote_swap_7Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_8Y)->setValue(usd_quote_swap_8Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_9Y)->setValue(usd_quote_swap_9Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_10Y)->setValue(usd_quote_swap_10Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_11Y)->setValue(usd_quote_swap_11Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_12Y)->setValue(usd_quote_swap_12Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_15Y)->setValue(usd_quote_swap_15Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_20Y)->setValue(usd_quote_swap_20Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_25Y)->setValue(usd_quote_swap_25Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_30Y)->setValue(usd_quote_swap_30Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_40Y)->setValue(usd_quote_swap_40Y->value() + bump);
 boost::dynamic_pointer_cast<SimpleQuote>(usd_quote_swap_50Y)->setValue(usd_quote_swap_50Y->value() + bump);
 //
 // re-print USD rates
 PrintUSDRates(settlementDate, curveHandle);
 //
 //
 //
 // create stand-alone quotes from CHF market data
 boost::shared_ptr<Quote> chf_quote_deposit_1W(new SimpleQuote(-0.00827));
 boost::shared_ptr<Quote> chf_quote_deposit_1M(new SimpleQuote(-0.00798));
 boost::shared_ptr<Quote> chf_quote_deposit_2M(new SimpleQuote(-0.00785));
 boost::shared_ptr<Quote> chf_quote_deposit_3M(new SimpleQuote(-0.00756));
 boost::shared_ptr<Quote> chf_quote_deposit_6M(new SimpleQuote(-0.006896));
 boost::shared_ptr<Quote> chf_quote_fra_6M12M(new SimpleQuote(-0.007103));
 boost::shared_ptr<Quote> chf_quote_swap_2Y(new SimpleQuote(-0.0068355));
 boost::shared_ptr<Quote> chf_quote_swap_3Y(new SimpleQuote(-0.006125));
 boost::shared_ptr<Quote> chf_quote_swap_4Y(new SimpleQuote(-0.0050195));
 boost::shared_ptr<Quote> chf_quote_swap_5Y(new SimpleQuote(-0.003725));
 boost::shared_ptr<Quote> chf_quote_swap_6Y(new SimpleQuote(-0.002425));
 boost::shared_ptr<Quote> chf_quote_swap_7Y(new SimpleQuote(-0.0011885));
 boost::shared_ptr<Quote> chf_quote_swap_8Y(new SimpleQuote(-0.000094));
 boost::shared_ptr<Quote> chf_quote_swap_9Y(new SimpleQuote(0.0008755));
 boost::shared_ptr<Quote> chf_quote_swap_10Y(new SimpleQuote(0.0016365));
 boost::shared_ptr<Quote> chf_quote_swap_12Y(new SimpleQuote(0.003));
 boost::shared_ptr<Quote> chf_quote_swap_15Y(new SimpleQuote(0.004525));
 boost::shared_ptr<Quote> chf_quote_swap_20Y(new SimpleQuote(0.0063));
 boost::shared_ptr<Quote> chf_quote_swap_25Y(new SimpleQuote(0.00735));
 boost::shared_ptr<Quote> chf_quote_swap_30Y(new SimpleQuote(0.007825));
 //
 // create curve builder for CHF Libor swap curve
 settlementDate = UnitedKingdom().advance(tradeDate, 2, Days);
 PiecewiseCurveBuilder<CHFLibor> CHFCurveBuilder(settlementDate, 
  UnitedKingdom(), Annual, Thirty360());
 //
 // add quotes (reference to shared pointer) into CHF curve builder
 CHFCurveBuilder.AddDeposit(chf_quote_deposit_1W, 1 * Weeks);
 CHFCurveBuilder.AddDeposit(chf_quote_deposit_1M, 1 * Months);
 CHFCurveBuilder.AddDeposit(chf_quote_deposit_2M, 2 * Months);
 CHFCurveBuilder.AddDeposit(chf_quote_deposit_3M, 3 * Months);
 CHFCurveBuilder.AddDeposit(chf_quote_deposit_6M, 6 * Months);
 CHFCurveBuilder.AddFRA(chf_quote_fra_6M12M, 6 * Months, 6 * Months);
 CHFCurveBuilder.AddSwap(chf_quote_swap_2Y, 2 * Years);
 CHFCurveBuilder.AddSwap(chf_quote_swap_3Y, 3 * Years);
 CHFCurveBuilder.AddSwap(chf_quote_swap_4Y, 4 * Years);
 CHFCurveBuilder.AddSwap(chf_quote_swap_5Y, 5 * Years);
 CHFCurveBuilder.AddSwap(chf_quote_swap_6Y, 6 * Years);
 CHFCurveBuilder.AddSwap(chf_quote_swap_7Y, 7 * Years);
 CHFCurveBuilder.AddSwap(chf_quote_swap_8Y, 8 * Years);
 CHFCurveBuilder.AddSwap(chf_quote_swap_9Y, 9 * Years);
 CHFCurveBuilder.AddSwap(chf_quote_swap_10Y, 10 * Years);
 CHFCurveBuilder.AddSwap(chf_quote_swap_12Y, 12 * Years);
 CHFCurveBuilder.AddSwap(chf_quote_swap_15Y, 15 * Years);
 CHFCurveBuilder.AddSwap(chf_quote_swap_20Y, 20 * Years);
 CHFCurveBuilder.AddSwap(chf_quote_swap_25Y, 25 * Years);
 CHFCurveBuilder.AddSwap(chf_quote_swap_30Y, 30 * Years);
 //
 // get relinkable curve handle from CHF curve builder and print discount factors
 curveHandle = CHFCurveBuilder.GetCurveHandle();
 PrintCHFDiscountFactors(settlementDate, curveHandle);
 //
 //
 //
 // create another curve builder for CHF Libor swap curve
 settlementDate = UnitedKingdom().advance(tradeDate, 2, Days);
 PiecewiseCurveBuilder<CHFLibor> CHFCurveBuilder2(settlementDate, 
  UnitedKingdom(), Annual, Thirty360());
 //
 // add market rates directly into CHF curve builder
 CHFCurveBuilder2.AddDeposit(-0.00827, 1 * Weeks);
 CHFCurveBuilder2.AddDeposit(-0.00798, 1 * Months);
 CHFCurveBuilder2.AddDeposit(-0.00785, 2 * Months);
 CHFCurveBuilder2.AddDeposit(-0.00756, 3 * Months);
 CHFCurveBuilder2.AddDeposit(-0.006896, 6 * Months);
 CHFCurveBuilder2.AddFRA(-0.007103, 6 * Months, 6 * Months);
 CHFCurveBuilder2.AddSwap(-0.0068355, 2 * Years);
 CHFCurveBuilder2.AddSwap(-0.006125, 3 * Years);
 CHFCurveBuilder2.AddSwap(-0.0050195, 4 * Years);
 CHFCurveBuilder2.AddSwap(-0.003725, 5 * Years);
 CHFCurveBuilder2.AddSwap(-0.002425, 6 * Years);
 CHFCurveBuilder2.AddSwap(-0.0011885, 7 * Years);
 CHFCurveBuilder2.AddSwap(-0.000094, 8 * Years);
 CHFCurveBuilder2.AddSwap(0.0008755, 9 * Years);
 CHFCurveBuilder2.AddSwap(0.0016365, 10 * Years);
 CHFCurveBuilder2.AddSwap(0.003, 12 * Years);
 CHFCurveBuilder2.AddSwap(0.004525, 15 * Years);
 CHFCurveBuilder2.AddSwap(0.0063, 20 * Years);
 CHFCurveBuilder2.AddSwap(0.00735, 25 * Years);
 CHFCurveBuilder2.AddSwap(0.007825, 30 * Years);
 //
 // get relinkable curve handle from CHF curve builder and re-print discount factors
 curveHandle = CHFCurveBuilder2.GetCurveHandle();
 PrintCHFDiscountFactors(settlementDate, curveHandle);
 return 0;
}
//
template <typename T> Rate GetSwapRate(Period swapMaturity, Date settlementDate, Period floatingLegTenor, 
 Handle<YieldTermStructure>& curveHandle, Calendar calendar, DayCounter fixedLegDayCount, Period fixedLegTenor)
{
 // using quantlib factory method for building vanilla swap
 boost::shared_ptr<IborIndex> index(new T(floatingLegTenor, curveHandle));
 VanillaSwap swap = MakeVanillaSwap(swapMaturity, index)
  .withEffectiveDate(settlementDate)
  .withFixedLegCalendar(calendar)
  .withFixedLegConvention(index->businessDayConvention())
  .withFixedLegDayCount(fixedLegDayCount)
  .withFixedLegTenor(fixedLegTenor)
  .withFloatingLegCalendar(calendar);
 return swap.fairRate();
}
//
void PrintUSDRates(Date settlementDate, Handle<YieldTermStructure>& curveHandle)
{
 Calendar calendar = UnitedKingdom();
 std::cout << std::endl;
 // print USD deposit rates
 std::cout << curveHandle->zeroRate(calendar.adjust(settlementDate + 1 * Weeks), 
  Actual360(), Simple).rate() << std::endl;
 std::cout << curveHandle->zeroRate(calendar.adjust(settlementDate + 1 * Months), 
  Actual360(), Simple).rate() << std::endl;
 std::cout << curveHandle->zeroRate(calendar.adjust(settlementDate + 2 * Months), 
  Actual360(), Simple).rate() << std::endl;
 std::cout << curveHandle->zeroRate(calendar.adjust(settlementDate + 3 * Months), 
  Actual360(), Simple).rate() << std::endl;
 // print USD forward rates
 std::cout << curveHandle->forwardRate(calendar.adjust(settlementDate + 3 * Months), 
  calendar.adjust(settlementDate + 6 * Months), Actual360(), Simple).rate() << std::endl;
 std::cout << curveHandle->forwardRate(calendar.adjust(settlementDate + 6 * Months), 
  calendar.adjust(settlementDate + 9 * Months), Actual360(), Simple).rate() << std::endl;
 std::cout << curveHandle->forwardRate(calendar.adjust(settlementDate + 9 * Months), 
  calendar.adjust(settlementDate + 12 * Months), Actual360(), Simple).rate() << std::endl;
 // print USD swap rates
 std::cout << GetSwapRate<USDLibor>(2 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(3 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(4 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(5 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(6 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(7 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(8 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(9 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(10 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(11 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(12 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(15 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(20 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(25 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(30 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(40 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
 std::cout << GetSwapRate<USDLibor>(50 * Years, settlementDate, 3 * Months, 
  curveHandle, calendar, Thirty360(), 1 * Years) << std::endl;
}
//
void PrintCHFDiscountFactors(Date settlementDate, Handle<YieldTermStructure>& curveHandle)
{
 // print CHF discount factors for every 6 months up to 30 years
 std::cout << std::endl;
 for(unsigned int i = 1; i != 61; i++)
 {
  std::cout << curveHandle->discount(UnitedKingdom()
   .adjust(settlementDate + (6 * i) * Months)) << std::endl;
 }
}