public override void Run() { StartTime = _startTime; EndTime = _endTime; AddDataSource(UNDERLYING_NICK); AddDataSource(VOLATILITY_NICK); foreach (var simTime in SimTimes) { ITimeSeries <double> underlying = FindInstrument(UNDERLYING_NICK).Close; ITimeSeries <double> volatility = FindInstrument(VOLATILITY_NICK).Close.Divide(100.0); DateTime previousFriday = SimTime[0] - TimeSpan.FromDays((int)SimTime[0].DayOfWeek + 2); for (int weeks = 1; weeks < 4 * 4; weeks++) { DateTime expiry = previousFriday + TimeSpan.FromDays(weeks * 7); double T = (expiry - SimTime[0].Date).TotalDays / 365.25; int lowStrike = 5 * (int)Math.Round(underlying[0] * 0.80 / 5.0); int highStrike = 5 * (int)Math.Round(underlying[0] * 1.20 / 5.0); for (int strike = lowStrike; strike <= highStrike; strike += 5) { for (int putCall = 0; putCall < 2; putCall++) // 0 = put, 1 = call { double z = (strike - underlying[0]) / (Math.Sqrt(T) * underlying[0] * volatility[0]); double vol = volatility[0] * (1.0 + 0.30 * Math.Abs(z)); double price = OptionSupport.GBlackScholes( putCall == 0 ? false : true, underlying[0], strike, T, 0.0, // risk-free rate 0.0, // cost-of-carry rate vol); Bar bar = new Bar( "SPX", //symbol, SimTime[0], default(double), default(double), default(double), default(double), default(long), false, price * 0.99, price * 1.01, 100, 100, true, expiry.Date, strike, putCall == 0 ? true : false); _data.Add(bar); } } } } }
public override void Run() { StartTime = _startTime; EndTime = _endTime; AddDataSource(UNDERLYING); #if MORE_VIX_PERIODS var volatilities = new Dictionary <double, DataSource> { { 9 / 365.25, AddDataSource(VOLATILITY_9D) }, { 30 / 365.25, AddDataSource(VOLATILITY_30D) }, { 91 / 365.25, AddDataSource(VOLATILITY_3M) }, { 182 / 365.25, AddDataSource(VOLATILITY_6M) }, { 365 / 365.25, AddDataSource(VOLATILITY_12M) }, }; #else var volatilities = new Dictionary <double, DataSource> { { 30 / 365.25, AddDataSource(VOLATILITY_30D) }, }; #endif var lowStrikes = new Dictionary <DateTime, int>(); var highStrikes = new Dictionary <DateTime, int>(); foreach (var simTime in SimTimes) { ITimeSeries <double> underlying = FindInstrument(UNDERLYING).Close; DateTime previousFriday = SimTime[0] - TimeSpan.FromDays((int)SimTime[0].DayOfWeek + 2); var expiries = new List <DateTime>(); for (int w = 1; w < 60; w++) { DateTime x = previousFriday + TimeSpan.FromDays(w * 7); if (w <= 13) { expiries.Add(x); } // 3rd Friday of the Month: // 15, if 1st is a Friday // 21, if 1st is a Saturday else if (x.Day <= 21 && x.Day >= 15) { expiries.Add(x); } } foreach (var expiry in expiries) { double T = (expiry - SimTime[0].Date).TotalDays / 365.25; var volatility = 0.0; if (T < volatilities.Keys.Min()) { volatility = volatilities[volatilities.Keys.Min()].Instrument.Close[0] / 100.0; } else if (T > volatilities.Keys.Max()) { volatility = volatilities[volatilities.Keys.Max()].Instrument.Close[0] / 100.0; } else { var vLow = volatilities .Where(v => v.Key <= T) .OrderByDescending(v => v.Key) .FirstOrDefault(); var vHigh = volatilities .Where(v => v.Key >= T) .OrderBy(v => v.Key) .FirstOrDefault(); var p = (T - vLow.Key) / (vHigh.Key - vLow.Key); volatility = 0.01 * (vLow.Value.Instrument.Close[0] + p * (vHigh.Value.Instrument.Close[0] - vLow.Value.Instrument.Close[0])); } lowStrikes[expiry] = Math.Min(5 * (int)Math.Round(underlying[0] * 0.70 / 5.0), lowStrikes.ContainsKey(expiry) ? lowStrikes[expiry] : int.MaxValue); highStrikes[expiry] = Math.Max(5 * (int)Math.Round(underlying[0] * 1.20 / 5.0), highStrikes.ContainsKey(expiry) ? highStrikes[expiry] : 0); int lowStrike = lowStrikes[expiry]; int highStrike = highStrikes[expiry]; for (int strike = lowStrike; strike <= highStrike; strike += 5) { for (int putCall = 0; putCall < 2; putCall++) // 0 = put, 1 = call { double z = (strike - underlying[0]) / (Math.Sqrt(T) * underlying[0] * volatility); double vol = volatility * (1.0 + 0.30 * Math.Abs(z)); double price = OptionSupport.GBlackScholes( putCall != 0, underlying[0], strike, T, 0.0, // risk-free rate 0.0, // cost-of-carry rate vol); Bar bar = new Bar( "SPX", SimTime[0],