public FdmHestonLocalVolatilityVarianceMesher(int size, HestonProcess process, LocalVolTermStructure leverageFct, double maturity, int tAvgSteps = 10, double epsilon = 0.0001) : base(size) { leverageFct_ = leverageFct; FdmHestonVarianceMesher mesher = new FdmHestonVarianceMesher(size, process, maturity, tAvgSteps, epsilon); for (int i = 0; i < size; ++i) { dplus_[i] = mesher.dplus(i); dminus_[i] = mesher.dminus(i); locations_[i] = mesher.location(i); } volaEstimate_ = mesher.volaEstimate(); if (leverageFct != null) { double s0 = process.s0().currentLink().value(); List <double> acc = new List <double>(); acc.Add(leverageFct.localVol(0.0, s0, true)); Handle <YieldTermStructure> rTS = process.riskFreeRate(); Handle <YieldTermStructure> qTS = process.dividendYield(); for (int l = 1; l <= tAvgSteps; ++l) { double t = (maturity * l) / tAvgSteps; double vol = volaEstimate_ * acc.Average(); double fwd = s0 * qTS.currentLink().discount(t) / rTS.currentLink().discount(t); int sAvgSteps = 50; Vector u = new Vector(sAvgSteps), sig = new Vector(sAvgSteps); for (int i = 0; i < sAvgSteps; ++i) { u[i] = epsilon + ((1.0 - 2.0 * epsilon) / (sAvgSteps - 1.0)) * i; double x = new InverseCumulativeNormal().value(u[i]); double gf = x * vol * Math.Sqrt(t); double f = fwd * Math.Exp(gf); sig[i] = Math.Pow(leverageFct.localVol(t, f, true), 2.0); } double leverageAvg = new GaussLobattoIntegral(10000, 1E-4).value(new interpolated_volatility(u, sig).value, u.First(), u.Last()) / (1.0 - 2.0 * epsilon); acc.Add(leverageAvg); } volaEstimate_ *= acc.Average(); } }
public FdmSolverDesc getSolverDesc(double x) { // 1. Mesher HestonProcess process = model_.currentLink().process(); double maturity = process.time(arguments_.exercise.lastDate()); // 1.1 The variance mesher int tGridMin = 5; FdmHestonVarianceMesher varianceMesher = new FdmHestonVarianceMesher(vGrid_, process, maturity, Math.Max(tGridMin, tGrid_ / 50)); // 1.2 The equity mesher StrikedTypePayoff payoff = arguments_.payoff as StrikedTypePayoff; Fdm1dMesher equityMesher; if (strikes_.empty()) { equityMesher = new FdmBlackScholesMesher( xGrid_, FdmBlackScholesMesher.processHelper( process.s0(), process.dividendYield(), process.riskFreeRate(), varianceMesher.volaEstimate()), maturity, payoff.strike(), null, null, 0.0001, x, new Pair <double?, double?>(payoff.strike(), 0.1), arguments_.cashFlow); } else { Utils.QL_REQUIRE(arguments_.cashFlow.empty(), () => "multiple strikes engine " + "does not work with discrete dividends"); equityMesher = new FdmBlackScholesMultiStrikeMesher( xGrid_, FdmBlackScholesMesher.processHelper( process.s0(), process.dividendYield(), process.riskFreeRate(), varianceMesher.volaEstimate()), maturity, strikes_, 0.0001, x, new Pair <double?, double?>(payoff.strike(), 0.075)); } FdmMesher mesher = new FdmMesherComposite(equityMesher, varianceMesher); // 2. Calculator FdmInnerValueCalculator calculator = new FdmLogInnerValue(arguments_.payoff, mesher, 0); // 3. Step conditions FdmStepConditionComposite conditions = FdmStepConditionComposite.vanillaComposite( arguments_.cashFlow, arguments_.exercise, mesher, calculator, process.riskFreeRate().currentLink().referenceDate(), process.riskFreeRate().currentLink().dayCounter()); // 4. Boundary conditions FdmBoundaryConditionSet boundaries = new FdmBoundaryConditionSet(); // 5. Solver FdmSolverDesc solverDesc = new FdmSolverDesc(); solverDesc.mesher = mesher; solverDesc.bcSet = boundaries; solverDesc.condition = conditions; solverDesc.calculator = calculator; solverDesc.maturity = maturity; solverDesc.dampingSteps = dampingSteps_; solverDesc.timeSteps = tGrid_; return(solverDesc); }