I have attached a simple code that tries a sanity check. Starting
with some discount curve, I want to see that I can recover correct zero coupon bond prices from a Hull White trinomial tree and a simulation. What I find is that the lattice does a perfect job recovering the term structure. The simulation does not unless I set volatility to zero. If I let the number of paths in the simulation grow very high (e.g. 200000), then zero prices out far on the time axis are better recovered, but it doesn’t seem sensible to me that I should require so many paths. Also, a third-party implementation does not require any large number of paths to recover the termstructure. You can run my test program with a command like this: ./discounttest 100 30 .01 .01 Any help you can provide would be appreciated. Thanks, Rakesh ---- begin code ---- #include <algorithm> #include <iostream> #include <sstream> #include <vector> #include <boost/shared_ptr.hpp> #include <ql/quantlib.hpp> using namespace std; using namespace boost; using namespace QuantLib; DiscountFactor discount(const Matrix &paths, const TimeGrid &grid, const Time &t) { Size nPaths(paths.rows()); vector<Real> spots(nPaths, 0.0); for (Size step(grid.index(t)); step > 0; --step) { for (Size path(0); path < nPaths; ++path) { spots[path] += paths[path][step - 1] * grid.dt(step - 1); } } vector<Real> dfs(paths.rows()); for (Size path(0); path < nPaths; ++path) { dfs[path] = exp(-spots[path]); } return accumulate(dfs.begin(), dfs.end(), 0.0) / dfs.size(); } int main(int argc, char *argv[]) { if (argc < 5) { cerr << "Usage: " << argv[0] << " <num-paths> <num-steps> <a> <sigma>" << endl; return -1; } istringstream sNumPaths(argv[1]), sNumSteps(argv[2]); istringstream sA(argv[3]), sSigma(argv[4]); const Date &referenceDate = Date::todaysDate(); Handle<Quote> forward(new SimpleQuote(0.05)); ActualActual dayCounter; shared_ptr<YieldTermStructure> yield(new FlatForward(referenceDate, forward, dayCounter)); Real a, sigma; sA >> a; sSigma >> sigma; shared_ptr<HullWhite> hw(new HullWhite(Handle<YieldTermStructure>(yield), a, sigma)); Size numPaths, numSteps; sNumPaths >> numPaths; sNumSteps >> numSteps; TimeGrid grid((Time)30, numSteps); shared_ptr<HullWhiteProcess> hwProcess(new HullWhiteProcess (Handle<YieldTermStructure>(yield), a, sigma)); PathGenerator<SobolBrownianBridgeRsg> generator(hwProcess, grid, SobolBrownianBridgeRsg(1, (grid.size() - 1)), false); numSteps = grid.size(); Matrix paths(numPaths, numSteps); for (Size path(0); path < numPaths; ++path) { const PathGenerator<SobolBrownianBridgeRsg>::sample_type &draw = generator.next(); for (Size step(0); step < numSteps; ++step) { paths[path][step] = draw.value[step]; } } for (TimeGrid::const_reverse_iterator t(grid.rbegin()); t != grid.rend(); t++) { DiscretizedDiscountBond zero; zero.initialize(hw->tree(grid), *t); cout << "Discount for time t = " << *t << " is " << yield->discount(*t) << "; HW Tree discount is " << zero.presentValue() << "; SIM discount is " << discount(paths, grid, *t) << endl; } return 0; } ---- end code ---- ------------------------------------------------------------------------------ Dive into the World of Parallel Programming The Go Parallel Website, sponsored by Intel and developed in partnership with Slashdot Media, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials and more. Take a look and join the conversation now. http://goparallel.sourceforge.net/ _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Free forum by Nabble | Edit this page |