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;
319 else if (!packet.Configuration.IsInternalFeed)
322 if ((delisting = baseData as
Delisting) !=
null)
324 if (delistings ==
null)
328 delistings[symbol] = delisting;
330 else if ((dividend = baseData as
Dividend) !=
null)
332 if (dividends ==
null)
334 dividends =
new Dividends(algorithmTime);
336 dividends[symbol] = dividend;
338 else if ((split = baseData as
Split) !=
null)
342 splits =
new Splits(algorithmTime);
344 splits[symbol] = split;
348 if (symbolChanges ==
null)
353 symbolChanges[packet.Configuration.Symbol] = symbolChange;
357 if (marginInterestRates ==
null)
361 marginInterestRates[packet.Configuration.Symbol] = marginInterestRate;
365 security.Add(
new UpdateData<ISecurityPrice>(packet.Security, baseData.GetType(),
new List<BaseData> { baseData }, packet.Configuration.IsInternalFeed, baseData.IsFillForward));
369 if (securityUpdate.Count > 0)
371 security.Add(
new UpdateData<ISecurityPrice>(packet.Security, packet.Configuration.Type, securityUpdate, packet.Configuration.IsInternalFeed, containsFillForwardData));
373 if (consolidatorUpdate.Count > 0)
375 consolidator.Add(
new UpdateData<SubscriptionDataConfig>(packet.Configuration, packet.Configuration.Type, consolidatorUpdate, packet.Configuration.IsInternalFeed, containsFillForwardData));
379 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);
381 return new TimeSlice(utcDateTime, count, slice, data, security, consolidator, custom ?? _emptyCustom, changes, universeData);
384 private void UpdateEmptyCollections(DateTime algorithmTime)
387 _emptyTradeBars.Clear();
388 _emptyQuoteBars.Clear();
390 _emptySplits.Clear();
391 _emptyDividends.Clear();
392 _emptyDelistings.Clear();
393 _emptyOptionChains.Clear();
394 _emptyFuturesChains.Clear();
395 _emptySymbolChangedEvents.Clear();
396 _emptyMarginInterestRates.Clear();
398 #pragma warning disable 0618 // DataDictionary.Time is deprecated, ignore until removed entirely
400 = _emptyQuoteBars.Time
403 = _emptyDividends.Time
404 = _emptyDelistings.Time
405 = _emptyOptionChains.Time
406 = _emptyFuturesChains.Time
407 = _emptySymbolChangedEvents.Time
408 = _emptyMarginInterestRates.Time = algorithmTime;
409 #pragma warning restore 0618
412 private bool HandleOptionData(DateTime algorithmTime,
BaseData baseData,
OptionChains optionChains,
ISecurityPrice security, Lazy<Slice> sliceFuture, IReadOnlyDictionary<Symbol, BaseData> optionUnderlyingUpdates)
414 var symbol = baseData.
Symbol;
417 var canonical = symbol.Canonical;
418 if (!optionChains.
TryGetValue(canonical, out chain))
421 optionChains[canonical] = chain;
428 if (option.Underlying ==
null)
430 Log.
Error($
"TimeSlice.HandleOptionData(): {algorithmTime}: Option underlying is null");
435 if (!optionUnderlyingUpdates.TryGetValue(option.Underlying.Symbol, out underlyingData))
437 underlyingData = option.Underlying.GetLastData();
440 if (underlyingData ==
null)
442 Log.
Error($
"TimeSlice.HandleOptionData(): {algorithmTime}: Option underlying GetLastData returned null");
445 chain.Underlying = underlyingData;
449 if (universeData !=
null)
451 if (universeData.Underlying !=
null)
453 foreach (var addedContract
in chain.Contracts)
455 addedContract.
Value.Update(chain.Underlying);
458 foreach (var contractSymbol
in universeData.FilteredContracts ?? Enumerable.Empty<Symbol>())
460 chain.FilteredContracts.Add(contractSymbol);
466 if (!chain.Contracts.TryGetValue(baseData.
Symbol, out contract))
470 chain.Contracts[baseData.
Symbol] = contract;
474 contract.SetOptionPriceModel(() => option.EvaluatePriceModel(sliceFuture.Value, contract));
482 var tick = (
Tick)baseData;
483 chain.Ticks.Add(tick.Symbol, tick);
484 contract.Update(tick);
489 chain.TradeBars[symbol] = tradeBar;
490 contract.Update(tradeBar);
495 chain.QuoteBars[symbol] = quote;
496 contract.Update(quote);
500 chain.AddAuxData(baseData);
509 var symbol = baseData.
Symbol;
512 var canonical = symbol.Canonical;
513 if (!futuresChains.
TryGetValue(canonical, out chain))
516 futuresChains[canonical] = chain;
520 if (universeData !=
null)
522 foreach (var contractSymbol
in universeData.FilteredContracts ?? Enumerable.Empty<Symbol>())
530 if (!chain.Contracts.TryGetValue(baseData.
Symbol, out contract))
536 LastPrice = security.
Close,
537 Volume = (long)security.
Volume,
539 BidSize = (
long)security.
BidSize,
541 AskSize = (long)security.
AskSize,
544 chain.Contracts[baseData.
Symbol] = contract;
551 var tick = (
Tick)baseData;
552 chain.Ticks.Add(tick.Symbol, tick);
553 UpdateContract(contract, tick);
558 chain.TradeBars[symbol] = tradeBar;
559 UpdateContract(contract, tradeBar);
564 chain.QuoteBars[symbol] = quote;
565 UpdateContract(contract, quote);
569 chain.AddAuxData(baseData);
610 if (tick.
Value != 0m)
619 if (tradeBar.
Close == 0m)
return;