20 using System.Collections.Generic;
21 using System.Runtime.CompilerServices;
34 private static readonly IReadOnlyList<BaseData> _empty =
new List<BaseData>();
37 private DateTime _lastQuoteBarUpdate;
38 private DateTime _lastOHLCUpdate;
41 private readonly
object _locker =
new();
42 private IReadOnlyList<BaseData> _lastTickQuotes = _empty;
43 private IReadOnlyList<BaseData> _lastTickTrades = _empty;
44 private Dictionary<Type, IReadOnlyList<BaseData>> _dataByType;
46 private Dictionary<string, object> _properties;
51 public decimal
Price {
get;
private set; }
56 public decimal
Open {
get;
private set; }
61 public decimal
High {
get;
private set; }
66 public decimal
Low {
get;
private set; }
71 public decimal
Close {
get;
private set; }
86 public decimal
BidSize {
get;
private set; }
91 public decimal
AskSize {
get;
private set; }
96 public decimal
Volume {
get;
private set; }
110 if (_properties ==
null)
112 _properties =
new Dictionary<string, object>();
123 public void AddDataList(IReadOnlyList<BaseData> data, Type dataType,
bool? containsFillForwardData =
null)
125 var nonFillForwardData = data;
127 if (containsFillForwardData !=
false)
129 var dataFiltered =
new List<BaseData>(data.Count);
130 for (var i = 0; i < data.Count; i++)
132 var dataPoint = data[i];
133 if (!dataPoint.IsFillForward)
135 dataFiltered.Add(dataPoint);
138 nonFillForwardData = dataFiltered;
140 if (nonFillForwardData.Count != 0)
149 var last = data[data.Count - 1];
173 var tick = data as
Tick;
178 StoreDataPoint(data);
189 StoreDataPoint(data);
200 if ((_lastData ==
null
201 || _lastQuoteBarUpdate != data.
EndTime
204 && isDefaultDataType)
211 if (tick.Value != 0)
Price = tick.Value;
213 switch (tick.TickType)
216 if (tick.Quantity != 0)
Volume = tick.Quantity;
220 if (tick.BidPrice != 0)
BidPrice = tick.BidPrice;
221 if (tick.BidSize != 0)
BidSize = tick.BidSize;
223 if (tick.AskPrice != 0)
AskPrice = tick.AskPrice;
224 if (tick.AskSize != 0)
AskSize = tick.AskSize;
230 var bar = data as
IBar;
235 if ((_lastQuoteBarUpdate != data.
EndTime || _lastOHLCUpdate != data.
EndTime) && isDefaultDataType)
237 _lastOHLCUpdate = data.
EndTime;
238 if (bar.Open != 0)
Open = bar.Open;
239 if (bar.High != 0)
High = bar.High;
240 if (bar.Low != 0)
Low = bar.Low;
249 if (tradeBar !=
null)
251 if (tradeBar.Volume != 0)
Volume = tradeBar.Volume;
255 if (quoteBar !=
null)
257 _lastQuoteBarUpdate = quoteBar.
EndTime;
258 if (quoteBar.Ask !=
null && quoteBar.Ask.Close != 0)
AskPrice = quoteBar.Ask.Close;
259 if (quoteBar.Bid !=
null && quoteBar.Bid.Close != 0)
BidPrice = quoteBar.Bid.Close;
260 if (quoteBar.LastBidSize != 0)
BidSize = quoteBar.LastBidSize;
261 if (quoteBar.LastAskSize != 0)
AskSize = quoteBar.LastAskSize;
278 public void StoreData(IReadOnlyList<BaseData> data, Type dataType)
280 if (dataType == typeof(
Tick))
282 var tick = data[data.Count - 1] as
Tick;
286 _lastTickTrades = data;
289 _lastTickQuotes = data;
296 _dataByType ??=
new();
297 _dataByType[dataType] = data;
318 IReadOnlyList<BaseData> list;
319 if (!
TryGetValue(typeof(T), out list) || list.Count == 0)
323 return list[list.Count - 1] as T;
332 if (typeof(T) == typeof(
Tick))
334 return _lastTickTrades.Concat(_lastTickQuotes).Cast<T>();
339 if (_dataByType ==
null || !_dataByType.TryGetValue(typeof(T), out var list))
341 return new List<T>();
344 return list.Cast<T>();
369 _lastTickQuotes = _empty;
370 _lastTickTrades = _empty;
384 public bool TryGetValue(Type type, out IReadOnlyList<BaseData> data)
396 else if (type == typeof(
Tick))
398 var quote = _lastTickQuotes.LastOrDefault();
399 var trade = _lastTickTrades.LastOrDefault();
400 var isQuoteDefaultDataType = quote !=
null &&
SubscriptionManager.IsDefaultDataType(quote);
401 var isTradeDefaultDataType = trade !=
null &&
SubscriptionManager.IsDefaultDataType(trade);
405 if (isQuoteDefaultDataType && isTradeDefaultDataType)
407 data = quote.EndTime > trade.EndTime ? _lastTickQuotes : _lastTickTrades;
411 data = isQuoteDefaultDataType ? _lastTickQuotes : _lastTickTrades;
412 return data?.Count > 0;
416 return _dataByType !=
null && _dataByType.TryGetValue(type, out data);
419 [MethodImpl(MethodImplOptions.AggressiveInlining)]
420 private void StoreDataPoint(
BaseData data)
422 if (data.GetType() == typeof(
Tick))
424 var tick = data as
Tick;
428 _lastTickTrades =
new List<BaseData> { tick };
431 _lastTickQuotes =
new List<BaseData> { tick };
439 _dataByType ??=
new();
441 IReadOnlyList<BaseData> list;
442 if (!_dataByType.TryGetValue(data.GetType(), out list))
444 list =
new List<BaseData> { data };
445 _dataByType[data.GetType()] = list;
451 ((List<BaseData>)list)[0] = data;
468 sourceToShare._dataByType ??=
new();
469 if (targetToModify._dataByType !=
null)
471 lock (targetToModify._locker)
473 lock (sourceToShare._locker)
475 foreach (var kvp
in targetToModify._dataByType)
477 sourceToShare._dataByType.TryAdd(kvp.Key, kvp.Value);
482 targetToModify._dataByType = sourceToShare._dataByType;
483 targetToModify._lastTickTrades = sourceToShare._lastTickTrades;
484 targetToModify._lastTickQuotes = sourceToShare._lastTickQuotes;
490 internal void ApplySplit(
Split split)
504 Action<BaseData> scale = data => data.Scale((target, factor, _) => target * factor, 1 / split.
SplitFactor, split.
SplitFactor, decimal.Zero);
505 _dataByType?.Values.DoForEach(x => x.DoForEach(scale));
506 _lastTickQuotes.DoForEach(scale);
507 _lastTickTrades.DoForEach(scale);