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