/*! \warning currently, this method returns the Black-Scholes implied volatility using analytic formulas for European options and a finite-difference method for American and Bermudan options. It will give unconsistent results if the pricing was performed with any other methods (such as jump-diffusion models.) \warning options with a gamma that changes sign (e.g., binary options) have values that are <b>not</b> monotonic in the volatility. In these cases, the calculation can fail and the result (if any) is almost meaningless. Another possible source of failure is to have a target value that is not attainable with any volatility, e.g., a target value lower than the intrinsic value in the case of American options. */ //public double impliedVolatility(double price, GeneralizedBlackScholesProcess process, // double accuracy = 1.0e-4, int maxEvaluations = 100, double minVol = 1.0e-7, double maxVol = 4.0) { public double impliedVolatility(double targetValue, GeneralizedBlackScholesProcess process, double accuracy, int maxEvaluations, double minVol, double maxVol) { if(isExpired()) throw new ApplicationException("option expired"); SimpleQuote volQuote = new SimpleQuote(); GeneralizedBlackScholesProcess newProcess = ImpliedVolatilityHelper.clone(process, volQuote); // engines are built-in for the time being IPricingEngine engine; switch (exercise_.type()) { case Exercise.Type.European: engine = new AnalyticEuropeanEngine(newProcess); break; case Exercise.Type.American: engine = new FDAmericanEngine(newProcess); break; case Exercise.Type.Bermudan: engine = new FDBermudanEngine(newProcess); break; default: throw new ArgumentException("unknown exercise type"); } return ImpliedVolatilityHelper.calculate(this, engine, volQuote, targetValue, accuracy, maxEvaluations, minVol, maxVol); }
public void testFdValues() { //("Testing finite-difference engine for American options..."); Date today = Date.Today; DayCounter dc = new Actual360(); SimpleQuote spot = new SimpleQuote(0.0); SimpleQuote qRate = new SimpleQuote(0.0); YieldTermStructure qTS = Utilities.flatRate(today, qRate, dc); SimpleQuote rRate = new SimpleQuote(0.0); YieldTermStructure rTS = Utilities.flatRate(today, rRate, dc); SimpleQuote vol = new SimpleQuote(0.0); BlackVolTermStructure volTS = Utilities.flatVol(today, vol, dc); double tolerance = 8.0e-2; for (int i = 0; i < juValues.Length; i++) { StrikedTypePayoff payoff = new PlainVanillaPayoff(juValues[i].type, juValues[i].strike); Date exDate = today + Convert.ToInt32(juValues[i].t * 360 + 0.5); Exercise exercise = new AmericanExercise(today, exDate); spot.setValue(juValues[i].s); qRate.setValue(juValues[i].q); rRate.setValue(juValues[i].r); vol.setValue(juValues[i].v); BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle <Quote>(spot), new Handle <YieldTermStructure>(qTS), new Handle <YieldTermStructure>(rTS), new Handle <BlackVolTermStructure>(volTS)); IPricingEngine engine = new FDAmericanEngine(stochProcess, 100, 100); VanillaOption option = new VanillaOption(payoff, exercise); option.setPricingEngine(engine); double calculated = option.NPV(); double error = Math.Abs(calculated - juValues[i].result); if (error > tolerance) { REPORT_FAILURE("value", payoff, exercise, juValues[i].s, juValues[i].q, juValues[i].r, today, juValues[i].v, juValues[i].result, calculated, error, tolerance); } } }
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(FDAmericanEngine obj) { return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr); }
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(FDAmericanEngine obj) { return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; }