public void TestLargeImpliedVol() { var stock = TestDataHelper.GetStock("RIO"); Assert.AreEqual("RIO", stock.Name); var stockObject = TestHelper.CreateStock(stock); ForwardExpiry fwd = new ForwardExpiry(DateTime.Parse("24-09-2009"), 5818); Strike str = new Strike(5800, null, null, Units.Cents); fwd.AddStrike(str, true); stockObject.VolatilitySurface.AddExpiry(fwd); foreach (ForwardExpiry fwdExp in stockObject.VolatilitySurface.Expiries) { foreach (Strike strike in fwdExp.Strikes) { if (strike.StrikePrice == 5800 && (fwdExp.ExpiryDate == DateTime.Parse("24-09-2009"))) { var vol0 = OptionHelper.GetImpliedVol(stockObject, fwdExp.ExpiryDate, strike.StrikePrice, false, "A", 450.0, 120); AmOptionAnalytics call = new AmOptionAnalytics(stockObject.Date, fwdExp.ExpiryDate, Convert.ToDouble(stockObject.Spot), strike.StrikePrice, vol0, "A", "P", stockObject.RateCurve, stockObject.Dividends, 120); Assert.AreEqual(call.Price(), 450, 0.01); } } } }
/// <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 void TestImpliedVol2() { var stock = TestDataHelper.GetStock("ANZ"); Assert.AreEqual("ANZ", stock.Name); Stock stockObject = TestHelper.CreateStock(stock); ForwardExpiry fwd = new ForwardExpiry(DateTime.Parse("29-10-2009"), 3676); Strike str = new Strike(3650, null, null, Units.Cents); fwd.AddStrike(str, true); stockObject.VolatilitySurface.AddExpiry(fwd); foreach (ForwardExpiry fwdExp in stockObject.VolatilitySurface.Expiries) { foreach (Strike strike in fwdExp.Strikes) { if (strike.StrikePrice == 3650 && (fwdExp.ExpiryDate == DateTime.Parse("29-10-2009"))) { stockObject.Spot = 3676; var vol0 = OptionHelper.GetImpliedVol(stockObject, fwdExp.ExpiryDate, strike.StrikePrice, true, "A", 224.5, 120); AmOptionAnalytics call = new AmOptionAnalytics(stockObject.Date, fwdExp.ExpiryDate, Convert.ToDouble(stockObject.Spot), strike.StrikePrice, vol0, "A", "C", stockObject.RateCurve, stockObject.Dividends, 120); Assert.AreEqual(call.Price(), 224.5, 0.01); } } } }
public void TestAmVega() { var stock = TestDataHelper.GetStock("ANZ"); Assert.AreEqual("ANZ", stock.Name); var stockObject = TestHelper.CreateStock(stock); var fwd = new ForwardExpiry(DateTime.Parse("23-12-2010"), 2220); var str = new Strike(2100, null, null, Units.Cents); var vp = new VolatilityPoint { Value = 0.30M }; str.SetVolatility(vp); fwd.AddStrike(str, true); stockObject.VolatilitySurface.AddExpiry(fwd); foreach (ForwardExpiry fwdExp in stockObject.VolatilitySurface.Expiries) { foreach (Strike strike in fwdExp.Strikes) { if ((strike.StrikePrice == 2100.0) && (fwdExp.ExpiryDate == DateTime.Parse("23-12-2010"))) { AmOptionAnalytics call = new AmOptionAnalytics(stockObject.Date, fwdExp.ExpiryDate, Convert.ToDouble(stockObject.Spot), strike.StrikePrice, Convert.ToDouble(strike.Volatility.Value), "A", "C", stockObject.RateCurve, stockObject.Dividends, 20); double callprice = call.Price(); Assert.AreEqual(callprice, 338.8661, 0.5); call.MakeVega(); Assert.AreEqual(call.Vega, 9.093, 0.02); AmOptionAnalytics put = new AmOptionAnalytics(stockObject.Date, fwdExp.ExpiryDate, Convert.ToDouble(stockObject.Spot), strike.StrikePrice, Convert.ToDouble(strike.Volatility.Value), "A", "P", stockObject.RateCurve, stockObject.Dividends, 20); double putprice = put.Price(); Assert.AreEqual(putprice, 239.6014, 0.5); put.MakeVega(); Assert.AreEqual(put.Vega, 9.093, 0.02); } } } }
/// <summary> /// Creates a test vol surface to test temporal and strike volatility interpolation /// </summary> /// <returns></returns> public IVolatilitySurface CreateTestVolSurface() { IVolatilitySurface volSurface = new VolatilitySurface("BHP", 4500M, DateTime.Today); ForwardExpiry expiry1 = new ForwardExpiry(DateTime.Parse("01-Jan-2010"), 4200); ForwardExpiry expiry2 = new ForwardExpiry(DateTime.Parse("01-Jan-2011"), 4400); OptionPosition call1 = new OptionPosition("1245", 104, PositionType.Call); OptionPosition put1 = new OptionPosition("1246", 1200, PositionType.Put); OptionPosition call2 = new OptionPosition("1645", 180, PositionType.Call); OptionPosition put2 = new OptionPosition("1646", 1300, PositionType.Put); Strike strike1 = new Strike(4200, call1, put1); Strike strike2 = new Strike(4000, call2, put2); IVolatilityPoint point1 = new VolatilityPoint(); point1.SetVolatility(0.30M, VolatilityState.Default()); put1.SetVolatility(point1); call1.SetVolatility(point1); IVolatilityPoint point2 = new VolatilityPoint(); point2.SetVolatility(0.40M, VolatilityState.Default()); call2.SetVolatility(point2); put2.SetVolatility(point2); expiry1.AddStrike(strike1, true); expiry2.AddStrike(strike2, true); volSurface.AddExpiry(expiry1); volSurface.AddExpiry(expiry2); return(volSurface); }
/// <summary> /// Creates the one point child. /// </summary> /// <returns></returns> public IVolatilitySurface CreateOnePointChild() { IVolatilitySurface volSurface = new VolatilitySurface("BHP", 4500M, DateTime.Today); ForwardExpiry expiry0 = new ForwardExpiry(DateTime.Parse("10-9-2009"), 4700); OptionPosition call0 = new OptionPosition("1145", 104, PositionType.Call); OptionPosition put0 = new OptionPosition("1146", 1200, PositionType.Put); Strike strike0 = new Strike(0.20, 4599, call0, put0); expiry0.AddStrike(strike0, true); volSurface.AddExpiry(expiry0); return(volSurface); }
/// <summary> /// Creates a null volatility surface to be used in extrapolation tests that utilise /// the historical volatility ratio /// </summary> /// <returns></returns> public IVolatilitySurface CreateNullVolSurface() { IVolatilitySurface volSurface = new VolatilitySurface("BHP", 4500M, DateTime.Today); ForwardExpiry expiry0 = new ForwardExpiry(DateTime.Parse("14-9-2009"), 4700); ForwardExpiry expiry1 = new ForwardExpiry(DateTime.Parse("16-9-2009"), 4700); ForwardExpiry expiry2 = new ForwardExpiry(DateTime.Parse("30-9-2009"), 4750); OptionPosition call0 = new OptionPosition("1145", 104, PositionType.Call); OptionPosition put0 = new OptionPosition("1146", 1200, PositionType.Put); OptionPosition call1 = new OptionPosition("1245", 104, PositionType.Call); OptionPosition put1 = new OptionPosition("1246", 1200, PositionType.Put); OptionPosition call2 = new OptionPosition("1645", 180, PositionType.Call); OptionPosition put2 = new OptionPosition("1646", 1300, PositionType.Put); Strike strike0 = new Strike(1.00, 4599, call0, put0); Strike strike1 = new Strike(0.867, 4700, call1, put1); Strike strike2 = new Strike(1.00, 4750, call2, put2); Strike strike3 = new Strike(1.2, 4750, call2, put2); Strike strike4 = new Strike(0.30, 4750, call2, put2); IVolatilityPoint point0 = new VolatilityPoint(); point0.SetVolatility(0.00M, VolatilityState.Default()); put0.SetVolatility(point0); call0.SetVolatility(point0); strike0.SetVolatility(point0); IVolatilityPoint point1 = new VolatilityPoint(); point1.SetVolatility(0.00M, VolatilityState.Default()); put1.SetVolatility(point1); call1.SetVolatility(point1); strike1.SetVolatility(point1); IVolatilityPoint point2 = new VolatilityPoint(); point2.SetVolatility(0.00M, VolatilityState.Default()); strike2.SetVolatility(point2); call2.SetVolatility(point2); put2.SetVolatility(point2); IVolatilityPoint point3 = new VolatilityPoint(); point3.SetVolatility(0.00M, VolatilityState.Default()); strike3.SetVolatility(point3); IVolatilityPoint point4 = new VolatilityPoint(); point4.SetVolatility(0.00M, VolatilityState.Default()); strike4.SetVolatility(point4); expiry0.AddStrike(strike0, true); expiry1.AddStrike(strike1, true); expiry2.AddStrike(strike2, true); expiry2.AddStrike(strike3, true); expiry2.AddStrike(strike4, true); volSurface.AddExpiry(expiry0); volSurface.AddExpiry(expiry1); volSurface.AddExpiry(expiry2); return(volSurface); }
/// <summary> /// Removes the expiry. /// </summary> /// <param name="expiry">The expiry.</param> public void RemoveExpiry(ForwardExpiry expiry) { ForwardExpiry matchedExpiry = ForwardExpiryHelper.FindExpiry(expiry.ExpiryDate, expiry.FwdPrice, expiry.InterestRate, _expiries); if (matchedExpiry == null) { _expiries.Remove(matchedExpiry); } if (_rawExpiryDates.Contains(expiry.ExpiryDate)) { _rawExpiryDates.Remove(expiry.ExpiryDate); _expiries.Remove(expiry); } }
public void WingCalibration() { var stock = TestDataHelper.GetStock("AGK"); Assert.AreEqual("AGK", stock.Name); var stockObject = TestHelper.CreateStock(stock); stockObject.CalcForwards(); if (stockObject.VolatilitySurface.Expiries[0].Strikes[0].InterpModel.GetType() == typeof(WingInterp)) { stockObject.VolatilitySurface.Calibrate(); var exp0 = new List <DateTime>(); var strike0 = new List <double>(); exp0.Add(new DateTime(2009, 09, 16)); strike0.Add(810); List <ForwardExpiry> expiry = stockObject.VolatilitySurface.ValueAt(stockObject, exp0, strike0, false); OrcWingParameters wing = new OrcWingParameters(); ForwardExpiry exp = stockObject.VolatilitySurface.Expiries[0]; Strike str = exp.Strikes[0]; wing.AtmForward = str.InterpModel.WingParams.AtmForward; wing.CallCurve = str.InterpModel.WingParams.CallCurve; wing.CurrentVol = str.InterpModel.WingParams.CurrentVol; double moneyness = Convert.ToDouble(exp.FwdPrice / stockObject.Spot); wing.DnCutoff = str.InterpModel.WingParams.DnCutoff; wing.Dsr = str.InterpModel.WingParams.Dsr; wing.PutCurve = str.InterpModel.WingParams.PutCurve; wing.RefFwd = str.InterpModel.WingParams.RefFwd; wing.RefVol = str.InterpModel.WingParams.CurrentVol; wing.Scr = str.InterpModel.WingParams.Scr; wing.SlopeRef = str.InterpModel.WingParams.SlopeRef; wing.Ssr = str.InterpModel.WingParams.Ssr; wing.UpCutoff = str.InterpModel.WingParams.UpCutoff; wing.Usr = str.InterpModel.WingParams.Usr; wing.Vcr = str.InterpModel.WingParams.Vcr; var forwardexpiry = stockObject.VolatilitySurface.ValueAt(stockObject, new DateTime(2009, 09, 16), strike0, wing, false, false); decimal calibrateBack = Math.Round(expiry[0].Strikes[0].Volatility.Value, 4); decimal ovridePoint = Math.Round(forwardexpiry.Strikes[0].Volatility.Value, 4); // Can we use ValueAt to value back at our calibrated point (x=7/365,y=8.66); Assert.AreEqual(0.59500M, calibrateBack); // Can we override with fitted model and arrive back at calibrated point (x=7/365,y=8.66); Assert.AreEqual(ovridePoint, 0.5950M); } }
/// <summary> /// Values at. /// </summary> /// <param name="stock"></param> /// <param name="expiries">The expiries.</param> /// <param name="strikes">The strikes.</param> /// <param name="?">Cache to vol object</param> /// <param name="cache"></param> /// <returns></returns> public List <ForwardExpiry> ValueAt(Stock stock, List <DateTime> expiries, List <Double> strikes, bool cache) { var forwardExpiries = new List <ForwardExpiry>(); foreach (DateTime exp in expiries) { var fwdExpiry = new ForwardExpiry(); foreach (double str in strikes) { var wingModel = new WingInterp(); double forward = stock.GetForward(stock.Date, exp.Date); double spot = Convert.ToDouble(stock.Spot); fwdExpiry.FwdPrice = Convert.ToDecimal(forward); double y = str; double x = (exp.Subtract(Date)).Days / 365.0; IPoint point = new Point2D(x, y); InterpCurve.Forward = forward; InterpCurve.Spot = spot; var val = InterpCurve.Value(point); IVolatilityPoint vp = new VolatilityPoint(); vp.SetVolatility(Convert.ToDecimal(val), VolatilityState.Default()); fwdExpiry.ExpiryDate = exp; bool node = VolatilitySurfaceHelper.IsMatch(str, exp, NodalExpiries); // copy model used to return ForwardExpiry object var newstrike = new Strike { StrikePrice = str }; var wing = (WingModelInterpolation)InterpCurve.GetYAxisInterpolatingFunction(); //SABRModelInterpolation wing = (SABRModelInterpolation)_interpCurve.GetYAxisInterpolatingFunction(); wingModel.WingParams = wing.WingParameters; newstrike.InterpModel = wingModel; fwdExpiry.AddStrike(newstrike, node); newstrike.SetVolatility(vp); } forwardExpiries.Add(fwdExpiry); } return(forwardExpiries); }
/// <summary> /// Tests the fitter. /// </summary> private void CalibrateToFoCurve(double fwd1, double cc1, double vc1, double dc1, double dsr1, double pc1, double scr1, double sr1, double ssr1, double uc1, double usr1, double vcr1, double fwd2, double cc2, double vc2, double dc2, double dsr2, double pc2, double scr2, double sr2, double ssr2, double uc2, double usr2, double vcr2, DateTime exp1, DateTime exp2) { var stock = TestDataHelper.GetStock("AGK"); Assert.AreEqual("AGK", stock.Name); var stockObject = TestHelper.CreateStock(stock); ForwardExpiry expiry1 = new ForwardExpiry(exp1, Convert.ToDecimal(fwd1)); ForwardExpiry expiry2 = new ForwardExpiry(exp2, Convert.ToDecimal(fwd2)); double[] sdStrikeMults = { 0.6, 0.7, 0.75, 0.8, 0.85, 0.87, 0.9, 0.92, 0.94, 0.95, 0.96, 0.98, 1, 1.02, 1.04, 1.05, 1.06, 1.08, 1.1, 1.12, 1.15, 1.2, 1.25, 1.3, 1.4, 1.45, 1.5, 1.55, 1.6, 1.65, 1.7, 1.75, 1.8, 1.85, 1.9, 1.95, 2 }; OrcWingParameters parms1 = new OrcWingParameters { AtmForward = fwd1, CallCurve = cc1, CurrentVol = vc1, DnCutoff = dc1, Dsr = dsr1, PutCurve = pc1, RefFwd = fwd1, RefVol = vc1, Scr = scr1, SlopeRef = sr1, Ssr = ssr1, UpCutoff = uc1, Usr = usr1, Vcr = vcr1 }; OrcWingParameters parms2 = new OrcWingParameters { AtmForward = fwd2, CallCurve = cc2, CurrentVol = vc2, DnCutoff = dc2, Dsr = dsr2, PutCurve = pc2, RefFwd = fwd2, RefVol = vc1, Scr = scr2, SlopeRef = sr2, Ssr = ssr2, UpCutoff = uc2, Usr = usr2, Vcr = vcr2 }; //Override double spot = Convert.ToDouble(stockObject.Spot); List <double> strikes = new List <double>(); foreach (double mul in sdStrikeMults) { Strike str0 = new Strike(mul * spot, null, null, Units.Cents); strikes.Add(str0.StrikePrice); } ForwardExpiry FOexpiry1 = stockObject.VolatilitySurface.ValueAt(stockObject, exp1, strikes, parms1, true, false); ForwardExpiry FOexpiry2 = stockObject.VolatilitySurface.ValueAt(stockObject, exp2, strikes, parms2, true, false); stockObject.VolatilitySurface.AddExpiry(FOexpiry1); stockObject.VolatilitySurface.AddExpiry(FOexpiry2); stockObject.VolatilitySurface.Calibrate(); // Then ValueAt() on an arbitrary grid now you have calibrated to your FO vols }
/// <summary> /// Adds the expiry. /// </summary> /// <param name="expiry">The expiry.</param> public void AddExpiry(ForwardExpiry expiry) { ForwardExpiryHelper.AddExpiry(expiry, _expiries); _rawExpiryDates.Add(expiry.ExpiryDate); }
public void TestPricevsORCExample() { DateTime[] rtDates = { DateTime.Parse("17-Aug-2010"), DateTime.Parse("17-Sep-2010"), DateTime.Parse("18-Oct-2010"), DateTime.Parse("17-Nov-2010"), DateTime.Parse("10-Dec-2010") }; double[] rates = { 0.045507232, 0.046609656, 0.047336042, 0.047655159, 0.047737236 }; RateCurve rc = new RateCurve("AUD", "Semi-Annual", DateTime.Parse("16-Aug-2010"), rtDates, rates); //Dividend d1 = new Dividend(DateTime.Parse("16-8-2010"), 11.745786M); Dividend d2 = new Dividend(DateTime.Parse("17-8-2010"), 0.893295M); Dividend d3 = new Dividend(DateTime.Parse("23-8-2010"), 7.856689M); Dividend d4 = new Dividend(DateTime.Parse("24-8-2010"), 2.898251M); Dividend d5 = new Dividend(DateTime.Parse("25-8-2010"), 3.344721M); Dividend d6 = new Dividend(DateTime.Parse("26-8-2010"), 0.485070M); Dividend d7 = new Dividend(DateTime.Parse("27-8-2010"), 0.835305M); Dividend d8 = new Dividend(DateTime.Parse("30-8-2010"), 3.952976M); Dividend d9 = new Dividend(DateTime.Parse("31-8-2010"), 0.884255M); Dividend d10 = new Dividend(DateTime.Parse("1-9-2010"), 2.013798M); Dividend d11 = new Dividend(DateTime.Parse("2-9-2010"), 1.241407M); Dividend d12 = new Dividend(DateTime.Parse("3-9-2010"), 0.613699M); Dividend d13 = new Dividend(DateTime.Parse("6-9-2010"), 11.712946M); Dividend d14 = new Dividend(DateTime.Parse("7-9-2010"), 3.775104M); Dividend d15 = new Dividend(DateTime.Parse("8-9-2010"), 0.606597M); Dividend d16 = new Dividend(DateTime.Parse("9-9-2010"), 0.268093M); Dividend d17 = new Dividend(DateTime.Parse("10-9-2010"), 0.144851M); Dividend d18 = new Dividend(DateTime.Parse("13-9-2010"), 1.600975M); Dividend d19 = new Dividend(DateTime.Parse("14-9-2010"), 1.499946M); Dividend d20 = new Dividend(DateTime.Parse("15-9-2010"), 0.238824M); Dividend d21 = new Dividend(DateTime.Parse("16-9-2010"), 0.117931M); List <Dividend> divCurve = new List <Dividend>() { d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16, d17, d18, d19, d20, d21 }; DateTime date0 = new DateTime(2010, 08, 16); DateTime exp = new DateTime(2010, 9, 16); double spot = 4447.62; //double future = 4420; double strike = 4200; string stockId = "XJO_Spot"; Stock stock = new Stock(date0, Convert.ToDecimal(spot), stockId, "XJO", rc, divCurve); double fwd = stock.GetForward(date0, exp); var wingParams1 = new OrcWingParameters { CurrentVol = 0.234828, RefVol = 0.234828, SlopeRef = -0.109109, PutCurve = 1.235556, CallCurve = 0.60895, DnCutoff = -0.493791, UpCutoff = 0.506209, RefFwd = 4420.092383, AtmForward = 4420.092383, Vcr = 0, Scr = 0, Ssr = 100, Dsr = 0.2, Usr = 0.2, }; VolatilitySurface vs = new VolatilitySurface(stockId, Convert.ToDecimal(spot), date0); ForwardExpiry expiry = new ForwardExpiry(exp, Convert.ToDecimal(fwd)); OptionPosition op = new OptionPosition("XJO_Vanilla_ETO_Sep10_4200.000_Put", 30.237108, PositionType.Put); Strike strike0 = new Strike(strike, null, op); expiry.AddStrike(strike0, true); List <double> strikes1 = new List <double> { 4200 }; ForwardExpiry forwardexpiry = vs.ValueAt(stock, exp, strikes1, wingParams1, true, false); double vol = Convert.ToDouble(forwardexpiry.Strikes[0].Volatility.Value); var utils = new AmOptionAnalytics(date0, exp, spot, strike, vol, "European", "Put", rc, divCurve, 120); double pr = Math.Round(utils.Price(), 7); }