public IEnumerable <TimeSlice> GetTimeSlices() { var bars = new TradeBars(); var quotes = new QuoteBars(); var ticks = new Ticks(); var options = new OptionChains(); var futures = new FuturesChains(); var splits = new Splits(); var dividends = new Dividends(); var delistings = new Delistings(); var symbolChanges = new SymbolChangedEvents(); var dataFeedPackets = new List <DataFeedPacket>(); var cashUpdateData = new List <UpdateData <Cash> >(); var customData = new List <UpdateData <Security> >(); var changes = SecurityChanges.None; do { var slice = new Slice(default(DateTime), _data, bars, quotes, ticks, options, futures, splits, dividends, delistings, symbolChanges); var timeSlice = new TimeSlice(_frontierUtc, _data.Count, slice, dataFeedPackets, cashUpdateData, securitiesUpdateData, _consolidatorUpdateData, customData, changes); yield return(timeSlice); _frontierUtc += FrontierStepSize; }while (_frontierUtc <= _endTimeUtc); }
/// <summary> /// Merge two slice with same Time /// </summary> /// <param name="inputSlice">slice instance</param> /// <remarks> Will change the input collection for re-use</remarks> public void MergeSlice(Slice inputSlice) { if (UtcTime != inputSlice.UtcTime) { throw new InvalidOperationException($"Slice with time {UtcTime} can't be merged with given slice with different {inputSlice.UtcTime}"); } _bars = (TradeBars)UpdateCollection(_bars, inputSlice.Bars); _quoteBars = (QuoteBars)UpdateCollection(_quoteBars, inputSlice.QuoteBars); _ticks = (Ticks)UpdateCollection(_ticks, inputSlice.Ticks); _optionChains = (OptionChains)UpdateCollection(_optionChains, inputSlice.OptionChains); _futuresChains = (FuturesChains)UpdateCollection(_futuresChains, inputSlice.FuturesChains); _splits = (Splits)UpdateCollection(_splits, inputSlice.Splits); _dividends = (Dividends)UpdateCollection(_dividends, inputSlice.Dividends); _delistings = (Delistings)UpdateCollection(_delistings, inputSlice.Delistings); _symbolChangedEvents = (SymbolChangedEvents)UpdateCollection(_symbolChangedEvents, inputSlice.SymbolChangedEvents); if (inputSlice._rawDataList.Count != 0) { if (_rawDataList.Count == 0) { _rawDataList = inputSlice._rawDataList; _data = inputSlice._data; } else { // Should keep this._rawDataList last so that selected data points are not overriden // while creating _data inputSlice._rawDataList.AddRange(_rawDataList); _rawDataList = inputSlice._rawDataList; _data = new Lazy <DataDictionary <SymbolData> >(() => CreateDynamicDataDictionary(_rawDataList)); } } }
public Slice(DateTime time, IEnumerable <BaseData> data, TradeBars tradeBars, QuoteBars quoteBars, Ticks ticks, OptionChains optionChains, Splits splits, Dividends dividends, Delistings delistings, SymbolChangedEvents symbolChanges, bool?hasData = null) { Time = time; _dataByType = new Dictionary <Type, Lazy <object> >(); _data = new Lazy <DataDictionary <SymbolData> >(() => CreateDynamicDataDictionary(data)); HasData = hasData ?? _data.Value.Count > 0; _ticks = CreateTicksCollection(ticks); _bars = CreateCollection <TradeBars, TradeBar>(tradeBars); _quoteBars = CreateCollection <QuoteBars, QuoteBar>(quoteBars); _optionChains = CreateCollection <OptionChains, OptionChain>(optionChains); _splits = CreateCollection <Splits, Split>(splits); _dividends = CreateCollection <Dividends, Dividend>(dividends); _delistings = CreateCollection <Delistings, Delisting>(delistings); _symbolChangedEvents = CreateCollection <SymbolChangedEvents, SymbolChangedEvent>(symbolChanges); }
/// <summary> /// Initializes a new instance of the <see cref="Slice"/> class /// </summary> /// <param name="time">The timestamp for this slice of data</param> /// <param name="data">The raw data in this slice</param> /// <param name="tradeBars">The trade bars for this slice</param> /// <param name="ticks">This ticks for this slice</param> /// <param name="splits">The splits for this slice</param> /// <param name="dividends">The dividends for this slice</param> /// <param name="delistings">The delistings for this slice</param> /// <param name="symbolChanges">The symbol changed events for this slice</param> public Slice(DateTime time, IEnumerable <BaseData> data, TradeBars tradeBars, Ticks ticks, Splits splits, Dividends dividends, Delistings delistings, SymbolChangedEvents symbolChanges) { Time = time; _dataByType = new Dictionary <Type, Lazy <object> >(); // market data _data = CreateDynamicDataDictionary(data); _ticks = CreateTicksCollection(ticks); _bars = CreateCollection <TradeBars, TradeBar>(tradeBars); // auxiliary data _splits = CreateCollection <Splits, Split>(splits); _dividends = CreateCollection <Dividends, Dividend>(dividends); _delistings = CreateCollection <Delistings, Delisting>(delistings); _symbolChangedEvents = CreateCollection <SymbolChangedEvents, SymbolChangedEvent>(symbolChanges); }
/// <summary> /// Initializes a new instance of the <see cref="Slice"/> class /// </summary> /// <param name="time">The timestamp for this slice of data</param> /// <param name="data">The raw data in this slice</param> /// <param name="tradeBars">The trade bars for this slice</param> /// <param name="quoteBars">The quote bars for this slice</param> /// <param name="ticks">This ticks for this slice</param> /// <param name="optionChains">The option chains for this slice</param> /// <param name="futuresChains">The futures chains for this slice</param> /// <param name="splits">The splits for this slice</param> /// <param name="dividends">The dividends for this slice</param> /// <param name="delistings">The delistings for this slice</param> /// <param name="symbolChanges">The symbol changed events for this slice</param> /// <param name="hasData">true if this slice contains data</param> public Slice(DateTime time, IEnumerable <BaseData> data, TradeBars tradeBars, QuoteBars quoteBars, Ticks ticks, OptionChains optionChains, FuturesChains futuresChains, Splits splits, Dividends dividends, Delistings delistings, SymbolChangedEvents symbolChanges, bool?hasData = null) { Time = time; // market data _data = new Lazy <DataDictionary <SymbolData> >(() => CreateDynamicDataDictionary(data)); HasData = hasData ?? _data.Value.Count > 0; _ticks = ticks; _bars = tradeBars; _quoteBars = quoteBars; _optionChains = optionChains; _futuresChains = futuresChains; // auxiliary data _splits = splits; _dividends = dividends; _delistings = delistings; _symbolChangedEvents = symbolChanges; }
/// <summary> /// Initializes a new instance used by the <see cref="PythonSlice"/> /// </summary> /// <param name="slice">slice object to wrap</param> /// <remarks>This is required so that python slice enumeration works correctly since it relies on the private <see cref="_data"/> collection</remarks> protected Slice(Slice slice) { Time = slice.Time; _dataByType = slice._dataByType; _data = slice._data; HasData = slice.HasData; _ticks = slice._ticks; _bars = slice._bars; _quoteBars = slice._quoteBars; _optionChains = slice._optionChains; _futuresChains = slice._futuresChains; // auxiliary data _splits = slice._splits; _dividends = slice._dividends; _delistings = slice._delistings; _symbolChangedEvents = slice._symbolChangedEvents; }
/// <summary> /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data /// </summary> /// <param name="utcDateTime">The UTC frontier date time</param> /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param> /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param> /// <param name="data">The data in this <see cref="TimeSlice"/></param> /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param> /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns> public static TimeSlice Create(DateTime utcDateTime, DateTimeZone algorithmTimeZone, CashBook cashBook, List <DataFeedPacket> data, SecurityChanges changes) { int count = 0; var security = new List <UpdateData <Security> >(); var custom = new List <UpdateData <Security> >(); var consolidator = new List <UpdateData <SubscriptionDataConfig> >(); var allDataForAlgorithm = new List <BaseData>(data.Count); var cash = new List <UpdateData <Cash> >(cashBook.Count); var cashSecurities = new HashSet <Symbol>(); foreach (var cashItem in cashBook.Values) { cashSecurities.Add(cashItem.SecuritySymbol); } Split split; Dividend dividend; Delisting delisting; SymbolChangedEvent symbolChange; // we need to be able to reference the slice being created in order to define the // evaluation of option price models, so we define a 'future' that can be referenced // in the option price model evaluation delegates for each contract Slice slice = null; var sliceFuture = new Lazy <Slice>(() => slice); var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone); var tradeBars = new TradeBars(algorithmTime); var quoteBars = new QuoteBars(algorithmTime); var ticks = new Ticks(algorithmTime); var splits = new Splits(algorithmTime); var dividends = new Dividends(algorithmTime); var delistings = new Delistings(algorithmTime); var optionChains = new OptionChains(algorithmTime); var futuresChains = new FuturesChains(algorithmTime); var symbolChanges = new SymbolChangedEvents(algorithmTime); foreach (var packet in data) { var list = packet.Data; var symbol = packet.Security.Symbol; if (list.Count == 0) { continue; } // keep count of all data points if (list.Count == 1 && list[0] is BaseDataCollection) { var baseDataCollectionCount = ((BaseDataCollection)list[0]).Data.Count; if (baseDataCollectionCount == 0) { continue; } count += baseDataCollectionCount; } else { count += list.Count; } if (!packet.Configuration.IsInternalFeed && packet.Configuration.IsCustomData) { // This is all the custom data custom.Add(new UpdateData <Security>(packet.Security, packet.Configuration.Type, list)); } var securityUpdate = new List <BaseData>(list.Count); var consolidatorUpdate = new List <BaseData>(list.Count); for (int i = 0; i < list.Count; i++) { var baseData = list[i]; if (!packet.Configuration.IsInternalFeed) { // this is all the data that goes into the algorithm allDataForAlgorithm.Add(baseData); } // don't add internal feed data to ticks/bars objects if (baseData.DataType != MarketDataType.Auxiliary) { if (!packet.Configuration.IsInternalFeed) { PopulateDataDictionaries(baseData, ticks, tradeBars, quoteBars, optionChains, futuresChains); // special handling of options data to build the option chain if (packet.Security.Type == SecurityType.Option) { if (baseData.DataType == MarketDataType.OptionChain) { optionChains[baseData.Symbol] = (OptionChain)baseData; } else if (!HandleOptionData(algorithmTime, baseData, optionChains, packet.Security, sliceFuture)) { continue; } } // special handling of futures data to build the futures chain if (packet.Security.Type == SecurityType.Future) { if (baseData.DataType == MarketDataType.FuturesChain) { futuresChains[baseData.Symbol] = (FuturesChain)baseData; } else if (!HandleFuturesData(algorithmTime, baseData, futuresChains, packet.Security)) { continue; } } // this is data used to update consolidators consolidatorUpdate.Add(baseData); } // this is the data used set market prices // do not add it if it is a Suspicious tick var tick = baseData as Tick; if (tick != null && tick.Suspicious) { continue; } securityUpdate.Add(baseData); } // include checks for various aux types so we don't have to construct the dictionaries in Slice else if ((delisting = baseData as Delisting) != null) { delistings[symbol] = delisting; } else if ((dividend = baseData as Dividend) != null) { dividends[symbol] = dividend; } else if ((split = baseData as Split) != null) { splits[symbol] = split; } else if ((symbolChange = baseData as SymbolChangedEvent) != null) { // symbol changes is keyed by the requested symbol symbolChanges[packet.Configuration.Symbol] = symbolChange; } } if (securityUpdate.Count > 0) { // check for 'cash securities' if we found valid update data for this symbol // and we need this data to update cash conversion rates, long term we should // have Cash hold onto it's security, then he can update himself, or rather, just // patch through calls to conversion rate to compue it on the fly using Security.Price if (cashSecurities.Contains(packet.Security.Symbol)) { foreach (var cashKvp in cashBook) { if (cashKvp.Value.SecuritySymbol == packet.Security.Symbol) { var cashUpdates = new List <BaseData> { securityUpdate[securityUpdate.Count - 1] }; cash.Add(new UpdateData <Cash>(cashKvp.Value, packet.Configuration.Type, cashUpdates)); } } } security.Add(new UpdateData <Security>(packet.Security, packet.Configuration.Type, securityUpdate)); } if (consolidatorUpdate.Count > 0) { consolidator.Add(new UpdateData <SubscriptionDataConfig>(packet.Configuration, packet.Configuration.Type, consolidatorUpdate)); } } slice = new Slice(algorithmTime, allDataForAlgorithm, tradeBars, quoteBars, ticks, optionChains, futuresChains, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0); return(new TimeSlice(utcDateTime, count, slice, data, cash, security, consolidator, custom, changes)); }
/// <summary> /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data /// </summary> /// <param name="utcDateTime">The UTC frontier date time</param> /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param> /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param> /// <param name="data">The data in this <see cref="TimeSlice"/></param> /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param> /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns> public static TimeSlice Create(DateTime utcDateTime, DateTimeZone algorithmTimeZone, CashBook cashBook, List<KeyValuePair<Security, List<BaseData>>> data, SecurityChanges changes) { int count = 0; var security = new List<KeyValuePair<Security, BaseData>>(); var custom = new List<KeyValuePair<Security, List<BaseData>>>(); var consolidator = new List<KeyValuePair<SubscriptionDataConfig, List<BaseData>>>(); var allDataForAlgorithm = new List<BaseData>(data.Count); var cash = new List<KeyValuePair<Cash, BaseData>>(cashBook.Count); var cashSecurities = new HashSet<Symbol>(); foreach (var cashItem in cashBook.Values) { cashSecurities.Add(cashItem.SecuritySymbol); } Split split; Dividend dividend; Delisting delisting; SymbolChangedEvent symbolChange; var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone); var tradeBars = new TradeBars(algorithmTime); var ticks = new Ticks(algorithmTime); var splits = new Splits(algorithmTime); var dividends = new Dividends(algorithmTime); var delistings = new Delistings(algorithmTime); var symbolChanges = new SymbolChangedEvents(algorithmTime); foreach (var kvp in data) { var list = kvp.Value; var symbol = kvp.Key.Symbol; // keep count of all data points if (list.Count == 1 && list[0] is BaseDataCollection) { count += ((BaseDataCollection) list[0]).Data.Count; } else { count += list.Count; } BaseData update = null; var consolidatorUpdate = new List<BaseData>(list.Count); for (int i = 0; i < list.Count; i++) { var baseData = list[i]; if (!kvp.Key.SubscriptionDataConfig.IsInternalFeed) { // this is all the data that goes into the algorithm allDataForAlgorithm.Add(baseData); if (kvp.Key.SubscriptionDataConfig.IsCustomData) { // this is all the custom data custom.Add(kvp); } } // don't add internal feed data to ticks/bars objects if (baseData.DataType != MarketDataType.Auxiliary) { if (!kvp.Key.SubscriptionDataConfig.IsInternalFeed) { // populate ticks and tradebars dictionaries with no aux data if (baseData.DataType == MarketDataType.Tick) { List<Tick> ticksList; if (!ticks.TryGetValue(symbol, out ticksList)) { ticksList = new List<Tick> {(Tick) baseData}; ticks[symbol] = ticksList; } ticksList.Add((Tick) baseData); } else if (baseData.DataType == MarketDataType.TradeBar) { tradeBars[symbol] = (TradeBar) baseData; } // this is data used to update consolidators consolidatorUpdate.Add(baseData); } // this is the data used set market prices update = baseData; } // include checks for various aux types so we don't have to construct the dictionaries in Slice else if ((delisting = baseData as Delisting) != null) { delistings[symbol] = delisting; } else if ((dividend = baseData as Dividend) != null) { dividends[symbol] = dividend; } else if ((split = baseData as Split) != null) { splits[symbol] = split; } else if ((symbolChange = baseData as SymbolChangedEvent) != null) { // symbol changes is keyed by the requested symbol symbolChanges[kvp.Key.SubscriptionDataConfig.Symbol] = symbolChange; } } // check for 'cash securities' if we found valid update data for this symbol // and we need this data to update cash conversion rates, long term we should // have Cash hold onto it's security, then he can update himself, or rather, just // patch through calls to conversion rate to compue it on the fly using Security.Price if (update != null && cashSecurities.Contains(kvp.Key.Symbol)) { foreach (var cashKvp in cashBook) { if (cashKvp.Value.SecuritySymbol == kvp.Key.Symbol) { cash.Add(new KeyValuePair<Cash, BaseData>(cashKvp.Value, update)); } } } security.Add(new KeyValuePair<Security, BaseData>(kvp.Key, update)); consolidator.Add(new KeyValuePair<SubscriptionDataConfig, List<BaseData>>(kvp.Key.SubscriptionDataConfig, consolidatorUpdate)); } var slice = new Slice(utcDateTime.ConvertFromUtc(algorithmTimeZone), allDataForAlgorithm, tradeBars, ticks, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0); return new TimeSlice(utcDateTime, count, slice, data, cash, security, consolidator, custom, changes); }
/// <summary> /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data /// </summary> /// <param name="utcDateTime">The UTC frontier date time</param> /// <param name="data">The data in this <see cref="TimeSlice"/></param> /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param> /// <param name="universeData"></param> /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns> public TimeSlice Create(DateTime utcDateTime, List <DataFeedPacket> data, SecurityChanges changes, Dictionary <Universe, BaseDataCollection> universeData) { int count = 0; var security = new List <UpdateData <ISecurityPrice> >(data.Count); List <UpdateData <ISecurityPrice> > custom = null; var consolidator = new List <UpdateData <SubscriptionDataConfig> >(data.Count); var allDataForAlgorithm = new List <BaseData>(data.Count); var optionUnderlyingUpdates = new Dictionary <Symbol, BaseData>(); Split split; Dividend dividend; Delisting delisting; SymbolChangedEvent symbolChange; // we need to be able to reference the slice being created in order to define the // evaluation of option price models, so we define a 'future' that can be referenced // in the option price model evaluation delegates for each contract Slice slice = null; var sliceFuture = new Lazy <Slice>(() => slice); var algorithmTime = utcDateTime.ConvertFromUtc(_timeZone); TradeBars tradeBars = null; QuoteBars quoteBars = null; Ticks ticks = null; Splits splits = null; Dividends dividends = null; Delistings delistings = null; OptionChains optionChains = null; FuturesChains futuresChains = null; SymbolChangedEvents symbolChanges = null; UpdateEmptyCollections(algorithmTime); if (universeData.Count > 0) { // count universe data foreach (var kvp in universeData) { count += kvp.Value.Data.Count; } } // ensure we read equity data before option data, so we can set the current underlying price foreach (var packet in data) { // filter out packets for removed subscriptions if (packet.IsSubscriptionRemoved) { continue; } var list = packet.Data; var symbol = packet.Configuration.Symbol; if (list.Count == 0) { continue; } // keep count of all data points if (list.Count == 1 && list[0] is BaseDataCollection) { var baseDataCollectionCount = ((BaseDataCollection)list[0]).Data.Count; if (baseDataCollectionCount == 0) { continue; } count += baseDataCollectionCount; } else { count += list.Count; } if (!packet.Configuration.IsInternalFeed && packet.Configuration.IsCustomData) { if (custom == null) { custom = new List <UpdateData <ISecurityPrice> >(1); } // This is all the custom data custom.Add(new UpdateData <ISecurityPrice>(packet.Security, packet.Configuration.Type, list, packet.Configuration.IsInternalFeed)); } var securityUpdate = new List <BaseData>(list.Count); var consolidatorUpdate = new List <BaseData>(list.Count); var containsFillForwardData = false; for (var i = 0; i < list.Count; i++) { var baseData = list[i]; if (!packet.Configuration.IsInternalFeed) { // this is all the data that goes into the algorithm allDataForAlgorithm.Add(baseData); } containsFillForwardData |= baseData.IsFillForward; // don't add internal feed data to ticks/bars objects if (baseData.DataType != MarketDataType.Auxiliary) { var tick = baseData as Tick; if (!packet.Configuration.IsInternalFeed) { // populate data dictionaries switch (baseData.DataType) { case MarketDataType.Tick: if (ticks == null) { ticks = new Ticks(algorithmTime); } ticks.Add(baseData.Symbol, (Tick)baseData); break; case MarketDataType.TradeBar: if (tradeBars == null) { tradeBars = new TradeBars(algorithmTime); } var newTradeBar = (TradeBar)baseData; TradeBar existingTradeBar; // if we have an existing bar keep the highest resolution one // e.g Hour and Minute resolution subscriptions for the same symbol // see CustomUniverseWithBenchmarkRegressionAlgorithm if (!tradeBars.TryGetValue(baseData.Symbol, out existingTradeBar) || existingTradeBar.Period > newTradeBar.Period) { tradeBars[baseData.Symbol] = newTradeBar; } break; case MarketDataType.QuoteBar: if (quoteBars == null) { quoteBars = new QuoteBars(algorithmTime); } var newQuoteBar = (QuoteBar)baseData; QuoteBar existingQuoteBar; // if we have an existing bar keep the highest resolution one // e.g Hour and Minute resolution subscriptions for the same symbol // see CustomUniverseWithBenchmarkRegressionAlgorithm if (!quoteBars.TryGetValue(baseData.Symbol, out existingQuoteBar) || existingQuoteBar.Period > newQuoteBar.Period) { quoteBars[baseData.Symbol] = newQuoteBar; } break; case MarketDataType.OptionChain: if (optionChains == null) { optionChains = new OptionChains(algorithmTime); } optionChains[baseData.Symbol] = (OptionChain)baseData; break; case MarketDataType.FuturesChain: if (futuresChains == null) { futuresChains = new FuturesChains(algorithmTime); } futuresChains[baseData.Symbol] = (FuturesChain)baseData; break; } // this is data used to update consolidators // do not add it if it is a Suspicious tick if (tick == null || !tick.Suspicious) { consolidatorUpdate.Add(baseData); } } // special handling of options data to build the option chain if (symbol.SecurityType.IsOption()) { // internal feeds, like open interest, will not create the chain but will update it if it exists // this is because the open interest could arrive at some closed market hours in which there is no other data and we don't // want to generate a chain object in this case if (optionChains == null && !packet.Configuration.IsInternalFeed) { optionChains = new OptionChains(algorithmTime); } if (baseData.DataType == MarketDataType.OptionChain) { optionChains[baseData.Symbol] = (OptionChain)baseData; } else if (optionChains != null && !HandleOptionData(algorithmTime, baseData, optionChains, packet.Security, sliceFuture, optionUnderlyingUpdates)) { continue; } } // special handling of futures data to build the futures chain if (symbol.SecurityType == SecurityType.Future) { // internal feeds, like open interest, will not create the chain but will update it if it exists // this is because the open interest could arrive at some closed market hours in which there is no other data and we don't // want to generate a chain object in this case if (futuresChains == null && !packet.Configuration.IsInternalFeed) { futuresChains = new FuturesChains(algorithmTime); } if (baseData.DataType == MarketDataType.FuturesChain) { futuresChains[baseData.Symbol] = (FuturesChain)baseData; } else if (futuresChains != null && !HandleFuturesData(algorithmTime, baseData, futuresChains, packet.Security)) { continue; } } // this is the data used set market prices // do not add it if it is a Suspicious tick if (tick != null && tick.Suspicious) { continue; } securityUpdate.Add(baseData); // option underlying security update if (!packet.Configuration.IsInternalFeed) { optionUnderlyingUpdates[symbol] = baseData; } } else if (!packet.Configuration.IsInternalFeed) { // include checks for various aux types so we don't have to construct the dictionaries in Slice if ((delisting = baseData as Delisting) != null) { if (delistings == null) { delistings = new Delistings(algorithmTime); } delistings[symbol] = delisting; } else if ((dividend = baseData as Dividend) != null) { if (dividends == null) { dividends = new Dividends(algorithmTime); } dividends[symbol] = dividend; } else if ((split = baseData as Split) != null) { if (splits == null) { splits = new Splits(algorithmTime); } splits[symbol] = split; } else if ((symbolChange = baseData as SymbolChangedEvent) != null) { if (symbolChanges == null) { symbolChanges = new SymbolChangedEvents(algorithmTime); } // symbol changes is keyed by the requested symbol symbolChanges[packet.Configuration.Symbol] = symbolChange; } } } if (securityUpdate.Count > 0) { security.Add(new UpdateData <ISecurityPrice>(packet.Security, packet.Configuration.Type, securityUpdate, packet.Configuration.IsInternalFeed, containsFillForwardData)); } if (consolidatorUpdate.Count > 0) { consolidator.Add(new UpdateData <SubscriptionDataConfig>(packet.Configuration, packet.Configuration.Type, consolidatorUpdate, packet.Configuration.IsInternalFeed, containsFillForwardData)); } } slice = new Slice(algorithmTime, allDataForAlgorithm, tradeBars ?? _emptyTradeBars, quoteBars ?? _emptyQuoteBars, ticks ?? _emptyTicks, optionChains ?? _emptyOptionChains, futuresChains ?? _emptyFuturesChains, splits ?? _emptySplits, dividends ?? _emptyDividends, delistings ?? _emptyDelistings, symbolChanges ?? _emptySymbolChangedEvents, allDataForAlgorithm.Count > 0); return(new TimeSlice(utcDateTime, count, slice, data, security, consolidator, custom ?? _emptyCustom, changes, universeData)); }
/// <summary> /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data /// </summary> /// <param name="utcDateTime">The UTC frontier date time</param> /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param> /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param> /// <param name="data">The data in this <see cref="TimeSlice"/></param> /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param> /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns> public static TimeSlice Create(DateTime utcDateTime, DateTimeZone algorithmTimeZone, CashBook cashBook, List <DataFeedPacket> data, SecurityChanges changes) { int count = 0; var security = new List <KeyValuePair <Security, BaseData> >(); var custom = new List <KeyValuePair <Security, IEnumerable <BaseData> > >(); var consolidator = new List <KeyValuePair <SubscriptionDataConfig, List <BaseData> > >(); var allDataForAlgorithm = new List <BaseData>(data.Count); var cash = new List <KeyValuePair <Cash, BaseData> >(cashBook.Count); var cashSecurities = new HashSet <Symbol>(); foreach (var cashItem in cashBook.Values) { cashSecurities.Add(cashItem.SecuritySymbol); } Split split; Dividend dividend; Delisting delisting; SymbolChangedEvent symbolChange; var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone); var tradeBars = new TradeBars(algorithmTime); var ticks = new Ticks(algorithmTime); var splits = new Splits(algorithmTime); var dividends = new Dividends(algorithmTime); var delistings = new Delistings(algorithmTime); var symbolChanges = new SymbolChangedEvents(algorithmTime); foreach (var packet in data) { var list = packet.Data; var symbol = packet.Security.Symbol; // keep count of all data points if (list.Count == 1 && list[0] is BaseDataCollection) { count += ((BaseDataCollection)list[0]).Data.Count; } else { count += list.Count; } BaseData update = null; var consolidatorUpdate = new List <BaseData>(list.Count); for (int i = 0; i < list.Count; i++) { var baseData = list[i]; if (!packet.Security.SubscriptionDataConfig.IsInternalFeed) { // this is all the data that goes into the algorithm allDataForAlgorithm.Add(baseData); if (packet.Security.SubscriptionDataConfig.IsCustomData) { // this is all the custom data custom.Add(new KeyValuePair <Security, IEnumerable <BaseData> >(packet.Security, list)); } } // don't add internal feed data to ticks/bars objects if (baseData.DataType != MarketDataType.Auxiliary) { if (!packet.Security.SubscriptionDataConfig.IsInternalFeed) { // populate ticks and tradebars dictionaries with no aux data switch (baseData.DataType) { case MarketDataType.Tick: List <Tick> ticksList; if (!ticks.TryGetValue(symbol, out ticksList)) { ticksList = new List <Tick> { (Tick)baseData }; ticks[symbol] = ticksList; } ticksList.Add((Tick)baseData); break; case MarketDataType.TradeBar: tradeBars[symbol] = (TradeBar)baseData; break; } // this is data used to update consolidators consolidatorUpdate.Add(baseData); } // this is the data used set market prices update = baseData; } // include checks for various aux types so we don't have to construct the dictionaries in Slice else if ((delisting = baseData as Delisting) != null) { delistings[symbol] = delisting; } else if ((dividend = baseData as Dividend) != null) { dividends[symbol] = dividend; } else if ((split = baseData as Split) != null) { splits[symbol] = split; } else if ((symbolChange = baseData as SymbolChangedEvent) != null) { // symbol changes is keyed by the requested symbol symbolChanges[packet.Security.SubscriptionDataConfig.Symbol] = symbolChange; } } // check for 'cash securities' if we found valid update data for this symbol // and we need this data to update cash conversion rates, long term we should // have Cash hold onto it's security, then he can update himself, or rather, just // patch through calls to conversion rate to compue it on the fly using Security.Price if (update != null && cashSecurities.Contains(packet.Security.Symbol)) { foreach (var cashKvp in cashBook) { if (cashKvp.Value.SecuritySymbol == packet.Security.Symbol) { cash.Add(new KeyValuePair <Cash, BaseData>(cashKvp.Value, update)); } } } security.Add(new KeyValuePair <Security, BaseData>(packet.Security, update)); consolidator.Add(new KeyValuePair <SubscriptionDataConfig, List <BaseData> >(packet.Security.SubscriptionDataConfig, consolidatorUpdate)); } var slice = new Slice(algorithmTime, allDataForAlgorithm, tradeBars, ticks, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0); return(new TimeSlice(utcDateTime, count, slice, data, cash, security, consolidator, custom, changes)); }
/// <summary> /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data /// </summary> /// <param name="utcDateTime">The UTC frontier date time</param> /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param> /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param> /// <param name="data">The data in this <see cref="TimeSlice"/></param> /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param> /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns> public static TimeSlice Create(DateTime utcDateTime, DateTimeZone algorithmTimeZone, CashBook cashBook, List<DataFeedPacket> data, SecurityChanges changes) { int count = 0; var security = new List<UpdateData<Security>>(); var custom = new List<UpdateData<Security>>(); var consolidator = new List<UpdateData<SubscriptionDataConfig>>(); var allDataForAlgorithm = new List<BaseData>(data.Count); var cash = new List<UpdateData<Cash>>(cashBook.Count); var cashSecurities = new HashSet<Symbol>(); foreach (var cashItem in cashBook.Values) { cashSecurities.Add(cashItem.SecuritySymbol); } Split split; Dividend dividend; Delisting delisting; SymbolChangedEvent symbolChange; // we need to be able to reference the slice being created in order to define the // evaluation of option price models, so we define a 'future' that can be referenced // in the option price model evaluation delegates for each contract Slice slice = null; var sliceFuture = new Lazy<Slice>(() => slice); var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone); var tradeBars = new TradeBars(algorithmTime); var quoteBars = new QuoteBars(algorithmTime); var ticks = new Ticks(algorithmTime); var splits = new Splits(algorithmTime); var dividends = new Dividends(algorithmTime); var delistings = new Delistings(algorithmTime); var optionChains = new OptionChains(algorithmTime); var symbolChanges = new SymbolChangedEvents(algorithmTime); foreach (var packet in data) { var list = packet.Data; var symbol = packet.Security.Symbol; if (list.Count == 0) continue; // keep count of all data points if (list.Count == 1 && list[0] is BaseDataCollection) { var baseDataCollectionCount = ((BaseDataCollection)list[0]).Data.Count; if (baseDataCollectionCount == 0) { continue; } count += baseDataCollectionCount; } else { count += list.Count; } if (!packet.Configuration.IsInternalFeed && packet.Configuration.IsCustomData) { // This is all the custom data custom.Add(new UpdateData<Security>(packet.Security, packet.Configuration.Type, list)); } var securityUpdate = new List<BaseData>(list.Count); var consolidatorUpdate = new List<BaseData>(list.Count); for (int i = 0; i < list.Count; i++) { var baseData = list[i]; if (!packet.Configuration.IsInternalFeed) { // this is all the data that goes into the algorithm allDataForAlgorithm.Add(baseData); } // don't add internal feed data to ticks/bars objects if (baseData.DataType != MarketDataType.Auxiliary) { if (!packet.Configuration.IsInternalFeed) { PopulateDataDictionaries(baseData, ticks, tradeBars, quoteBars, optionChains); // special handling of options data to build the option chain if (packet.Security.Type == SecurityType.Option) { if (baseData.DataType == MarketDataType.OptionChain) { optionChains[baseData.Symbol] = (OptionChain) baseData; } else if (!HandleOptionData(algorithmTime, baseData, optionChains, packet.Security, sliceFuture)) { continue; } } // this is data used to update consolidators consolidatorUpdate.Add(baseData); } // this is the data used set market prices securityUpdate.Add(baseData); } // include checks for various aux types so we don't have to construct the dictionaries in Slice else if ((delisting = baseData as Delisting) != null) { delistings[symbol] = delisting; } else if ((dividend = baseData as Dividend) != null) { dividends[symbol] = dividend; } else if ((split = baseData as Split) != null) { splits[symbol] = split; } else if ((symbolChange = baseData as SymbolChangedEvent) != null) { // symbol changes is keyed by the requested symbol symbolChanges[packet.Configuration.Symbol] = symbolChange; } } if (securityUpdate.Count > 0) { // check for 'cash securities' if we found valid update data for this symbol // and we need this data to update cash conversion rates, long term we should // have Cash hold onto it's security, then he can update himself, or rather, just // patch through calls to conversion rate to compue it on the fly using Security.Price if (cashSecurities.Contains(packet.Security.Symbol)) { foreach (var cashKvp in cashBook) { if (cashKvp.Value.SecuritySymbol == packet.Security.Symbol) { var cashUpdates = new List<BaseData> {securityUpdate[securityUpdate.Count - 1]}; cash.Add(new UpdateData<Cash>(cashKvp.Value, packet.Configuration.Type, cashUpdates)); } } } security.Add(new UpdateData<Security>(packet.Security, packet.Configuration.Type, securityUpdate)); } if (consolidatorUpdate.Count > 0) { consolidator.Add(new UpdateData<SubscriptionDataConfig>(packet.Configuration, packet.Configuration.Type, consolidatorUpdate)); } } slice = new Slice(algorithmTime, allDataForAlgorithm, tradeBars, quoteBars, ticks, optionChains, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0); return new TimeSlice(utcDateTime, count, slice, data, cash, security, consolidator, custom, changes); }
/// <summary> /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data /// </summary> /// <param name="utcDateTime">The UTC frontier date time</param> /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param> /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param> /// <param name="data">The data in this <see cref="TimeSlice"/></param> /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param> /// <param name="universeData"></param> /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns> public static TimeSlice Create(DateTime utcDateTime, DateTimeZone algorithmTimeZone, CashBook cashBook, List <DataFeedPacket> data, SecurityChanges changes, Dictionary <Universe, BaseDataCollection> universeData) { int count = 0; var security = new List <UpdateData <Security> >(); var custom = new List <UpdateData <Security> >(); var consolidator = new List <UpdateData <SubscriptionDataConfig> >(); var allDataForAlgorithm = new List <BaseData>(data.Count); var optionUnderlyingUpdates = new Dictionary <Symbol, BaseData>(); Split split; Dividend dividend; Delisting delisting; SymbolChangedEvent symbolChange; // we need to be able to reference the slice being created in order to define the // evaluation of option price models, so we define a 'future' that can be referenced // in the option price model evaluation delegates for each contract Slice slice = null; var sliceFuture = new Lazy <Slice>(() => slice); var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone); var tradeBars = new TradeBars(algorithmTime); var quoteBars = new QuoteBars(algorithmTime); var ticks = new Ticks(algorithmTime); var splits = new Splits(algorithmTime); var dividends = new Dividends(algorithmTime); var delistings = new Delistings(algorithmTime); var optionChains = new OptionChains(algorithmTime); var futuresChains = new FuturesChains(algorithmTime); var symbolChanges = new SymbolChangedEvents(algorithmTime); if (universeData.Count > 0) { // count universe data foreach (var kvp in universeData) { count += kvp.Value.Data.Count; } } // ensure we read equity data before option data, so we can set the current underlying price foreach (var packet in data) { // filter out packets for removed subscriptions if (packet.IsSubscriptionRemoved) { continue; } var list = packet.Data; var symbol = packet.Security.Symbol; if (list.Count == 0) { continue; } // keep count of all data points if (list.Count == 1 && list[0] is BaseDataCollection) { var baseDataCollectionCount = ((BaseDataCollection)list[0]).Data.Count; if (baseDataCollectionCount == 0) { continue; } count += baseDataCollectionCount; } else { count += list.Count; } if (!packet.Configuration.IsInternalFeed && packet.Configuration.IsCustomData) { // This is all the custom data custom.Add(new UpdateData <Security>(packet.Security, packet.Configuration.Type, list)); } var securityUpdate = new List <BaseData>(list.Count); var consolidatorUpdate = new List <BaseData>(list.Count); for (int i = 0; i < list.Count; i++) { var baseData = list[i]; if (!packet.Configuration.IsInternalFeed) { // this is all the data that goes into the algorithm allDataForAlgorithm.Add(baseData); } // don't add internal feed data to ticks/bars objects if (baseData.DataType != MarketDataType.Auxiliary) { if (!packet.Configuration.IsInternalFeed) { PopulateDataDictionaries(baseData, ticks, tradeBars, quoteBars, optionChains, futuresChains); // special handling of options data to build the option chain if (packet.Security.Type == SecurityType.Option) { if (baseData.DataType == MarketDataType.OptionChain) { optionChains[baseData.Symbol] = (OptionChain)baseData; } else if (!HandleOptionData(algorithmTime, baseData, optionChains, packet.Security, sliceFuture, optionUnderlyingUpdates)) { continue; } } // special handling of futures data to build the futures chain if (packet.Security.Type == SecurityType.Future) { if (baseData.DataType == MarketDataType.FuturesChain) { futuresChains[baseData.Symbol] = (FuturesChain)baseData; } else if (!HandleFuturesData(algorithmTime, baseData, futuresChains, packet.Security)) { continue; } } // this is data used to update consolidators consolidatorUpdate.Add(baseData); } // this is the data used set market prices // do not add it if it is a Suspicious tick var tick = baseData as Tick; if (tick != null && tick.Suspicious) { continue; } securityUpdate.Add(baseData); // option underlying security update if (packet.Security.Symbol.SecurityType == SecurityType.Equity) { optionUnderlyingUpdates[packet.Security.Symbol] = baseData; } } // include checks for various aux types so we don't have to construct the dictionaries in Slice else if ((delisting = baseData as Delisting) != null) { delistings[symbol] = delisting; } else if ((dividend = baseData as Dividend) != null) { dividends[symbol] = dividend; } else if ((split = baseData as Split) != null) { splits[symbol] = split; } else if ((symbolChange = baseData as SymbolChangedEvent) != null) { // symbol changes is keyed by the requested symbol symbolChanges[packet.Configuration.Symbol] = symbolChange; } } if (securityUpdate.Count > 0) { security.Add(new UpdateData <Security>(packet.Security, packet.Configuration.Type, securityUpdate)); } if (consolidatorUpdate.Count > 0) { consolidator.Add(new UpdateData <SubscriptionDataConfig>(packet.Configuration, packet.Configuration.Type, consolidatorUpdate)); } } slice = new Slice(algorithmTime, allDataForAlgorithm, tradeBars, quoteBars, ticks, optionChains, futuresChains, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0); return(new TimeSlice(utcDateTime, count, slice, data, security, consolidator, custom, changes, universeData)); }