/// <summary> /// Values at, overriding calibrated Wing Model with supplied parms /// </summary> /// <param name="stock"></param> /// <param name="expiry">The expiry.</param> /// <param name="strikes">The strikes.</param> /// <param name="parms">The parms.</param> /// <param name="oride"></param> /// <param name="cache">if set to <c>true</c> [cache].</param> /// <returns></returns> public ForwardExpiry ValueAt(Stock stock, DateTime expiry, List <Double> strikes, OrcWingParameters parms, bool oride, bool cache) { var fwdExpiry = new ForwardExpiry { ExpiryDate = expiry }; double forward = stock.GetForward(stock.Date, expiry); fwdExpiry.FwdPrice = Convert.ToDecimal(forward); foreach (double strike in strikes) { double val = OrcWingVol.Value(strike, parms); IVolatilityPoint vp = new VolatilityPoint(); vp.SetVolatility(Convert.ToDecimal(val), VolatilityState.Default()); bool node = VolatilitySurfaceHelper.IsMatch(strike, expiry, NodalExpiries); Strike newstrike; if (node & oride) { newstrike = VolatilitySurfaceHelper.GetStrike(strike, expiry, NodalExpiries); //new data points, derefernce fitting model newstrike.InterpModel = null; } else { //var wingModel = new WingInterp {WingParams = parms}; newstrike = new Strike { StrikePrice = strike, InterpModel = null }; //newstrike.InterpModel = wingModel; fwdExpiry.AddStrike(newstrike, node); } newstrike.SetVolatility(vp); } return(fwdExpiry); }
public static double FindZeroCostCall(ZeroCurve myZero, DivList myDiv, OrcWingVol myVol, double t, double strike, double spot, string style, string paystyle, double gridsteps) { //compute the cost of the put double callPrice = 0.0; double putPrice = FindPrice(myZero, myDiv, myVol, t, strike, spot, style, "p", gridsteps); //start looking for the call using the ATM strike //double callStrike = GetATMfwd(myZero, myDiv, spot, t); double callStrike = strike; const double tol = 0.0001; for (int idx = 0; idx < 1000; idx++) { callPrice = FindPrice(myZero, myDiv, myVol, t, callStrike, spot, style, "c", gridsteps); if (Math.Abs(callPrice - putPrice) < tol) { break; } //apply newton double dk = 0.001 * callStrike; double callPriceUp = FindPrice(myZero, myDiv, myVol, t, callStrike + dk, spot, style, "c", gridsteps); callStrike -= (callPrice - putPrice) * dk / (callPriceUp - callPrice); } if (Math.Abs(callPrice - putPrice) > tol) { throw new Exception("Price did not converge"); } return(callStrike); }
/// <summary> /// Gets the Wing volatility /// </summary> /// <param name="volSurface">The vol surface.</param> /// <param name="time">The time.</param> /// <param name="strike">The strike.</param> /// <param name="wingParameterList"></param> /// <returns></returns> public static double GetWingValue(List <OrcWingParameters> wingParameterList, IInterpolation xInterp, double time, double strike) { double eps = 0.0001; IPoint pt1 = new Point2D(time, strike * (1 + eps)); IPoint pt2 = new Point2D(time, strike * (1 - eps)); double[] _years = new double[wingParameterList.Count]; for (int idx = 0; idx < wingParameterList.Count; idx++) { _years[idx] = wingParameterList[idx].TimeToMaturity; } var volArray = new double[wingParameterList.Count]; for (int idx = 0; idx < wingParameterList.Count; idx++) { volArray[idx] = OrcWingVol.Value(strike, wingParameterList[idx]); } double res = 0; if (volArray.Length > 1) { xInterp.Initialize(_years, volArray); res = xInterp.ValueAt(time, false); } else { res = volArray[0]; } return(res); }
public void SimpleOrcWingModel() { const double vc = 0.2417; const double sr = -0.1243; const double pc = 0.2283; const double cc = -1.1478; const double dc = -0.2871; const double uc = 0.1327; const double refFwd = 3065.0; const double refVol = 0.2417; const double vcr = 0.0; const double scr = 0.0; const double ssr = 100.0; const double dsm = 0.5; const double usm = 0.5; const double time = 0.2931507; OrcWingVol volSurface = new OrcWingVol(); volSurface.currentVol = vc; volSurface.dnCutoff = dc; volSurface.dsr = dsm; volSurface.putCurve = pc; volSurface.callCurve = cc; volSurface.refFwd = refFwd; volSurface.refVol = refVol; volSurface.scr = scr; volSurface.slopeRef = sr; volSurface.ssr = ssr; volSurface.timeToMaturity = time; volSurface.upCutoff = uc; volSurface.usr = usm; volSurface.vcr = vcr; double res1 = volSurface.orcvol(3065.0, 1508.64); double res2 = volSurface.orcvol(3065.0, 2222.65); double res3 = volSurface.orcvol(3065.0, 2591.17); double res4 = volSurface.orcvol(3065.0, 3224.57); double res5 = volSurface.orcvol(3065.0, 3454.89); double res6 = volSurface.orcvol(3065.0, 4502.88); Assert.IsTrue(res1 < 0.3147); Assert.IsTrue(res1 > 0.3143); Assert.IsTrue(res2 < 0.3040); Assert.IsTrue(res2 > 0.3035); Assert.IsTrue(res3 < 0.2692); Assert.IsTrue(res3 > 0.2688); Assert.IsTrue(res4 < 0.2325); Assert.IsTrue(res4 > 0.2321); Assert.IsTrue(res5 < 0.2105); Assert.IsTrue(res5 > 0.2101); //Test floor; Assert.IsTrue(res6 < 0.1909); Assert.IsTrue(res6 > 0.1905); }
public static double FindPrice(ZeroCurve myZero, DivList myDiv, OrcWingVol myVol, double t, double strike, double spot, string style, string paystyle, double gridsteps) { //get the atfwd double atFwd = GetATMfwd(myZero, myDiv, spot, t); //set up the tree var myTree = new Tree(); int nGridsteps = (gridsteps < 20.0) ? 20 : Convert.ToInt32(gridsteps); myTree.Gridsteps = nGridsteps; myTree.Tau = t; myTree.Sig = myVol.orcvol(atFwd, strike); myTree.Spot = spot; myTree.MakeGrid(myZero, myDiv); //create pricer var myPrice = new Pricer { Strike = strike, Payoff = paystyle, Smoothing = "y", Style = style }; myPrice.MakeGrid(myTree); double pr = myPrice.Price(); return(pr); }
/// <summary> /// Perform a wing model interpolation on a vector of values /// We must assume the points are arranged x0 <=x <= x1 for this to work/> /// </summary> /// <param name="axisValue">The axis value</param> /// <param name="extrapolation">This is not currently implemented.</param> /// <returns></returns> public double ValueAt(double axisValue, bool extrapolation) { var result = OrcWingVol.Value(axisValue, WingParameters); return(result); }