17 using System.Collections.Generic;
18 using System.Globalization;
21 using System.Runtime.CompilerServices;
42 private static readonly HashSet<Type> _strictDailyEndTimesDataTypes =
new()
53 .Select(x => x.ToLowerInvariant()).Union(
new[] {
"alternative" }).ToHashSet();
63 var clone = data.
Clone();
64 clone.
Time = data.
Time.ConvertTo(exchangeTimeZone, dataTimeZone);
65 return GenerateLine(clone, clone.Symbol.ID.SecurityType, resolution);
78 var index = line.IndexOf(
',', StringComparison.InvariantCulture);
79 return date.AddTicks(Convert.ToInt64(10000 * decimal.Parse(line.AsSpan(0, index))));
84 throw new ArgumentOutOfRangeException(nameof(resolution), resolution,
null);
93 var milliseconds = data.
Time.TimeOfDay.TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
102 var tick = (
Tick)data;
103 if (tick.TickType ==
TickType.Trade)
105 return ToCsv(milliseconds, Scale(tick.LastPrice), tick.Quantity, tick.ExchangeCode, tick.SaleCondition, tick.Suspicious ?
"1" :
"0");
107 if (tick.TickType ==
TickType.Quote)
109 return ToCsv(milliseconds, Scale(tick.BidPrice), tick.BidSize, Scale(tick.AskPrice), tick.AskSize, tick.ExchangeCode, tick.SaleCondition, tick.Suspicious ?
"1" :
"0");
115 if (tradeBar !=
null)
117 return ToCsv(milliseconds, Scale(tradeBar.Open), Scale(tradeBar.High), Scale(tradeBar.Low), Scale(tradeBar.Close), tradeBar.Volume);
120 if (quoteBar !=
null)
122 return ToCsv(milliseconds,
123 ToScaledCsv(quoteBar.Bid), quoteBar.LastBidSize,
124 ToScaledCsv(quoteBar.Ask), quoteBar.LastAskSize);
131 if (bigTradeBar !=
null)
133 return ToCsv(longTime, Scale(bigTradeBar.Open), Scale(bigTradeBar.High), Scale(bigTradeBar.Low), Scale(bigTradeBar.Close), bigTradeBar.Volume);
136 if (bigQuoteBar !=
null)
138 return ToCsv(longTime,
139 ToScaledCsv(bigQuoteBar.Bid), bigQuoteBar.LastBidSize,
140 ToScaledCsv(bigQuoteBar.Ask), bigQuoteBar.LastAskSize);
151 var tick = data as
Tick;
154 throw new ArgumentException($
"{securityType} tick could not be created", nameof(data));
156 if (tick.TickType ==
TickType.Trade)
158 return ToCsv(milliseconds, tick.LastPrice, tick.Quantity, tick.Suspicious ?
"1" :
"0");
160 if (tick.TickType ==
TickType.Quote)
162 return ToCsv(milliseconds, tick.BidPrice, tick.BidSize, tick.AskPrice, tick.AskSize, tick.Suspicious ?
"1" :
"0");
164 throw new ArgumentException($
"{securityType} tick could not be created");
168 if (quoteBar !=
null)
170 return ToCsv(milliseconds,
171 ToNonScaledCsv(quoteBar.Bid), quoteBar.LastBidSize,
172 ToNonScaledCsv(quoteBar.Ask), quoteBar.LastAskSize);
175 if (tradeBar !=
null)
177 return ToCsv(milliseconds, tradeBar.Open, tradeBar.High, tradeBar.Low, tradeBar.Close, tradeBar.Volume);
179 throw new ArgumentException($
"{securityType} minute/second bar could not be created", nameof(data));
184 if (bigQuoteBar !=
null)
186 return ToCsv(longTime,
187 ToNonScaledCsv(bigQuoteBar.Bid), bigQuoteBar.LastBidSize,
188 ToNonScaledCsv(bigQuoteBar.Ask), bigQuoteBar.LastAskSize);
191 if (bigTradeBar !=
null)
193 return ToCsv(longTime,
200 throw new ArgumentException($
"{securityType} hour/daily bar could not be created", nameof(data));
208 var tick = data as
Tick;
211 throw new ArgumentException(
"Expected data of type 'Tick'", nameof(data));
213 return ToCsv(milliseconds, tick.BidPrice, tick.AskPrice);
220 throw new ArgumentException(
"Expected data of type 'QuoteBar'", nameof(data));
222 return ToCsv(milliseconds,
223 ToNonScaledCsv(bar.Bid), bar.LastBidSize,
224 ToNonScaledCsv(bar.Ask), bar.LastAskSize);
231 throw new ArgumentException(
"Expected data of type 'QuoteBar'", nameof(data));
233 return ToCsv(longTime,
234 ToNonScaledCsv(bigBar.Bid), bigBar.LastBidSize,
235 ToNonScaledCsv(bigBar.Ask), bigBar.LastAskSize);
243 var tick = (
Tick)data;
244 return ToCsv(milliseconds, tick.LastPrice, tick.Quantity,
string.Empty,
string.Empty,
"0");
250 throw new ArgumentException(
"Expected data of type 'TradeBar'", nameof(data));
252 return ToCsv(milliseconds, bar.Open, bar.High, bar.Low, bar.Close, bar.Volume);
256 return ToCsv(longTime, bigTradeBar.Open, bigTradeBar.High, bigTradeBar.Low, bigTradeBar.Close, bigTradeBar.Volume);
265 var tick = (
Tick)data;
266 if (tick.TickType ==
TickType.Trade)
268 return ToCsv(milliseconds,
269 Scale(tick.LastPrice), tick.Quantity, tick.ExchangeCode, tick.SaleCondition, tick.Suspicious ?
"1" :
"0");
271 if (tick.TickType ==
TickType.Quote)
273 return ToCsv(milliseconds,
274 Scale(tick.BidPrice), tick.BidSize, Scale(tick.AskPrice), tick.AskSize, tick.ExchangeCode, tick.Suspicious ?
"1" :
"0");
276 if (tick.TickType ==
TickType.OpenInterest)
278 return ToCsv(milliseconds, tick.Value);
286 if (quoteBar !=
null)
288 return ToCsv(milliseconds,
289 ToScaledCsv(quoteBar.Bid), quoteBar.LastBidSize,
290 ToScaledCsv(quoteBar.Ask), quoteBar.LastAskSize);
293 if (tradeBar !=
null)
295 return ToCsv(milliseconds,
296 Scale(tradeBar.Open), Scale(tradeBar.High), Scale(tradeBar.Low), Scale(tradeBar.Close), tradeBar.Volume);
299 if (openInterest !=
null)
301 return ToCsv(milliseconds, openInterest.Value);
309 if (bigQuoteBar !=
null)
311 return ToCsv(longTime,
312 ToScaledCsv(bigQuoteBar.Bid), bigQuoteBar.LastBidSize,
313 ToScaledCsv(bigQuoteBar.Ask), bigQuoteBar.LastAskSize);
316 if (bigTradeBar !=
null)
318 return ToCsv(longTime, ToScaledCsv(bigTradeBar), bigTradeBar.Volume);
321 if (bigOpenInterest !=
null)
323 return ToCsv(longTime, bigOpenInterest.Value);
328 throw new ArgumentOutOfRangeException(nameof(resolution), resolution,
null);
336 var tick = (
Tick)data;
337 if (tick.TickType ==
TickType.Trade)
339 return ToCsv(milliseconds,
340 tick.LastPrice, tick.Quantity, tick.ExchangeCode, tick.SaleCondition, tick.Suspicious ?
"1" :
"0");
342 if (tick.TickType ==
TickType.Quote)
344 return ToCsv(milliseconds,
345 tick.BidPrice, tick.BidSize, tick.AskPrice, tick.AskSize, tick.ExchangeCode, tick.Suspicious ?
"1" :
"0");
347 if (tick.TickType ==
TickType.OpenInterest)
349 return ToCsv(milliseconds, tick.Value);
357 if (quoteBar !=
null)
359 return ToCsv(milliseconds,
360 ToNonScaledCsv(quoteBar.Bid), quoteBar.LastBidSize,
361 ToNonScaledCsv(quoteBar.Ask), quoteBar.LastAskSize);
364 if (tradeBar !=
null)
366 return ToCsv(milliseconds,
367 tradeBar.Open, tradeBar.High, tradeBar.Low, tradeBar.Close, tradeBar.Volume);
370 if (openInterest !=
null)
372 return ToCsv(milliseconds, openInterest.Value);
380 if (bigQuoteBar !=
null)
382 return ToCsv(longTime,
383 ToNonScaledCsv(bigQuoteBar.Bid), bigQuoteBar.LastBidSize,
384 ToNonScaledCsv(bigQuoteBar.Ask), bigQuoteBar.LastAskSize);
387 if (bigTradeBar !=
null)
389 return ToCsv(longTime, ToNonScaledCsv(bigTradeBar), bigTradeBar.Volume);
392 if (bigOpenInterest !=
null)
394 return ToCsv(longTime, bigOpenInterest.Value);
399 throw new ArgumentOutOfRangeException(nameof(resolution), resolution,
null);
407 var tick = (
Tick)data;
408 if (tick.TickType ==
TickType.Trade)
410 return ToCsv(milliseconds,
411 tick.LastPrice, tick.Quantity, tick.ExchangeCode, tick.SaleCondition, tick.Suspicious ?
"1" :
"0");
413 if (tick.TickType ==
TickType.Quote)
415 return ToCsv(milliseconds,
416 tick.BidPrice, tick.BidSize, tick.AskPrice, tick.AskSize, tick.ExchangeCode, tick.Suspicious ?
"1" :
"0");
418 if (tick.TickType ==
TickType.OpenInterest)
420 return ToCsv(milliseconds, tick.Value);
428 if (quoteBar !=
null)
430 return ToCsv(milliseconds,
431 ToNonScaledCsv(quoteBar.Bid), quoteBar.LastBidSize,
432 ToNonScaledCsv(quoteBar.Ask), quoteBar.LastAskSize);
435 if (tradeBar !=
null)
437 return ToCsv(milliseconds,
438 tradeBar.Open, tradeBar.High, tradeBar.Low, tradeBar.Close, tradeBar.Volume);
441 if (openInterest !=
null)
443 return ToCsv(milliseconds, openInterest.Value);
451 if (bigQuoteBar !=
null)
453 return ToCsv(longTime,
454 ToNonScaledCsv(bigQuoteBar.Bid), bigQuoteBar.LastBidSize,
455 ToNonScaledCsv(bigQuoteBar.Ask), bigQuoteBar.LastAskSize);
458 if (bigTradeBar !=
null)
460 return ToCsv(longTime, ToNonScaledCsv(bigTradeBar), bigTradeBar.Volume);
463 if (bigOpenInterest !=
null)
465 return ToCsv(longTime, bigOpenInterest.Value);
470 throw new ArgumentOutOfRangeException(nameof(resolution), resolution,
null);
475 throw new ArgumentOutOfRangeException(nameof(securityType), securityType,
null);
478 throw new NotImplementedException(Invariant(
479 $
"LeanData.GenerateLine has not yet been implemented for security type: {securityType} at resolution: {resolution}"
507 if (baseDataType == typeof(
Tick) ||
553 var securityType = symbol.
SecurityType.SecurityTypeToLower();
555 var market = symbol.
ID.
Market.ToLowerInvariant();
556 var res = resolution.ResolutionToLower();
557 var directory = Path.Combine(securityType, market, res);
566 return !isHourOrDaily ? Path.Combine(directory, symbol.
Value.ToLowerInvariant()) : directory;
570 return !isHourOrDaily ? Path.Combine(directory, symbol.
ID.
Symbol.ToLowerInvariant()) : directory;
574 return !isHourOrDaily ? Path.Combine(directory, symbol.
Underlying.
Value.ToLowerInvariant()) : directory;
583 return Path.Combine(directory, futureOptionPath);
587 return !isHourOrDaily ? Path.Combine(directory, symbol.
ID.
Symbol.ToLowerInvariant()) : directory;
591 throw new ArgumentOutOfRangeException();
604 symbol.
Value.ToLowerInvariant() +
".csv");
620 var directory = Path.Combine(securityType.SecurityTypeToLower(), market.ToLowerInvariant(), resolution.ResolutionToLower());
623 directory = Path.Combine(directory, symbol.ToLowerInvariant());
626 return Path.Combine(directory,
GenerateZipFileName(symbol, securityType, date, resolution));
634 var path = Path.Combine(symbol.
SecurityType.SecurityTypeToLower(), symbol.
ID.
Market,
"universes");
642 path = Path.Combine(path, symbol.
ID.
Symbol.ToLowerInvariant());
646 path = Path.Combine(path,
652 path = Path.Combine(path, symbol.
ID.
Symbol.ToLowerInvariant());
656 throw new ArgumentOutOfRangeException($
"Unsupported security type {symbol.SecurityType}");
688 return Invariant($
"{formattedDate}_{symbol.Value.ToLowerInvariant()}_{tickType}_{resolution}.csv");
693 return $
"{symbol.Value.ToLowerInvariant()}.csv";
696 return Invariant($
"{formattedDate}_{symbol.Value.ToLowerInvariant()}_{resolution.ResolutionToLower()}_{tickType.TickTypeToLower()}.csv");
703 return string.Join(
"_",
705 tickType.TickTypeToLower(),
713 return string.Join(
"_",
716 resolution.ResolutionToLower(),
717 tickType.TickTypeToLower(),
727 var optionTickerBasedPath = symbol.
ID.
Symbol.ToLowerInvariant();
731 return string.Join(
"_",
732 optionTickerBasedPath,
733 tickType.TickTypeToLower(),
741 return string.Join(
"_",
743 optionTickerBasedPath,
744 resolution.ResolutionToLower(),
745 tickType.TickTypeToLower(),
759 string expirationTag;
760 var expiryDate = symbol.
ID.
Date;
764 var contractYearMonth = expiryDate.AddMonths(monthsToAdd).ToStringInvariant(
DateFormat.
YearMonth);
766 expirationTag = $
"{contractYearMonth}_{expiryDate.ToStringInvariant(DateFormat.EightCharacter)}";
770 expirationTag =
"perp";
775 return string.Join(
"_",
776 symbol.
ID.
Symbol.ToLowerInvariant(),
777 tickType.TickTypeToLower(),
782 return string.Join(
"_",
784 symbol.
ID.
Symbol.ToLowerInvariant(),
785 resolution.ResolutionToLower(),
786 tickType.TickTypeToLower(),
792 throw new ArgumentOutOfRangeException();
801 var tickTypeString = tickType.TickTypeToLower();
814 return $
"{symbol.Value.ToLowerInvariant()}.zip";
817 return $
"{formattedDate}_{tickTypeString}.zip";
821 return $
"{symbol.Value.ToLowerInvariant()}_{tickTypeString}.zip";
824 return $
"{formattedDate}_{tickTypeString}.zip";
830 return $
"{optionPath}_{date.Year}_{tickTypeString}_{symbol.ID.OptionStyle.OptionStyleToLower()}.zip";
833 return $
"{formattedDate}_{tickTypeString}_{symbol.ID.OptionStyle.OptionStyleToLower()}.zip";
840 var optionTickerBasedPath = symbol.
ID.
Symbol.ToLowerInvariant();
841 return $
"{optionTickerBasedPath}_{date.Year}_{tickTypeString}_{symbol.ID.OptionStyle.OptionStyleToLower()}.zip";
844 return $
"{formattedDate}_{tickTypeString}_{symbol.ID.OptionStyle.OptionStyleToLower()}.zip";
850 return $
"{symbol.ID.Symbol.ToLowerInvariant()}_{tickTypeString}.zip";
853 return $
"{formattedDate}_{tickTypeString}.zip";
857 throw new ArgumentOutOfRangeException();
868 return $
"{symbol.ToLowerInvariant()}.zip";
873 if (tickType ==
null)
885 var suffix = Invariant($
"_{tickType.Value.TickTypeToLower()}.zip");
886 return zipFileName + suffix;
913 var parts = zipEntryName.Replace(
".csv",
string.Empty).Split(
'_');
921 var style = parts[2].ParseOptionStyle();
922 var right = parts[3].ParseOptionRight();
929 var style = parts[4].ParseOptionStyle();
930 var right = parts[5].ParseOptionRight();
941 var futureExpiry = futureExpiryFunc(expiryYearMonth);
948 var futureExpiry = futureExpiryFunc(expiryYearMonth);
953 throw new NotImplementedException(Invariant(
954 $
"ReadSymbolFromZipEntry is not implemented for {symbol.ID.SecurityType} {symbol.ID.Market} {resolution}"
962 private static long Scale(decimal value)
964 return (
long)(value * 10000);
970 private static string ToCsv(params
object[] args)
973 for (var i = 0; i < args.Length; i++)
976 if (value is decimal)
978 args[i] = ((decimal)value).Normalize();
982 var argsFormatted = args.Select(x => Convert.ToString(x, CultureInfo.InvariantCulture));
983 return string.Join(
",", argsFormatted);
989 private static string ToScaledCsv(
IBar bar)
993 return ToCsv(
string.Empty,
string.Empty,
string.Empty,
string.Empty);
996 return ToCsv(Scale(bar.
Open), Scale(bar.
High), Scale(bar.
Low), Scale(bar.
Close));
1003 private static string ToNonScaledCsv(
IBar bar)
1007 return ToCsv(
string.Empty,
string.Empty,
string.Empty,
string.Empty);
1038 if (type == typeof(
Tick))
1054 if (securityType.Equals(
"alternative", StringComparison.InvariantCultureIgnoreCase))
1070 market =
string.Empty;
1074 var info = SplitDataPath(fileName);
1081 var foundMarket = info.Find(x => existingMarkets.Contains(x.ToLowerInvariant()));
1082 if (foundMarket !=
null)
1084 market = foundMarket;
1089 Log.
Error($
"LeanData.TryParsePath(): Error encountered while parsing the path {fileName}. Error: {e.GetBaseException()}");
1112 resolution =
default;
1116 if (!
TryParsePath(filePath, out symbol, out date, out resolution, out var isUniverses))
1122 var fileName = Path.GetFileNameWithoutExtension(filePath);
1123 if (fileName.Contains(
'_', StringComparison.InvariantCulture))
1126 var tickTypePosition = 1;
1127 if (resolution >=
Resolution.Hour && symbol.SecurityType.IsOption())
1131 tickTypePosition = 2;
1133 tickType = (
TickType)Enum.Parse(typeof(
TickType), fileName.Split(
'_')[tickTypePosition],
true);
1139 catch (Exception ex)
1141 Log.
Debug($
"LeanData.TryParsePath(): Error encountered while parsing the path {filePath}. Error: {ex.GetBaseException()}");
1155 return TryParsePath(fileName, out symbol, out date, out resolution, out _);
1170 date =
default(DateTime);
1171 isUniverses =
default;
1175 var info = SplitDataPath(fileName);
1180 if (startIndex == -1)
1184 Log.
Debug($
"LeanData.TryParsePath(): Failed to parse '{fileName}' unexpected SecurityType");
1194 if (!Enum.TryParse(info[startIndex + 2],
true, out resolution))
1197 isUniverses = info[startIndex + 2].Equals(
"universes", StringComparison.InvariantCultureIgnoreCase);
1204 Log.
Debug($
"LeanData.TryParsePath(): Failed to parse '{fileName}' unexpected Resolution");
1210 (symbol, date) = ParseUniversePath(info, securityType);
1218 var fileNameNoPath = info[info.Count - 1].Split(
'_').First();
1220 if (!DateTime.TryParseExact(fileNameNoPath,
1222 DateTimeFormatInfo.InvariantInfo,
1223 DateTimeStyles.None,
1227 ticker = fileNameNoPath;
1232 ticker = info[info.Count - 2];
1238 market = info[startIndex + 1];
1239 var components = info[startIndex + 3].Split(
'_');
1242 ticker = components[0];
1247 var dateIndex = securityType ==
SecurityType.FutureOption ? startIndex + 5 : startIndex + 4;
1253 var year =
int.Parse(components[1], CultureInfo.InvariantCulture);
1254 date =
new DateTime(year, 01, 01);
1265 symbol = CreateSymbol(ticker, securityType, market,
null, date);
1268 catch (Exception ex)
1270 Log.
Debug($
"LeanData.TryParsePath(): Error encountered while parsing the path {fileName}. Error: {ex.GetBaseException()}");
1295 private static (
Symbol symbol, DateTime processingDate) ParseUniversePath(IReadOnlyList<string> filePathParts,
SecurityType securityType)
1297 if (!filePathParts.Contains(
"universes", StringComparer.InvariantCultureIgnoreCase))
1299 throw new ArgumentException($
"LeanData.{nameof(ParseUniversePath)}:The file path must contain a 'universes' part, but it was not found.");
1302 var symbol =
default(
Symbol);
1303 var market = filePathParts[2];
1304 var ticker = filePathParts[^2];
1305 var universeFileDate = DateTime.ParseExact(filePathParts[^1],
DateFormat.
EightCharacter, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None);
1306 switch (securityType)
1310 var dataType = filePathParts.Contains(
"etf", StringComparer.InvariantCultureIgnoreCase) ? typeof(
ETFConstituentUniverse) : default;
1311 symbol = CreateSymbol(ticker, securityType, market, dataType, universeFileDate);
1314 symbol = CreateSymbol(ticker, securityType, market,
null, universeFileDate);
1317 symbol = CreateSymbol(ticker, securityType, market,
null,
default);
1327 throw new NotSupportedException($
"LeanData.{nameof(ParseUniversePath)}:The security type '{securityType}' is not supported for data universe files.");
1330 return (symbol, universeFileDate);
1351 private static Symbol CreateSymbol(
string ticker,
SecurityType securityType,
string market, Type dataType, DateTime mappingResolveDate =
default)
1355 var symbol =
new Symbol(SecurityIdentifier.GenerateEquity(ticker, market, mappingResolveDate: mappingResolveDate), ticker);
1356 return securityType ==
SecurityType.Option ? Symbol.CreateCanonicalOption(symbol) : symbol;
1362 var underlyingFuture = Symbol.CreateFuture(underlyingTicker, market, mappingResolveDate);
1363 return Symbol.CreateCanonicalOption(underlyingFuture);
1369 var underlyingIndex = Symbol.Create(underlyingTicker,
SecurityType.Index, market);
1370 return Symbol.CreateCanonicalOption(underlyingIndex, ticker, market,
null);
1374 return Symbol.Create(ticker, securityType, market, baseDataType: dataType);
1378 private static List<string> SplitDataPath(
string fileName)
1380 var pathSeparators =
new[] {
'/',
'\\' };
1383 fileName = fileName.Replace(fileName.GetExtension(),
string.Empty);
1386 while (fileName.First() ==
'.' || pathSeparators.Any(x => x == fileName.First()))
1388 fileName = fileName.Remove(0, 1);
1392 return fileName.Split(pathSeparators, StringSplitOptions.RemoveEmptyEntries).ToList();
1466 var period = endTime - startTime;
1475 var nextMidnight = exchangeTimeZoneDate.Date.AddDays(1);
1478 return nextMidnight;
1481 var nextMarketClose = exchangeHours.
GetLastDailyMarketClose(exchangeTimeZoneDate, extendedMarketHours:
false);
1482 if (nextMarketClose > nextMidnight)
1485 if (!exchangeHours.
IsOpen(exchangeTimeZoneDate, extendedMarketHours:
false))
1487 return nextMarketClose;
1489 return nextMidnight;
1491 return nextMarketClose;
1497 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1508 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1519 return dailyStrictEndTimeEnabled;
1552 return dataType !=
null && _strictDailyEndTimesDataTypes.Contains(dataType);
1561 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1564 if (baseData ==
null)
1569 var dataType = baseData.GetType();
1576 if (dailyCalendar.End < baseData.
Time)
1581 baseData.
Time = dailyCalendar.Start;
1582 baseData.
EndTime = dailyCalendar.End;
1592 public static void ParseKey(
string key, out
string fileName, out
string entryName)
1604 var hashIndex = key.LastIndexOf(
"#", StringComparison.Ordinal);
1605 if (hashIndex != -1)
1607 entryName = key.Substring(hashIndex + 1);
1608 fileName = key.Substring(0, hashIndex);
1635 var getConsolidatedBar = () =>
1637 if (lastAggregated != consolidator.Consolidated && consolidator.Consolidated !=
null)
1640 lastAggregated = consolidator.Consolidated;
1641 lastAggregated.
Symbol = symbol;
1642 return lastAggregated;
1647 foreach (var dataPoint
in dataPoints)
1649 consolidator.Update(dataPoint);
1650 var consolidated = getConsolidatedBar();
1651 if (consolidated !=
null)
1653 yield
return (T)consolidated;
1658 consolidator.Scan(Time.EndOfTime);
1659 var lastConsolidated = getConsolidatedBar();
1660 if (lastConsolidated !=
null)
1662 yield
return (T)lastConsolidated;
1666 consolidator.DisposeSafely();