public void testMonteCarloLookback() { double tolerance = 0.1; DayCounter dc = new Actual360(); Date today = Date.Today; double strike = 90; double t = 1; double t1 = 0.25; Date exDate = today + Convert.ToInt32(t * 360 + 0.5); Exercise exercise = new EuropeanExercise(exDate); 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); spot.setValue(100); qRate.setValue(0); rRate.setValue(0.06); vol.setValue(0.1); BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess( new Handle <Quote>(spot), new Handle <YieldTermStructure>(qTS), new Handle <YieldTermStructure>(rTS), new Handle <BlackVolTermStructure>(volTS)); Option.Type[] types = new Option.Type[] { Option.Type.Call, Option.Type.Put }; for (int i = 0; i < types.Length; i++) { Option.Type type = types[i]; StrikedTypePayoff payoff = new PlainVanillaPayoff(type, strike); /** * Partial Fixed * **/ Date lookbackStart = today + Convert.ToInt32(t1 * 360 + 0.5); ContinuousPartialFixedLookbackOption partialFixedLookback = new ContinuousPartialFixedLookbackOption(lookbackStart, payoff, exercise); IPricingEngine engine = new AnalyticContinuousPartialFixedLookbackEngine(stochProcess); partialFixedLookback.setPricingEngine(engine); double analytical = partialFixedLookback.NPV(); IPricingEngine mcpartialfixedengine = new MakeMCLookbackEngine <ContinuousPartialFixedLookbackOption.Arguments, ContinuousPartialFixedLookbackOption.Results, PseudoRandom, Statistics>(stochProcess) .withSteps(2000) .withAntitheticVariate() .withSeed(1) .withAbsoluteTolerance(tolerance) .value(); partialFixedLookback.setPricingEngine(mcpartialfixedengine); double monteCarlo = partialFixedLookback.NPV(); double diff = Math.Abs(analytical - monteCarlo); if (diff > tolerance) { REPORT_FAILURE_MC("Partial Fixed", type, analytical, monteCarlo, tolerance); } /** * Fixed * **/ double minMax = 100; ContinuousFixedLookbackOption fixedLookback = new ContinuousFixedLookbackOption(minMax, payoff, exercise); IPricingEngine analyticalfixedengine = new AnalyticContinuousFixedLookbackEngine(stochProcess); fixedLookback.setPricingEngine(analyticalfixedengine); analytical = fixedLookback.NPV(); IPricingEngine mcfixedengine = new MakeMCLookbackEngine <ContinuousFixedLookbackOption.Arguments, ContinuousFixedLookbackOption.Results, PseudoRandom, Statistics>(stochProcess) .withSteps(2000) .withAntitheticVariate() .withSeed(1) .withAbsoluteTolerance(tolerance) .value(); fixedLookback.setPricingEngine(mcfixedengine); monteCarlo = fixedLookback.NPV(); diff = Math.Abs(analytical - monteCarlo); if (diff > tolerance) { REPORT_FAILURE_MC("Fixed", type, analytical, monteCarlo, tolerance); } /** * Partial Floating * **/ double lambda = 1; Date lookbackEnd = today + Convert.ToInt32(t1 * 360 + 0.5); FloatingTypePayoff floatingPayoff = new FloatingTypePayoff(type); ContinuousPartialFloatingLookbackOption partialFloating = new ContinuousPartialFloatingLookbackOption(minMax, lambda, lookbackEnd, floatingPayoff, exercise); IPricingEngine analyticalpartialFloatingengine = new AnalyticContinuousPartialFloatingLookbackEngine(stochProcess); partialFloating.setPricingEngine(analyticalpartialFloatingengine); analytical = partialFloating.NPV(); IPricingEngine mcpartialfloatingengine = new MakeMCLookbackEngine <ContinuousPartialFloatingLookbackOption.Arguments, ContinuousPartialFloatingLookbackOption.Results, PseudoRandom, Statistics> (stochProcess) .withSteps(2000) .withAntitheticVariate() .withSeed(1) .withAbsoluteTolerance(tolerance) .value(); partialFloating.setPricingEngine(mcpartialfloatingengine); monteCarlo = partialFloating.NPV(); diff = Math.Abs(analytical - monteCarlo); if (diff > tolerance) { REPORT_FAILURE_MC("Partial Floating", type, analytical, monteCarlo, tolerance); } /** * Floating * **/ ContinuousFloatingLookbackOption floating = new ContinuousFloatingLookbackOption(minMax, floatingPayoff, exercise); IPricingEngine analyticalFloatingengine = new AnalyticContinuousFloatingLookbackEngine(stochProcess); floating.setPricingEngine(analyticalFloatingengine); analytical = floating.NPV(); IPricingEngine mcfloatingengine = new MakeMCLookbackEngine <ContinuousFloatingLookbackOption.Arguments, ContinuousFloatingLookbackOption.Results, PseudoRandom, Statistics> (stochProcess) .withSteps(2000) .withAntitheticVariate() .withSeed(1) .withAbsoluteTolerance(tolerance) .value(); floating.setPricingEngine(mcfloatingengine); monteCarlo = floating.NPV(); diff = Math.Abs(analytical - monteCarlo); if (diff > tolerance) { REPORT_FAILURE_MC("Floating", type, analytical, monteCarlo, tolerance); } } }
public void testAnalyticContinuousFloatingLookback() { // Testing analytic continuous floating-strike lookback options LookbackOptionData[] values = { // data from "Option Pricing Formulas", Haug, 1998, pg.61-62 new LookbackOptionData(Option.Type.Call, 0, 100, 120.0, 0.06, 0.10, 0.50, 0.30, 0, 0, 25.3533, 1.0e-4), // data from "Connecting discrete and continuous path-dependent options", // Broadie, Glasserman & Kou, 1999, pg.70-74 new LookbackOptionData(Option.Type.Call, 0, 100, 100.0, 0.00, 0.05, 1.00, 0.30, 0, 0, 23.7884, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 100, 100.0, 0.00, 0.05, 0.20, 0.30, 0, 0, 10.7190, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 100, 110.0, 0.00, 0.05, 0.20, 0.30, 0, 0, 14.4597, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 100, 100.0, 0.00, 0.10, 0.50, 0.30, 0, 0, 15.3526, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 110, 100.0, 0.00, 0.10, 0.50, 0.30, 0, 0, 16.8468, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 120, 100.0, 0.00, 0.10, 0.50, 0.30, 0, 0, 21.0645, 1.0e-4), }; DayCounter dc = new Actual360(); Date today = Date.Today; 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); for (int i = 0; i < values.Length; i++) { Date exDate = today + Convert.ToInt32(values[i].t * 360 + 0.5); Exercise exercise = new EuropeanExercise(exDate); spot.setValue(values[i].s); qRate.setValue(values[i].q); rRate.setValue(values[i].r); vol.setValue(values[i].v); FloatingTypePayoff payoff = new FloatingTypePayoff(values[i].type); BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess( new Handle <Quote>(spot), new Handle <YieldTermStructure>(qTS), new Handle <YieldTermStructure>(rTS), new Handle <BlackVolTermStructure>(volTS)); IPricingEngine engine = new AnalyticContinuousFloatingLookbackEngine(stochProcess); ContinuousFloatingLookbackOption option = new ContinuousFloatingLookbackOption(values[i].minmax, payoff, exercise); option.setPricingEngine(engine); double calculated = option.NPV(); double expected = values[i].result; double error = Math.Abs(calculated - expected); if (error > values[i].tol) { REPORT_FAILURE_FLOATING("value", values[i].minmax, payoff, exercise, values[i].s, values[i].q, values[i].r, today, values[i].v, expected, calculated, error, values[i].tol); } } }