internal static global::System.Runtime.InteropServices.HandleRef getCPtr(KirkEngine obj) { return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr); }
public void testEuroTwoValues() { // Testing two-asset European basket options... /* * Data from: * Excel spreadsheet www.maths.ox.ac.uk/~firth/computing/excel.shtml * and * "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 pag 56-58 * European two asset max basket options */ BasketOptionTwoData[] values = { // basketType, optionType, strike, s1, s2, q1, q2, r, t, v1, v2, rho, result, tol // data from http://www.maths.ox.ac.uk/~firth/computing/excel.shtml new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.90, 10.898, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.70, 8.483, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.50, 6.844, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30, 5.531, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.10, 4.413, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.50, 0.70, 0.00, 4.981, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.50, 0.30, 0.00, 4.159, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.50, 0.10, 0.00, 2.597, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.50, 0.10, 0.50, 4.030, 1.0e-3), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.90, 17.565, 1.0e-3), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.70, 19.980, 1.0e-3), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.50, 21.619, 1.0e-3), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30, 22.932, 1.0e-3), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.10, 24.049, 1.1e-3), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Call, 100.0, 80.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30, 16.508, 1.0e-3), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Call, 100.0, 80.0, 80.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30, 8.049, 1.0e-3), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Call, 100.0, 80.0, 120.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30, 30.141, 1.0e-3), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Call, 100.0, 120.0, 120.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30, 42.889, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Put, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.90, 11.369, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Put, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.70, 12.856, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Put, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.50, 13.890, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Put, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30, 14.741, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Put, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.10, 15.485, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Put, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 0.50, 0.30, 0.30, 0.10, 11.893, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Put, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 0.25, 0.30, 0.30, 0.10, 8.881, 1.0e-3), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Put, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 2.00, 0.30, 0.30, 0.10, 19.268, 1.0e-3), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Put, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.90, 7.339, 1.0e-3), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Put, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.70, 5.853, 1.0e-3), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Put, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.50, 4.818, 1.0e-3), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Put, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30, 3.967, 1.1e-3), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Put, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.10, 3.223, 1.0e-3), // basketType, optionType, strike, s1, s2, q1, q2, r, t, v1, v2, rho, result, tol // data from "Option pricing formulas" VB code + spreadsheet new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Call, 98.0, 100.0, 105.0, 0.00, 0.00, 0.05, 0.50, 0.11, 0.16, 0.63, 4.8177, 1.0e-4), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Call, 98.0, 100.0, 105.0, 0.00, 0.00, 0.05, 0.50, 0.11, 0.16, 0.63, 11.6323, 1.0e-4), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Put, 98.0, 100.0, 105.0, 0.00, 0.00, 0.05, 0.50, 0.11, 0.16, 0.63, 2.0376, 1.0e-4), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Put, 98.0, 100.0, 105.0, 0.00, 0.00, 0.05, 0.50, 0.11, 0.16, 0.63, 0.5731, 1.0e-4), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Call, 98.0, 100.0, 105.0, 0.06, 0.09, 0.05, 0.50, 0.11, 0.16, 0.63, 2.9340, 1.0e-4), new BasketOptionTwoData(BasketType.MinBasket, Option.Type.Put, 98.0, 100.0, 105.0, 0.06, 0.09, 0.05, 0.50, 0.11, 0.16, 0.63, 3.5224, 1.0e-4), // data from "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 pag 58 new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Call, 98.0, 100.0, 105.0, 0.06, 0.09, 0.05, 0.50, 0.11, 0.16, 0.63, 8.0701, 1.0e-4), new BasketOptionTwoData(BasketType.MaxBasket, Option.Type.Put, 98.0, 100.0, 105.0, 0.06, 0.09, 0.05, 0.50, 0.11, 0.16, 0.63, 1.2181, 1.0e-4), /* "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 pag 59-60 * Kirk approx. for a european spread option on two futures*/ new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.1, 0.20, 0.20, -0.5, 4.7530, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.1, 0.20, 0.20, 0.0, 3.7970, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.1, 0.20, 0.20, 0.5, 2.5537, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.1, 0.25, 0.20, -0.5, 5.4275, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.1, 0.25, 0.20, 0.0, 4.3712, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.1, 0.25, 0.20, 0.5, 3.0086, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.1, 0.20, 0.25, -0.5, 5.4061, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.1, 0.20, 0.25, 0.0, 4.3451, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.1, 0.20, 0.25, 0.5, 2.9723, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.5, 0.20, 0.20, -0.5, 10.7517, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.5, 0.20, 0.20, 0.0, 8.7020, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.5, 0.20, 0.20, 0.5, 6.0257, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.5, 0.25, 0.20, -0.5, 12.1941, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.5, 0.25, 0.20, 0.0, 9.9340, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.5, 0.25, 0.20, 0.5, 7.0067, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.5, 0.20, 0.25, -0.5, 12.1483, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.5, 0.20, 0.25, 0.0, 9.8780, 1.0e-3), new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call, 3.0, 122.0, 120.0, 0.0, 0.0, 0.10, 0.5, 0.20, 0.25, 0.5, 6.9284, 1.0e-3) }; DayCounter dc = new Actual360(); Date today = Date.Today; SimpleQuote spot1 = new SimpleQuote(0.0); SimpleQuote spot2 = new SimpleQuote(0.0); SimpleQuote qRate1 = new SimpleQuote(0.0); YieldTermStructure qTS1 = Utilities.flatRate(today, qRate1, dc); SimpleQuote qRate2 = new SimpleQuote(0.0); YieldTermStructure qTS2 = Utilities.flatRate(today, qRate2, dc); SimpleQuote rRate = new SimpleQuote(0.0); YieldTermStructure rTS = Utilities.flatRate(today, rRate, dc); SimpleQuote vol1 = new SimpleQuote(0.0); BlackVolTermStructure volTS1 = Utilities.flatVol(today, vol1, dc); SimpleQuote vol2 = new SimpleQuote(0.0); BlackVolTermStructure volTS2 = Utilities.flatVol(today, vol2, dc); //double mcRelativeErrorTolerance = 0.01; //double fdRelativeErrorTolerance = 0.01; for (int i = 0; i < values.Length; i++) { PlainVanillaPayoff payoff = new PlainVanillaPayoff(values[i].type, values[i].strike); Date exDate = today + (int)(values[i].t * 360 + 0.5); Exercise exercise = new EuropeanExercise(exDate); spot1.setValue(values[i].s1); spot2.setValue(values[i].s2); qRate1.setValue(values[i].q1); qRate2.setValue(values[i].q2); rRate.setValue(values[i].r); vol1.setValue(values[i].v1); vol2.setValue(values[i].v2); IPricingEngine analyticEngine = null; GeneralizedBlackScholesProcess p1 = null, p2 = null; switch (values[i].basketType) { case BasketType.MaxBasket: case BasketType.MinBasket: p1 = new BlackScholesMertonProcess(new Handle <Quote>(spot1), new Handle <YieldTermStructure>(qTS1), new Handle <YieldTermStructure>(rTS), new Handle <BlackVolTermStructure>(volTS1)); p2 = new BlackScholesMertonProcess(new Handle <Quote>(spot2), new Handle <YieldTermStructure>(qTS2), new Handle <YieldTermStructure>(rTS), new Handle <BlackVolTermStructure>(volTS2)); analyticEngine = new StulzEngine(p1, p2, values[i].rho); break; case BasketType.SpreadBasket: p1 = new BlackProcess(new Handle <Quote>(spot1), new Handle <YieldTermStructure>(rTS), new Handle <BlackVolTermStructure>(volTS1)); p2 = new BlackProcess(new Handle <Quote>(spot2), new Handle <YieldTermStructure>(rTS), new Handle <BlackVolTermStructure>(volTS2)); analyticEngine = new KirkEngine((BlackProcess)p1, (BlackProcess)p2, values[i].rho); break; default: Utils.QL_FAIL("unknown basket type"); break; } List <StochasticProcess1D> procs = new List <StochasticProcess1D> { p1, p2 }; Matrix correlationMatrix = new Matrix(2, 2, values[i].rho); for (int j = 0; j < 2; j++) { correlationMatrix[j, j] = 1.0; } StochasticProcessArray process = new StochasticProcessArray(procs, correlationMatrix); //IPricingEngine mcEngine = MakeMCEuropeanBasketEngine<PseudoRandom, Statistics>(process) // .withStepsPerYear(1) // .withSamples(10000) // .withSeed(42); //IPricingEngine fdEngine = new Fd2dBlackScholesVanillaEngine(p1, p2, values[i].rho, 50, 50, 15); BasketOption basketOption = new BasketOption(basketTypeToPayoff(values[i].basketType, payoff), exercise); // analytic engine basketOption.setPricingEngine(analyticEngine); double calculated = basketOption.NPV(); double expected = values[i].result; double error = Math.Abs(calculated - expected); if (error > values[i].tol) { REPORT_FAILURE_2("value", values[i].basketType, payoff, exercise, values[i].s1, values[i].s2, values[i].q1, values[i].q2, values[i].r, today, values[i].v1, values[i].v2, values[i].rho, values[i].result, calculated, error, values[i].tol); } // // fd engine // basketOption.setPricingEngine(fdEngine); // calculated = basketOption.NPV(); // double relError = relativeError(calculated, expected, expected); // if (relError > mcRelativeErrorTolerance ) // { // REPORT_FAILURE_2("FD value", values[i].basketType, payoff, // exercise, values[i].s1, values[i].s2, // values[i].q1, values[i].q2, values[i].r, // today, values[i].v1, values[i].v2, values[i].rho, // values[i].result, calculated, relError, // fdRelativeErrorTolerance); // } //// mc engine //basketOption.setPricingEngine(mcEngine); //calculated = basketOption.NPV(); //relError = relativeError(calculated, expected, values[i].s1); //if (relError > mcRelativeErrorTolerance ) //{ // REPORT_FAILURE_2("MC value", values[i].basketType, payoff, // exercise, values[i].s1, values[i].s2, // values[i].q1, values[i].q2, values[i].r, // today, values[i].v1, values[i].v2, values[i].rho, // values[i].result, calculated, relError, // mcRelativeErrorTolerance); //} } }
public static string eqInstSpreadOptionKirk( [ExcelArgument(Description = "id of option to be constructed ")] string ObjectId, [ExcelArgument(Description = "Option type (Call/Put) ")] string optype, [ExcelArgument(Description = "Spot price leg 1")] double spot1, [ExcelArgument(Description = "Spot price leg 2")] double spot2, [ExcelArgument(Description = "Strike price ")] double stirkeprice, [ExcelArgument(Description = "Expiry Date ")] DateTime exdate, [ExcelArgument(Description = "Risk free rate ")] double riskfreerate, [ExcelArgument(Description = "Black-Scholes Vol for leg 1 ")] double vol1, [ExcelArgument(Description = "Black-Scholes Vol for leg 2 ")] double vol2, [ExcelArgument(Description = "correlation between leg 1 and leg 2 ")] double corr, [ExcelArgument(Description = "DayCounter ")] string daycounter, [ExcelArgument(Description = "Calendar ")] string calendar, [ExcelArgument(Description = "trigger ")] object trigger) { if (ExcelUtil.CallFromWizard()) { return(""); } string callerAddress = ""; callerAddress = ExcelUtil.getActiveCellAddress(); try { if (exdate == DateTime.MinValue) { throw new Exception("Date must not be empty. "); } if (ExcelUtil.isNull(daycounter)) { daycounter = "ACTUAL365"; } if (ExcelUtil.isNull(calendar)) { calendar = "NYC"; } Option.Type optiontype; if (optype.ToUpper() == "CALL") { optiontype = Option.Type.Call; } else if (optype.ToUpper() == "PUT") { optiontype = Option.Type.Put; } else { throw new Exception("Unknow option type"); } EliteQuant.Calendar cal = EliteQuant.EQConverter.ConvertObject <EliteQuant.Calendar>(calendar); EliteQuant.DayCounter dc = EliteQuant.EQConverter.ConvertObject <EliteQuant.DayCounter>(daycounter); EliteQuant.Date maturitydate = EliteQuant.EQConverter.ConvertObject <EliteQuant.Date>(exdate); EliteQuant.Date today = EliteQuant.Settings.instance().getEvaluationDate(); EliteQuant.Date settlementdate = today; // T+2 if (maturitydate.serialNumber() <= today.serialNumber()) { throw new Exception("Option already expired."); } YieldTermStructureHandle rTSH = new YieldTermStructureHandle( new FlatForward(settlementdate, riskfreerate, dc)); BlackVolTermStructureHandle flatVolTSH1 = new BlackVolTermStructureHandle( new BlackConstantVol(settlementdate, cal, vol1, dc)); BlackVolTermStructureHandle flatVolTSH2 = new BlackVolTermStructureHandle( new BlackConstantVol(settlementdate, cal, vol2, dc)); Quote qh1 = new SimpleQuote(spot1); Quote qh2 = new SimpleQuote(spot2); QuoteHandle s1 = new QuoteHandle(qh1); QuoteHandle s2 = new QuoteHandle(qh2); BlackProcess p1 = new BlackProcess(s1, rTSH, flatVolTSH1); BlackProcess p2 = new BlackProcess(s2, rTSH, flatVolTSH2); Payoff payoff1 = new PlainVanillaPayoff(optiontype, stirkeprice); Payoff payoff2 = new SpreadBasketPayoff(payoff1); Exercise exercise = new EuropeanExercise(maturitydate); PricingEngine engine = new KirkEngine(p1, p2, corr); BasketOption bo = new BasketOption(payoff2, exercise); bo.setPricingEngine(engine); // Store the option and return its id string id = "OPTION@" + ObjectId; OHRepository.Instance.storeObject(id, bo, callerAddress); id += "#" + (String)DateTime.Now.ToString(@"HH:mm:ss"); return(id); } catch (Exception e) { ExcelUtil.logError(callerAddress, System.Reflection.MethodInfo.GetCurrentMethod().Name.ToString(), e.Message); return("#EQ_ERR!"); } }