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)); }
/// <summary> /// Returns the Black implied forward yield volatility /// <remarks> /// the forward yield volatility, see Hull, Fourth Edition, /// Chapter 20, pg 536). Relevant only to European put/call /// schedules /// </remarks> /// </summary> /// <param name="targetValue"></param> /// <param name="discountCurve"></param> /// <param name="accuracy"></param> /// <param name="maxEvaluations"></param> /// <param name="minVol"></param> /// <param name="maxVol"></param> /// <returns></returns> public double impliedVolatility(double targetValue, Handle <YieldTermStructure> discountCurve, double accuracy, int maxEvaluations, double minVol, double maxVol) { calculate(); Utils.QL_REQUIRE(!isExpired(), () => "instrument expired"); double guess = 0.5 * (minVol + maxVol); blackDiscountCurve_.linkTo(discountCurve, false); ImpliedVolHelper f = new ImpliedVolHelper(this, targetValue); Brent solver = new Brent(); solver.setMaxEvaluations(maxEvaluations); return(solver.solve(f, accuracy, guess, minVol, maxVol)); }
public double impliedVolatility( double targetValue, Handle <YieldTermStructure> discountCurve, double guess, double accuracy, int maxEvaluations, double minVol, double maxVol, VolatilityType type, double displacement) { calculate(); if (isExpired()) { throw new ArgumentException("instrument expired"); } ImpliedVolHelper f = new ImpliedVolHelper(this, discountCurve, targetValue, displacement, type); NewtonSafe solver = new NewtonSafe(); solver.setMaxEvaluations(maxEvaluations); return(solver.solve(f, accuracy, guess, minVol, maxVol)); }