public FdHestonVanillaEngine(HestonModel model, uint tGrid) : this(NQuantLibcPINVOKE.new_FdHestonVanillaEngine__SWIG_5(HestonModel.getCPtr(model), tGrid), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } }
public FdHestonVanillaEngine(HestonModel model, uint tGrid, uint xGrid, uint vGrid, uint dampingSteps, FdmSchemeDesc schemeDesc, LocalVolTermStructure leverageFct) : this(NQuantLibcPINVOKE.new_FdHestonVanillaEngine__SWIG_0(HestonModel.getCPtr(model), tGrid, xGrid, vGrid, dampingSteps, FdmSchemeDesc.getCPtr(schemeDesc), LocalVolTermStructure.getCPtr(leverageFct)), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } }
public AnalyticHestonEngine(HestonModel model, double relTolerance, uint maxEvaluations) : this(NQuantLibcPINVOKE.new_AnalyticHestonEngine__SWIG_2(HestonModel.getCPtr(model), relTolerance, maxEvaluations), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } }
public COSHestonEngine(HestonModel model, double L) : this(NQuantLibcPINVOKE.new_COSHestonEngine__SWIG_1(HestonModel.getCPtr(model), L), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } }
public FdHestonDoubleBarrierEngine(HestonModel model) : this(NQuantLibcPINVOKE.new_FdHestonDoubleBarrierEngine__SWIG_6(HestonModel.getCPtr(model)), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } }
public HestonModelHandle(HestonModel arg0) : this(NQuantLibcPINVOKE.new_HestonModelHandle__SWIG_0(HestonModel.getCPtr(arg0)), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } }
public FdHestonDoubleBarrierEngine(HestonModel model, uint tGrid, uint xGrid, uint vGrid, uint dampingSteps, FdmSchemeDesc schemeDesc) : this(NQuantLibcPINVOKE.new_FdHestonDoubleBarrierEngine__SWIG_1(HestonModel.getCPtr(model), tGrid, xGrid, vGrid, dampingSteps, FdmSchemeDesc.getCPtr(schemeDesc)), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } }
public FdHestonDoubleBarrierEngine(HestonModel model, uint tGrid, uint xGrid, uint vGrid) : this(NQuantLibcPINVOKE.new_FdHestonDoubleBarrierEngine__SWIG_3(HestonModel.getCPtr(model), tGrid, xGrid, vGrid), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } }
public AnalyticHestonEngine(HestonModel model) : this(NQuantLibcPINVOKE.new_AnalyticHestonEngine__SWIG_1(HestonModel.getCPtr(model)), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } }
public AnalyticHestonEngine(HestonModel model, AnalyticHestonEngine.ComplexLogFormula cpxLog, AnalyticHestonEngine.AnalyticHestonEngine_Integration itg) : this(NQuantLibcPINVOKE.new_AnalyticHestonEngine__SWIG_4(HestonModel.getCPtr(model), (int)cpxLog, AnalyticHestonEngine.AnalyticHestonEngine_Integration.getCPtr(itg)), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } }
public HestonSLVFDMModel(LocalVolTermStructure localVol, HestonModel model, Date endDate, HestonSLVFokkerPlanckFdmParams params_) : this(NQuantLibcPINVOKE.new_HestonSLVFDMModel__SWIG_2(LocalVolTermStructure.getCPtr(localVol), HestonModel.getCPtr(model), Date.getCPtr(endDate), HestonSLVFokkerPlanckFdmParams.getCPtr(params_)), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } }
public HestonSLVMCModel(LocalVolTermStructure localVol, HestonModel model, BrownianGeneratorFactory brownianGeneratorFactory, Date endDate) : this(NQuantLibcPINVOKE.new_HestonSLVMCModel__SWIG_4(LocalVolTermStructure.getCPtr(localVol), HestonModel.getCPtr(model), BrownianGeneratorFactory.getCPtr(brownianGeneratorFactory), Date.getCPtr(endDate)), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } }
public HestonSLVMCModel(LocalVolTermStructure localVol, HestonModel model, BrownianGeneratorFactory brownianGeneratorFactory, Date endDate, uint timeStepsPerYear, uint nBins, uint calibrationPaths) : this(NQuantLibcPINVOKE.new_HestonSLVMCModel__SWIG_1(LocalVolTermStructure.getCPtr(localVol), HestonModel.getCPtr(model), BrownianGeneratorFactory.getCPtr(brownianGeneratorFactory), Date.getCPtr(endDate), timeStepsPerYear, nBins, calibrationPaths), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } }
public HestonModel __deref__() { global::System.IntPtr cPtr = NQuantLibcPINVOKE.HestonModelHandle___deref__(swigCPtr); HestonModel ret = (cPtr == global::System.IntPtr.Zero) ? null : new HestonModel(cPtr, true); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(HestonModel obj) { return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr); }
public void testH1HWPricingEngine() { /* * Example taken from Lech Aleksander Grzelak, * Equity and Foreign Exchange Hybrid Models for Pricing Long-Maturity * Financial Derivatives, * http://repository.tudelft.nl/assets/uuid:a8e1a007-bd89-481a-aee3-0e22f15ade6b/PhDThesis_main.pdf */ Date today = new Date(15, Month.July, 2012); Settings.Instance.setEvaluationDate(today); Date exerciseDate = new Date(13, Month.July, 2022); DayCounter dc = new Actual365Fixed(); Exercise exercise = new EuropeanExercise(exerciseDate); Handle <Quote> s0 = new Handle <Quote>(new SimpleQuote(100.0)); double r = 0.02; double q = 0.00; double v0 = 0.05; double theta = 0.05; double kappa_v = 0.3; double[] sigma_v = { 0.3, 0.6 }; double rho_sv = -0.30; double rho_sr = 0.6; double kappa_r = 0.01; double sigma_r = 0.01; Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, r, dc)); Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, q, dc)); Handle <BlackVolTermStructure> flatVolTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(today, 0.20, dc)); GeneralizedBlackScholesProcess bsProcess = new GeneralizedBlackScholesProcess(s0, qTS, rTS, flatVolTS); HullWhiteProcess hwProcess = new HullWhiteProcess(rTS, kappa_r, sigma_r); HullWhite hullWhiteModel = new HullWhite(new Handle <YieldTermStructure>(rTS), kappa_r, sigma_r); double tol = 0.0001; double[] strikes = { 40, 80, 100, 120, 180 }; double[][] expected = { new double[] { 0.267503, 0.235742, 0.228223, 0.223461, 0.217855 }, new double[] { 0.263626, 0.211625, 0.199907, 0.193502, 0.190025 } }; for (int j = 0; j < sigma_v.Length; ++j) { HestonProcess hestonProcess = new HestonProcess(rTS, qTS, s0, v0, kappa_v, theta, sigma_v[j], rho_sv); HestonModel hestonModel = new HestonModel(hestonProcess); for (int i = 0; i < strikes.Length; ++i) { StrikedTypePayoff payoff = new PlainVanillaPayoff(Option.Type.Call, strikes[i]); VanillaOption option = new VanillaOption(payoff, exercise); IPricingEngine analyticH1HWEngine = new AnalyticH1HWEngine(hestonModel, hullWhiteModel, rho_sr, 144); option.setPricingEngine(analyticH1HWEngine); double impliedH1HW = option.impliedVolatility(option.NPV(), bsProcess); if (Math.Abs(expected[j][i] - impliedH1HW) > tol) { QAssert.Fail("Failed to reproduce H1HW implied volatility" + "\n expected : " + expected[j][i] + "\n calculated : " + impliedH1HW + "\n tol : " + tol + "\n strike : " + strikes[i] + "\n sigma : " + sigma_v[j]); } } } }
public void testAnalyticHestonHullWhitePricing() { // Testing analytic Heston Hull-White option pricing DayCounter dc = new Actual360(); Date today = Date.Today; Settings.Instance.setEvaluationDate(today); // construct a strange yield curve to check drifts and discounting // of the joint stochastic process List <Date> dates = new List <Date>(); List <double> times = new List <double>(); List <double> rates = new List <double>(), divRates = new List <double>(); for (int i = 0; i <= 40; ++i) { dates.Add(today + new Period(i, TimeUnit.Years)); // FLOATING_POINT_EXCEPTION rates.Add(0.03 + 0.0001 * Math.Exp(Math.Sin(i / 4.0))); divRates.Add(0.02 + 0.0002 * Math.Exp(Math.Sin(i / 3.0))); times.Add(dc.yearFraction(today, dates.Last())); } Date maturity = today + new Period(5, TimeUnit.Years); Handle <Quote> s0 = new Handle <Quote>(new SimpleQuote(100)); Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(new InterpolatedZeroCurve <Linear>(dates, rates, dc)); Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(new InterpolatedZeroCurve <Linear>(dates, divRates, dc)); HestonProcess hestonProcess = new HestonProcess(rTS, qTS, s0, 0.08, 1.5, 0.0625, 0.5, -0.8); HestonModel hestonModel = new HestonModel(hestonProcess); HullWhiteForwardProcess hwFwdProcess = new HullWhiteForwardProcess(rTS, 0.01, 0.01); hwFwdProcess.setForwardMeasureTime(dc.yearFraction(today, maturity)); HullWhite hullWhiteModel = new HullWhite(rTS, hwFwdProcess.a(), hwFwdProcess.sigma()); double tol = 0.002; double[] strike = { 80, 120 }; Option.Type[] types = { Option.Type.Put, Option.Type.Call }; for (int i = 0; i < types.Length; ++i) { for (int j = 0; j < strike.Length; ++j) { HybridHestonHullWhiteProcess jointProcess = new HybridHestonHullWhiteProcess(hestonProcess, hwFwdProcess, 0.0, HybridHestonHullWhiteProcess.Discretization.Euler); StrikedTypePayoff payoff = new PlainVanillaPayoff(types[i], strike[j]); Exercise exercise = new EuropeanExercise(maturity); VanillaOption optionHestonHW = new VanillaOption(payoff, exercise); optionHestonHW.setPricingEngine(new MakeMCHestonHullWhiteEngine <PseudoRandom, Statistics>(jointProcess) .withSteps(1) .withAntitheticVariate() .withControlVariate() .withAbsoluteTolerance(tol) .withSeed(42).getAsPricingEngine()); VanillaOption optionPureHeston = new VanillaOption(payoff, exercise); optionPureHeston.setPricingEngine(new AnalyticHestonHullWhiteEngine(hestonModel, hullWhiteModel, 128)); double calculated = optionHestonHW.NPV(); double error = optionHestonHW.errorEstimate(); double expected = optionPureHeston.NPV(); if (Math.Abs(calculated - expected) > 3 * error && Math.Abs(calculated - expected) > tol) { QAssert.Fail("Failed to reproduce hw heston vanilla prices" + "\n strike: " + strike[j] + "\n calculated: " + calculated + "\n error: " + error + "\n expected: " + expected); } } } }
public void testCompareBsmHWandHestonHW() { // Comparing European option pricing for a BSM process with one-factor Hull-White model DayCounter dc = new Actual365Fixed(); Date today = Date.Today; Settings.Instance.setEvaluationDate(today); Handle <Quote> spot = new Handle <Quote>(new SimpleQuote(100.0)); List <Date> dates = new List <Date>(); List <double> rates = new List <double>(), divRates = new List <double>(); for (int i = 0; i <= 40; ++i) { dates.Add(today + new Period(i, TimeUnit.Years)); // FLOATING_POINT_EXCEPTION rates.Add(0.01 + 0.0002 * Math.Exp(Math.Sin(i / 4.0))); divRates.Add(0.02 + 0.0001 * Math.Exp(Math.Sin(i / 5.0))); } Handle <Quote> s0 = new Handle <Quote>(new SimpleQuote(100)); Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>( new InterpolatedZeroCurve <Linear>(dates, rates, dc)); Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>( new InterpolatedZeroCurve <Linear>(dates, divRates, dc)); SimpleQuote vol = new SimpleQuote(0.25); Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(today, vol, dc)); BlackScholesMertonProcess bsmProcess = new BlackScholesMertonProcess(spot, qTS, rTS, volTS); HestonProcess hestonProcess = new HestonProcess(rTS, qTS, spot, vol.value() * vol.value(), 1.0, vol.value() * vol.value(), 1e-4, 0.0); HestonModel hestonModel = new HestonModel(hestonProcess); HullWhite hullWhiteModel = new HullWhite(new Handle <YieldTermStructure>(rTS), 0.01, 0.01); IPricingEngine bsmhwEngine = new AnalyticBSMHullWhiteEngine(0.0, bsmProcess, hullWhiteModel); IPricingEngine hestonHwEngine = new AnalyticHestonHullWhiteEngine(hestonModel, hullWhiteModel, 128); double tol = 1e-5; double[] strike = { 0.25, 0.5, 0.75, 0.8, 0.9, 1.0, 1.1, 1.2, 1.5, 2.0, 4.0 }; int[] maturity = { 1, 2, 3, 5, 10, 15, 20, 25, 30 }; Option.Type[] types = { Option.Type.Put, Option.Type.Call }; for (int i = 0; i < types.Length; ++i) { for (int j = 0; j < strike.Length; ++j) { for (int l = 0; l < maturity.Length; ++l) { Date maturityDate = today + new Period(maturity[l], TimeUnit.Years); Exercise exercise = new EuropeanExercise(maturityDate); double fwd = strike[j] * spot.link.value() * qTS.link.discount(maturityDate) / rTS.link.discount(maturityDate); StrikedTypePayoff payoff = new PlainVanillaPayoff(types[i], fwd); EuropeanOption option = new EuropeanOption(payoff, exercise); option.setPricingEngine(bsmhwEngine); double calculated = option.NPV(); option.setPricingEngine(hestonHwEngine); double expected = option.NPV(); if (Math.Abs(calculated - expected) > calculated * tol && Math.Abs(calculated - expected) > tol) { QAssert.Fail("Failed to reproduce npvs" + "\n calculated: " + calculated + "\n expected : " + expected + "\n strike : " + strike[j] + "\n maturity : " + maturity[l] + "\n type : " + ((types[i] == QLCore.Option.Type.Put) ? "Put" : "Call")); } } } } }
public void testSpuriousOscillations() { //Testing for spurious oscillations when solving the Heston PDEs... using (SavedSettings backup = new SavedSettings()) { DayCounter dc = new Actual365Fixed(); Date today = new Date(7, 6, 2018); Settings.Instance.setEvaluationDate(today); Handle <Quote> spot = new Handle <Quote>(new SimpleQuote(100.0)); Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.1, dc)); Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.0, dc)); double v0 = 0.005; double kappa = 1.0; double theta = 0.005; double sigma = 0.4; double rho = -0.75; Date maturity = today + new Period(1, TimeUnit.Years); HestonProcess process = new HestonProcess( rTS, qTS, spot, v0, kappa, theta, sigma, rho); HestonModel model = new HestonModel(process); FdHestonVanillaEngine hestonEngine = new FdHestonVanillaEngine( model, 6, 200, 13, 0, new FdmSchemeDesc().TrBDF2()); VanillaOption option = new VanillaOption(new PlainVanillaPayoff(Option.Type.Call, spot.currentLink().value()), new EuropeanExercise(maturity)); option.setupArguments(hestonEngine.getArguments()); List <Tuple <FdmSchemeDesc, string, bool> > descs = new List <Tuple <FdmSchemeDesc, string, bool> >(); descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().CraigSneyd(), "Craig-Sneyd", true)); descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().Hundsdorfer(), "Hundsdorfer", true)); descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().ModifiedHundsdorfer(), "Mod. Hundsdorfer", true)); descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().Douglas(), "Douglas", true)); descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().CrankNicolson(), "Crank-Nicolson", true)); descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().ImplicitEuler(), "Implicit", false)); descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().TrBDF2(), "TR-BDF2", false)); for (int j = 0; j < descs.Count; ++j) { FdmHestonSolver solver = new FdmHestonSolver(new Handle <HestonProcess>(process), hestonEngine.getSolverDesc(1.0), descs[j].Item1); List <double> gammas = new List <double>(); for (double x = 99; x < 101.001; x += 0.1) { gammas.Add(solver.gammaAt(x, v0)); } double maximum = Double.MinValue; for (int i = 1; i < gammas.Count; ++i) { double diff = Math.Abs(gammas[i] - gammas[i - 1]); if (diff > maximum) { maximum = diff; } } double tol = 0.01; bool hasSpuriousOscillations = maximum > tol; if (hasSpuriousOscillations != descs[j].Item3) { QAssert.Fail("unable to reproduce spurious oscillation behaviour " + "\n scheme name : " + descs[j].Item2 + "\n oscillations observed: " + hasSpuriousOscillations + "\n oscillations expected: " + descs[j].Item3 ); } } } }
public AnalyticHestonEngine(HestonModel model) : this(NQuantLibcPINVOKE.new_AnalyticHestonEngine__SWIG_1(HestonModel.getCPtr(model)), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); }
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(HestonModel obj) { return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; }
static void Main(string[] args) { DateTime timer = DateTime.Now; //////////////// DATES ////////////////////////////////////////////// Calendar calendar = new TARGET(); Date todaysDate = new Date(15, Month.January, 2017); Date settlementDate = new Date(todaysDate); Settings.setEvaluationDate(todaysDate); DayCounter dayCounter = new Actual365Fixed(); //////////////// MARKET ////////////////////////////////////////////// // Spot double underlying = 4468.17; Handle <Quote> underlyingH = new Handle <Quote>(new SimpleQuote(underlying)); // riskfree double riskFreeRate = 0.035; Handle <YieldTermStructure> flatTermStructure = new Handle <YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter)); // dividend double dividendYield = 0.0; double fixedDiv = 5.0; Handle <YieldTermStructure> flatDividendTS = new Handle <YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter)); Handle <YieldTermStructure> FixedDivTermStructure = new Handle <YieldTermStructure>(new FixedForward(settlementDate, fixedDiv, underlying, dayCounter)); // vol surface Date StartDateVol = settlementDate + new Period(1, TimeUnit.Months); List <int> maturityInDays = new InitializedList <int>() { 0, 13, 41, 90, 165, 256, 345, 524, 703 }; List <Date> datesVol = new InitializedList <Date>(); for (int d = 1; d < maturityInDays.Count; d++) { datesVol.Add(calendar.advance(settlementDate, new Period(maturityInDays[d], TimeUnit.Days))); } List <double> strikes = new InitializedList <double>() { 3400, 3600, 3800, 4000, 4200, 4400, 4500, 4600, 4800, 5000, 5200, 5400, 5600 }; Matrix blackVolMatrix = new Matrix(maturityInDays.Count - 1, strikes.Count, 0.2); var vols = new InitializedList <double>() { 0.6625, 0.4875, 0.4204, 0.3667, 0.3431, 0.3267, 0.3121, 0.3121, 0.6007, 0.4543, 0.3967, 0.3511, 0.3279, 0.3154, 0.2984, 0.2921, 0.5084, 0.4221, 0.3718, 0.3327, 0.3155, 0.3027, 0.2919, 0.2889, 0.4541, 0.3869, 0.3492, 0.3149, 0.2963, 0.2926, 0.2819, 0.2800, 0.4060, 0.3607, 0.3330, 0.2999, 0.2887, 0.2811, 0.2751, 0.2775, 0.3726, 0.3396, 0.3108, 0.2781, 0.2788, 0.2722, 0.2661, 0.2686, 0.3550, 0.3277, 0.3012, 0.2781, 0.2781, 0.2661, 0.2661, 0.2681, 0.3428, 0.3209, 0.2958, 0.2740, 0.2688, 0.2627, 0.2580, 0.2620, 0.3302, 0.3062, 0.2799, 0.2631, 0.2573, 0.2533, 0.2504, 0.2544, 0.3343, 0.2959, 0.2705, 0.2540, 0.2504, 0.2464, 0.2448, 0.2462, 0.3460, 0.2845, 0.2624, 0.2463, 0.2425, 0.2385, 0.2373, 0.2422, 0.3857, 0.2860, 0.2578, 0.2399, 0.2357, 0.2327, 0.2312, 0.2351, 0.3976, 0.2860, 0.2607, 0.2356, 0.2297, 0.2268, 0.2241, 0.2320 }; for (int i = 0; i < vols.Count; i++) { int testraw = (int)(i % (datesVol.Count)); int testcol = (int)(i / (datesVol.Count)); blackVolMatrix[testraw, testcol] = vols[i]; } BlackVarianceSurface mySurface = new BlackVarianceSurface(settlementDate, calendar, datesVol, strikes, Matrix.transpose(blackVolMatrix), dayCounter); Handle <BlackVolTermStructure> mySurfaceH = new Handle <BlackVolTermStructure>(mySurface); //////////////// CALIBRATION ////////////////////////////////////////////// Period helperPeriod = new Period(); //helpers List <CalibrationHelper> calibrationHelpers = new List <CalibrationHelper>(); for (int k = 0; k < strikes.Count; k++) { for (int d = 0; d < datesVol.Count; d++) { helperPeriod = new Period(datesVol[d] - settlementDate, TimeUnit.Days); calibrationHelpers.Add(new HestonModelHelper(helperPeriod, calendar, underlying, strikes[k], new Handle <Quote>(new SimpleQuote(blackVolMatrix[d, k])), flatTermStructure, flatDividendTS, CalibrationHelper.CalibrationErrorType.ImpliedVolError)); } } // starting data double v0 = 0.1; double kappa = 1.0; double theta = 0.1; double sigma = 0.5; double rho = -0.5; // model HestonProcess hestonProcess = new HestonProcess(flatTermStructure, flatDividendTS, underlyingH, v0, kappa, theta, sigma, rho); HestonModel hestonmodel = new HestonModel(hestonProcess); AnalyticHestonEngine analyticHestonEngine = new AnalyticHestonEngine(hestonmodel); foreach (HestonModelHelper hmh in calibrationHelpers) { hmh.setPricingEngine(analyticHestonEngine); } // optimization double tolerance = 1.0e-8; LevenbergMarquardt optimizationmethod = new LevenbergMarquardt(tolerance, tolerance, tolerance); hestonmodel.calibrate(calibrationHelpers, optimizationmethod, new EndCriteria(400, 40, tolerance, tolerance, tolerance)); double error = 0.0; List <double> errorList = new InitializedList <double>(); //////////////// CALIBRATION RESULTS ////////////////////////////////////////////// Console.WriteLine("Calbration :"); Console.WriteLine("-----------"); foreach (HestonModelHelper hmh in calibrationHelpers) { error += Math.Abs(hmh.calibrationError()); errorList.Add(Math.Abs(hmh.calibrationError())); } Vector hestonParameters = hestonmodel.parameters(); Console.WriteLine("v0 = {0:0.00%}", hestonParameters[4]); Console.WriteLine("kappa = {0:0.00%}", hestonParameters[1]); Console.WriteLine("theta = {0:0.00%}", hestonParameters[0]); Console.WriteLine("sigma = {0:0.00%}", hestonParameters[2]); Console.WriteLine("rho = {0:0.00%}", hestonParameters[3]); Console.WriteLine(); Console.WriteLine("Total error = {0:0.0000}", error); Console.WriteLine("Mean error = {0:0.0000%}", error / (errorList.Count - 1)); Console.WriteLine(); int StepsPerYear = 52; double absoluteTolerance = 80.0; ulong mcSeed = 42; // MC Heston process HestonProcess calibratedHestonProcess = new HestonProcess(flatTermStructure, flatDividendTS, underlyingH, hestonParameters[4], hestonParameters[1], hestonParameters[0], hestonParameters[2], hestonParameters[3]); // BS process GeneralizedBlackScholesProcessTolerance bsmProcess = new GeneralizedBlackScholesProcessTolerance(underlyingH, FixedDivTermStructure, flatTermStructure, mySurfaceH); //////////////// ENGINES ///////////////////////////////////////////////// IPricingEngine mcHestonEngine = new MakeMCEuropeanHestonEngine <PseudoRandom, Statistics>(calibratedHestonProcess) .withStepsPerYear(StepsPerYear) .withAbsoluteTolerance(absoluteTolerance) .withSeed(mcSeed) .getAsPricingEngine(); double absoluteTolerance2 = 1.0; IPricingEngine mcGenHestonEngineTestbs = new MakeMCGenericScriptInstrument <PseudoRandom>(bsmProcess) .withStepsPerYear(StepsPerYear) .withAbsoluteTolerance(absoluteTolerance2) .withSeed(mcSeed) .value(); IPricingEngine mcGenHestonEngineTestbs2 = new MakeMCGenericScriptInstrument <PseudoRandom>(calibratedHestonProcess) .withStepsPerYear(StepsPerYear) .withAbsoluteTolerance(absoluteTolerance2) .withSeed(mcSeed) .value(); //////////////// PRICING ////////////////////////////////////////////// Console.WriteLine("Pricing Vanilla:"); Console.WriteLine("---------------"); Date maturity = new Date(17, Month.May, 2019); Exercise europeanExercise = new EuropeanExercise(maturity); Option.Type type = Option.Type.Call; double strike = underlying; StrikedTypePayoff payoff = new PlainVanillaPayoff(type, strike); VanillaOption europeanOption = new VanillaOption(payoff, europeanExercise); // heston europeanOption.setPricingEngine(analyticHestonEngine); Console.Write("Heston pricing = {0:0.0000}", europeanOption.NPV()); Console.WriteLine(" -> {0:0.0000%}", europeanOption.NPV() / underlying); // Mc heston europeanOption.setPricingEngine(mcHestonEngine); Console.Write("HestMC pricing = {0:0.0000}", europeanOption.NPV()); Console.Write(" -> {0:0.0000%}", europeanOption.NPV() / underlying); Console.WriteLine(" tolerance {0:0.0} / {1:0.00%}", absoluteTolerance, absoluteTolerance / underlying); // analytic bs europeanOption.setPricingEngine(new AnalyticEuropeanEngine(bsmProcess)); Console.Write("BS pricing = {0:0.0000}", europeanOption.NPV()); Console.WriteLine(" -> {0:0.0000%}", europeanOption.NPV() / underlying); Console.WriteLine(); //////////////// AUTOCALL HESTON ////////////////////////////////////////////// List <Date> fixingdates = new InitializedList <Date>(); double coupon = 0.05; double barrierlvl = 0.6; for (int i = 1; i <= 4; i++) { fixingdates.Add(settlementDate + new Period(i, TimeUnit.Years)); } ScriptGenericAutocall myGenericAutocallHTTEst = new ScriptGenericAutocall(fixingdates, coupon, barrierlvl, underlying); myGenericAutocallHTTEst.setPricingEngine(mcGenHestonEngineTestbs); Console.WriteLine("Pricing Autocall BS :"); Console.WriteLine("---------------------"); Console.WriteLine("test = {0:0.0000}", myGenericAutocallHTTEst.NPV()); Console.WriteLine("Err = {0:0.0000%}", myGenericAutocallHTTEst.errorEstimate() / myGenericAutocallHTTEst.NPV()); Console.WriteLine("Samples = {0}", myGenericAutocallHTTEst.samples()); Console.Write("\n"); for (int i = 0; i < 4; i++) { Console.WriteLine("ProbaCall {1} = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaCall " + i), i + 1); } Console.WriteLine("ProbaMid = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaMid")); Console.WriteLine("probaDown = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown")); Console.WriteLine("test = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown")); Console.WriteLine("AvgDown/Proba = {0:0.0000%}", myGenericAutocallHTTEst.inspout("AvgDown") / myGenericAutocallHTTEst.inspout("ProbaDown")); Console.Write("\n"); myGenericAutocallHTTEst.setPricingEngine(mcGenHestonEngineTestbs2); Console.WriteLine("Pricing Autocall Heston:"); Console.WriteLine("------------------------"); Console.WriteLine("test = {0:0.0000}", myGenericAutocallHTTEst.NPV()); Console.WriteLine("Err = {0:0.0000%}", myGenericAutocallHTTEst.errorEstimate() / myGenericAutocallHTTEst.NPV()); Console.WriteLine("Samples = {0}", myGenericAutocallHTTEst.samples()); Console.Write("\n"); for (int i = 0; i < 4; i++) { Console.WriteLine("ProbaCall {1} = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaCall " + i), i + 1); } Console.WriteLine("ProbaMid = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaMid")); Console.WriteLine("probaDown = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown")); Console.WriteLine("test = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown")); Console.WriteLine("AvgDown/Proba = {0:0.0000%}", myGenericAutocallHTTEst.inspout("AvgDown") / myGenericAutocallHTTEst.inspout("ProbaDown")); Console.Write("\n"); //////////////// END TEST ////////////////////////////////////////////// Console.WriteLine(); Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer); Console.WriteLine(); Console.Write("Press any key to continue ..."); Console.ReadKey(); }
public AnalyticHestonEngine(HestonModel model, double relTolerance, uint maxEvaluations) : this(NQuantLibcPINVOKE.new_AnalyticHestonEngine__SWIG_2(HestonModel.getCPtr(model), relTolerance, maxEvaluations), true) { if (NQuantLibcPINVOKE.SWIGPendingException.Pending) throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); }
public void testMethodOfLinesAndCN() { //Testing method of lines to solve Heston PDEs... using (SavedSettings backup = new SavedSettings()) { DayCounter dc = new Actual365Fixed(); Date today = new Date(21, 2, 2018); Settings.Instance.setEvaluationDate(today); Handle <Quote> spot = new Handle <Quote>(new SimpleQuote(100.0)); Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.0, dc)); Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.0, dc)); double v0 = 0.09; double kappa = 1.0; double theta = v0; double sigma = 0.4; double rho = -0.75; Date maturity = today + new Period(3, TimeUnit.Months); HestonModel model = new HestonModel( new HestonProcess(rTS, qTS, spot, v0, kappa, theta, sigma, rho)); int xGrid = 21; int vGrid = 7; IPricingEngine fdmDefault = new FdHestonVanillaEngine(model, 10, xGrid, vGrid, 0); IPricingEngine fdmMol = new FdHestonVanillaEngine( model, 10, xGrid, vGrid, 0, new FdmSchemeDesc().MethodOfLines()); PlainVanillaPayoff payoff = new PlainVanillaPayoff(Option.Type.Put, spot.currentLink().value()); VanillaOption option = new VanillaOption(payoff, new AmericanExercise(maturity)); option.setPricingEngine(fdmMol); double calculatedMoL = option.NPV(); option.setPricingEngine(fdmDefault); double expected = option.NPV(); double tol = 0.005; double diffMoL = Math.Abs(expected - calculatedMoL); if (diffMoL > tol) { QAssert.Fail("Failed to reproduce european option values with MOL" + "\n calculated: " + calculatedMoL + "\n expected: " + expected + "\n difference: " + diffMoL + "\n tolerance: " + tol); } IPricingEngine fdmCN = new FdHestonVanillaEngine(model, 10, xGrid, vGrid, 0, new FdmSchemeDesc().CrankNicolson()); option.setPricingEngine(fdmCN); double calculatedCN = option.NPV(); double diffCN = Math.Abs(expected - calculatedCN); if (diffCN > tol) { QAssert.Fail("Failed to reproduce european option values with Crank-Nicolson" + "\n calculated: " + calculatedCN + "\n expected: " + expected + "\n difference: " + diffCN + "\n tolerance: " + tol); } BarrierOption barrierOption = new BarrierOption(Barrier.Type.DownOut, 85.0, 10.0, payoff, new EuropeanExercise(maturity)); barrierOption.setPricingEngine(new FdHestonBarrierEngine(model, 100, 31, 11)); double expectedBarrier = barrierOption.NPV(); barrierOption.setPricingEngine(new FdHestonBarrierEngine(model, 100, 31, 11, 0, new FdmSchemeDesc().MethodOfLines())); double calculatedBarrierMoL = barrierOption.NPV(); double barrierTol = 0.01; double barrierDiffMoL = Math.Abs(expectedBarrier - calculatedBarrierMoL); if (barrierDiffMoL > barrierTol) { QAssert.Fail("Failed to reproduce barrier option values with MOL" + "\n calculated: " + calculatedBarrierMoL + "\n expected: " + expectedBarrier + "\n difference: " + barrierDiffMoL + "\n tolerance: " + barrierTol); } barrierOption.setPricingEngine(new FdHestonBarrierEngine(model, 100, 31, 11, 0, new FdmSchemeDesc().CrankNicolson())); double calculatedBarrierCN = barrierOption.NPV(); double barrierDiffCN = Math.Abs(expectedBarrier - calculatedBarrierCN); if (barrierDiffCN > barrierTol) { QAssert.Fail("Failed to reproduce barrier option values with Crank-Nicolson" + "\n calculated: " + calculatedBarrierCN + "\n expected: " + expectedBarrier + "\n difference: " + barrierDiffCN + "\n tolerance: " + barrierTol); } } }