[QuantLib-users] Hull-White Model and Monte Carlo Simulations

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

[QuantLib-users] Hull-White Model and Monte Carlo Simulations

Smith, Dale (Norcross)

Hello,

 

I calibrated the Hull-White model to market data from earlier in the year, in order to test my monte carlo code. However, I’m getting a very large variance when calculating the PV of a bullet bond.

 

I’m using the Jamshidian model from QuantLib to calculate implied vols for swaptions and then using the HullWhite::calibrate method. I’m using Sobol numbers and the HullWhiteProcess::evolve method to produce paths. I put these paths, one by one, into our existing bullet bond pricer and then average the results. I’ve already validated the existing bond pricer, so I know it’s producing the correct results.

 

I tried a flat yield curve and volatility, and am getting pretty good results. However, using actual market data gives me a very large difference for the same bullet bond. Increasing the number of simulated paths didn’t help. I also monitored the actual interest rates along the paths and the variation is between 23% and -13% for 5,000 or 50,000 paths.

I’ve followed the BermudanSwaption example in the QuantLib project for some of my work, and checked the unit tests in QuantLib for further examples or guidance but didn’t find anything I could use. Here’s the relevant code section I’m using to generate paths:

 

                     Handle< YieldTermStructure > hts(ts_);

                     boost::shared_ptr <HullWhiteProcess> hwProcess(new HullWhiteProcess(hts, alpha, sigma));

                     Size numVals = grid_.size();

                     ublas::matrix<double> myPath(numPaths, numVals);

                     // TODO Assumes months here; we may need to change this in the future.

                     Time t = 0.0, dt = 1.0/12.0; // assume months!

                     Real dw = 0.0;

                     Real ir = 0.0;

                     Real irSaved = 0.0;

                     Real rr = 0.0;

                     Real rr2 = 0.0;

                     SobolRsg sobol(numVals, defaultSeed_);

                     InverseCumulativeRsg<SobolRsg, InverseCumulativeNormal> generator(sobol);

                     vector<Real> sample(numVals);

                     Real rateLimitUp = 0.0;

                     Real rateLimitDn = 0.0;

                     for (QuantLib::Size i = 0; i < numPaths; i++) {

                           ir = ts_->zeroRate(0.0, Continuous); // Note the compounding

                           sample = generator.nextSequence().value;

                           for (QuantLib::Size j = 0; j < numVals; j++)

                           {

                                  t = grid_[j];

                                  dw = sample[j];

                                  irSaved = ir;

                                  ir = hwProcess->evolve(t, ir, dt, dw);

                                  rr = (ir*dt + std::log(A(t, t + dt)))/B(t, t + dt); // use the interest rate from the tree

                                  myPath(i, j) = rr;

                           }

                     }

                     return myPath;

 

ts_ is a boost::shared_ptr<YieldTermStructure>. I’m using LogLinear interpolation to generate an InterpolatedDiscountCurve. The above calculation of rr follows Hull & White suggestion from equation 4  - 6 of “Using Hull-White Interest Rate Trees”.

 

At this point, I am wondering if I should take a different approach. I expect some negative rates, given the current low rates in the market, but I think what I’m getting is not quite right. Any suggestions are welcome.

 

Thanks,

Dale Smith, Ph.D.

Senior Financial Quantitative Analyst

Risk & Compliance

Fiserv.

107 Technology Park

Norcross, GA 30092

Office: 678-375-5315

Mail: [hidden email]

www.fiserv.com

 


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: [QuantLib-users] Hull-White Model and Monte CarloSimulations

Simon Ibbotson-2

Hi Dale,

 

I suspect this email would be better directed towards the quantlib-dev mailing list (as it contains code).

 

However, having briefly looked at your code, I suspect that your Sobol generator isn’t implemented correctly.

 

1) Most people – when generating low-discrepancy Brownian variables – use Sobol sequencing with Brownian bridging to span between specific maturities (see SobolBrownianGenerator as an example), so the first Sobol sequence is normally used for generating the variable at the final maturity, second Sobol sequence is used for forming a Brownian bridge for an intermediate date (such as an exercise date) and so forth. This is because the first few dimensions of a Sobol sequence are more reliable (and independent) than the later dimensions.

 

2) Sobol sequences absolutely need to have the correct number of paths for them to behave properly! You can’t simply take an arbitrary number of paths and expect to have an unbiased sample of the distribution. A simple 1D Sobol sequence may look like {0.5, 0.25, 0.75, 0.125, 0.875, 0.375, 0.625…}, so if you choose any number of paths other than 1, 3, 7 etc. then you can’t expect an unbiased sample. It gets more complicated in larger dimensionality (in your case, more than one time-step).

 

Have you tried using a different random number generator – such as MersenneTwisterUniformRng for comparison?

 

PseudoRandom::rsg_type generator(PseudoRandom::make_sequence_generator( numvals, seed );

 

 

 

Regards,

 

Simon

 


From: Smith, Dale [mailto:[hidden email]]
Sent: 18 September 2012 17:26
To: [hidden email]
Subject: [Quantlib-users] [QuantLib-users] Hull-White Model and Monte CarloSimulations

 

Hello,

 

I calibrated the Hull-White model to market data from earlier in the year, in order to test my monte carlo code. However, I’m getting a very large variance when calculating the PV of a bullet bond.

 

I’m using the Jamshidian model from QuantLib to calculate implied vols for swaptions and then using the HullWhite::calibrate method. I’m using Sobol numbers and the HullWhiteProcess::evolve method to produce paths. I put these paths, one by one, into our existing bullet bond pricer and then average the results. I’ve already validated the existing bond pricer, so I know it’s producing the correct results.

 

I tried a flat yield curve and volatility, and am getting pretty good results. However, using actual market data gives me a very large difference for the same bullet bond. Increasing the number of simulated paths didn’t help. I also monitored the actual interest rates along the paths and the variation is between 23% and -13% for 5,000 or 50,000 paths.

 

I’ve followed the BermudanSwaption example in the QuantLib project for some of my work, and checked the unit tests in QuantLib for further examples or guidance but didn’t find anything I could use. Here’s the relevant code section I’m using to generate paths:

 

                     Handle< YieldTermStructure > hts(ts_);

                     boost::shared_ptr <HullWhiteProcess> hwProcess(new HullWhiteProcess(hts, alpha, sigma));

                     Size numVals = grid_.size();

                     ublas::matrix<double> myPath(numPaths, numVals);

                     // TODO Assumes months here; we may need to change this in the future.

                     Time t = 0.0, dt = 1.0/12.0; // assume months!

                     Real dw = 0.0;

                     Real ir = 0.0;

                     Real irSaved = 0.0;

                     Real rr = 0.0;

                     Real rr2 = 0.0;

                     SobolRsg sobol(numVals, defaultSeed_);

                     InverseCumulativeRsg<SobolRsg, InverseCumulativeNormal> generator(sobol);

                     vector<Real> sample(numVals);

                     Real rateLimitUp = 0.0;

                     Real rateLimitDn = 0.0;

                     for (QuantLib::Size i = 0; i < numPaths; i++) {

                           ir = ts_->zeroRate(0.0, Continuous); // Note the compounding

                           sample = generator.nextSequence().value;

                           for (QuantLib::Size j = 0; j < numVals; j++)

                           {

                                  t = grid_[j];

                                  dw = sample[j];

                                  irSaved = ir;

                                  ir = hwProcess->evolve(t, ir, dt, dw);

                                  rr = (ir*dt + std::log(A(t, t + dt)))/B(t, t + dt); // use the interest rate from the tree

                                  myPath(i, j) = rr;

                           }

                     }

                     return myPath;

 

ts_ is a boost::shared_ptr<YieldTermStructure>. I’m using LogLinear interpolation to generate an InterpolatedDiscountCurve. The above calculation of rr follows Hull & White suggestion from equation 4  - 6 of “Using Hull-White Interest Rate Trees”.

 

At this point, I am wondering if I should take a different approach. I expect some negative rates, given the current low rates in the market, but I think what I’m getting is not quite right. Any suggestions are welcome.

 

Thanks,

Dale Smith, Ph.D.

Senior Financial Quantitative Analyst

Risk & Compliance

Fiserv.

107 Technology Park

Norcross, GA 30092

Office: 678-375-5315

Mail: [hidden email]

www.fiserv.com

 



This communication and any attachments contains information which is confidential and may be subject to legal privilege. It is for intended recipients only. If you are not the intended recipient you must not copy, distribute, publish, rely on or otherwise use it without our consent. Some of our communications may contain confidential information which it could be a criminal offence for you to disclose or use without authority. If you have received this email in error please notify [hidden email] immediately and delete the email from your computer.

The FSA reserves the right to monitor all email communications for compliance with legal, regulatory and professional standards.

This email is not intended to nor should it be taken to create any legal relations or contractual relationships. This email has originated from

The Financial Services Authority (FSA)
25 The North Colonnade,
Canary Wharf,
London
E14 5HS
United Kingdom

Registered as a Limited Company in England and Wales No.1920623.
Registered Office as above

Switchboard: 020 7066 1000
Web Site: http://www.fsa.gov.uk
*****************************************************************


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: [QuantLib-users] Hull-White Model and Monte CarloSimulations

Smith, Dale (Norcross)

Simon,

 

Thanks for the response. My first inclination was to go back to first principles, as you have suggested. However, my next step was to use Halton. Obviously, there’s more to the low-discrepancy sequences than I suspected. I’m switching back to what I was using before – Mersenne Twister with Box-Mueller to get normal random variates. I will have to do more reading if I need to use low-discrepancy sequences.

 

Thanks,

Dale Smith, Ph.D.

Senior Financial Quantitative Analyst

Risk & Compliance

Fiserv.

107 Technology Park

Norcross, GA 30092

Office: 678-375-5315

Mail: [hidden email]

www.fiserv.com

 

From: Simon Ibbotson [mailto:[hidden email]]
Sent: Wednesday, September 19, 2012 5:35 AM
To: Smith, Dale; [hidden email]
Subject: RE: [Quantlib-users] [QuantLib-users] Hull-White Model and Monte CarloSimulations

 

Hi Dale,

 

I suspect this email would be better directed towards the quantlib-dev mailing list (as it contains code).

 

However, having briefly looked at your code, I suspect that your Sobol generator isn’t implemented correctly.

 

1) Most people – when generating low-discrepancy Brownian variables – use Sobol sequencing with Brownian bridging to span between specific maturities (see SobolBrownianGenerator as an example), so the first Sobol sequence is normally used for generating the variable at the final maturity, second Sobol sequence is used for forming a Brownian bridge for an intermediate date (such as an exercise date) and so forth. This is because the first few dimensions of a Sobol sequence are more reliable (and independent) than the later dimensions.

 

2) Sobol sequences absolutely need to have the correct number of paths for them to behave properly! You can’t simply take an arbitrary number of paths and expect to have an unbiased sample of the distribution. A simple 1D Sobol sequence may look like {0.5, 0.25, 0.75, 0.125, 0.875, 0.375, 0.625…}, so if you choose any number of paths other than 1, 3, 7 etc. then you can’t expect an unbiased sample. It gets more complicated in larger dimensionality (in your case, more than one time-step).

 

Have you tried using a different random number generator – such as MersenneTwisterUniformRng for comparison?

 

PseudoRandom::rsg_type generator(PseudoRandom::make_sequence_generator( numvals, seed );

 

 

 

Regards,

 

Simon

 


From: Smith, Dale [[hidden email]]
Sent: 18 September 2012 17:26
To: [hidden email]
Subject: [Quantlib-users] [QuantLib-users] Hull-White Model and Monte CarloSimulations

 

Hello,

 

I calibrated the Hull-White model to market data from earlier in the year, in order to test my monte carlo code. However, I’m getting a very large variance when calculating the PV of a bullet bond.

 

I’m using the Jamshidian model from QuantLib to calculate implied vols for swaptions and then using the HullWhite::calibrate method. I’m using Sobol numbers and the HullWhiteProcess::evolve method to produce paths. I put these paths, one by one, into our existing bullet bond pricer and then average the results. I’ve already validated the existing bond pricer, so I know it’s producing the correct results.

 

I tried a flat yield curve and volatility, and am getting pretty good results. However, using actual market data gives me a very large difference for the same bullet bond. Increasing the number of simulated paths didn’t help. I also monitored the actual interest rates along the paths and the variation is between 23% and -13% for 5,000 or 50,000 paths.

 

I’ve followed the BermudanSwaption example in the QuantLib project for some of my work, and checked the unit tests in QuantLib for further examples or guidance but didn’t find anything I could use. Here’s the relevant code section I’m using to generate paths:

 

                     Handle< YieldTermStructure > hts(ts_);

                     boost::shared_ptr <HullWhiteProcess> hwProcess(new HullWhiteProcess(hts, alpha, sigma));

                     Size numVals = grid_.size();

                     ublas::matrix<double> myPath(numPaths, numVals);

                     // TODO Assumes months here; we may need to change this in the future.

                     Time t = 0.0, dt = 1.0/12.0; // assume months!

                     Real dw = 0.0;

                     Real ir = 0.0;

                     Real irSaved = 0.0;

                     Real rr = 0.0;

                     Real rr2 = 0.0;

                     SobolRsg sobol(numVals, defaultSeed_);

                     InverseCumulativeRsg<SobolRsg, InverseCumulativeNormal> generator(sobol);

                     vector<Real> sample(numVals);

                     Real rateLimitUp = 0.0;

                     Real rateLimitDn = 0.0;

                     for (QuantLib::Size i = 0; i < numPaths; i++) {

                           ir = ts_->zeroRate(0.0, Continuous); // Note the compounding

                           sample = generator.nextSequence().value;

                           for (QuantLib::Size j = 0; j < numVals; j++)

                           {

                                  t = grid_[j];

                                  dw = sample[j];

                                  irSaved = ir;

                                  ir = hwProcess->evolve(t, ir, dt, dw);

                                  rr = (ir*dt + std::log(A(t, t + dt)))/B(t, t + dt); // use the interest rate from the tree

                                  myPath(i, j) = rr;

                           }

                     }

                     return myPath;

 

ts_ is a boost::shared_ptr<YieldTermStructure>. I’m using LogLinear interpolation to generate an InterpolatedDiscountCurve. The above calculation of rr follows Hull & White suggestion from equation 4  - 6 of “Using Hull-White Interest Rate Trees”.

 

At this point, I am wondering if I should take a different approach. I expect some negative rates, given the current low rates in the market, but I think what I’m getting is not quite right. Any suggestions are welcome.

 

Thanks,

Dale Smith, Ph.D.

Senior Financial Quantitative Analyst

Risk & Compliance

Fiserv.

107 Technology Park

Norcross, GA 30092

Office: 678-375-5315

Mail: [hidden email]

www.fiserv.com

 



This communication and any attachments contains information which is confidential and may be subject to legal privilege. It is for intended recipients only. If you are not the intended recipient you must not copy, distribute, publish, rely on or otherwise use it without our consent. Some of our communications may contain confidential information which it could be a criminal offence for you to disclose or use without authority. If you have received this email in error please notify [hidden email] immediately and delete the email from your computer.

The FSA reserves the right to monitor all email communications for compliance with legal, regulatory and professional standards.

This email is not intended to nor should it be taken to create any legal relations or contractual relationships. This email has originated from

The Financial Services Authority (FSA)
25 The North Colonnade,
Canary Wharf,
London
E14 5HS
United Kingdom

Registered as a Limited Company in England and Wales No.1920623.
Registered Office as above

Switchboard: 020 7066 1000
Web Site: http://www.fsa.gov.uk
*****************************************************************


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users