protected override double blackVolImpl(double t, double strike) { HestonProcess process = hestonModel_.link.process(); double df = process.riskFreeRate().link.discount(t, true); double div = process.dividendYield().link.discount(t, true); double spotPrice = process.s0().link.value(); double fwd = spotPrice * process.dividendYield().link.discount(t, true) / process.riskFreeRate().link.discount(t, true); var payoff = new PlainVanillaPayoff(fwd > strike ? Option.Type.Put : Option.Type.Call, strike); double kappa = hestonModel_.link.kappa(); double theta = hestonModel_.link.theta(); double rho = hestonModel_.link.rho(); double sigma = hestonModel_.link.sigma(); double v0 = hestonModel_.link.v0(); AnalyticHestonEngine.ComplexLogFormula cpxLogFormula = AnalyticHestonEngine.ComplexLogFormula.Gatheral; AnalyticHestonEngine hestonEnginePtr = null; double?npv = null; int evaluations = 0; AnalyticHestonEngine.doCalculation( df, div, spotPrice, strike, t, kappa, theta, sigma, v0, rho, payoff, integration_, cpxLogFormula, hestonEnginePtr, ref npv, ref evaluations); if (npv <= 0.0) { return(Math.Sqrt(theta)); } Brent solver = new Brent(); solver.setMaxEvaluations(10000); double guess = Math.Sqrt(theta); double accuracy = Const.QL_EPSILON; var f = new ImpliedVolHelper(payoff.optionType(), strike, fwd, t, df, npv.Value); return(solver.solve(f, accuracy, guess, 0.01)); }
public HestonModel(HestonProcess process) : base(5) { process_ = process; arguments_[0] = new ConstantParameter(process.theta(), new PositiveConstraint()); arguments_[1] = new ConstantParameter(process.kappa(), new PositiveConstraint()); arguments_[2] = new ConstantParameter(process.sigma(), new PositiveConstraint()); arguments_[3] = new ConstantParameter(process.rho(), new BoundaryConstraint(-1.0, 1.0)); arguments_[4] = new ConstantParameter(process.v0(), new PositiveConstraint()); generateArguments(); process_.riskFreeRate().registerWith(update); process_.dividendYield().registerWith(update); process_.s0().registerWith(update); }
public override void calculate() { // this is a european option pricer Utils.QL_REQUIRE(arguments_.exercise.type() == Exercise.Type.European, () => "not an European option"); // plain vanilla PlainVanillaPayoff payoff = arguments_.payoff as PlainVanillaPayoff; Utils.QL_REQUIRE(payoff != null, () => "non plain vanilla payoff given"); HestonProcess process = model_.link.process(); double riskFreeDiscount = process.riskFreeRate().link.discount(arguments_.exercise.lastDate()); double dividendDiscount = process.dividendYield().link.discount(arguments_.exercise.lastDate()); double spotPrice = process.s0().link.value(); Utils.QL_REQUIRE(spotPrice > 0.0, () => "negative or null underlying given"); double strikePrice = payoff.strike(); double term = process.time(arguments_.exercise.lastDate()); double?resultsValue = null; doCalculation(riskFreeDiscount, dividendDiscount, spotPrice, strikePrice, term, model_.link.kappa(), model_.link.theta(), model_.link.sigma(), model_.link.v0(), model_.link.rho(), payoff, integration_, cpxLog_, this, ref resultsValue, ref evaluations_); results_.value = resultsValue; }