23 using System.Collections.Generic;
33 private readonly DateTimeZone _timeZone;
37 private readonly List<UpdateData<ISecurityPrice>> _emptyCustom =
new List<UpdateData<ISecurityPrice>>();
40 private readonly
Ticks _emptyTicks =
new Ticks();
89 List<DataFeedPacket> data,
91 Dictionary<Universe, BaseDataCollection> universeData)
94 var security =
new List<UpdateData<ISecurityPrice>>(data.Count);
95 List<UpdateData<ISecurityPrice>> custom =
null;
96 var consolidator =
new List<UpdateData<SubscriptionDataConfig>>(data.Count);
97 var allDataForAlgorithm =
new List<BaseData>(data.Count);
98 var optionUnderlyingUpdates =
new Dictionary<Symbol, BaseData>();
110 var sliceFuture =
new Lazy<Slice>(() => slice);
112 var algorithmTime = utcDateTime.ConvertFromUtc(_timeZone);
124 UpdateEmptyCollections(algorithmTime);
126 if (universeData.Count > 0)
129 foreach (var kvp
in universeData)
131 count += kvp.Value.Data.Count;
136 foreach (var packet
in data)
139 if (packet.IsSubscriptionRemoved)
144 var list = packet.Data;
145 var symbol = packet.Configuration.Symbol;
147 if (list.Count == 0)
continue;
153 if (baseDataCollectionCount == 0)
157 count += baseDataCollectionCount;
164 if (!packet.Configuration.IsInternalFeed && packet.Configuration.IsCustomData)
168 custom =
new List<UpdateData<ISecurityPrice>>(1);
171 custom.Add(
new UpdateData<ISecurityPrice>(packet.Security, packet.Configuration.Type, list, packet.Configuration.IsInternalFeed));
174 var securityUpdate =
new List<BaseData>(list.Count);
175 var consolidatorUpdate =
new List<BaseData>(list.Count);
176 var containsFillForwardData =
false;
177 for (var i = 0; i < list.Count; i++)
179 var baseData = list[i];
180 if (!packet.Configuration.IsInternalFeed)
183 allDataForAlgorithm.Add(baseData);
186 containsFillForwardData |= baseData.IsFillForward;
191 var tick = baseData as
Tick;
193 if (!packet.Configuration.IsInternalFeed)
196 switch (baseData.DataType)
201 ticks =
new Ticks(algorithmTime);
203 ticks.Add(baseData.Symbol, (
Tick)baseData);
207 if (tradeBars ==
null)
209 tradeBars =
new TradeBars(algorithmTime);
212 var newTradeBar = (
TradeBar)baseData;
217 if (!tradeBars.TryGetValue(baseData.
Symbol, out existingTradeBar)
218 || existingTradeBar.Period > newTradeBar.Period)
220 tradeBars[baseData.
Symbol] = newTradeBar;
225 if (quoteBars ==
null)
227 quoteBars =
new QuoteBars(algorithmTime);
230 var newQuoteBar = (
QuoteBar)baseData;
235 if (!quoteBars.TryGetValue(baseData.
Symbol, out existingQuoteBar)
236 || existingQuoteBar.Period > newQuoteBar.Period)
238 quoteBars[baseData.
Symbol] = newQuoteBar;
243 if (optionChains ==
null)
251 if (futuresChains ==
null)
261 if (tick ==
null || !tick.Suspicious)
263 consolidatorUpdate.Add(baseData);
268 if (symbol.SecurityType.IsOption())
273 if (optionChains ==
null && !packet.Configuration.IsInternalFeed)
280 optionChains[baseData.Symbol] = (
OptionChain)baseData;
282 else if (optionChains !=
null && !HandleOptionData(algorithmTime, baseData, optionChains, packet.Security, sliceFuture, optionUnderlyingUpdates))
290 if (symbol.SecurityType ==
SecurityType.Future && !symbol.IsCanonical() && !packet.Configuration.IsInternalFeed)
292 if (futuresChains ==
null)
298 futuresChains[baseData.Symbol] = (
FuturesChain)baseData;
300 else if (futuresChains !=
null && !HandleFuturesData(algorithmTime, baseData, futuresChains, packet.Security))
308 if (tick !=
null && tick.Suspicious)
continue;
310 securityUpdate.Add(baseData);
313 if (!packet.Configuration.IsInternalFeed)
315 optionUnderlyingUpdates[symbol] = baseData;
318 else if (!packet.Configuration.IsInternalFeed)
321 if ((delisting = baseData as
Delisting) !=
null)
323 if (delistings ==
null)
327 delistings[symbol] = delisting;
329 else if ((dividend = baseData as
Dividend) !=
null)
331 if (dividends ==
null)
333 dividends =
new Dividends(algorithmTime);
335 dividends[symbol] = dividend;
337 else if ((split = baseData as
Split) !=
null)
341 splits =
new Splits(algorithmTime);
343 splits[symbol] = split;
347 if (symbolChanges ==
null)
352 symbolChanges[packet.Configuration.Symbol] = symbolChange;
356 if (marginInterestRates ==
null)
360 marginInterestRates[packet.Configuration.Symbol] = marginInterestRate;
364 security.Add(
new UpdateData<ISecurityPrice>(packet.Security, baseData.GetType(),
new List<BaseData> { baseData }, packet.Configuration.IsInternalFeed, baseData.IsFillForward));
368 if (securityUpdate.Count > 0)
370 security.Add(
new UpdateData<ISecurityPrice>(packet.Security, packet.Configuration.Type, securityUpdate, packet.Configuration.IsInternalFeed, containsFillForwardData));
372 if (consolidatorUpdate.Count > 0)
374 consolidator.Add(
new UpdateData<SubscriptionDataConfig>(packet.Configuration, packet.Configuration.Type, consolidatorUpdate, packet.Configuration.IsInternalFeed, containsFillForwardData));
378 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);
380 return new TimeSlice(utcDateTime, count, slice, data, security, consolidator, custom ?? _emptyCustom, changes, universeData);
383 private void UpdateEmptyCollections(DateTime algorithmTime)
386 _emptyTradeBars.Clear();
387 _emptyQuoteBars.Clear();
389 _emptySplits.Clear();
390 _emptyDividends.Clear();
391 _emptyDelistings.Clear();
392 _emptyOptionChains.Clear();
393 _emptyFuturesChains.Clear();
394 _emptySymbolChangedEvents.Clear();
395 _emptyMarginInterestRates.Clear();
397 #pragma warning disable 0618 // DataDictionary.Time is deprecated, ignore until removed entirely
399 = _emptyQuoteBars.Time
402 = _emptyDividends.Time
403 = _emptyDelistings.Time
404 = _emptyOptionChains.Time
405 = _emptyFuturesChains.Time
406 = _emptySymbolChangedEvents.Time
407 = _emptyMarginInterestRates.Time = algorithmTime;
408 #pragma warning restore 0618
411 private bool HandleOptionData(DateTime algorithmTime,
BaseData baseData,
OptionChains optionChains,
ISecurityPrice security, Lazy<Slice> sliceFuture, IReadOnlyDictionary<Symbol, BaseData> optionUnderlyingUpdates)
413 var symbol = baseData.
Symbol;
416 var canonical = symbol.Canonical;
417 if (!optionChains.
TryGetValue(canonical, out chain))
420 optionChains[canonical] = chain;
427 if (option.Underlying ==
null)
429 Log.
Error($
"TimeSlice.HandleOptionData(): {algorithmTime}: Option underlying is null");
434 if (!optionUnderlyingUpdates.TryGetValue(option.Underlying.Symbol, out underlyingData))
436 underlyingData = option.Underlying.GetLastData();
439 if (underlyingData ==
null)
441 Log.
Error($
"TimeSlice.HandleOptionData(): {algorithmTime}: Option underlying GetLastData returned null");
444 chain.Underlying = underlyingData;
448 if (universeData !=
null)
450 if (universeData.Underlying !=
null)
452 foreach (var addedContract
in chain.Contracts)
454 addedContract.
Value.UnderlyingLastPrice = chain.Underlying.Price;
457 foreach (var contractSymbol
in universeData.FilteredContracts)
459 chain.FilteredContracts.Add(contractSymbol);
465 if (!chain.Contracts.TryGetValue(baseData.
Symbol, out contract))
469 chain.Contracts[baseData.
Symbol] = contract;
473 contract.SetOptionPriceModel(() => option.EvaluatePriceModel(sliceFuture.Value, contract));
481 var tick = (
Tick)baseData;
482 chain.Ticks.Add(tick.Symbol, tick);
483 UpdateContract(contract, tick);
488 chain.TradeBars[symbol] = tradeBar;
489 UpdateContract(contract, tradeBar);
494 chain.QuoteBars[symbol] = quote;
495 UpdateContract(contract, quote);
499 chain.AddAuxData(baseData);
508 var symbol = baseData.
Symbol;
511 var canonical = symbol.Canonical;
512 if (!futuresChains.
TryGetValue(canonical, out chain))
515 futuresChains[canonical] = chain;
519 if (universeData !=
null)
521 foreach (var contractSymbol
in universeData.FilteredContracts)
529 if (!chain.Contracts.TryGetValue(baseData.
Symbol, out contract))
535 LastPrice = security.
Close,
536 Volume = (long)security.
Volume,
538 BidSize = (
long)security.
BidSize,
540 AskSize = (long)security.
AskSize,
543 chain.Contracts[baseData.
Symbol] = contract;
550 var tick = (
Tick)baseData;
551 chain.Ticks.Add(tick.Symbol, tick);
552 UpdateContract(contract, tick);
557 chain.TradeBars[symbol] = tradeBar;
558 UpdateContract(contract, tradeBar);
563 chain.QuoteBars[symbol] = quote;
564 UpdateContract(contract, quote);
568 chain.AddAuxData(baseData);
609 if (tick.
Value != 0m)
618 if (tradeBar.
Close == 0m)
return;
658 if (tick.
Value != 0m)
667 if (tradeBar.
Close == 0m)
return;