Quantcast
Channel: Path
Viewing all articles
Browse latest Browse all 83

QuantLib : Simulating HW1F paths using PathGenerator

$
0
0
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
      unsignedlong 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);
      voidPrintMatrix(const Matrix& matrix, std::string filePathName);
      //
      intmain()
      {
      // 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
      unsignedlong 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(unsignedint 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(unsignedint 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");
      return0;
      }
      //
      voidPrintMatrix(const Matrix& matrix, std::string filePathName)
      {
      // open text file for input, loop through matrix rows
      std::ofstream file(filePathName);
      for(unsignedint i =0; i != matrix.rows(); i++)
      {
      // concatenate column values into string separated by semicolon
      std::string stream;
      for(unsignedint 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

      Viewing all articles
      Browse latest Browse all 83

      Trending Articles