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 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 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; }
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); }
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); }