Пример #1
0
        public void HistoricalDataRequestsAreForwardedToTheBroker()
        {
            var instrument = new Instrument
            {
                ID = 1,
                Symbol = "SPY",
                Datasource = new Datasource { ID = 1, Name = "MockSource" },
                Exchange = new Exchange
                {
                    ID = 1,
                    Name = "Exchange",
                    Timezone = "Eastern Standard Time"
                }
            };
            var request = new HistoricalDataRequest(instrument, BarSize.OneDay, new DateTime(2012, 1, 1), new DateTime(2013, 1, 1));

            _client.RequestHistoricalData(request);
            // TODO: Think about delay amount
            Thread.Sleep(1500);

            _historicalDataBrokerMock.Verify(
                x => x.RequestHistoricalData(
                    It.Is<HistoricalDataRequest>(
                        r =>
                            r.Instrument.ID == 1 &&
                            r.Frequency == BarSize.OneDay &&
                            r.StartingDate == new DateTime(2012, 1, 1) &&
                            r.EndingDate == new DateTime(2013, 1, 1))),
                Times.Once);
        }
Пример #2
0
        public void EmailReportSentOnBrokerError()
        {
            var settings = new UpdateJobSettings(errors: true, timeout: 1, toEmail: "*****@*****.**", fromEmail: "*****@*****.**");
            var job = new DataUpdateJob(_brokerMock.Object, _mailMock.Object, settings, _localStorageMock.Object, _instrumentManagerMock.Object);

            _brokerMock
                .Setup(x => x.RequestHistoricalData(It.IsAny<HistoricalDataRequest>()))
                .Throws(new Exception("TestException123"));

            Instrument inst = new Instrument() { ID = 1, Symbol = "SPY", Currency = "USD", Type = InstrumentType.Stock };
            _instrumentManagerMock
                .Setup(x => x.FindInstruments(It.IsAny<Expression<Func<Instrument, bool>>>(), It.IsAny<MyDBContext>()))
                .Returns(new List<Instrument>() { inst });

            _localStorageMock
                .Setup(x => x.GetStorageInfo(It.IsAny<int>()))
                .Returns(new List<StoredDataInfo>() { 
                    new StoredDataInfo() 
                    { 
                        Frequency = BarSize.OneDay, 
                        InstrumentID = inst.ID.Value, 
                        LatestDate = DateTime.Now.AddDays(-2)
                    } });

            job.Execute(_contextMock.Object);

            _mailMock.Verify(x => 
                x.Send(
                    It.IsAny<string>(), 
                    It.Is<string>(y => y == "*****@*****.**"), 
                    It.IsAny<string>(), 
                    It.Is<string>(y => y.Contains("TestException123"))));
        }
Пример #3
0
 public DataAdditionRequest(BarSize frequency, Instrument instrument, List<OHLCBar> data, bool overwrite = true)
 {
     Data = data;
     Frequency = frequency;
     Instrument = instrument;
     Overwrite = overwrite;
 }
Пример #4
0
        public HistoricalRequestWindow(Instrument instrument)
        {
            InitializeComponent();
            DataContext = this;

            Random r = new Random(); //we have to randomize the name of the client, can't reuse the identity

            Title = string.Format("Data Request - {0} @ {1}", instrument.Symbol, instrument.Datasource.Name);

            _client = new QDMSClient.QDMSClient(
            string.Format("DataRequestClient-{0}", r.Next()),
            "localhost",
            Properties.Settings.Default.rtDBReqPort,
            Properties.Settings.Default.rtDBPubPort,
            Properties.Settings.Default.instrumentServerPort,
            Properties.Settings.Default.hDBPort);

            _client.HistoricalDataReceived += _client_HistoricalDataReceived;
            _client.Error += _client_Error;
            _client.Connect();

            Data = new ObservableCollection<OHLCBar>();

            TheInstrument = instrument;

            StartTime = new DateTime(1950, 1, 1, 0, 0, 0, 0);
            EndTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0, 0);

            if (!TheInstrument.ID.HasValue) return;

            ShowDialog();
        }
Пример #5
0
        /// <summary>
        /// Delete an instrument and all locally stored data.
        /// </summary>
        public static void RemoveInstrument(Instrument instrument)
        {
            using (var entityContext = new MyDBContext())
            {
                //hacking around the circular reference issue
                if (instrument.IsContinuousFuture)
                {
                    entityContext.Instruments.Attach(instrument);
                    var tmpCF = instrument.ContinuousFuture;
                    instrument.ContinuousFuture = null;
                    instrument.ContinuousFutureID = null;
                    entityContext.SaveChanges();

                    entityContext.ContinuousFutures.Attach(tmpCF);
                    entityContext.ContinuousFutures.Remove(tmpCF);
                    entityContext.SaveChanges();
                }

                entityContext.Instruments.Attach(instrument);
                entityContext.Instruments.Remove(instrument);
                entityContext.SaveChanges();
            }

            using (var localStorage = DataStorageFactory.Get())
            {
                localStorage.Connect();

                localStorage.DeleteAllInstrumentData(instrument);
            }
        }
Пример #6
0
        public static Contract InstrumentToContract(Instrument instrument)
        {
            string symbol = string.IsNullOrEmpty(instrument.DatasourceSymbol) ? instrument.Symbol : instrument.DatasourceSymbol;
            var contract = new Contract(
                0,
                symbol,
                SecurityTypeConverter(instrument.Type),
                instrument.Expiration.HasValue ? instrument.Expiration.Value.ToString("yyyyMM", CultureInfo.InvariantCulture) : "",
                0,
                OptionTypeToRightType(instrument.OptionType),
                instrument.Multiplier.ToString(),
                "",
                instrument.Currency,
                null,
                null,
                SecurityIdType.None,
                string.Empty);

            if (instrument.Strike.HasValue)
                contract.Strike = (double)instrument.Strike.Value;

            if (instrument.Exchange != null)
                contract.Exchange = instrument.Exchange.Name;

            return contract;
        }
Пример #7
0
 public RealTimeDataRequest(Instrument instrument, BarSize frequency, bool rthOnly = true, bool savetoLocalStorage = false)
 {
     Instrument = instrument;
     Frequency = frequency;
     RTHOnly = rthOnly;
     SaveToLocalStorage = savetoLocalStorage;
 }
Пример #8
0
        public static Instrument ContractDetailsToInstrument(ContractDetails contract)
        {
            var instrument =  new Instrument
            {
                Symbol = contract.Summary.LocalSymbol,
                UnderlyingSymbol = contract.Summary.Symbol,
                Name = contract.LongName,
                OptionType = RightTypeToOptionType(contract.Summary.Right),
                Type = InstrumentTypeConverter(contract.Summary.SecurityType),
                Multiplier = contract.Summary.Multiplier == null ? 1 : int.Parse(contract.Summary.Multiplier),
                Expiration = string.IsNullOrEmpty(contract.Summary.Expiry) ? (DateTime?)null : DateTime.ParseExact(contract.Summary.Expiry, "yyyyMMdd", CultureInfo.InvariantCulture),
                Strike = (decimal)contract.Summary.Strike,
                Currency = contract.Summary.Currency,
                MinTick = (decimal)contract.MinTick,
                Industry = contract.Industry,
                Category = contract.Category,
                Subcategory = contract.Subcategory,
                IsContinuousFuture = false,
                ValidExchanges = contract.ValidExchanges
            };

            if (!string.IsNullOrEmpty(contract.Summary.PrimaryExchange))
                instrument.PrimaryExchange = new Exchange { Name = contract.Summary.PrimaryExchange };
            return instrument;
        }
Пример #9
0
        public void SetUp()
        {
            _instrument = new Instrument
            {
                ID = 1,
                Symbol = "SPY",
                Datasource = new Datasource { ID = 1, Name = "MockSource" }
            };

            _instrument.Exchange = new Exchange()
            {
                ID = 1,
                Name = "Exchange",
                Timezone = "Eastern Standard Time"
            };

            _dataSourceMock = new Mock<IHistoricalDataSource>();
            _dataSourceMock.SetupGet(x => x.Name).Returns("MockSource");
            _dataSourceMock.SetupGet(x => x.Connected).Returns(false);

            _localStorageMock = new Mock<IDataStorage>();

            _cfBrokerMock = new Mock<IContinuousFuturesBroker>();
            _cfBrokerMock.SetupGet(x => x.Connected).Returns(true);

            _broker = new HistoricalDataBroker(_cfBrokerMock.Object, _localStorageMock.Object, new List<IHistoricalDataSource> { _dataSourceMock.Object });

            _dataSourceMock.SetupGet(x => x.Connected).Returns(true);
        }
Пример #10
0
        public DataImportWindow(Instrument instrument)
        {
            InitializeComponent();

            //reload the instrument first to make sure we have up-to-date data
            using (var context = new MyDBContext())
            {
                context.Instruments.Attach(instrument);
                context.Entry(instrument).Reload();
                _instrument = instrument;
            }

            Title += " - " + _instrument.Symbol;

            //fill frequency combo box
            var values = MyUtils.GetEnumValues<BarSize>();
            foreach (BarSize s in values)
            {
                FrequencyComboBox.Items.Add(s);
            }
            FrequencyComboBox.SelectedItem = BarSize.OneDay;

            MinDT.Value = new DateTime(1950, 1, 1);
            MaxDT.Value = DateTime.Now;
        }
Пример #11
0
        public void DataPushRequestIsForwardedToLocalStorage()
        {
            var instrument = new Instrument
            {
                ID = 1,
                Symbol = "SPY",
                Datasource = new Datasource { ID = 1, Name = "MockSource" }
            };

            var data = new List<OHLCBar>
            {
                new OHLCBar {Open = 1, High = 2, Low = 3, Close = 4, DT = new DateTime(2013, 1, 1) }
            };

            var req = new DataAdditionRequest(BarSize.OneDay, instrument, data, true);

            _client.PushData(req);

            Thread.Sleep(50);

            _brokerMock.Verify(x => x.AddData(
                It.Is<DataAdditionRequest>(y =>
                    y.Frequency == BarSize.OneDay &&
                    y.Instrument.ID == 1 &&
                    y.Data.Count == 1)
                ), Times.Once);
        }
Пример #12
0
        public void ProtoBufSerializeAndDeserializeResultsInIdenticalObject()
        {
            var inst = new Instrument
            {
                ID               = 5,
                Symbol           = "test",
                UnderlyingSymbol = "123",
                Exchange         = new Exchange
                {
                    ID   = 1,
                    Name = "CBOE"
                },
                Type = InstrumentType.Stock
            };
            var ms = new MemoryStream();

            var instDeserialized = MyUtils.ProtoBufDeserialize <Instrument>(MyUtils.ProtoBufSerialize(inst, ms), ms);

            Assert.AreEqual(inst.ID, instDeserialized.ID);
            Assert.AreEqual(inst.Symbol, instDeserialized.Symbol);
            Assert.AreEqual(inst.UnderlyingSymbol, instDeserialized.UnderlyingSymbol);
            Assert.AreEqual(inst.Type, instDeserialized.Type);
            Assert.AreEqual(inst.Exchange.ID, instDeserialized.Exchange.ID);
            Assert.AreEqual(inst.Exchange.Name, instDeserialized.Exchange.Name);
        }
Пример #13
0
        public void ServerCorrectlyForwardsRealTimeData()
        {
            var ds = new Datasource() { ID = 1, Name = "TestDS" };
            var inst = new Instrument() { ID = 15, Datasource = ds, DatasourceID = 1, Symbol = "SPY", Type = InstrumentType.Stock };
            var req = new RealTimeDataRequest(inst, BarSize.FiveSeconds, rthOnly: false, savetoLocalStorage: false);

            _brokerMock.Setup(x => x.RequestRealTimeData(It.IsAny<RealTimeDataRequest>())).Returns(true);

            _client.RequestRealTimeData(req);

            Thread.Sleep(50);

            RealTimeDataEventArgs receivedData = null;
            _client.RealTimeDataReceived += (s,e) => receivedData = e;

            long dt = DateTime.Now.ToBinary();
            _brokerMock.Raise(x => x.RealTimeDataArrived += null, new RealTimeDataEventArgs(15, dt, 100m, 105m, 95m, 99m, 10000000, 101, 500, 1));

            Thread.Sleep(50);

            Assert.IsNotNull(receivedData);
            Assert.AreEqual(15, receivedData.InstrumentID);
            Assert.AreEqual(dt, receivedData.Time);
            Assert.AreEqual(100m, receivedData.Open);
            Assert.AreEqual(105m, receivedData.High);
            Assert.AreEqual(95m, receivedData.Low);
            Assert.AreEqual(99m, receivedData.Close);
            Assert.AreEqual(10000000, receivedData.Volume);
            Assert.AreEqual(500, receivedData.Count);
            Assert.AreEqual(101, receivedData.Wap);
        }
Пример #14
0
 public void GetTZInfoThrowsExceptionIfNonExistingTimezoneIsSpecified()
 {
     var inst = new Instrument { Exchange = new Exchange { Timezone = "asdf____" } };
     Assert.Throws<TimeZoneNotFoundException>(() =>
     {
         TimeZoneInfo tz = inst.GetTZInfo();
     });
 }
Пример #15
0
 public RealTimeStreamInfo(Instrument instrument, int requestID, string datasource, BarSize frequency, bool rthOnly) : this()
 {
     Instrument = instrument;
     RequestID = requestID;
     Datasource = datasource;
     Frequency = frequency;
     RTHOnly = rthOnly;
 }
Пример #16
0
        public void ServerCorrectlyForwardsCancellationRequestsToBroker()
        {
            var ds = new Datasource() { ID = 1, Name = "TestDS" };
            var inst = new Instrument() { ID = 15, Datasource = ds, DatasourceID = 1, Symbol = "SPY", Type = InstrumentType.Stock };
            _client.CancelRealTimeData(inst);

            _brokerMock.Verify(x => x.CancelRTDStream(It.Is<int>(y => y == 15)));
        }
Пример #17
0
        //utility function to get the contracts used for the continuous futures calculations
        public static List<Instrument> GetVIXFutures()
        {
            var nov12 = new Instrument
            {
                ID = 1,
                Type = InstrumentType.Future,
                Expiration = new DateTime(2012, 11, 21),
                UnderlyingSymbol = "VIX",
                Symbol = "VIXX12"
            };

            var dec12 = new Instrument
            {
                ID = 2,
                Type = InstrumentType.Future,
                Expiration = new DateTime(2012, 12, 19),
                UnderlyingSymbol = "VIX",
                Symbol = "VIXZ12"
            };

            var jan13 = new Instrument
            {
                ID = 3,
                Type = InstrumentType.Future,
                Expiration = new DateTime(2013, 1, 16),
                UnderlyingSymbol = "VIX",
                Symbol = "VIXF13"
            };

            var feb13 = new Instrument
            {
                ID = 4,
                Type = InstrumentType.Future,
                Expiration = new DateTime(2013, 2, 13),
                UnderlyingSymbol = "VIX",
                Symbol = "VIXG13"
            };

            var mar13 = new Instrument
            {
                ID = 5,
                Type = InstrumentType.Future,
                Expiration = new DateTime(2013, 3, 20),
                UnderlyingSymbol = "VIX",
                Symbol = "VIXH13"
            };

            var futures = new List<Instrument>
            {
                nov12,
                dec12,
                jan13,
                feb13,
                mar13
            };

            return futures;
        }
Пример #18
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="continuousFuture"></param>
        /// <returns>The current front future for this continuous futures contract. Null if it is not found.</returns>
        public Instrument GetCurrentFrontFuture(Instrument continuousFuture)
        {
            var searchInstrument = new Instrument { UnderlyingSymbol = continuousFuture.UnderlyingSymbol, Type = InstrumentType.Future };
            var futures = InstrumentManager.FindInstruments(search: searchInstrument);

            if (futures.Count == 0) return null;

            return new Instrument();
        }
Пример #19
0
        public void BarTimeAdjustmentsHappenCorrectly()
        {
            string json = @"{
	""status"": {
		""code"": 200,
		""message"": ""Success.""
	},
	""results"": [{
		""symbol"": ""IBM"",
		""timestamp"": ""2016-08-15T09:00:00-04:00"",
		""tradingDay"": ""2016-08-15"",
		""open"": 162.4,
		""high"": 162.97,
		""low"": 162.38,
		""close"": 162.77,
		""volume"": 215371
	},
	{
		""symbol"": ""IBM"",
		""timestamp"": ""2016-08-15T10:00:00-04:00"",
		""tradingDay"": ""2016-08-15"",
		""open"": 162.8,
		""high"": 162.95,
		""low"": 162.61,
		""close"": 162.63,
		""volume"": 222815
	}]
}";
            
            var exchange = new Exchange
            {
                Timezone = "Eastern Standard Time"
            };

            var instrument = new Instrument()
            {
                Symbol = "IBM",
                Exchange = exchange,
                Sessions = new List<InstrumentSession>{
                new InstrumentSession{ OpeningDay = DayOfTheWeek.Monday, OpeningTime = new TimeSpan(9, 30, 0) } }
            };

            var request = new HistoricalDataRequest(instrument, BarSize.OneHour, DateTime.Now, DateTime.Now);
            List<OHLCBar> bars = BarChartUtils.ParseJson(JObject.Parse(json), request);

            //opening time set to the session opening instead of earlier
            Assert.AreEqual(new DateTime(2016, 8, 15, 9, 30, 0), bars[0].DTOpen.Value);

            //Bar closing time set correctly
            Assert.AreEqual(new DateTime(2016, 8, 15, 10, 0, 0), bars[0].DT);


            //timezone conversion has happened properly
            Assert.AreEqual(new DateTime(2016, 8, 15, 10, 0, 0), bars[1].DTOpen.Value);
        }
Пример #20
0
 public HistoricalDataRequest(Instrument instrument, BarSize frequency, DateTime startingDate, DateTime endingDate, bool forceFreshData = false, bool localStorageOnly = false, bool saveToLocalStorage = true, bool rthOnly = false)
 {
     Frequency = frequency;
     Instrument = instrument;
     StartingDate = startingDate;
     EndingDate = endingDate;
     ForceFreshData = forceFreshData;
     LocalStorageOnly = localStorageOnly;
     SaveDataToStorage = saveToLocalStorage;
     RTHOnly = rthOnly;
 }
Пример #21
0
        /// <summary>
        /// Add a new instrument or update an existing instrument in the database.
        /// </summary>
        /// <param name="instrument"></param>
        /// <param name="updateIfExists"></param>
        /// <param name="saveChanges">Set to true if saving to db should be done.</param>
        /// <returns>True if the insertion or update succeeded. False if it did not.</returns>
        public static bool AddInstrument(Instrument instrument, bool updateIfExists = false, bool saveChanges = true)
        {
            if (instrument.IsContinuousFuture)
            {
                throw new Exception("Cannot add continuous futures using this method");
            }

            using (var context = new MyDBContext())
            {
                var existingInstrument = context.Instruments.SingleOrDefault(x =>
                    (x.ID == instrument.ID) ||
                    (x.Symbol == instrument.Symbol && x.DatasourceID == instrument.DatasourceID && x.ExchangeID == instrument.ExchangeID));

                if (existingInstrument == null) //object doesn't exist, so we add it
                {
                    //if necessary, load sessions from teplate or exchange
                    if (instrument.SessionsSource == SessionsSource.Exchange)
                    {
                        instrument.Sessions = new List<InstrumentSession>();
                        var exchange = context.Exchanges.Include("Sessions").First(x => x.ID == instrument.ExchangeID);
                        foreach (ExchangeSession s in exchange.Sessions)
                        {
                            instrument.Sessions.Add(MyUtils.SessionConverter(s));
                        }
                    }
                    else if (instrument.SessionsSource == SessionsSource.Template)
                    {
                        instrument.Sessions = new List<InstrumentSession>();
                        var template = context.SessionTemplates.Include("Sessions").First(x => x.ID == instrument.SessionTemplateID);
                        foreach (TemplateSession s in template.Sessions)
                        {
                            instrument.Sessions.Add(MyUtils.SessionConverter(s));
                        }
                    }

                    context.Instruments.Add(instrument);
                    context.Database.Connection.Open();
                    if (saveChanges) context.SaveChanges();
                    return true;
                }
                else if (updateIfExists) //object exist, but we want to update it
                {
                    context.Entry(existingInstrument).CurrentValues.SetValues(instrument);
                    if (saveChanges) context.SaveChanges();
                    return true;
                }
            }
            return false; //object exists and we don't update it
        }
Пример #22
0
        public void ServerCorrectlyForwardsRealTimeDataRequestsToBroker()
        {
            var ds = new Datasource() { ID = 1, Name = "TestDS" };
            var inst = new Instrument() { ID = 15, Datasource = ds, DatasourceID = 1, Symbol = "SPY", Type = InstrumentType.Stock };
            var req = new RealTimeDataRequest(inst, BarSize.FiveSeconds, rthOnly: false, savetoLocalStorage: false);
            _client.RequestRealTimeData(req);

            _brokerMock.Verify(x => x.RequestRealTimeData(It.Is<RealTimeDataRequest>(
                y => y.Frequency == BarSize.FiveSeconds &&
                y.RTHOnly == false &&
                y.SaveToLocalStorage == false &&
                y.Instrument.ID == 15 &&
                y.Instrument.Symbol == "SPY" &&
                y.Instrument.Datasource.Name == "TestDS")));
        }
Пример #23
0
        public DataEditWindow(Instrument instrument)
        {
            InitializeComponent();
            DataContext = this;

            Data = new ObservableCollection<OHLCBar>();

            //grab and update the instrument
            using (var context = new MyDBContext())
            {
                context.Instruments.Attach(instrument);
                context.Entry(instrument).Reload();
                TheInstrument = instrument;
            }

            string timezone = TheInstrument.Exchange == null ? "UTC" : TheInstrument.Exchange.Timezone;
            _tzInfo = TimeZoneInfo.FindSystemTimeZoneById(timezone);

            StartTime = new DateTime(1950, 1, 1, 0, 0, 0, 0);
            EndTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0, 0);

            if (!TheInstrument.ID.HasValue) return;

            //grab the data info
            using (var localStorage = DataStorageFactory.Get())
            {
                var storageInfo = localStorage.GetStorageInfo(TheInstrument.ID.Value);

                if (storageInfo.Count == 0) //if it doesn't have any data, we just exit
                {
                    MessageBox.Show("This instrument has no data.");
                    Hide();
                }
                else
                {
                    foreach (StoredDataInfo s in storageInfo) //fill the resolution box
                    {
                        ResolutionComboBox.Items.Add(s.Frequency);
                    }
                }
            }

            
            
        }
Пример #24
0
        public void InstrumentAdditionRequestsAreSentCorrectly()
        {
            var instrumentSourceMock = new Mock<IInstrumentSource>();
            var instrumentsServer = new InstrumentsServer(5555, instrumentSourceMock.Object);
            instrumentsServer.StartServer();

            var rtdBrokerMock = new Mock<IRealTimeDataBroker>();
            var rtdServer = new RealTimeDataServer(5554, 5553, rtdBrokerMock.Object);
            rtdServer.StartServer();

            

            _client.Connect();

            var exchange = new Exchange() { ID = 1, Name = "NYSE", Sessions = new List<ExchangeSession>(), Timezone = "Eastern Standard Time" };
            var datasource = new Datasource() { ID = 1, Name = "Yahoo" };
            var instrument = new Instrument() { Symbol = "SPY", UnderlyingSymbol = "SPY", Type = InstrumentType.Stock, Currency = "USD", Exchange = exchange, Datasource = datasource, Multiplier = 1 };

            instrumentSourceMock.Setup(x => x.AddInstrument(It.IsAny<Instrument>(), It.IsAny<bool>(), It.IsAny<bool>())).Returns(instrument);
            
            Instrument result = _client.AddInstrument(instrument);

            Thread.Sleep(50);

            Assert.IsTrue(result != null);

            instrumentSourceMock.Verify(x => x.AddInstrument(
                It.Is<Instrument>(y =>
                    y.Symbol == "SPY" &&
                    y.Exchange != null &&
                    y.Exchange.Name == "NYSE" &&
                    y.Datasource != null &&
                    y.Datasource.Name == "Yahoo" &&
                    y.Type == InstrumentType.Stock &&
                    y.Currency == "USD" &&
                    y.Multiplier == 1),
                It.Is<bool>(y => y == false),
                It.Is<bool>(y => y == true)));

            rtdServer.StopServer();
            rtdServer.Dispose();

            instrumentsServer.StopServer();
            instrumentsServer.Dispose();
        }
Пример #25
0
        public void AcceptAvailableDataRequestsAreForwardedToTheHistoricalDataBroker()
        {
            var instrument = new Instrument
            {
                ID = 1,
                Symbol = "SPY",
                Datasource = new Datasource { ID = 1, Name = "MockSource" }
            };

            _client.GetLocallyAvailableDataInfo(instrument);

            Thread.Sleep(50);

            _brokerMock.Verify(x => x.GetAvailableDataInfo(
                It.Is<Instrument>(y =>
                    y.ID == 1 &&
                    y.Symbol == "SPY")
                    ), Times.Once);
        }
Пример #26
0
        /// <summary>
        /// Finds the currently active futures contract for a continuous futures instrument.
        /// The contract is returned asynchronously through the FoundFrontContract event.
        /// </summary>
        /// <returns>Returns an ID uniquely identifying this request.</returns>
        public int RequestFrontContract(Instrument cfInstrument, DateTime?date = null)
        {
            if (!cfInstrument.IsContinuousFuture)
            {
                throw new Exception("Not a continuous future instrument.");
            }

            _lastFrontDontractRequestID++;
            var req = new FrontContractRequest
            {
                ID         = _lastFrontDontractRequestID,
                Instrument = cfInstrument,
                Date       = date
            };

            ProcessFrontContractRequest(req);

            return(_lastFrontDontractRequestID);
        }
Пример #27
0
        public void HistoricalRequestsAreSplitToRespectRequestLimits()
        {
            int[] requestCount = {0};

            _ibClientMock.Setup(
                x => x.RequestHistoricalData(
                    It.IsAny<int>(),
                    It.IsAny<Contract>(),
                    It.IsAny<DateTime>(),
                    It.IsAny<string>(),
                    It.IsAny<BarSize>(),
                    It.IsAny<HistoricalDataType>(),
                    It.IsAny<int>()))
                .Callback<int, Contract, DateTime, string, BarSize, HistoricalDataType, int>(
                    (a, b, c, d, e, f, g) => requestCount[0]++);

            var requests = new Dictionary<KeyValuePair<BarSize, int>, int> //left side is barsize/seconds, right side is expected splits
            {
                { new KeyValuePair<BarSize, int>(BarSize.OneDay, 500 * 24 * 3600), 2},
                { new KeyValuePair<BarSize, int>(BarSize.OneHour, 75 * 24 * 3600), 3},
                { new KeyValuePair<BarSize, int>(BarSize.ThirtyMinutes, 22 * 24 * 3600), 4},
                { new KeyValuePair<BarSize, int>(BarSize.OneMinute, 9 * 24 * 3600), 5},
                { new KeyValuePair<BarSize, int>(BarSize.ThirtySeconds, 40 * 3600), 2},
                { new KeyValuePair<BarSize, int>(BarSize.FifteenSeconds, 4 * 14400), 5},
                { new KeyValuePair<BarSize, int>(BarSize.FiveSeconds, 2 * 7200), 3},
                { new KeyValuePair<BarSize, int>(BarSize.OneSecond, 10 * 1800), 11}
            };

            var inst = new Instrument();

            foreach (var kvp in requests)
            {
                _ibDatasource.RequestHistoricalData(new HistoricalDataRequest(
                    inst,
                    TWSUtils.BarSizeConverter(kvp.Key.Key),
                    DateTime.Now.AddSeconds(-kvp.Key.Value),
                    DateTime.Now,
                    dataLocation: DataLocation.ExternalOnly));

                Assert.AreEqual(kvp.Value, requestCount[0], kvp.Key.Key.ToString());
                requestCount[0] = 0;
            }
        }
Пример #28
0
        public void DoesNotRepeatRequestToSourceWhenARealTimeStreamAlreadyExists()
        {
            var inst = new Instrument
            {
                ID = 1,
                Symbol = "SPY",
                Datasource = new Datasource { ID = 999, Name = "MockSource" }
            };

            var req = new RealTimeDataRequest(inst, BarSize.FiveSeconds);

            _broker.RequestRealTimeData(req);
            Thread.Sleep(100);
            _broker.RequestRealTimeData(req);

            _dataSourceMock.Verify(x => x.RequestRealTimeData(
                It.IsAny<RealTimeDataRequest>()),
                Times.Once);
        }
Пример #29
0
        public void RealTimeDataRequestsForwardedToDataSource()
        {
            var inst = new Instrument
            {
                ID = 1,
                Symbol = "SPY",
                Datasource = new Datasource { ID = 999, Name = "MockSource" }
            };

            var req = new RealTimeDataRequest(inst, BarSize.FiveSeconds);

            _broker.RequestRealTimeData(req);

            _dataSourceMock.Verify(x => x.RequestRealTimeData(
                It.Is<RealTimeDataRequest>(
                    r => r.Instrument.ID == 1 &&
                    r.Instrument.Symbol == "SPY" &&
                    r.Frequency == BarSize.FiveSeconds)),
                Times.Once);
        }
Пример #30
0
        public static Contract InstrumentToContract(Instrument instrument)
        {
            string symbol = string.IsNullOrEmpty(instrument.DatasourceSymbol) ? instrument.UnderlyingSymbol : instrument.DatasourceSymbol;
            string expirationString = "";

            //multiple options expire each month so the string needs to be more specific there
            if(instrument.Type == InstrumentType.Option && instrument.Expiration.HasValue)
            {
                expirationString = instrument.Expiration.Value.ToString("yyyyMMdd", CultureInfo.InvariantCulture);
            }
            else if (instrument.Expiration.HasValue)
            {
                expirationString = instrument.Expiration.Value.ToString("yyyyMM", CultureInfo.InvariantCulture);
            }

            var contract = new Contract(
                0,
                symbol,
                SecurityTypeConverter(instrument.Type),
                expirationString,
                0,
                OptionTypeToRightType(instrument.OptionType),
                instrument.Multiplier.ToString(),
                "",
                instrument.Currency,
                null,
                instrument.PrimaryExchange == null ? null : instrument.PrimaryExchange.Name,
                SecurityIdType.None,
                string.Empty);
            contract.IncludeExpired = instrument.Expiration.HasValue; //only set IncludeExpired to true if the contract can actually expire

            if (instrument.Strike.HasValue && instrument.Strike.Value != 0)
                contract.Strike = (double)instrument.Strike.Value;

            if (instrument.Exchange != null)
                contract.Exchange = instrument.Exchange.Name;

            return contract;
        }
Пример #31
0
        public void ServerReturnsErrorToClientIfNoInstrumentIdIsSet()
        {
            var ds = new Datasource { ID = 1, Name = "TestDS" };
            var inst = new Instrument { ID = null, Datasource = ds, DatasourceID = 1, Symbol = "SPY", Type = InstrumentType.Stock };
            var req = new RealTimeDataRequest(inst, BarSize.FiveSeconds, false);

            string error = null;
            int? requestId = null;

            _client.Error += (s, e) =>
            {
                error = e.ErrorMessage;
                requestId = e.RequestID;
            };

            _client.RequestRealTimeData(req);

            Thread.Sleep(DefaultDelayInMilliseconds);

            Assert.IsTrue(!string.IsNullOrEmpty(error));
            Assert.IsTrue(requestId.HasValue);
        }
Пример #32
0
        public void SetUp()
        {
            _clientMock = new Mock<IDataClient>();
            _instrumentMgrMock = new Mock<IInstrumentSource>();
            _broker = new ContinuousFuturesBroker(_clientMock.Object, _instrumentMgrMock.Object);

            _cfInst = new Instrument();
            _cfInst.Type = InstrumentType.Future;
            _cfInst.DatasourceID = 1;
            _cfInst.Datasource = new Datasource { ID = 1, Name = "Interactive Brokers" };

            var cf = new ContinuousFuture();
            cf.Month = 1;
            _cfInst.IsContinuousFuture = true;
            _cfInst.ContinuousFuture = cf;
            _cfInst.ContinuousFuture.AdjustmentMode = ContinuousFuturesAdjustmentMode.NoAdjustment;

            var vix = new UnderlyingSymbol();
            vix.Rule = new ExpirationRule
            {
                DaysBefore = 30,
                DayType = DayType.Calendar,
                ReferenceRelativeMonth = RelativeMonth.NextMonth,
                ReferenceUsesDays = false,
                ReferenceWeekDay = DayOfTheWeek.Friday,
                ReferenceWeekDayCount = WeekDayCount.Third,
                ReferenceDayMustBeBusinessDay = true
            };
            vix.Symbol = "VIX";

            _cfInst.ContinuousFuture.UnderlyingSymbol = vix;

            _req = new HistoricalDataRequest(
                _cfInst,
                BarSize.OneDay,
                new DateTime(2013, 1, 1),
                new DateTime(2013, 2, 1));
        }
Пример #33
0
        /// <summary>
        /// Historical data has arrived.
        /// Add it to our data store, then check if all requests have been
        /// fulfilled for a particular continuous futures request. If they
        /// have, go do the calculations.
        /// </summary>
        private void _client_HistoricalDataReceived(object sender, HistoricalDataEventArgs e)
        {
            if (e.Request.Instrument.ID == null)
            {
                return;
            }
            int id    = e.Request.Instrument.ID.Value;
            var kvpID = new KeyValuePair <int, BarSize>(id, e.Request.Frequency);

            lock (_data)
            {
                if (_data.ContainsKey(kvpID))
                {
                    //We already have data on this instrument ID/Frequency combo.
                    //Add the arrived data, then discard any doubles, then order.
                    _data[kvpID].AddRange(e.Data);
                    _data[kvpID] = _data[kvpID].Distinct((x, y) => x.DT == y.DT).ToList();
                    _data[kvpID] = _data[kvpID].OrderBy(x => x.DT).ToList();
                }
                else
                {
                    //We have nothing on this instrument ID/Frequency combo.
                    //Just add a new entry in the dictionary.
                    _data.Add(kvpID, e.Data);
                }
            }

            //Here we check if all necessary requests have arrived. If they have, do some work.
            lock (_reqCountLock)
            {
                //get the request id of the continuous futures request that caused this contract request
                int cfReqID = _histReqIDMap[e.Request.RequestID];
                _histReqIDMap.Remove(e.Request.RequestID);
                _requestCounts[cfReqID]--;

                if (_requestCounts[cfReqID] == 0)
                {
                    //we have received all the data we asked for
                    _requestCounts.Remove(e.Request.RequestID);
                    HistoricalDataRequest req;
                    lock (_requestsLock)
                    {
                        req = _requests[cfReqID];
                        _requests.Remove(cfReqID);
                    }

                    if (_requestTypes[cfReqID])
                    {
                        //This request originates from a CF data request
                        //so now we want to generate the continuous prices
                        GetContFutData(req);
                    }
                    else
                    {
                        //This request originates from a front contract request
                        Instrument           frontContract = GetContFutData(req, false);
                        FrontContractRequest originalReq   = _frontContractRequestMap[cfReqID];
                        lock (_frontContractReturnLock)
                        {
                            RaiseEvent(FoundFrontContract, this, new FoundFrontContractEventArgs(originalReq.ID, frontContract, originalReq.Date == null ? DateTime.Now : originalReq.Date.Value));
                        }
                    }

                    _requestTypes.Remove(e.Request.AssignedID);
                }
            }
        }
Пример #34
0
        /// <summary>
        /// Finds the front contract for continuous futures with time-based roll.
        /// </summary>
        private void ProcessTimeBasedFrontContractRequest(FrontContractRequest request)
        {
            DateTime currentDate = request.Date ?? DateTime.Now;
            var      cf          = request.Instrument.ContinuousFuture;

            //if the roll-over is time based, we can find the appropriate contract programmatically
            DateTime selectedDate = currentDate;

            while (!cf.MonthIsUsed(selectedDate.Month))
            {
                selectedDate = selectedDate.AddMonths(1);
            }

            DateTime currentMonthsExpirationDate = cf.UnderlyingSymbol.ExpirationDate(selectedDate.Year, selectedDate.Month);
            DateTime switchOverDate = currentMonthsExpirationDate;

            Calendar calendar = MyUtils.GetCalendarFromCountryCode("US");

            //the front contract
            //find the switchover date
            int daysBack = cf.RolloverDays;

            while (daysBack > 0)
            {
                switchOverDate = switchOverDate.AddDays(-1);
                if (calendar.isBusinessDay(switchOverDate))
                {
                    daysBack--;
                }
            }

            //this month's contract has already been switched to the next one
            int monthsLeft = 1;
            int count      = 0;

            if (currentDate >= switchOverDate)
            {
                while (monthsLeft > 0)
                {
                    count++;
                    if (cf.MonthIsUsed(selectedDate.AddMonths(count).Month))
                    {
                        monthsLeft--;
                    }
                }
                selectedDate = selectedDate.AddMonths(count);
            }

            //we found the "front" month, no go back the required number of months
            //while skipping unused months
            monthsLeft = cf.Month - 1;
            count      = 0;
            while (monthsLeft > 0)
            {
                if (cf.MonthIsUsed(selectedDate.AddMonths(count).Month))
                {
                    monthsLeft--;
                }
                count++;
            }
            selectedDate = selectedDate.AddMonths(count);

            string tradingClass = request.Instrument.TradingClass;

            //we got the month we want! find the contract
            Instrument contract = _instrumentRepo.FindInstruments(x => x.Expiration.HasValue &&
                                                                  x.Expiration.Value.Month == selectedDate.Month &&
                                                                  x.Expiration.Value.Year == selectedDate.Year &&
                                                                  x.UnderlyingSymbol == cf.UnderlyingSymbol.Symbol &&
                                                                  (string.IsNullOrEmpty(tradingClass) || x.TradingClass == tradingClass)).Result.FirstOrDefault();

            var timer = new Timer(50)
            {
                AutoReset = false
            };

            timer.Elapsed += (sender, e) =>
            {
                lock (_frontContractReturnLock)
                {
                    RaiseEvent(FoundFrontContract, this, new FoundFrontContractEventArgs(request.ID, contract, currentDate));
                }
            };
            timer.Start();
        }
Пример #35
0
        /// <summary>
        /// Taking a historical data request for a continuous futures instrument,
        /// it returns a list of requests for the underlying contracts that are needed to fulfill it.
        /// </summary>
        private List <HistoricalDataRequest> GetRequiredRequests(HistoricalDataRequest request)
        {
            var requests = new List <HistoricalDataRequest>();

            var cf = request.Instrument.ContinuousFuture;

            var futures = _instrumentRepo.FindInstruments(x =>
                                                          x.UnderlyingSymbol == request.Instrument.ContinuousFuture.UnderlyingSymbol.Symbol &&
                                                          x.Type == InstrumentType.Future &&
                                                          x.DatasourceID == request.Instrument.DatasourceID).Result;


            if (futures == null)
            {
                Log(LogLevel.Error, "CFB: Error in GetRequiredRequests, failed to return any contracts to historical request ID: " + request.AssignedID);
                return(requests);
            }

            //remove any continuous futures
            futures = futures.Where(x => !x.IsContinuousFuture).ToList();

            //order them by ascending expiration date
            futures = futures.OrderBy(x => x.Expiration).ToList();

            //filter the futures months, we may not want all of them.
            for (int i = 1; i <= 12; i++)
            {
                if (cf.MonthIsUsed(i))
                {
                    continue;
                }
                int i1 = i;
                futures = futures.Where(x => x.Expiration.HasValue && x.Expiration.Value.Month != i1).ToList();
            }

            //nothing found, return with empty hands
            if (futures.Count == 0)
            {
                return(requests);
            }

            //the first contract we need is the first one expiring before the start of the request period
            var expiringBeforeStart = futures
                                      .Where(x => x.Expiration != null && x.Expiration.Value < request.StartingDate)
                                      .Select(x => x.Expiration.Value).ToList();

            DateTime firstExpiration =
                expiringBeforeStart.Count > 0
                    ? expiringBeforeStart.Max()
                    : futures.Select(x => x.Expiration.Value).Min();

            futures = futures.Where(x => x.Expiration != null && x.Expiration.Value >= firstExpiration).ToList();

            //I think the last contract we need is the one that is N months after the second contract that expires after the request period end
            //where N is the number of months away from the front contract that the CF uses
            var firstExpAfterEnd = futures.Where(x => x.Expiration > request.EndingDate).ElementAtOrDefault(1);

            if (firstExpAfterEnd != null)
            {
                DateTime limitDate = firstExpAfterEnd.Expiration.Value.AddMonths(request.Instrument.ContinuousFuture.Month - 1);
                futures = futures.Where(x => x.Expiration.Value.Year < limitDate.Year ||
                                        (x.Expiration.Value.Year == limitDate.Year && x.Expiration.Value.Month <= limitDate.Month)).ToList();
            }

            //Make sure each month's contract is allowed only once, even if there are multiple copies in the db
            //Sometimes you might get two versions of the same contract with 1 day difference in expiration date
            //so this step is necessary to clean that up
            futures = futures.Distinct(x => x.Expiration.Value.ToString("yyyyMM").GetHashCode()).ToList();

            //save the number of requests we're gonna make
            lock (_reqCountLock)
            {
                _requestCounts.Add(request.AssignedID, futures.Count);
            }

            //save the contracts used, we need them later
            _contracts.Add(request.AssignedID, futures);

            Log(LogLevel.Info, string.Format("CFB: fulfilling historical request ID {0}, requested data on contracts: {1}",
                                             request.AssignedID,
                                             string.Join(", ", futures.Select(x => x.Symbol))));

            Instrument prevInst = null;

            //request the data for all futures left
            foreach (Instrument i in futures)
            {
                //the question of how much data, exactly, to ask for is complicated...
                //I'm going with: difference of expiration dates (unless it's the first one, in which case 30 days)
                //plus a month
                //plus the CF selected month
                int daysBack = 30;
                if (prevInst == null)
                {
                    daysBack += 30;
                }
                else
                {
                    daysBack += (int)(i.Expiration.Value - prevInst.Expiration.Value).TotalDays;
                }
                daysBack += 30 * cf.Month;

                var endDate = i.Expiration.Value > DateTime.Now.Date ? DateTime.Now.Date : i.Expiration.Value;

                var req = new HistoricalDataRequest(
                    i,
                    request.Frequency,
                    endDate.AddDays(-daysBack),
                    endDate,
                    rthOnly: request.RTHOnly,
                    dataLocation: request.DataLocation == DataLocation.LocalOnly ? DataLocation.LocalOnly : DataLocation.Both);

                requests.Add(req);

                prevInst = i;
            }

            return(requests);
        }
Пример #36
0
        /// <summary>
        ///
        /// </summary>
        /// <returns>The last contract used in the construction of this continuous futures instrument.</returns>
        private Instrument GetContFutData(HistoricalDataRequest request, bool raiseDataEvent = true)
        {
            //copy over the list of contracts that we're gonna be using
            List <Instrument> futures = new List <Instrument>(_contracts[request.AssignedID]);

            //start by cleaning up the data, it is possible that some of the futures may not have had ANY data returned!
            lock (_dataLock)
            {
                futures = futures.Where(x => _data[new KeyValuePair <int, BarSize>(x.ID.Value, request.Frequency)].Count > 0).ToList();
            }

            if (futures.Count == 0)
            {
                Log(LogLevel.Warn, "No data found");

                if (raiseDataEvent)
                {
                    RaiseEvent(HistoricalDataArrived, this, new HistoricalDataEventArgs(request, new List <OHLCBar>()));
                }

                return(null);
            }

            var cf = request.Instrument.ContinuousFuture;

            Instrument frontFuture = futures.FirstOrDefault();
            Instrument backFuture  = futures.ElementAt(1);

            //sometimes the contract will be based on the Xth month
            //this is where we keep track of the actual contract currently being used
            Instrument selectedFuture         = futures.ElementAt(cf.Month - 1);
            Instrument lastUsedSelectedFuture = selectedFuture;

            //final date is the earliest of: the last date of data available, or the request's endingdate
            DateTime lastDateAvailable = new DateTime(1, 1, 1);

            TimeSeries frontData, backData, selectedData;

            lock (_dataLock)
            {
                frontData    = new TimeSeries(_data[new KeyValuePair <int, BarSize>(frontFuture.ID.Value, request.Frequency)]);
                backData     = new TimeSeries(_data[new KeyValuePair <int, BarSize>(backFuture.ID.Value, request.Frequency)]);
                selectedData = new TimeSeries(_data[new KeyValuePair <int, BarSize>(selectedFuture.ID.Value, request.Frequency)]);

                lastDateAvailable = _data[new KeyValuePair <int, BarSize>(futures.Last().ID.Value, request.Frequency)].Last().DT;
            }

            DateTime finalDate = request.EndingDate < lastDateAvailable ? request.EndingDate : lastDateAvailable;

            //This is a super dirty hack to make non-time based rollovers actually work.
            //The reason is that the starting point will otherwise be a LONG time before the date we're interested in.
            //And at that time both the front and back futures are really far from expiration.
            //As such volumes can be wonky, and thus result in a rollover far before we ACTUALLY would
            //want to roll over if we had access to even earlier data.
            DateTime currentDate = frontFuture.Expiration.Value.AddDays(-20 - cf.RolloverDays);

            frontData.AdvanceTo(currentDate);
            backData.AdvanceTo(currentDate);
            selectedData.AdvanceTo(currentDate);

            List <OHLCBar> cfData = new List <OHLCBar>();

            Calendar calendar = MyUtils.GetCalendarFromCountryCode("US");

            bool        switchContract = false;
            int         counter = 0;                               //some rollover rules require multiple consecutive days of greater vol/OI...this keeps track of that
            List <long> frontDailyVolume = new List <long>();      //keeps track of how much volume has occured in each day
            List <int>  frontDailyOpenInterest = new List <int>(); //keeps track of open interest on a daily basis
            List <long> backDailyVolume = new List <long>();
            List <int>  backDailyOpenInterest = new List <int>();
            long        frontTodaysVolume = 0, backTodaysVolume = 0;

            //add the first piece of data we have available, and start looping
            cfData.Add(selectedData[0]);

            //the first time we go from one day to the next we don't want to check for switching conditions
            //because we need to ensure that we use an entire day's worth of volume data.
            bool firstDaySwitchover = true;

            while (currentDate < finalDate)
            {
                //keep track of total volume "today"
                if (frontData[0].Volume.HasValue)
                {
                    frontTodaysVolume += frontData[0].Volume.Value;
                }
                if (backData != null && backData[0].Volume.HasValue)
                {
                    backTodaysVolume += backData[0].Volume.Value;
                }

                if (frontData.CurrentBar > 0 && frontData[0].DT.Day != frontData[1].DT.Day)
                {
                    if (firstDaySwitchover)
                    {
                        firstDaySwitchover = false;
                        frontTodaysVolume  = 0;
                        backTodaysVolume   = 0;
                    }

                    frontDailyVolume.Add(frontTodaysVolume);
                    backDailyVolume.Add(backTodaysVolume);

                    if (frontData[0].OpenInterest.HasValue)
                    {
                        frontDailyOpenInterest.Add(frontData[0].OpenInterest.Value);
                    }
                    if (backData != null && backData[0].OpenInterest.HasValue)
                    {
                        backDailyOpenInterest.Add(backData[0].OpenInterest.Value);
                    }

                    frontTodaysVolume = 0;
                    backTodaysVolume  = 0;

                    //do we need to switch contracts?
                    switch (cf.RolloverType)
                    {
                    case ContinuousFuturesRolloverType.Time:
                        if (MyUtils.BusinessDaysBetween(currentDate, frontFuture.Expiration.Value, calendar) <= cf.RolloverDays)
                        {
                            switchContract = true;
                        }
                        break;

                    case ContinuousFuturesRolloverType.Volume:
                        if (backData != null && backDailyVolume.Last() > frontDailyVolume.Last())
                        {
                            counter++;
                        }
                        else
                        {
                            counter = 0;
                        }
                        switchContract = counter >= cf.RolloverDays;
                        break;

                    case ContinuousFuturesRolloverType.OpenInterest:
                        if (backData != null && backDailyOpenInterest.Last() > frontDailyOpenInterest.Last())
                        {
                            counter++;
                        }
                        else
                        {
                            counter = 0;
                        }
                        switchContract = counter >= cf.RolloverDays;
                        break;

                    case ContinuousFuturesRolloverType.VolumeAndOpenInterest:
                        if (backData != null && backDailyOpenInterest.Last() > frontDailyOpenInterest.Last() &&
                            backDailyVolume.Last() > frontDailyVolume.Last())
                        {
                            counter++;
                        }
                        else
                        {
                            counter = 0;
                        }
                        switchContract = counter >= cf.RolloverDays;
                        break;

                    case ContinuousFuturesRolloverType.VolumeOrOpenInterest:
                        if (backData != null && backDailyOpenInterest.Last() > frontDailyOpenInterest.Last() ||
                            backDailyVolume.Last() > frontDailyVolume.Last())
                        {
                            counter++;
                        }
                        else
                        {
                            counter = 0;
                        }
                        switchContract = counter >= cf.RolloverDays;
                        break;
                    }
                }

                if (frontFuture.Expiration.Value <= currentDate)
                {
                    //no matter what, obviously we need to switch if the contract expires
                    switchContract = true;
                }

                //finally if we have simply run out of data, we're forced to switch
                if (frontData.ReachedEndOfSeries)
                {
                    switchContract = true;
                }

                //finally advance the time and indices...keep moving forward until the selected series has moved
                frontData.NextBar();
                currentDate = frontData[0].DT;
                if (backData != null)
                {
                    backData.AdvanceTo(currentDate);
                }
                selectedData.AdvanceTo(currentDate);

                //this next check here is necessary for the time-based switchover to work after weekends or holidays
                if (cf.RolloverType == ContinuousFuturesRolloverType.Time &&
                    (frontFuture.Expiration.Value < currentDate ||
                     MyUtils.BusinessDaysBetween(currentDate, frontFuture.Expiration.Value, calendar) <= cf.RolloverDays))
                {
                    switchContract = true;
                }

                //we switch to the next contract
                if (switchContract)
                {
                    //make any required price adjustments
                    decimal adjustmentFactor;
                    if (cf.AdjustmentMode == ContinuousFuturesAdjustmentMode.Difference)
                    {
                        adjustmentFactor = backData[0].Close - frontData[0].Close;
                        foreach (OHLCBar bar in cfData)
                        {
                            AdjustBar(bar, adjustmentFactor, cf.AdjustmentMode);
                        }
                    }
                    else if (cf.AdjustmentMode == ContinuousFuturesAdjustmentMode.Ratio)
                    {
                        adjustmentFactor = backData[0].Close / frontData[0].Close;
                        foreach (OHLCBar bar in cfData)
                        {
                            AdjustBar(bar, adjustmentFactor, cf.AdjustmentMode);
                        }
                    }

                    //update the contracts
                    var prevFront = frontFuture;
                    frontFuture = backFuture;
                    backFuture  = futures.FirstOrDefault(x => x.Expiration > backFuture.Expiration);
                    var prevSelected = selectedFuture;
                    selectedFuture = futures.Where(x => x.Expiration >= frontFuture.Expiration).ElementAtOrDefault(cf.Month - 1);

                    Log(LogLevel.Info,
                        string.Format("CFB Filling request for {0}: switching front contract from {1} to {2} (selected contract from {3} to {4}) at {5}",
                                      request.Instrument.Symbol,
                                      prevFront.Symbol,
                                      frontFuture.Symbol,
                                      prevSelected.Symbol,
                                      selectedFuture == null
                            ? ""
                            : selectedFuture.Symbol,
                                      currentDate.ToString("yyyy-MM-dd")));

                    if (frontFuture == null)
                    {
                        break;                      //no other futures left, get out
                    }
                    if (selectedFuture == null)
                    {
                        break;
                    }

                    lock (_dataLock)
                    {
                        frontData    = new TimeSeries(_data[new KeyValuePair <int, BarSize>(frontFuture.ID.Value, request.Frequency)]);
                        backData     = backFuture != null ? new TimeSeries(_data[new KeyValuePair <int, BarSize>(backFuture.ID.Value, request.Frequency)]) : null;
                        selectedData = new TimeSeries(_data[new KeyValuePair <int, BarSize>(selectedFuture.ID.Value, request.Frequency)]);
                    }

                    frontData.AdvanceTo(currentDate);
                    if (backData != null)
                    {
                        backData.AdvanceTo(currentDate);
                    }
                    selectedData.AdvanceTo(currentDate);

                    //TODO make sure that the data series actually cover the current date

                    switchContract         = false;
                    lastUsedSelectedFuture = selectedFuture;
                }

                cfData.Add(selectedData[0]);
            }

            //clean up
            _contracts.Remove(request.AssignedID);

            //throw out any data from before the start of the request
            cfData = cfData.Where(x => x.DT >= request.StartingDate && x.DT <= request.EndingDate).ToList();

            //we're done, so just raise the event
            if (raiseDataEvent)
            {
                RaiseEvent(HistoricalDataArrived, this, new HistoricalDataEventArgs(request, cfData));
            }

            //clean up some data!
            lock (_dataUsesLock)
            {
                foreach (Instrument i in futures)
                {
                    var kvp = new KeyValuePair <int, BarSize>(i.ID.Value, request.Frequency);
                    if (_dataUsesPending[kvp] == 1) //this data isn't needed anywhere else, we can delete it
                    {
                        _dataUsesPending.Remove(kvp);
                        lock (_dataLock)
                        {
                            _data.Remove(kvp);
                        }
                    }
                    else
                    {
                        _dataUsesPending[kvp]--;
                    }
                }
            }

            return(lastUsedSelectedFuture);
        }