23 using System.Collections.Generic;
34 private readonly DateTimeZone _timeZone;
38 private readonly List<UpdateData<ISecurityPrice>> _emptyCustom =
new List<UpdateData<ISecurityPrice>>();
41 private readonly
Ticks _emptyTicks =
new Ticks();
90 List<DataFeedPacket> data,
92 Dictionary<Universe, BaseDataCollection> universeData)
95 var security =
new List<UpdateData<ISecurityPrice>>(data.Count);
96 List<UpdateData<ISecurityPrice>> custom =
null;
97 var consolidator =
new List<UpdateData<SubscriptionDataConfig>>(data.Count);
98 var allDataForAlgorithm =
new List<BaseData>(data.Count);
99 var optionUnderlyingUpdates =
new Dictionary<Symbol, BaseData>();
111 var sliceFuture =
new Lazy<Slice>(() => slice);
113 var algorithmTime = utcDateTime.ConvertFromUtc(_timeZone);
125 UpdateEmptyCollections(algorithmTime);
127 if (universeData.Count > 0)
130 foreach (var kvp
in universeData)
132 count += kvp.Value.Data.Count;
137 foreach (var packet
in data)
140 if (packet.IsSubscriptionRemoved)
145 var list = packet.Data;
146 var symbol = packet.Configuration.Symbol;
148 if (list.Count == 0)
continue;
154 if (baseDataCollectionCount == 0)
158 count += baseDataCollectionCount;
165 if (!packet.Configuration.IsInternalFeed && packet.Configuration.IsCustomData)
169 custom =
new List<UpdateData<ISecurityPrice>>(1);
172 custom.Add(
new UpdateData<ISecurityPrice>(packet.Security, packet.Configuration.Type, list, packet.Configuration.IsInternalFeed));
175 var securityUpdate =
new List<BaseData>(list.Count);
176 var consolidatorUpdate =
new List<BaseData>(list.Count);
177 var containsFillForwardData =
false;
178 for (var i = 0; i < list.Count; i++)
180 var baseData = list[i];
181 if (!packet.Configuration.IsInternalFeed)
184 allDataForAlgorithm.Add(baseData);
187 containsFillForwardData |= baseData.IsFillForward;
192 var tick = baseData as
Tick;
194 if (!packet.Configuration.IsInternalFeed)
197 switch (baseData.DataType)
202 ticks =
new Ticks(algorithmTime);
204 ticks.Add(baseData.Symbol, (
Tick)baseData);
208 if (tradeBars ==
null)
210 tradeBars =
new TradeBars(algorithmTime);
213 var newTradeBar = (
TradeBar)baseData;
218 if (!tradeBars.TryGetValue(baseData.
Symbol, out existingTradeBar)
219 || existingTradeBar.Period > newTradeBar.Period)
221 tradeBars[baseData.
Symbol] = newTradeBar;
226 if (quoteBars ==
null)
228 quoteBars =
new QuoteBars(algorithmTime);
231 var newQuoteBar = (
QuoteBar)baseData;
236 if (!quoteBars.TryGetValue(baseData.
Symbol, out existingQuoteBar)
237 || existingQuoteBar.Period > newQuoteBar.Period)
239 quoteBars[baseData.
Symbol] = newQuoteBar;
244 if (optionChains ==
null)
252 if (futuresChains ==
null)
262 if (tick ==
null || !tick.Suspicious)
264 consolidatorUpdate.Add(baseData);
269 if (symbol.SecurityType.IsOption())
274 if (optionChains ==
null && !packet.Configuration.IsInternalFeed)
281 optionChains[baseData.Symbol] = (
OptionChain)baseData;
283 else if (optionChains !=
null && !HandleOptionData(algorithmTime, baseData, optionChains, packet.Security, sliceFuture, optionUnderlyingUpdates))
291 if (symbol.SecurityType ==
SecurityType.Future && !symbol.IsCanonical() && !packet.Configuration.IsInternalFeed)
293 if (futuresChains ==
null)
299 futuresChains[baseData.Symbol] = (
FuturesChain)baseData;
301 else if (futuresChains !=
null && !HandleFuturesData(algorithmTime, baseData, futuresChains, packet.Security))
309 if (tick !=
null && tick.Suspicious)
continue;
311 securityUpdate.Add(baseData);
314 if (!packet.Configuration.IsInternalFeed)
316 optionUnderlyingUpdates[symbol] = baseData;
321 else if ((delisting = baseData as
Delisting) !=
null || !packet.Configuration.IsInternalFeed)
324 if (delisting !=
null)
326 if (delistings ==
null)
330 delistings[symbol] = delisting;
332 else if ((dividend = baseData as
Dividend) !=
null)
334 if (dividends ==
null)
336 dividends =
new Dividends(algorithmTime);
338 dividends[symbol] = dividend;
340 else if ((split = baseData as
Split) !=
null)
344 splits =
new Splits(algorithmTime);
346 splits[symbol] = split;
350 if (symbolChanges ==
null)
355 symbolChanges[packet.Configuration.Symbol] = symbolChange;
359 if (marginInterestRates ==
null)
363 marginInterestRates[packet.Configuration.Symbol] = marginInterestRate;
367 security.Add(
new UpdateData<ISecurityPrice>(packet.Security, baseData.GetType(),
new List<BaseData> { baseData }, packet.Configuration.IsInternalFeed, baseData.IsFillForward));
371 if (securityUpdate.Count > 0)
373 security.Add(
new UpdateData<ISecurityPrice>(packet.Security, packet.Configuration.Type, securityUpdate, packet.Configuration.IsInternalFeed, containsFillForwardData));
375 if (consolidatorUpdate.Count > 0)
377 consolidator.Add(
new UpdateData<SubscriptionDataConfig>(packet.Configuration, packet.Configuration.Type, consolidatorUpdate, packet.Configuration.IsInternalFeed, containsFillForwardData));
381 slice =
new Slice(algorithmTime, allDataForAlgorithm, tradeBars ?? _emptyTradeBars, quoteBars ?? _emptyQuoteBars, ticks ?? _emptyTicks, optionChains ?? _emptyOptionChains, futuresChains ?? _emptyFuturesChains, splits ?? _emptySplits, dividends ?? _emptyDividends, delistings ?? _emptyDelistings, symbolChanges ?? _emptySymbolChangedEvents, marginInterestRates ?? _emptyMarginInterestRates, utcDateTime, allDataForAlgorithm.Count > 0);
383 return new TimeSlice(utcDateTime, count, slice, data, security, consolidator, custom ?? _emptyCustom, changes, universeData);
386 private void UpdateEmptyCollections(DateTime algorithmTime)
389 _emptyTradeBars.Clear();
390 _emptyQuoteBars.Clear();
392 _emptySplits.Clear();
393 _emptyDividends.Clear();
394 _emptyDelistings.Clear();
395 _emptyOptionChains.Clear();
396 _emptyFuturesChains.Clear();
397 _emptySymbolChangedEvents.Clear();
398 _emptyMarginInterestRates.Clear();
400 #pragma warning disable 0618 // DataDictionary.Time is deprecated, ignore until removed entirely
402 = _emptyQuoteBars.Time
405 = _emptyDividends.Time
406 = _emptyDelistings.Time
407 = _emptyOptionChains.Time
408 = _emptyFuturesChains.Time
409 = _emptySymbolChangedEvents.Time
410 = _emptyMarginInterestRates.Time = algorithmTime;
411 #pragma warning restore 0618
414 private bool HandleOptionData(DateTime algorithmTime,
BaseData baseData,
OptionChains optionChains,
ISecurityPrice security, Lazy<Slice> sliceFuture, IReadOnlyDictionary<Symbol, BaseData> optionUnderlyingUpdates)
416 var symbol = baseData.
Symbol;
419 var canonical = symbol.Canonical;
420 if (!optionChains.
TryGetValue(canonical, out chain))
423 optionChains[canonical] = chain;
430 if (option.Underlying ==
null)
432 Log.
Error($
"TimeSlice.HandleOptionData(): {algorithmTime}: Option underlying is null");
437 if (!optionUnderlyingUpdates.TryGetValue(option.Underlying.Symbol, out underlyingData))
439 underlyingData = option.Underlying.GetLastData();
442 if (underlyingData ==
null)
444 Log.
Error($
"TimeSlice.HandleOptionData(): {algorithmTime}: Option underlying GetLastData returned null");
447 chain.Underlying = underlyingData;
451 if (universeData !=
null)
453 if (universeData.Underlying !=
null)
455 foreach (var addedContract
in chain.Contracts)
457 addedContract.
Value.Update(chain.Underlying);
460 foreach (var contractSymbol
in universeData.FilteredContracts ?? Enumerable.Empty<Symbol>())
462 chain.FilteredContracts.Add(contractSymbol);
468 if (!chain.Contracts.TryGetValue(baseData.
Symbol, out contract))
472 chain.Contracts[baseData.
Symbol] = contract;
476 contract.SetOptionPriceModel(() => option.EvaluatePriceModel(sliceFuture.Value, contract));
484 var tick = (
Tick)baseData;
485 chain.Ticks.Add(tick.Symbol, tick);
486 contract.Update(tick);
491 chain.TradeBars[symbol] = tradeBar;
492 contract.Update(tradeBar);
497 chain.QuoteBars[symbol] = quote;
498 contract.Update(quote);
502 chain.AddAuxData(baseData);
511 var symbol = baseData.
Symbol;
514 var canonical = symbol.Canonical;
515 if (!futuresChains.
TryGetValue(canonical, out chain))
518 futuresChains[canonical] = chain;
522 if (universeData !=
null)
524 foreach (var contractSymbol
in universeData.FilteredContracts ?? Enumerable.Empty<Symbol>())
532 if (!chain.Contracts.TryGetValue(baseData.
Symbol, out contract))
538 LastPrice = security.
Close,
539 Volume = (long)security.
Volume,
541 BidSize = (
long)security.
BidSize,
543 AskSize = (long)security.
AskSize,
546 chain.Contracts[baseData.
Symbol] = contract;
553 var tick = (
Tick)baseData;
554 chain.Ticks.Add(tick.Symbol, tick);
555 UpdateContract(contract, tick);
560 chain.TradeBars[symbol] = tradeBar;
561 UpdateContract(contract, tradeBar);
566 chain.QuoteBars[symbol] = quote;
567 UpdateContract(contract, quote);
571 chain.AddAuxData(baseData);
612 if (tick.
Value != 0m)
621 if (tradeBar.
Close == 0m)
return;