/// <summary> /// This method allows to fit the implied volatility using different models. /// </summary> /// <param name="Hdataset"></param> /// <returns></returns> IFunction FitImplVolModel(CallPriceMarketData Hdataset) { int model = 1; switch (model) { case 0: PFunction2D.PFunction2D pf = new PFunction2D.PFunction2D(Hdataset.Maturity, Hdataset.Strike, Hdataset.Volatility); pf.Interpolation = DVPLUtils.EInterpolationType.LEAST_SQUARES; pf.Extrapolation = DVPLUtils.ExtrapolationType.USEMODEL; pf.Parse(null); return(pf); case 1: //define a model for fitting the implied volatility Fairmat.Statistics.LinearModel impVol = new Fairmat.Statistics.LinearModel( new Fairmat.Statistics.Predictor[] { delegate(Vector xx) { return(1); }, delegate(Vector xx) { return(xx[0]); }, delegate(Vector xx) { return(xx[1]); }, delegate(Vector xx) { return(System.Math.Pow(xx[0], 2)); }, delegate(Vector xx) { return(System.Math.Pow(xx[1], 2)); }, delegate(Vector xx) { return(xx[0] * xx[1]); }, }); // Unroll matrix and coordinate vectors in order to make it suitable // for the Quadratic model implementation. int n = Hdataset.Volatility.R * Hdataset.Volatility.C; Matrix xy = new Matrix(n, 2); Vector z = new Vector(n); int count = 0; for (int x = 0; x < Hdataset.Volatility.R; x++) { for (int y = 0; y < Hdataset.Volatility.C; y++) { if (Hdataset.Volatility[x, y] > 0.01) { xy[count, Range.All] = (new Vector() { Hdataset.Maturity[x], Hdataset.Strike[y] }).T; z[count] = Hdataset.Volatility[x, y]; count++; } } } xy.Resize(count, xy.C); z.Resize(count); impVol.Estimate(xy, z); return(impVol); } return(null); }
/// <summary> /// Initializes a new instance of the HestonCallOptimizationProblem class using the /// EquityCalibrationData data structure. /// </summary> /// <param name="equityCalData"> /// An EquityCalibrationData object containing market data for calibration. /// </param> /// <param name="matBound"> /// A vector containing the minimum and maximum values /// for maturities to be used in calibration. /// </param> /// <param name="strikeBound"> /// A vector containing the minimum and maximum values /// for strikes to be used in calibration. /// </param> public HestonCallOptimizationProblem(EquityCalibrationData equityCalData, Vector matBound, Vector strikeBound) { this.cpmd = equityCalData.Hdata; this.matBound = matBound; this.strikeBound = strikeBound; SetVariables(equityCalData.Hdata.CallPrice, equityCalData.Hdata.Maturity, equityCalData.Hdata.Strike, equityCalData.CallMatrixRiskFreeRate, equityCalData.CallMatrixDividendYield, equityCalData.Hdata.S0); displayObjInfo = false; }
private EstimationResult FairmatEstimate(CurveMarketData discountingCurve, CallPriceMarketData Hdataset) { EquityCalibrationData HCalData = new EquityCalibrationData(Hdataset, discountingCurve); //HCalData.Setup(Hdataset, discountingCurve); bool hasArbitrage = HCalData.HasArbitrageOpportunity(10e-2); if (hasArbitrage) { Console.WriteLine("Market data contains arbitrage opportunity"); } this.r = new DVPLDOM.PFunction(discountingCurve.Durations, discountingCurve.Values); this.q = HCalData.dyFunc as PFunction; //this.q.Expr = (double[,])ArrayHelper.Concat(HCalData.MaturityDY.ToArray(), HCalData.DividendYield.ToArray()); this.r.Parse(null); this.q.Parse(null); Vector locVolMat, locVolStr; //IFunction fittedSurface = FitImplVolModel(Hdataset); //Matrix locVolMatrix = LocVolMatrixFromImpliedVol(Hdataset, fittedSurface, out locVolMat, out locVolStr); CallPriceSurface fittedSurface = CallPriceSurface.NoArbitrageSurface(HCalData); Matrix locVolMatrix = LocVolMatrixFromCallPrices(Hdataset, fittedSurface, out locVolMat, out locVolStr); Console.WriteLine(locVolMatrix); // Create dupire outputs. PFunction2D.PFunction2D localVol = new PFunction2D.PFunction2D(locVolMat, locVolStr, locVolMatrix); localVol.Parse(null); string[] names = new string[] { "S0" }; Vector param = new Vector(1); param[0] = Hdataset.S0; EstimationResult result = new EstimationResult(names, param); //result.Objects = new object[3]; result.Objects = new object[4]; result.Objects[0] = this.r; result.Objects[1] = this.q; result.Objects[2] = localVol; result.Objects[3] = fittedSurface; //Console.WriteLine("r = " + HCalData.Rate.ToString()); //Console.WriteLine("q = " + HCalData.DividendYield.ToString()); return(result); }
private Matrix LocVolMatrixFromImpliedVol(CallPriceMarketData Hdataset, IFunction impVol, out Vector locVolMat, out Vector locVolStr) { int nmat = calibrationSettings.LocalVolatilityMaturities; int nstrike = calibrationSettings.LocalVolatilityStrikes; double lastMat = Hdataset.Maturity[Range.End]; double lastStr = Hdataset.Strike[Range.End]; locVolMat = Vector.Linspace(Hdataset.Maturity[0], lastMat, nmat); locVolStr = Vector.Linspace(Hdataset.Strike[0], lastStr, nstrike); Matrix locVolMatrix = new Matrix(nmat, nstrike); Integrate integrate = new Integrate(this); double sigma, dSigmadk, num, y, den, avgGrowthRate; Vector x = new Vector(2); for (int i = 0; i < nmat; i++) { avgGrowthRate = integrate.AdaptLobatto(0.0, locVolMat[i]); int j = 0; x[0] = locVolMat[i]; x[1] = locVolStr[j]; sigma = impVol.Evaluate(x); dSigmadk = impVol.Partial(x, 1); num = Math.Pow(sigma, 2) + 2.0 * sigma * x[0] * impVol.Partial(x, 0); den = 1.0; locVolMatrix[i, j] = Math.Sqrt(num / den); // The rest of the cycle. for (j = 1; j < nstrike; j++) { x[1] = locVolStr[j]; sigma = impVol.Evaluate(x); dSigmadk = impVol.Partial(x, 1); num = Math.Pow(sigma, 2) + 2.0 * sigma * x[0] * (impVol.Partial(x, 0) + avgGrowthRate * x[1] * dSigmadk); y = Math.Log(locVolStr[j] / Hdataset.S0) + avgGrowthRate; den = System.Math.Pow(1.0 - x[1] * y * dSigmadk / sigma, 2) + x[1] * sigma * x[0] * (dSigmadk - 0.25 * x[1] * sigma * x[0] * dSigmadk * dSigmadk + x[1] * impVol.Partial2(x, 1)); locVolMatrix[i, j] = Math.Sqrt(num / den); } } return(locVolMatrix); }
/// <summary> /// Attempts to solve the Variance Gamma Optimization problem using /// <see cref="Heston.VarianceGammaOptimizationProblem"/>. /// </summary> /// <param name="data"> /// The data to be used in order to perform the optimization. /// </param> /// <param name="settings">The parameter is not used.</param> /// <returns>The results of the optimization.</returns> public EstimationResult Estimate(List <object> data, IEstimationSettings settings = null, IController controller = null, Dictionary <string, object> properties = null) { EquitySpotMarketData espmd = data[0] as EquitySpotMarketData; CallPriceMarketData cpmd = data[1] as CallPriceMarketData; DiscountingCurveMarketData dcmd = data[2] as DiscountingCurveMarketData; EquityCalibrationData ecd = new EquityCalibrationData(cpmd, dcmd); this.s0 = espmd.Price; this.r = espmd.RiskFreeRate; this.q = espmd.DividendYield; this.k = ecd.Hdata.Strike; this.m = ecd.Hdata.Maturity; this.cp = ecd.Hdata.CallPrice; Vector x0 = (Vector) new double[] { -0.1, 0.2, 0.1 }; IOptimizationAlgorithm algorithm = new QADE(); OptimizationSettings optimizationSettings = new DESettings(); // Maximum number of iteration allowed. // Positive integer values print debug info. optimizationSettings.Verbosity = 1; // Tolerance. optimizationSettings.epsilon = 10e-5; var solution = algorithm.Minimize(new VarianceGammaOptimizationProblem(this.q, this.s0, this.k, this.r, this.cp, this.m), optimizationSettings, x0); if (solution.errors) { return(new EstimationResult(solution.message)); } var er = new EstimationResult(); er.Names = new string[] { "S0", "theta", "sigma", "nu", "rate", "dividend" }; er.Values = new double[] { this.s0, solution.x[0], solution.x[1], solution.x[2], this.r, this.q }; return(er); }
public EstimationResult Estimate(System.Collections.Generic.List <object> marketData, IEstimationSettings settings = null, IController controller = null, System.Collections.Generic.Dictionary <string, object> properties = null) { CurveMarketData discountingCurve = (CurveMarketData)marketData[0]; CallPriceMarketData Hdataset = (CallPriceMarketData)marketData[1]; //gets the settings calibrationSettings = settings as DupireCalibrationSettings; //return this.FairmatEstimate(discountingCurve, Hdataset); // Removed quantlib estimate, it does not work correctly switch (calibrationSettings.LocalVolatilityCalculation) { case LocalVolatilityCalculation.Method1: return(this.FairmatEstimate(discountingCurve, Hdataset)); case LocalVolatilityCalculation.QuantLib: return(QuantLibEstimate(discountingCurve, Hdataset)); default: throw new NotImplementedException("Method not implemented"); } }
private EstimationResult FairmatEstimate(CurveMarketData discountingCurve, CallPriceMarketData Hdataset) { EquityCalibrationData HCalData = new EquityCalibrationData(Hdataset, discountingCurve); //HCalData.Setup(Hdataset, discountingCurve); bool hasArbitrage = HCalData.HasArbitrageOpportunity(10e-2); if (hasArbitrage) Console.WriteLine("Market data contains arbitrage opportunity"); this.r = new DVPLDOM.PFunction(discountingCurve.Durations,discountingCurve.Values); this.q = HCalData.dyFunc as PFunction; //this.q.Expr = (double[,])ArrayHelper.Concat(HCalData.MaturityDY.ToArray(), HCalData.DividendYield.ToArray()); this.r.Parse(null); this.q.Parse(null); Vector locVolMat, locVolStr; //IFunction fittedSurface = FitImplVolModel(Hdataset); //Matrix locVolMatrix = LocVolMatrixFromImpliedVol(Hdataset, fittedSurface, out locVolMat, out locVolStr); CallPriceSurface fittedSurface = CallPriceSurface.NoArbitrageSurface(HCalData); Matrix locVolMatrix = LocVolMatrixFromCallPrices(Hdataset, fittedSurface, out locVolMat, out locVolStr); Console.WriteLine(locVolMatrix); // Create dupire outputs. PFunction2D.PFunction2D localVol = new PFunction2D.PFunction2D(locVolMat, locVolStr, locVolMatrix); localVol.Parse(null); string[] names = new string[] { "S0" }; Vector param = new Vector(1); param[0] = Hdataset.S0; EstimationResult result = new EstimationResult(names, param); //result.Objects = new object[3]; result.Objects = new object[4]; result.Objects[0] = this.r; result.Objects[1] = this.q; result.Objects[2] = localVol; result.Objects[3] = fittedSurface; //Console.WriteLine("r = " + HCalData.Rate.ToString()); //Console.WriteLine("q = " + HCalData.DividendYield.ToString()); return result; }
public static void Main(string[] args) { int Caso = 1; if (Caso == 0) { InterestRateMarketData MData = InterestRateMarketData.FromFile("../../../TestData/InterestRatesModels/05052009-EU.xml"); CallPriceMarketData test = CallPriceMarketData.FromFile("../../../TestData/Heston/05052009-SX5E-HestonData.xml"); EquityCalibrationData CalData = new EquityCalibrationData(test, MData); Matrix CallMarketPrice = (Matrix)test.CallPrice; Vector Maturity = (Vector)test.Maturity; Vector Strike = (Vector)test.Strike; Vector DividendYield = (Vector)test.DividendYield; Vector Drift = CalData.Rate - CalData.DividendYield; Vector Rate = CalData.Rate; double u, kappa, theta, sigma, rho, v0, s0, r, q, T, K, val; u = 1.0; kappa = 19.4; theta = 0.235; sigma = 0.00500999; rho = -0.96; v0 = 0.664; s0 = 3872.15; r = -0.0867303549580581; q = 0; T = 0.50; K = 6000; Vector MatBound = new Vector(2); Vector StrikeBound = new Vector(2); MatBound[0] = 0.0; MatBound[1] = 2.0; StrikeBound[0] = 0.7; StrikeBound[1] = 1.3; Matrix Volatility = new Matrix(test.CallPrice.R, test.CallPrice.C); HestonCallOptimizationProblem HP = new HestonCallOptimizationProblem(CallMarketPrice, Maturity, Strike, Rate, DividendYield, test.S0, MatBound, StrikeBound, Volatility); Complex Cval, Cu; Cu = u - Complex.I; HestonCall hc = new HestonCall(HP); Cval = hc.phi(u, kappa, theta, sigma, rho, s0, v0, r, T); Console.WriteLine("phi1 = {0}", Cval); Cval = hc.phi(Cu, kappa, theta, sigma, rho, s0, v0, r, T); Console.WriteLine("phi2 = {0}", Cval); val = hc.IntegrandFunc(u, kappa, theta, sigma, rho, s0, v0, r, q, T, K); Console.WriteLine("IntFunc = {0}", val); Vector x = new Vector(5); x[0] = kappa; x[1] = theta; x[2] = sigma; x[3] = rho; x[4] = v0; DateTime T1, T2; TimeSpan ElapsedTime; double Time, Time2, Time3; T1 = DateTime.Now; val = hc.HestonCallPrice(x, s0, T, K, r, q); T2 = DateTime.Now; ElapsedTime = T2 - T1; Time = (double)ElapsedTime.Milliseconds; Time2 = (double)ElapsedTime.Seconds; Console.WriteLine("Price = {0}", val); Console.WriteLine("Elapsed Time = {0}", Time2 + Time / 1000); int NProve = 10; int NPassi = 1000; double val2; Random CasNum = new Random(); for (int i = 0; i < NProve; i++) { for (int j = 0; j < 5; j++) { val2 = ((double)CasNum.Next(0, NPassi)) / ((double)NPassi); x[j] = HP.Bounds.Lb[j] + (HP.Bounds.Ub[j] - HP.Bounds.Lb[j]) * val2; } Console.Write("Trial {0} x = " + x.ToString(), i + 1); T1 = DateTime.Now; val = HP.Obj(x); T2 = DateTime.Now; ElapsedTime = T2 - T1; Time = (double)ElapsedTime.Milliseconds; Time2 = (double)ElapsedTime.Seconds; Time3 = (double)ElapsedTime.Minutes; Console.WriteLine(" Time = {0}' {1}'' Val = {2}", Time3, Time2 + Time / 1000, val); } } if (Caso == 1) { TestHestonCallEstimation NewTest = new TestHestonCallEstimation(); bool Result = NewTest.Run(); } }
protected virtual EstimationResult BuildEstimate(Scalar spotPrice, CurveMarketData interestDataSet, CallPriceMarketData callDataSet, EquityCalibrationData equityCalData, SolutionInfo solution) { string[] names = new string[] { "S0", "kappa", "theta", "sigma", "rho", "V0" }; Vector param = new Vector(6); param[0] = spotPrice.Value; param[Range.New(1, 5)] = solution.x; var result = new EstimationResult(names, param); // In the following the two function describing the ZR and dividend yields are created //Matrix zerorate = new Matrix(interestDataSet.Durations.Length, 2); //zerorate[Range.All, 0] = interestDataSet.Durations; //zerorate[Range.All, 1] = interestDataSet.Values; //Matrix dividendYield = new Matrix(equityCalData.MaturityDY.Length, 2); //dividendYield[Range.All, 0] = equityCalData.MaturityDY; //dividendYield[Range.All, 1] = equityCalData.DividendYield; Matrix zerorate = new Matrix((equityCalData.zrFunc as PFunction).Expr); //Matrix dividendYield = new Matrix((equityCalData.dyFunc as PFunction).Expr); Matrix dividendYield = ToMatrix(IstantaneousDividendYield(equityCalData)); result.Objects = new object[2]; result.Objects[0] = zerorate; result.Objects[1] = dividendYield; result.Fit = solution.obj; Console.WriteLine(result); return result; }
private EstimationResult QuantLibEstimate(CurveMarketData discoutingCurve, CallPriceMarketData Hdataset) { EquityCalibrationData HCalData = new EquityCalibrationData(Hdataset, discoutingCurve); bool hasArbitrage = HCalData.HasArbitrageOpportunity(10e-2); if (hasArbitrage) Console.WriteLine("Market data contains arbitrage opportunity"); this.r = new DVPLDOM.PFunction(discoutingCurve.Durations,discoutingCurve.Values); this.q = HCalData.dyFunc as PFunction; //this.r.Parse(null); //this.q.Parse(null); Hdataset.Volatility = new Matrix(Hdataset.CallPrice.R, Hdataset.CallPrice.C); for (int i = 0; i < Hdataset.Volatility.R; i++) { double m=Hdataset.Maturity[i]; for (int j = 0; j < Hdataset.Volatility.C; j++) { if (Hdataset.CallPrice[i, j] > 0) { var bs = new Fairmat.Finance.BlackScholes(r.Evaluate(m), Hdataset.S0, Hdataset.Strike[j], 0, m, q.Evaluate(m)); //Hdataset.Volatility[i, j] = Hdataset.Volatility[i, j] * Hdataset.Volatility[i, j] * Hdataset.Maturity[i]; //Hdataset.Volatility[i, j] = bs.ImpliedCallVolatility(Hdataset.CallPrice[i, j]); } } } Console.WriteLine(Hdataset.Volatility); IFunction impVol = FitImplVolModel(Hdataset); Document doc = new Document(); ProjectROV prj = new ProjectROV(doc); doc.Part.Add(prj); prj.Symbols.Add(impVol); // doc.WriteToXMLFile("impVol.fair"); int nmat = calibrationSettings.LocalVolatilityMaturities; int nstrike = calibrationSettings.LocalVolatilityStrikes; double lastMat = Hdataset.Maturity[SymbolicIntervalExtremes.End]; double lastStr = Hdataset.Strike[SymbolicIntervalExtremes.End]; Vector locVolMat = Vector.Linspace(Hdataset.Maturity[0], lastMat, nmat); Vector locVolStr = Vector.Linspace(Hdataset.Strike[0], lastStr, nstrike); Matrix locVolMatrix = new Matrix(nmat, nstrike); double t, dt, forwardValue, y, dy, strike, strikep, strikem, w, wp, wm, dwdy; double d2wdy2, den1, den2, den3, strikept, strikemt, wpt, wmt, dwdt; Integrate integrate = new Integrate(this); for (int i = 0; i < nmat; i++) { t = locVolMat[i]; forwardValue = Hdataset.S0 * Math.Exp(integrate.AdaptLobatto(0.0, t)); for (int j = 0; j < nstrike; j++) { strike = locVolStr[j]; y = Math.Log(strike / forwardValue); dy = ((Math.Abs(y) > 0.001) ? y * 0.0001 : 0.000001); // strike derivative strikep = strike * Math.Exp(dy); strikem = strike / Math.Exp(dy); w = impVol.Evaluate(t, strike); wp = impVol.Evaluate(t, strikep); wm = impVol.Evaluate(t, strikem); dwdy = (wp - wm) / (2.0 * dy); d2wdy2 = (wp - 2.0 * w + wm) / (dy * dy); // time derivative if (t == 0.0) { dt = 0.0001; strikept = strike * Math.Exp(integrate.AdaptLobatto(0.0, t + dt)); wpt = impVol.Evaluate(t + dt, strikept); // if (wpt < w) // Console.WriteLine("Decreasing variance at strike {0} between time {1} and time {2}", strike, t, t + dt); dwdt = (wpt - w) / dt; } else { dt = Math.Min(0.0001, t / 2.0); strikept = strike * Math.Exp(integrate.AdaptLobatto(t, t + dt)); strikemt = strike * Math.Exp(-integrate.AdaptLobatto(t - dt, t)); wpt = impVol.Evaluate(t + dt, strikept); wmt = impVol.Evaluate(t + dt, strikemt); //if (wpt < w) // Console.WriteLine("Decreasing variance at strike {0} between time {1} and time {2}", strike, t, t + dt); //if (w < wmt) // Console.WriteLine("Decreasing variance at strike {0} between time {1} and time {2}", strike, t-dt, t); dwdt = (wpt - wmt) / (2.0 * dt); } if (dwdy == 0.0 && d2wdy2 == 0.0) locVolMatrix[i, j] = Math.Sqrt(dwdt); else { den1 = 1.0 - y / w * dwdy; den2 = 0.25 * (-0.25 - 1.0 / w + y * y / w / w) * dwdy * dwdy; den3 = 0.5 * d2wdy2; locVolMatrix[i, j] = dwdt / (den1 + den2 + den3); //if (locVolMatrix[i,j] < 0.0) // Console.WriteLine("Negative local vol^2 at strike {0} and time {1}; " + // "Black vol surface is not smooth enought.", strike, t); } } } // Create dupire outputs. Console.WriteLine(locVolMat); PFunction2D.PFunction2D localVol = new PFunction2D.PFunction2D(locVolMat, locVolStr, locVolMatrix); localVol.Parse(null); string[] names = new string[] { "S0" }; Vector param = new Vector(1); param[0] = Hdataset.S0; EstimationResult result = new EstimationResult(names, param); //result.Objects = new object[3]; result.Objects = new object[4]; result.Objects[0] = this.r; result.Objects[1] = this.q; result.Objects[2] = localVol; result.Objects[3] = impVol; //Console.WriteLine("r = " + HCalData.Rate.ToString()); //Console.WriteLine("q = " + HCalData.DividendYield.ToString()); return result; }
private Matrix LocVolMatrixFromImpliedVol(CallPriceMarketData Hdataset, IFunction impVol, out Vector locVolMat, out Vector locVolStr) { int nmat = calibrationSettings.LocalVolatilityMaturities; int nstrike = calibrationSettings.LocalVolatilityStrikes; double lastMat = Hdataset.Maturity[Range.End]; double lastStr = Hdataset.Strike[Range.End]; locVolMat = Vector.Linspace(Hdataset.Maturity[0], lastMat, nmat); locVolStr = Vector.Linspace(Hdataset.Strike[0], lastStr, nstrike); Matrix locVolMatrix = new Matrix(nmat, nstrike); Integrate integrate = new Integrate(this); double sigma, dSigmadk, num, y, den, avgGrowthRate; Vector x = new Vector(2); for (int i = 0; i < nmat; i++) { avgGrowthRate = integrate.AdaptLobatto(0.0, locVolMat[i]); int j = 0; x[0] = locVolMat[i]; x[1] = locVolStr[j]; sigma = impVol.Evaluate(x); dSigmadk = impVol.Partial(x, 1); num = Math.Pow(sigma, 2) + 2.0 * sigma * x[0] * impVol.Partial(x, 0); den = 1.0; locVolMatrix[i, j] = Math.Sqrt(num / den); // The rest of the cycle. for (j = 1; j < nstrike; j++) { x[1] = locVolStr[j]; sigma = impVol.Evaluate(x); dSigmadk = impVol.Partial(x, 1); num = Math.Pow(sigma, 2) + 2.0 * sigma * x[0] * (impVol.Partial(x, 0) + avgGrowthRate * x[1] * dSigmadk); y = Math.Log(locVolStr[j] / Hdataset.S0) + avgGrowthRate; den = System.Math.Pow(1.0 - x[1] * y * dSigmadk / sigma, 2) + x[1] * sigma * x[0] * (dSigmadk - 0.25 * x[1] * sigma * x[0] * dSigmadk * dSigmadk + x[1] * impVol.Partial2(x, 1)); locVolMatrix[i, j] = Math.Sqrt(num / den); } } return locVolMatrix; }
private static Vector Test(int nm, int nk, double q, double s0, double r, double t, double theta, double sigma, double nu) { // Simulate synthetic data. Vector m = new Vector(nm); Vector k = new Vector(nk); Matrix cp = new Matrix(nm, nk); Random rand = new Random(); for (int i = 0; i < nm; i++) { m[i] = 0.01 + rand.NextDouble() * 0.99; } for (int i = 0; i < nk; i++) { k[i] = 60 + rand.NextDouble() * 90; } for (int i = 0; i < nm; i++) { for (int j = 0; j < nk; j++) { cp[i, j] = VarianceGammaOptionsCalibration.VGCall(theta, sigma, nu, m[i], k[j], q, s0, r); } } Console.WriteLine("Benchmark value"); Console.WriteLine(new Vector() { theta, sigma, nu }); Console.WriteLine("Call prices"); Console.WriteLine(cp); // VGDiff at optimum. double fopt = VarianceGammaOptimizationProblem.VGDiff(new Vector() { theta, sigma, nu }, q, s0, k, r, cp, m); Console.WriteLine("fopt"); Console.WriteLine(fopt); VarianceGammaOptionsCalibration c = new VarianceGammaOptionsCalibration(); List<object> marketData = new List<object>(); EquitySpotMarketData espmd = new EquitySpotMarketData(); CallPriceMarketData cpmd = new CallPriceMarketData(); espmd.Price = s0; espmd.RiskFreeRate = r; espmd.DividendYield = q; cpmd.Strike = k; cpmd.Maturity = m; cpmd.CallPrice = cp; marketData.Add(espmd); marketData.Add(cpmd); EstimationResult res = c.Estimate(marketData, null); return (Vector)res.Values; }
protected override EstimationResult BuildEstimate(Scalar spotPrice, CurveMarketData interestDataSet, CallPriceMarketData callDataSet, EquityCalibrationData equityCalData, SolutionInfo solution) { string[] names = new string[] { "S0", "kappa", "theta", "sigma", "rho", "V0", "r", "q" }; Vector param = new Vector(8); param[0] = spotPrice.Value; param[Range.New(1, 5)] = solution.x[Range.New(0, 4)]; param[6] = equityCalData.zrFunc.Evaluate(TheoreticalModelsSettings.ConstantDYRFMaturity); if (impliedDividends) param[7] = solution.x[Range.End];// equityCalData.dyFunc.Evaluate(TheoreticalModelsSettings.ConstantDYRFMaturity); else param[7] = DY(equityCalData); var result = new EstimationResult(names, param); result.Fit = HestonCallOptimizationProblem.avgPricingError; Console.WriteLine(result); return result; }
protected virtual EstimationResult BuildEstimate(Scalar spotPrice, CurveMarketData interestDataSet, CallPriceMarketData callDataSet, EquityCalibrationData equityCalData, SolutionInfo solution) { string[] names = new string[] { "S0", "kappa", "theta", "sigma", "rho", "V0" }; Vector param = new Vector(6); param[0] = spotPrice.Value; param[Range.New(1, 5)] = solution.x; var result = new EstimationResult(names, param); // In the following the two function describing the ZR and dividend yields are created //Matrix zerorate = new Matrix(interestDataSet.Durations.Length, 2); //zerorate[Range.All, 0] = interestDataSet.Durations; //zerorate[Range.All, 1] = interestDataSet.Values; //Matrix dividendYield = new Matrix(equityCalData.MaturityDY.Length, 2); //dividendYield[Range.All, 0] = equityCalData.MaturityDY; //dividendYield[Range.All, 1] = equityCalData.DividendYield; Matrix zerorate = new Matrix((equityCalData.zrFunc as PFunction).Expr); //Matrix dividendYield = new Matrix((equityCalData.dyFunc as PFunction).Expr); Matrix dividendYield = ToMatrix(IstantaneousDividendYield(equityCalData)); result.Objects = new object[2]; result.Objects[0] = zerorate; result.Objects[1] = dividendYield; result.Fit = solution.obj; Console.WriteLine(result); return(result); }
private EstimationResult QuantLibEstimate(CurveMarketData discoutingCurve, CallPriceMarketData Hdataset) { EquityCalibrationData HCalData = new EquityCalibrationData(Hdataset, discoutingCurve); bool hasArbitrage = HCalData.HasArbitrageOpportunity(10e-2); if (hasArbitrage) { Console.WriteLine("Market data contains arbitrage opportunity"); } this.r = new DVPLDOM.PFunction(discoutingCurve.Durations, discoutingCurve.Values); this.q = HCalData.dyFunc as PFunction; //this.r.Parse(null); //this.q.Parse(null); Hdataset.Volatility = new Matrix(Hdataset.CallPrice.R, Hdataset.CallPrice.C); for (int i = 0; i < Hdataset.Volatility.R; i++) { double m = Hdataset.Maturity[i]; for (int j = 0; j < Hdataset.Volatility.C; j++) { if (Hdataset.CallPrice[i, j] > 0) { var bs = new Fairmat.Finance.BlackScholes(r.Evaluate(m), Hdataset.S0, Hdataset.Strike[j], 0, m, q.Evaluate(m)); //Hdataset.Volatility[i, j] = Hdataset.Volatility[i, j] * Hdataset.Volatility[i, j] * Hdataset.Maturity[i]; //Hdataset.Volatility[i, j] = bs.ImpliedCallVolatility(Hdataset.CallPrice[i, j]); } } } Console.WriteLine(Hdataset.Volatility); IFunction impVol = FitImplVolModel(Hdataset); Document doc = new Document(); ProjectROV prj = new ProjectROV(doc); doc.Part.Add(prj); prj.Symbols.Add(impVol); // doc.WriteToXMLFile("impVol.fair"); int nmat = calibrationSettings.LocalVolatilityMaturities; int nstrike = calibrationSettings.LocalVolatilityStrikes; double lastMat = Hdataset.Maturity[SymbolicIntervalExtremes.End]; double lastStr = Hdataset.Strike[SymbolicIntervalExtremes.End]; Vector locVolMat = Vector.Linspace(Hdataset.Maturity[0], lastMat, nmat); Vector locVolStr = Vector.Linspace(Hdataset.Strike[0], lastStr, nstrike); Matrix locVolMatrix = new Matrix(nmat, nstrike); double t, dt, forwardValue, y, dy, strike, strikep, strikem, w, wp, wm, dwdy; double d2wdy2, den1, den2, den3, strikept, strikemt, wpt, wmt, dwdt; Integrate integrate = new Integrate(this); for (int i = 0; i < nmat; i++) { t = locVolMat[i]; forwardValue = Hdataset.S0 * Math.Exp(integrate.AdaptLobatto(0.0, t)); for (int j = 0; j < nstrike; j++) { strike = locVolStr[j]; y = Math.Log(strike / forwardValue); dy = ((Math.Abs(y) > 0.001) ? y * 0.0001 : 0.000001); // strike derivative strikep = strike * Math.Exp(dy); strikem = strike / Math.Exp(dy); w = impVol.Evaluate(t, strike); wp = impVol.Evaluate(t, strikep); wm = impVol.Evaluate(t, strikem); dwdy = (wp - wm) / (2.0 * dy); d2wdy2 = (wp - 2.0 * w + wm) / (dy * dy); // time derivative if (t == 0.0) { dt = 0.0001; strikept = strike * Math.Exp(integrate.AdaptLobatto(0.0, t + dt)); wpt = impVol.Evaluate(t + dt, strikept); // if (wpt < w) // Console.WriteLine("Decreasing variance at strike {0} between time {1} and time {2}", strike, t, t + dt); dwdt = (wpt - w) / dt; } else { dt = Math.Min(0.0001, t / 2.0); strikept = strike * Math.Exp(integrate.AdaptLobatto(t, t + dt)); strikemt = strike * Math.Exp(-integrate.AdaptLobatto(t - dt, t)); wpt = impVol.Evaluate(t + dt, strikept); wmt = impVol.Evaluate(t + dt, strikemt); //if (wpt < w) // Console.WriteLine("Decreasing variance at strike {0} between time {1} and time {2}", strike, t, t + dt); //if (w < wmt) // Console.WriteLine("Decreasing variance at strike {0} between time {1} and time {2}", strike, t-dt, t); dwdt = (wpt - wmt) / (2.0 * dt); } if (dwdy == 0.0 && d2wdy2 == 0.0) { locVolMatrix[i, j] = Math.Sqrt(dwdt); } else { den1 = 1.0 - y / w * dwdy; den2 = 0.25 * (-0.25 - 1.0 / w + y * y / w / w) * dwdy * dwdy; den3 = 0.5 * d2wdy2; locVolMatrix[i, j] = dwdt / (den1 + den2 + den3); //if (locVolMatrix[i,j] < 0.0) // Console.WriteLine("Negative local vol^2 at strike {0} and time {1}; " + // "Black vol surface is not smooth enought.", strike, t); } } } // Create dupire outputs. Console.WriteLine(locVolMat); PFunction2D.PFunction2D localVol = new PFunction2D.PFunction2D(locVolMat, locVolStr, locVolMatrix); localVol.Parse(null); string[] names = new string[] { "S0" }; Vector param = new Vector(1); param[0] = Hdataset.S0; EstimationResult result = new EstimationResult(names, param); //result.Objects = new object[3]; result.Objects = new object[4]; result.Objects[0] = this.r; result.Objects[1] = this.q; result.Objects[2] = localVol; result.Objects[3] = impVol; //Console.WriteLine("r = " + HCalData.Rate.ToString()); //Console.WriteLine("q = " + HCalData.DividendYield.ToString()); return(result); }
private Matrix LocVolMatrixFromCallPrices(CallPriceMarketData Hdataset, CallPriceSurface CallPrice, out Vector locVolMat, out Vector locVolStr) { Integrate integrate = new Integrate(this); int nmat = calibrationSettings.LocalVolatilityMaturities; int nstrike = calibrationSettings.LocalVolatilityStrikes; double firstMat = CallPrice.MinMaturity; double lastMat = CallPrice.MaxMaturity; double firstStr = CallPrice.MinStrike; double lastStr = CallPrice.MaxStrike; double delta = (lastStr - firstStr) / nstrike; locVolMat = Vector.Linspace(firstMat, lastMat, nmat); locVolStr = Vector.Linspace(firstStr + delta, lastStr - delta, nstrike); Matrix locVolMatrix = new Matrix(nmat, nstrike); // this next matrix is created only for debugging pourpose Matrix squaredLocVolMatrix = new Matrix(nmat, nstrike); double num, den, call, dCdt, dCdk, d2Cdk2; Vector x = new Vector(2); double h0 = 0.02 * Hdataset.S0; //increment for numerical derivatives (stock) double ht = 0.02; // 0.25 * (lastMat - firstMat) / nmat;//increment for numerical derivatives (maturities) double hs = h0; double d2Threshold = 10e-5; for (int i = 0; i < nmat; i++) { double growthRate = integrate.AdaptLobatto(0.0, locVolMat[i]); x[0] = locVolMat[i]; for (int j = 0; j < nstrike; j++) { x[1] = locVolStr[j]; var support = CallPrice.SupportY(x[0]); //if (x[1] > support[1] && j > 1) if (x[1] < support[0] || x[1] > support[1]) { //skip...fill later //squaredLocVolMatrix[i, j] = squaredLocVolMatrix[i, j - 1]; //locVolMatrix[i, j] = locVolMatrix[i, j-1]; } else { bool fail = false; call = CallPrice.Evaluate(x); dCdt = CallPrice.Partial(x, 0, ht); //do // { dCdk = CallPrice.Partial(x, 1, hs); d2Cdk2 = CallPrice.Partial2(x, 1, hs); //if (Math.Abs(d2Cdk2) > d2Threshold || hs > 0.1 * Hdataset.S0) if (Math.Abs(d2Cdk2) < d2Threshold) { fail = true; //break; } // hs *= 2; //} while (true); if (!fail) { double qq = this.q.Evaluate(x[0]); num = dCdt + growthRate * x[1] * dCdk + qq * call; den = x[1] * x[1] * d2Cdk2; squaredLocVolMatrix[i, j] = 2.0 * num / den; locVolMatrix[i, j] = Math.Sqrt(Math.Abs(2.0 * num / den)); } } } } //Fill missing vol for (int i = 0; i < nmat; i++) { double lastVol = 0; for (int j = 0; j < nstrike; j++) { if (locVolMatrix[i, j] != 0) { lastVol = locVolMatrix[i, j]; } else { locVolMatrix[i, j] = lastVol; } } lastVol = 0; for (int j = nstrike - 1; j >= 0; j--) { if (locVolMatrix[i, j] != 0) { lastVol = locVolMatrix[i, j]; } else { locVolMatrix[i, j] = lastVol; } } // } return(locVolMatrix); }
/// <summary> /// Attempts to solve the Heston optimization problem using /// <see cref="Heston.HestonOptimizationProblem"/>. /// </summary> /// <param name="marketData">Data to be used in order to perform the optimization.</param> /// <param name="settings">The parameter is not used.</param> /// <param name="controller">IController.</param> /// <returns>The results of the optimization.</returns> public EstimationResult Estimate(List <object> marketData, IEstimationSettings settings = null, IController controller = null, Dictionary <string, object> properties = null) { DateTime t0 = DateTime.Now; var interestDataSet = (CurveMarketData)marketData[0]; CallPriceMarketData callDataSet = (CallPriceMarketData)marketData[1]; EquityCalibrationData equityCalData = new EquityCalibrationData(callDataSet, interestDataSet); var spotPrice = (DVPLI.MarketDataTypes.Scalar)marketData[2]; Setup(equityCalData, settings); var calSettings = settings as HestonCalibrationSettings; // Creates the context. Document doc = new Document(); ProjectROV prj = new ProjectROV(doc); doc.Part.Add(prj); // Optimization problem instance. Vector matBound = new Vector(2); Vector strikeBound = new Vector(2); if (calSettings != null) { matBound[0] = calSettings.MinMaturity; matBound[1] = calSettings.MaxMaturity; strikeBound[0] = calSettings.MinStrike; strikeBound[1] = calSettings.MaxStrike; } else { //use defaults matBound[0] = 1.0 / 12; // .25; matBound[1] = 6; // 10; //Up to 6Y maturities strikeBound[0] = 0.4; strikeBound[1] = 1.6; } Console.WriteLine(callDataSet); /* * //CBA TEST * matBound[0] = 1;// .25; * matBound[1] = 3.5;// 10; //Up to 6Y maturities * strikeBound[0] = 0.5;// 0.5; * strikeBound[1] = 2;//1.5; */ HestonCallOptimizationProblem problem = NewOptimizationProblem(equityCalData, matBound, strikeBound); int totalOpts = problem.numCall + problem.numPut; Console.WriteLine("Calibration based on " + totalOpts + " options. (" + problem.numCall + " call options and " + problem.numPut + " put options)."); IOptimizationAlgorithm solver = new QADE(); //IOptimizationAlgorithm solver = new MultiLevelSingleLinkage(); IOptimizationAlgorithm solver2 = new SteepestDescent(); DESettings o = new DESettings(); o.controller = controller; // If true the optimization algorithm will operate in parallel. o.Parallel = Engine.MultiThread; o.h = 10e-8; o.epsilon = 10e-8; SolutionInfo solution = null; double minObj = double.MaxValue; Vector minX = null; int Z = 1; //if (problem.GetType() == typeof(Heston.HestonCallSimulationOptimizationProblem)) // Z = 2; for (int z = 0; z < Z; z++) { if (solver.GetType() == typeof(MultiLevelSingleLinkage)) { o.NP = 50; o.MaxIter = 25; o.MaxGamma = 6; } else { o.NP = 60; o.MaxIter = 35; } o.Verbosity = 1; Vector x0 = null;// new Vector(new double[] { 0.5, 0.5, 0.8, -0.5, 0.05 }); // GA solution = solver.Minimize(problem, o, x0); if (solution.errors) { return(null); } o.options = "qn"; o.MaxIter = 500;// 1000; if (solution != null) { solution = solver2.Minimize(problem, o, solution.x); } else { solution = solver2.Minimize(problem, o, x0); } if (solution.errors) { return(null); } if (solution.obj < minObj) { minObj = solution.obj; minX = solution.x.Clone(); } } solution.obj = minObj; solution.x = minX; //Displays pricing error structure HestonCallOptimizationProblem.displayObjInfo = true; problem.Obj(solution.x); HestonCallOptimizationProblem.displayObjInfo = false; Console.WriteLine("Calibration Time (s)\t" + (DateTime.Now - t0).TotalSeconds); return(BuildEstimate(spotPrice, interestDataSet, callDataSet, equityCalData, solution)); }
/// <summary> /// This method allows to fit the implied volatility using different models. /// </summary> /// <param name="Hdataset"></param> /// <returns></returns> IFunction FitImplVolModel(CallPriceMarketData Hdataset) { int model = 1; switch (model) { case 0: PFunction2D.PFunction2D pf = new PFunction2D.PFunction2D(Hdataset.Maturity, Hdataset.Strike, Hdataset.Volatility); pf.Interpolation = DVPLUtils.EInterpolationType.LEAST_SQUARES; pf.Extrapolation = DVPLUtils.ExtrapolationType.USEMODEL; pf.Parse(null); return pf; case 1: //define a model for fitting the implied volatility Fairmat.Statistics.LinearModel impVol = new Fairmat.Statistics.LinearModel( new Fairmat.Statistics.Predictor[] { delegate(Vector xx) { return 1; }, delegate(Vector xx) { return xx[0]; }, delegate(Vector xx) { return xx[1]; }, delegate(Vector xx) { return System.Math.Pow(xx[0], 2); }, delegate(Vector xx) { return System.Math.Pow(xx[1], 2); }, delegate(Vector xx) { return xx[0] * xx[1]; }, }); // Unroll matrix and coordinate vectors in order to make it suitable // for the Quadratic model implementation. int n = Hdataset.Volatility.R * Hdataset.Volatility.C; Matrix xy = new Matrix(n, 2); Vector z = new Vector(n); int count = 0; for (int x = 0; x < Hdataset.Volatility.R; x++) { for (int y = 0; y < Hdataset.Volatility.C; y++) { if (Hdataset.Volatility[x, y] > 0.01) { xy[count, Range.All] = (new Vector() { Hdataset.Maturity[x],Hdataset.Strike[y] }).T; z[count] = Hdataset.Volatility[x, y]; count++; } } } xy.Resize(count, xy.C); z.Resize(count); impVol.Estimate(xy, z); return impVol; } return null; }
private static Vector Test(int nm, int nk, double q, double s0, double r, double t, double theta, double sigma, double nu) { // Simulate synthetic data. Vector m = new Vector(nm); Vector k = new Vector(nk); Matrix cp = new Matrix(nm, nk); Random rand = new Random(); for (int i = 0; i < nm; i++) { m[i] = 0.01 + rand.NextDouble() * 0.99; } for (int i = 0; i < nk; i++) { k[i] = 60 + rand.NextDouble() * 90; } for (int i = 0; i < nm; i++) { for (int j = 0; j < nk; j++) { cp[i, j] = VarianceGammaOptionsCalibration.VGCall(theta, sigma, nu, m[i], k[j], q, s0, r); } } Console.WriteLine("Benchmark value"); Console.WriteLine(new Vector() { theta, sigma, nu }); Console.WriteLine("Call prices"); Console.WriteLine(cp); // VGDiff at optimum. double fopt = VarianceGammaOptimizationProblem.VGDiff(new Vector() { theta, sigma, nu }, q, s0, k, r, cp, m); Console.WriteLine("fopt"); Console.WriteLine(fopt); VarianceGammaOptionsCalibration c = new VarianceGammaOptionsCalibration(); List <object> marketData = new List <object>(); var espmd = new EquitySpotMarketData(); espmd.Price = s0; espmd.RiskFreeRate = r; espmd.DividendYield = q; var cpmd = new CallPriceMarketData(); cpmd.Strike = k; cpmd.Maturity = m; cpmd.CallPrice = cp; var dc = new DiscountingCurveMarketData(); dc.Durations = new Vector() { 0 }; dc.Values = new Vector() { r }; marketData.Add(espmd); marketData.Add(cpmd); marketData.Add(dc); EstimationResult res = c.Estimate(marketData, null); return((Vector)res.Values); }
private Matrix LocVolMatrixFromCallPrices(CallPriceMarketData Hdataset, CallPriceSurface CallPrice, out Vector locVolMat, out Vector locVolStr) { Integrate integrate = new Integrate(this); int nmat = calibrationSettings.LocalVolatilityMaturities; int nstrike = calibrationSettings.LocalVolatilityStrikes; double firstMat = CallPrice.MinMaturity; double lastMat = CallPrice.MaxMaturity; double firstStr = CallPrice.MinStrike; double lastStr = CallPrice.MaxStrike; double delta = (lastStr - firstStr) / nstrike; locVolMat = Vector.Linspace(firstMat, lastMat, nmat); locVolStr = Vector.Linspace(firstStr + delta, lastStr - delta, nstrike); Matrix locVolMatrix = new Matrix(nmat, nstrike); // this next matrix is created only for debugging pourpose Matrix squaredLocVolMatrix = new Matrix(nmat, nstrike); double num, den, call, dCdt, dCdk, d2Cdk2; Vector x = new Vector(2); double h0 = 0.02*Hdataset.S0;//increment for numerical derivatives (stock) double ht = 0.02;// 0.25 * (lastMat - firstMat) / nmat;//increment for numerical derivatives (maturities) double hs = h0; double d2Threshold=10e-5; for (int i = 0; i < nmat; i++) { double growthRate = integrate.AdaptLobatto(0.0, locVolMat[i]); x[0] = locVolMat[i]; for (int j = 0; j < nstrike; j++) { x[1] = locVolStr[j]; var support=CallPrice.SupportY(x[0]); //if (x[1] > support[1] && j > 1) if(x[1]<support[0]||x[1]>support[1]) { //skip...fill later //squaredLocVolMatrix[i, j] = squaredLocVolMatrix[i, j - 1]; //locVolMatrix[i, j] = locVolMatrix[i, j-1]; } else { bool fail = false; call = CallPrice.Evaluate(x); dCdt = CallPrice.Partial(x, 0, ht); //do // { dCdk = CallPrice.Partial(x, 1, hs); d2Cdk2 = CallPrice.Partial2(x, 1, hs); //if (Math.Abs(d2Cdk2) > d2Threshold || hs > 0.1 * Hdataset.S0) if (Math.Abs(d2Cdk2) < d2Threshold) { fail = true; //break; } // hs *= 2; //} while (true); if (!fail) { double qq = this.q.Evaluate(x[0]); num = dCdt + growthRate * x[1] * dCdk + qq * call; den = x[1] * x[1] * d2Cdk2; squaredLocVolMatrix[i, j] = 2.0 * num / den; locVolMatrix[i, j] = Math.Sqrt(Math.Abs(2.0 * num / den)); } } } } //Fill missing vol for (int i = 0; i < nmat; i++) { double lastVol=0; for (int j = 0; j < nstrike; j++) { if (locVolMatrix[i, j] != 0) lastVol = locVolMatrix[i, j]; else locVolMatrix[i, j] = lastVol; } lastVol = 0; for (int j = nstrike-1; j >=0; j--) { if (locVolMatrix[i, j] != 0) lastVol = locVolMatrix[i, j]; else locVolMatrix[i, j] = lastVol; } // } return locVolMatrix; }
public void TestCalibration() { InterestRateMarketData IData = InterestRateMarketData.FromFile("../../TestData/IRMD-sample.xml"); CallPriceMarketData HData = CallPriceMarketData.FromFile("../../TestData/CallData-sample.xml"); //InterestRateMarketData IData = InterestRateMarketData.FromFile("../../../EquityModels.Tests/TestData/IRMD-EU-30102012-close.xml"); //CallPriceMarketData HData = CallPriceMarketData.FromFile("../../../EquityModels.Tests/TestData/30102012-SX5E_Index-HestonData.xml"); //CallPriceMarketData HData = ObjectSerialization.ReadFromXMLFile("../../../EquityModels.Tests/TestData/FTSE.xml") as CallPriceMarketData; List <object> l = new List <object>(); l.Add(IData.DiscountingCurve); l.Add(HData); DupireEstimator DE = new DupireEstimator(); DupireCalibrationSettings settings = new DupireCalibrationSettings(); settings.LocalVolatilityCalculation = LocalVolatilityCalculation.Method1; //settings.LocalVolatilityCalculation = LocalVolatilityCalculation.QuantLib; EstimationResult res = DE.Estimate(l, settings); //int nmat = HData.Maturity.Length; //int nstrike = HData.Strike.Length; int i = 5; // Maturity. int j = 4; // Strike. Engine.MultiThread = true; Document doc = new Document(); ProjectROV rov = new ProjectROV(doc); doc.Part.Add(rov); doc.DefaultProject.NMethods.m_UseAntiteticPaths = true; int n_sim = 10000; int n_steps = 500; double strike = HData.Strike[j]; //double volatility = HData.Volatility[i, j]; /* * PFunction2D.PFunction2D impvolfunc = new PFunction2D.PFunction2D(rov); * impvolfunc = res.Objects[3] as PFunction2D.PFunction2D; * impvolfunc.VarName = "impvol"; * rov.Symbols.Add(impvolfunc); * double volatility = impvolfunc.Evaluate(HData.Maturity[i], HData.Strike[j]); */ double volatility = 0.2; double maturity = HData.Maturity[i]; ModelParameter Pstrike = new ModelParameter(strike, string.Empty, "strike"); rov.Symbols.Add(Pstrike); AFunction payoff = new AFunction(rov); payoff.VarName = "payoff"; payoff.m_IndependentVariables = 1; payoff.m_Value = (RightValue)("max(x1 - strike ; 0)"); rov.Symbols.Add(payoff); bool found; double S0 = PopulateHelper.GetValue("S0", res.Names, res.Values, out found); ModelParameter PS0 = new ModelParameter(S0, string.Empty, "S0"); rov.Symbols.Add(PS0); PFunction rfunc = new PFunction(rov); rfunc = res.Objects[0] as PFunction; rfunc.VarName = "r"; rov.Symbols.Add(rfunc); PFunction qfunc = new PFunction(rov); qfunc = res.Objects[1] as PFunction; qfunc.VarName = "q"; rov.Symbols.Add(qfunc); PFunction2D.PFunction2D volfunc = new PFunction2D.PFunction2D(rov); volfunc = res.Objects[2] as PFunction2D.PFunction2D; volfunc.VarName = "localvol"; rov.Symbols.Add(volfunc); DupireProcess process = new DupireProcess(); process.s0 = (ModelParameter)"S0"; process.r = (ModelParameter)"@r"; process.q = (ModelParameter)"@q"; process.localVol = (ModelParameter)"@localvol"; double rate = rfunc.Evaluate(maturity); double dy = qfunc.Evaluate(maturity); StochasticProcessExtendible s = new StochasticProcessExtendible(rov, process); rov.Processes.AddProcess(s); // Set the discounting. RiskFreeInfo rfi = rov.GetDiscountingModel() as RiskFreeInfo; rfi.ActualizationType = EActualizationType.RiskFree; rfi.m_deterministicRF = rate; OptionTree op = new OptionTree(rov); op.PayoffInfo.PayoffExpression = "payoff(v1)"; op.PayoffInfo.Timing.EndingTime.m_Value = (RightValue)maturity; op.PayoffInfo.European = true; rov.Map.Root = op; rov.NMethods.Technology = ETechType.T_SIMULATION; rov.NMethods.PathsNumber = n_sim; rov.NMethods.SimulationSteps = n_steps; ROVSolver solver = new ROVSolver(); solver.BindToProject(rov); solver.DoValuation(-1); if (rov.HasErrors) { rov.DisplayErrors(); } Assert.IsFalse(rov.HasErrors); ResultItem price = rov.m_ResultList[0] as ResultItem; double samplePrice = price.value; double sampleDevSt = price.stdDev / Math.Sqrt((double)n_sim); Console.WriteLine("Surf = " + volfunc.Expr); // Calculation of the theoretical value of the call. double theoreticalPrice = BlackScholes.Call(rate, S0, strike, volatility, maturity, dy); Console.WriteLine("Theoretical Price = " + theoreticalPrice.ToString()); Console.WriteLine("Monte Carlo Price = " + samplePrice); Console.WriteLine("Standard Deviation = " + sampleDevSt.ToString()); double tol = 4.0 * sampleDevSt; doc.WriteToXMLFile("Dupire.fair"); Assert.LessOrEqual(Math.Abs(theoreticalPrice - samplePrice), tol); }
protected override EstimationResult BuildEstimate(Scalar spotPrice, CurveMarketData interestDataSet, CallPriceMarketData callDataSet, EquityCalibrationData equityCalData, SolutionInfo solution) { string[] names = new string[] { "S0", "kappa", "theta", "sigma", "rho", "V0", "r", "q" }; Vector param = new Vector(8); param[0] = spotPrice.Value; param[Range.New(1, 5)] = solution.x[Range.New(0, 4)]; param[6] = equityCalData.zrFunc.Evaluate(TheoreticalModelsSettings.ConstantDYRFMaturity); if (impliedDividends) { param[7] = solution.x[Range.End];// equityCalData.dyFunc.Evaluate(TheoreticalModelsSettings.ConstantDYRFMaturity); } else { param[7] = DY(equityCalData); } var result = new EstimationResult(names, param); result.Fit = HestonCallOptimizationProblem.avgPricingError; Console.WriteLine(result); return(result); }