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 testAnalyticContinuousPartialFloatingLookback() { // Testing analytic continuous partial floating-strike lookback options..."); LookbackOptionData[] values = { // data from "Option Pricing Formulas, Second Edition", Haug, 2006, pg.146 //type, strike, minmax, s, q, r, t, v, l, t1, result, tol new LookbackOptionData(Option.Type.Call, 0, 90, 90, 0, 0.06, 1, 0.1, 1, 0.25, 8.6524, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 90, 90, 0, 0.06, 1, 0.1, 1, 0.5, 9.2128, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 90, 90, 0, 0.06, 1, 0.1, 1, 0.75, 9.5567, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.1, 1, 0.25, 10.5751, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.1, 1, 0.5, 11.2601, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.1, 1, 0.75, 11.6804, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 90, 90, 0, 0.06, 1, 0.2, 1, 0.25, 13.3402, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 90, 90, 0, 0.06, 1, 0.2, 1, 0.5, 14.5121, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 90, 90, 0, 0.06, 1, 0.2, 1, 0.75, 15.314, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.2, 1, 0.25, 16.3047, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.2, 1, 0.5, 17.737, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.2, 1, 0.75, 18.7171, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 90, 90, 0, 0.06, 1, 0.3, 1, 0.25, 17.9831, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 90, 90, 0, 0.06, 1, 0.3, 1, 0.5, 19.6618, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 90, 90, 0, 0.06, 1, 0.3, 1, 0.75, 20.8493, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.3, 1, 0.25, 21.9793, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.3, 1, 0.5, 24.0311, 1.0e-4), new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.3, 1, 0.75, 25.4825, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 90, 90, 0, 0.06, 1, 0.1, 1, 0.25, 2.7189, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 90, 90, 0, 0.06, 1, 0.1, 1, 0.5, 3.4639, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 90, 90, 0, 0.06, 1, 0.1, 1, 0.75, 4.1912, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 110, 110, 0, 0.06, 1, 0.1, 1, 0.25, 3.3231, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 110, 110, 0, 0.06, 1, 0.1, 1, 0.5, 4.2336, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 110, 110, 0, 0.06, 1, 0.1, 1, 0.75, 5.1226, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 90, 90, 0, 0.06, 1, 0.2, 1, 0.25, 7.9153, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 90, 90, 0, 0.06, 1, 0.2, 1, 0.5, 9.5825, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 90, 90, 0, 0.06, 1, 0.2, 1, 0.75, 11.0362, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 110, 110, 0, 0.06, 1, 0.2, 1, 0.25, 9.6743, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 110, 110, 0, 0.06, 1, 0.2, 1, 0.5, 11.7119, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 110, 110, 0, 0.06, 1, 0.2, 1, 0.75, 13.4887, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 90, 90, 0, 0.06, 1, 0.3, 1, 0.25, 13.4719, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 90, 90, 0, 0.06, 1, 0.3, 1, 0.5, 16.1495, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 90, 90, 0, 0.06, 1, 0.3, 1, 0.75, 18.4071, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 110, 110, 0, 0.06, 1, 0.3, 1, 0.25, 16.4657, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 110, 110, 0, 0.06, 1, 0.3, 1, 0.5, 19.7383, 1.0e-4), new LookbackOptionData(Option.Type.Put, 0, 110, 110, 0, 0.06, 1, 0.3, 1, 0.75, 22.4976, 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 AnalyticContinuousPartialFloatingLookbackEngine(stochProcess); Date lookbackEnd = today + Convert.ToInt32(values[i].t1 * 360 + 0.5); ContinuousPartialFloatingLookbackOption option = new ContinuousPartialFloatingLookbackOption( values[i].minmax, values[i].l, lookbackEnd, 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); } } }