public void Populate(IStochasticProcess container, EstimationResult estimate) { bool found; this.s0 = new ModelParameter(PopulateHelper.GetValue("S0", estimate.Names, estimate.Values, out found), this.s0.Description); bool errors = RetrieveCurve(container.Context, false); if (!errors) { PFunction rFunc = estimate.Objects[0] as PFunction; PFunction rFuncDest = this.r.fVRef() as PFunction; rFuncDest.Expr = rFunc.Expr; PFunction qFunc = estimate.Objects[1] as PFunction; PFunction qFuncDest = this.q.fVRef() as PFunction; qFuncDest.Expr = qFunc.Expr; //Calibrator assumes dividend yield is a step constant function, the simulation model must be coherent with that assumption. qFuncDest.m_Function.iType = DVPLUtils.EInterpolationType.ZERO_ORDER_LEFT; PFunction2D.PFunction2D localVolSrc = estimate.Objects[2] as PFunction2D.PFunction2D; PFunction2D.PFunction2D localVolDest = this.localVol.fVRef() as PFunction2D.PFunction2D; localVolDest.Expr = localVolSrc.Expr; localVolDest.Interpolation = localVolSrc.Interpolation; } }
/// <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 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 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); }
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; }
/// <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 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 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); }