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],