public HullWhiteForwardProcess(Handle <YieldTermStructure> h, double a, double sigma) { process_ = new OrnsteinUhlenbeckProcess(a, sigma, h.link.forwardRate(0.0, 0.0, Compounding.Continuous, Frequency.NoFrequency).value()); h_ = h; a_ = a; sigma_ = sigma; }
public HullWhiteProcess(Handle <YieldTermStructure> h, double a, double sigma) { process_ = new OrnsteinUhlenbeckProcess(a, sigma, h.link.forwardRate(0.0, 0.0, Compounding.Continuous, Frequency.NoFrequency).value()); h_ = h; a_ = a; sigma_ = sigma; Utils.QL_REQUIRE(a_ >= 0.0, () => "negative a given"); Utils.QL_REQUIRE(sigma_ >= 0.0, () => "negative sigma given"); }
public void testMultiPathGenerator() { //("Testing n-D path generation against cached values..."); //SavedSettings backup; Settings.setEvaluationDate(new Date(26,4,2005)); Handle<Quote> x0=new Handle<Quote> (new SimpleQuote(100.0)); Handle<YieldTermStructure> r =new Handle<YieldTermStructure> (Utilities.flatRate(0.05, new Actual360())); Handle<YieldTermStructure> q=new Handle<YieldTermStructure> (Utilities.flatRate(0.02, new Actual360())); Handle<BlackVolTermStructure> sigma=new Handle<BlackVolTermStructure> (Utilities.flatVol(0.20, new Actual360())); Matrix correlation=new Matrix(3,3); correlation[0,0] = 1.0; correlation[0,1] = 0.9; correlation[0,2] = 0.7; correlation[1,0] = 0.9; correlation[1,1] = 1.0; correlation[1,2] = 0.4; correlation[2,0] = 0.7; correlation[2,1] = 0.4; correlation[2,2] = 1.0; List<StochasticProcess1D> processes = new List<StochasticProcess1D>(3); StochasticProcess process; processes.Add(new BlackScholesMertonProcess(x0,q,r,sigma)); processes.Add(new BlackScholesMertonProcess(x0,q,r,sigma)); processes.Add(new BlackScholesMertonProcess(x0,q,r,sigma)); process = new StochasticProcessArray(processes,correlation); // commented values must be used when Halley's correction is enabled double[] result1 = { 188.2235868185, 270.6713069569, 113.0431145652 }; // Real result1[] = { // 188.2235869273, // 270.6713071508, // 113.0431145652 }; double[] result1a = { 64.89105742957, 45.12494404804, 108.0475146914 }; // Real result1a[] = { // 64.89105739157, // 45.12494401537, // 108.0475146914 }; testMultiple(process, "Black-Scholes", result1, result1a); processes[0] = new GeometricBrownianMotionProcess(100.0, 0.03, 0.20); processes[1] = new GeometricBrownianMotionProcess(100.0, 0.03, 0.20); processes[2] = new GeometricBrownianMotionProcess(100.0, 0.03, 0.20); process = new StochasticProcessArray(processes,correlation); double[] result2 = { 174.8266131680, 237.2692443633, 119.1168555440 }; // Real result2[] = { // 174.8266132344, // 237.2692444869, // 119.1168555605 }; double[] result2a = { 57.69082393020, 38.50016862915, 116.4056510107 }; // Real result2a[] = { // 57.69082387657, // 38.50016858691, // 116.4056510107 }; testMultiple(process, "geometric Brownian", result2, result2a); processes[0] = new OrnsteinUhlenbeckProcess(0.1, 0.20); processes[1] = new OrnsteinUhlenbeckProcess(0.1, 0.20); processes[2] = new OrnsteinUhlenbeckProcess(0.1, 0.20); process = new StochasticProcessArray(processes,correlation); double[] result3 = { 0.2942058437284, 0.5525006418386, 0.02650931054575 }; double[] result3a = { -0.2942058437284, -0.5525006418386, -0.02650931054575 }; testMultiple(process, "Ornstein-Uhlenbeck", result3, result3a); processes[0] = new SquareRootProcess(0.1, 0.1, 0.20, 10.0); processes[1] = new SquareRootProcess(0.1, 0.1, 0.20, 10.0); processes[2] = new SquareRootProcess(0.1, 0.1, 0.20, 10.0); process = new StochasticProcessArray(processes,correlation); double[] result4 = { 4.279510844897, 4.943783503533, 3.590930385958 }; double[] result4a = { 2.763967737724, 2.226487196647, 3.503859264341 }; testMultiple(process, "square-root", result4, result4a); }
public override void calculate() { // 1. Term structure Handle <YieldTermStructure> ts = model_.currentLink().termStructure(); // 2. Mesher DayCounter dc = ts.currentLink().dayCounter(); Date referenceDate = ts.currentLink().referenceDate(); double maturity = dc.yearFraction(referenceDate, arguments_.exercise.lastDate()); OrnsteinUhlenbeckProcess process = new OrnsteinUhlenbeckProcess(model_.currentLink().a(), model_.currentLink().sigma()); Fdm1dMesher shortRateMesher = new FdmSimpleProcess1DMesher(xGrid_, process, maturity, 1, invEps_); FdmMesher mesher = new FdmMesherComposite(shortRateMesher); // 3. Inner Value Calculator List <Date> exerciseDates = arguments_.exercise.dates(); Dictionary <double, Date> t2d = new Dictionary <double, Date>(); for (int i = 0; i < exerciseDates.Count; ++i) { double t = dc.yearFraction(referenceDate, exerciseDates[i]); Utils.QL_REQUIRE(t >= 0, () => "exercise dates must not contain past date"); t2d.Add(t, exerciseDates[i]); } Handle <YieldTermStructure> disTs = model_.currentLink().termStructure(); Handle <YieldTermStructure> fwdTs = arguments_.swap.iborIndex().forwardingTermStructure(); Utils.QL_REQUIRE(fwdTs.currentLink().dayCounter() == disTs.currentLink().dayCounter(), () => "day counter of forward and discount curve must match"); Utils.QL_REQUIRE(fwdTs.currentLink().referenceDate() == disTs.currentLink().referenceDate(), () => "reference date of forward and discount curve must match"); HullWhite fwdModel = new HullWhite(fwdTs, model_.currentLink().a(), model_.currentLink().sigma()); FdmInnerValueCalculator calculator = new FdmAffineModelSwapInnerValue <HullWhite>( model_.currentLink(), fwdModel, arguments_.swap, t2d, mesher, 0); // 4. Step conditions FdmStepConditionComposite conditions = FdmStepConditionComposite.vanillaComposite( new DividendSchedule(), arguments_.exercise, mesher, calculator, referenceDate, dc); // 5. Boundary conditions FdmBoundaryConditionSet boundaries = new FdmBoundaryConditionSet(); // 6. Solver FdmSolverDesc solverDesc = new FdmSolverDesc(); solverDesc.mesher = mesher; solverDesc.bcSet = boundaries; solverDesc.condition = conditions; solverDesc.calculator = calculator; solverDesc.maturity = maturity; solverDesc.timeSteps = tGrid_; solverDesc.dampingSteps = dampingSteps_; FdmHullWhiteSolver solver = new FdmHullWhiteSolver(model_, solverDesc, schemeDesc_); results_.value = solver.valueAt(0.0); }