17 using System.Collections.Generic;
18 using System.Globalization;
21 using System.Runtime.CompilerServices;
46 .Select(x => x.ToLowerInvariant()).Union(
new[] {
"alternative" }).ToHashSet();
56 var clone = data.
Clone();
57 clone.
Time = data.
Time.ConvertTo(exchangeTimeZone, dataTimeZone);
58 return GenerateLine(clone, clone.Symbol.ID.SecurityType, resolution);
71 var index = line.IndexOf(
',', StringComparison.InvariantCulture);
72 return date.AddTicks(Convert.ToInt64(10000 * decimal.Parse(line.AsSpan(0, index))));
77 throw new ArgumentOutOfRangeException(nameof(resolution), resolution,
null);
86 var milliseconds = data.
Time.TimeOfDay.TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
95 var tick = (
Tick) data;
98 return ToCsv(milliseconds, Scale(tick.LastPrice), tick.Quantity, tick.ExchangeCode, tick.SaleCondition, tick.Suspicious ?
"1" :
"0");
100 if (tick.TickType ==
TickType.Quote)
102 return ToCsv(milliseconds, Scale(tick.BidPrice), tick.BidSize, Scale(tick.AskPrice), tick.AskSize, tick.ExchangeCode, tick.SaleCondition, tick.Suspicious ?
"1" :
"0");
108 if (tradeBar !=
null)
110 return ToCsv(milliseconds, Scale(tradeBar.Open), Scale(tradeBar.High), Scale(tradeBar.Low), Scale(tradeBar.Close), tradeBar.Volume);
113 if (quoteBar !=
null)
115 return ToCsv(milliseconds,
116 ToScaledCsv(quoteBar.Bid), quoteBar.LastBidSize,
117 ToScaledCsv(quoteBar.Ask), quoteBar.LastAskSize);
124 if (bigTradeBar !=
null)
126 return ToCsv(longTime, Scale(bigTradeBar.Open), Scale(bigTradeBar.High), Scale(bigTradeBar.Low), Scale(bigTradeBar.Close), bigTradeBar.Volume);
129 if (bigQuoteBar !=
null)
131 return ToCsv(longTime,
132 ToScaledCsv(bigQuoteBar.Bid), bigQuoteBar.LastBidSize,
133 ToScaledCsv(bigQuoteBar.Ask), bigQuoteBar.LastAskSize);
144 var tick = data as
Tick;
147 throw new ArgumentException($
"{securityType} tick could not be created", nameof(data));
149 if (tick.TickType ==
TickType.Trade)
151 return ToCsv(milliseconds, tick.LastPrice, tick.Quantity, tick.Suspicious ?
"1" :
"0");
153 if (tick.TickType ==
TickType.Quote)
155 return ToCsv(milliseconds, tick.BidPrice, tick.BidSize, tick.AskPrice, tick.AskSize, tick.Suspicious ?
"1" :
"0");
157 throw new ArgumentException($
"{securityType} tick could not be created");
161 if (quoteBar !=
null)
163 return ToCsv(milliseconds,
164 ToNonScaledCsv(quoteBar.Bid), quoteBar.LastBidSize,
165 ToNonScaledCsv(quoteBar.Ask), quoteBar.LastAskSize);
168 if (tradeBar !=
null)
170 return ToCsv(milliseconds, tradeBar.Open, tradeBar.High, tradeBar.Low, tradeBar.Close, tradeBar.Volume);
172 throw new ArgumentException($
"{securityType} minute/second bar could not be created", nameof(data));
177 if (bigQuoteBar !=
null)
179 return ToCsv(longTime,
180 ToNonScaledCsv(bigQuoteBar.Bid), bigQuoteBar.LastBidSize,
181 ToNonScaledCsv(bigQuoteBar.Ask), bigQuoteBar.LastAskSize);
184 if (bigTradeBar !=
null)
186 return ToCsv(longTime,
193 throw new ArgumentException($
"{securityType} hour/daily bar could not be created", nameof(data));
201 var tick = data as
Tick;
204 throw new ArgumentException(
"Expected data of type 'Tick'", nameof(data));
206 return ToCsv(milliseconds, tick.BidPrice, tick.AskPrice);
213 throw new ArgumentException(
"Expected data of type 'QuoteBar'", nameof(data));
215 return ToCsv(milliseconds,
216 ToNonScaledCsv(bar.Bid), bar.LastBidSize,
217 ToNonScaledCsv(bar.Ask), bar.LastAskSize);
224 throw new ArgumentException(
"Expected data of type 'QuoteBar'", nameof(data));
226 return ToCsv(longTime,
227 ToNonScaledCsv(bigBar.Bid), bigBar.LastBidSize,
228 ToNonScaledCsv(bigBar.Ask), bigBar.LastAskSize);
236 var tick = (
Tick) data;
237 return ToCsv(milliseconds, tick.LastPrice, tick.Quantity,
string.Empty,
string.Empty,
"0");
243 throw new ArgumentException(
"Expected data of type 'TradeBar'", nameof(data));
245 return ToCsv(milliseconds, bar.Open, bar.High, bar.Low, bar.Close, bar.Volume);
249 return ToCsv(longTime, bigTradeBar.Open, bigTradeBar.High, bigTradeBar.Low, bigTradeBar.Close, bigTradeBar.Volume);
258 var tick = (
Tick)data;
259 if (tick.TickType ==
TickType.Trade)
261 return ToCsv(milliseconds,
262 Scale(tick.LastPrice), tick.Quantity, tick.ExchangeCode, tick.SaleCondition, tick.Suspicious ?
"1" :
"0");
264 if (tick.TickType ==
TickType.Quote)
266 return ToCsv(milliseconds,
267 Scale(tick.BidPrice), tick.BidSize, Scale(tick.AskPrice), tick.AskSize, tick.ExchangeCode, tick.Suspicious ?
"1" :
"0");
269 if (tick.TickType ==
TickType.OpenInterest)
271 return ToCsv(milliseconds, tick.Value);
279 if (quoteBar !=
null)
281 return ToCsv(milliseconds,
282 ToScaledCsv(quoteBar.Bid), quoteBar.LastBidSize,
283 ToScaledCsv(quoteBar.Ask), quoteBar.LastAskSize);
286 if (tradeBar !=
null)
288 return ToCsv(milliseconds,
289 Scale(tradeBar.Open), Scale(tradeBar.High), Scale(tradeBar.Low), Scale(tradeBar.Close), tradeBar.Volume);
292 if (openInterest !=
null)
294 return ToCsv(milliseconds, openInterest.Value);
302 if (bigQuoteBar !=
null)
304 return ToCsv(longTime,
305 ToScaledCsv(bigQuoteBar.Bid), bigQuoteBar.LastBidSize,
306 ToScaledCsv(bigQuoteBar.Ask), bigQuoteBar.LastAskSize);
309 if (bigTradeBar !=
null)
311 return ToCsv(longTime, ToScaledCsv(bigTradeBar), bigTradeBar.Volume);
314 if (bigOpenInterest !=
null)
316 return ToCsv(longTime, bigOpenInterest.Value);
321 throw new ArgumentOutOfRangeException(nameof(resolution), resolution,
null);
329 var tick = (
Tick)data;
330 if (tick.TickType ==
TickType.Trade)
332 return ToCsv(milliseconds,
333 tick.LastPrice, tick.Quantity, tick.ExchangeCode, tick.SaleCondition, tick.Suspicious ?
"1" :
"0");
335 if (tick.TickType ==
TickType.Quote)
337 return ToCsv(milliseconds,
338 tick.BidPrice, tick.BidSize, tick.AskPrice, tick.AskSize, tick.ExchangeCode, tick.Suspicious ?
"1" :
"0");
340 if (tick.TickType ==
TickType.OpenInterest)
342 return ToCsv(milliseconds, tick.Value);
350 if (quoteBar !=
null)
352 return ToCsv(milliseconds,
353 ToNonScaledCsv(quoteBar.Bid), quoteBar.LastBidSize,
354 ToNonScaledCsv(quoteBar.Ask), quoteBar.LastAskSize);
357 if (tradeBar !=
null)
359 return ToCsv(milliseconds,
360 tradeBar.Open, tradeBar.High, tradeBar.Low, tradeBar.Close, tradeBar.Volume);
363 if (openInterest !=
null)
365 return ToCsv(milliseconds, openInterest.Value);
373 if (bigQuoteBar !=
null)
375 return ToCsv(longTime,
376 ToNonScaledCsv(bigQuoteBar.Bid), bigQuoteBar.LastBidSize,
377 ToNonScaledCsv(bigQuoteBar.Ask), bigQuoteBar.LastAskSize);
380 if (bigTradeBar !=
null)
382 return ToCsv(longTime, ToNonScaledCsv(bigTradeBar), bigTradeBar.Volume);
385 if (bigOpenInterest !=
null)
387 return ToCsv(longTime, bigOpenInterest.Value);
392 throw new ArgumentOutOfRangeException(nameof(resolution), resolution,
null);
400 var tick = (
Tick)data;
401 if (tick.TickType ==
TickType.Trade)
403 return ToCsv(milliseconds,
404 tick.LastPrice, tick.Quantity, tick.ExchangeCode, tick.SaleCondition, tick.Suspicious ?
"1":
"0");
406 if (tick.TickType ==
TickType.Quote)
408 return ToCsv(milliseconds,
409 tick.BidPrice, tick.BidSize, tick.AskPrice, tick.AskSize, tick.ExchangeCode, tick.Suspicious ?
"1" :
"0");
411 if (tick.TickType ==
TickType.OpenInterest)
413 return ToCsv(milliseconds, tick.Value);
421 if (quoteBar !=
null)
423 return ToCsv(milliseconds,
424 ToNonScaledCsv(quoteBar.Bid), quoteBar.LastBidSize,
425 ToNonScaledCsv(quoteBar.Ask), quoteBar.LastAskSize);
428 if (tradeBar !=
null)
430 return ToCsv(milliseconds,
431 tradeBar.Open, tradeBar.High, tradeBar.Low, tradeBar.Close, tradeBar.Volume);
434 if (openInterest !=
null)
436 return ToCsv(milliseconds, openInterest.Value);
444 if (bigQuoteBar !=
null)
446 return ToCsv(longTime,
447 ToNonScaledCsv(bigQuoteBar.Bid), bigQuoteBar.LastBidSize,
448 ToNonScaledCsv(bigQuoteBar.Ask), bigQuoteBar.LastAskSize);
451 if (bigTradeBar !=
null)
453 return ToCsv(longTime, ToNonScaledCsv(bigTradeBar), bigTradeBar.Volume);
456 if (bigOpenInterest !=
null)
458 return ToCsv(longTime, bigOpenInterest.Value);
463 throw new ArgumentOutOfRangeException(nameof(resolution), resolution,
null);
468 throw new ArgumentOutOfRangeException(nameof(securityType), securityType,
null);
471 throw new NotImplementedException(Invariant(
472 $
"LeanData.GenerateLine has not yet been implemented for security type: {securityType} at resolution: {resolution}"
500 if (baseDataType == typeof(
Tick) ||
546 var securityType = symbol.
SecurityType.SecurityTypeToLower();
548 var market = symbol.
ID.
Market.ToLowerInvariant();
549 var res = resolution.ResolutionToLower();
550 var directory = Path.Combine(securityType, market, res);
559 return !isHourOrDaily ? Path.Combine(directory, symbol.
Value.ToLowerInvariant()) : directory;
563 return !isHourOrDaily ? Path.Combine(directory, symbol.
ID.
Symbol.ToLowerInvariant()) : directory;
567 return !isHourOrDaily ? Path.Combine(directory, symbol.
Underlying.
Value.ToLowerInvariant()) : directory;
576 return Path.Combine(directory, futureOptionPath);
580 return !isHourOrDaily ? Path.Combine(directory, symbol.
ID.
Symbol.ToLowerInvariant()) : directory;
584 throw new ArgumentOutOfRangeException();
597 symbol.
Value.ToLowerInvariant() +
".csv");
613 var directory = Path.Combine(securityType.SecurityTypeToLower(), market.ToLowerInvariant(), resolution.ResolutionToLower());
616 directory = Path.Combine(directory, symbol.ToLowerInvariant());
619 return Path.Combine(directory,
GenerateZipFileName(symbol, securityType, date, resolution));
640 return Invariant($
"{formattedDate}_{symbol.Value.ToLowerInvariant()}_{tickType}_{resolution}.csv");
645 return $
"{symbol.Value.ToLowerInvariant()}.csv";
648 return Invariant($
"{formattedDate}_{symbol.Value.ToLowerInvariant()}_{resolution.ResolutionToLower()}_{tickType.TickTypeToLower()}.csv");
655 return string.Join(
"_",
657 tickType.TickTypeToLower(),
665 return string.Join(
"_",
668 resolution.ResolutionToLower(),
669 tickType.TickTypeToLower(),
679 var optionTickerBasedPath = symbol.
ID.
Symbol.ToLowerInvariant();
683 return string.Join(
"_",
684 optionTickerBasedPath,
685 tickType.TickTypeToLower(),
693 return string.Join(
"_",
695 optionTickerBasedPath,
696 resolution.ResolutionToLower(),
697 tickType.TickTypeToLower(),
711 string expirationTag;
712 var expiryDate = symbol.
ID.
Date;
716 var contractYearMonth = expiryDate.AddMonths(monthsToAdd).ToStringInvariant(
DateFormat.
YearMonth);
718 expirationTag = $
"{contractYearMonth}_{expiryDate.ToStringInvariant(DateFormat.EightCharacter)}";
722 expirationTag =
"perp";
727 return string.Join(
"_",
728 symbol.
ID.
Symbol.ToLowerInvariant(),
729 tickType.TickTypeToLower(),
734 return string.Join(
"_",
736 symbol.
ID.
Symbol.ToLowerInvariant(),
737 resolution.ResolutionToLower(),
738 tickType.TickTypeToLower(),
744 throw new ArgumentOutOfRangeException();
753 var tickTypeString = tickType.TickTypeToLower();
766 return $
"{symbol.Value.ToLowerInvariant()}.zip";
769 return $
"{formattedDate}_{tickTypeString}.zip";
773 return $
"{symbol.Value.ToLowerInvariant()}_{tickTypeString}.zip";
776 return $
"{formattedDate}_{tickTypeString}.zip";
782 return $
"{optionPath}_{date.Year}_{tickTypeString}_{symbol.ID.OptionStyle.OptionStyleToLower()}.zip";
785 return $
"{formattedDate}_{tickTypeString}_{symbol.ID.OptionStyle.OptionStyleToLower()}.zip";
792 var optionTickerBasedPath = symbol.
ID.
Symbol.ToLowerInvariant();
793 return $
"{optionTickerBasedPath}_{date.Year}_{tickTypeString}_{symbol.ID.OptionStyle.OptionStyleToLower()}.zip";
796 return $
"{formattedDate}_{tickTypeString}_{symbol.ID.OptionStyle.OptionStyleToLower()}.zip";
802 return $
"{symbol.ID.Symbol.ToLowerInvariant()}_{tickTypeString}.zip";
805 return $
"{formattedDate}_{tickTypeString}.zip";
809 throw new ArgumentOutOfRangeException();
820 return $
"{symbol.ToLowerInvariant()}.zip";
825 if (tickType ==
null)
836 var suffix = Invariant($
"_{tickType.Value.TickTypeToLower()}.zip");
837 return zipFileName + suffix;
864 var parts = zipEntryName.Replace(
".csv",
string.Empty).Split(
'_');
872 var style = parts[2].ParseOptionStyle();
873 var right = parts[3].ParseOptionRight();
880 var style = parts[4].ParseOptionStyle();
881 var right = parts[5].ParseOptionRight();
892 var futureExpiry = futureExpiryFunc(expiryYearMonth);
899 var futureExpiry = futureExpiryFunc(expiryYearMonth);
904 throw new NotImplementedException(Invariant(
905 $
"ReadSymbolFromZipEntry is not implemented for {symbol.ID.SecurityType} {symbol.ID.Market} {resolution}"
913 private static long Scale(decimal value)
915 return (
long)(value*10000);
921 private static string ToCsv(params
object[] args)
924 for (var i = 0; i < args.Length; i++)
927 if (value is decimal)
929 args[i] = ((decimal) value).Normalize();
933 var argsFormatted = args.Select(x => Convert.ToString(x, CultureInfo.InvariantCulture));
934 return string.Join(
",", argsFormatted);
940 private static string ToScaledCsv(
IBar bar)
944 return ToCsv(
string.Empty,
string.Empty,
string.Empty,
string.Empty);
947 return ToCsv(Scale(bar.
Open), Scale(bar.
High), Scale(bar.
Low), Scale(bar.
Close));
954 private static string ToNonScaledCsv(
IBar bar)
958 return ToCsv(
string.Empty,
string.Empty,
string.Empty,
string.Empty);
989 if (type == typeof(
Tick))
1005 if (securityType.Equals(
"alternative", StringComparison.InvariantCultureIgnoreCase))
1021 market =
string.Empty;
1025 var info = SplitDataPath(fileName);
1032 var foundMarket = info.Find(x => existingMarkets.Contains(x.ToLowerInvariant()));
1033 if (foundMarket !=
null)
1035 market = foundMarket;
1040 Log.
Error($
"LeanData.TryParsePath(): Error encountered while parsing the path {fileName}. Error: {e.GetBaseException()}");
1063 resolution =
default;
1067 if (!
TryParsePath(filePath, out symbol, out date, out resolution))
1073 var fileName = Path.GetFileNameWithoutExtension(filePath);
1074 if (fileName.Contains(
"_"))
1077 var tickTypePosition = 1;
1078 if (resolution >=
Resolution.Hour && symbol.SecurityType.IsOption())
1082 tickTypePosition = 2;
1084 tickType = (
TickType)Enum.Parse(typeof(
TickType), fileName.Split(
'_')[tickTypePosition],
true);
1090 catch (Exception ex)
1092 Log.
Debug($
"LeanData.TryParsePath(): Error encountered while parsing the path {filePath}. Error: {ex.GetBaseException()}");
1108 date =
default(DateTime);
1112 var info = SplitDataPath(fileName);
1117 if(startIndex == -1)
1121 Log.
Debug($
"LeanData.TryParsePath(): Failed to parse '{fileName}' unexpected SecurityType");
1130 var isUniverses =
false;
1131 if (!Enum.TryParse(info[startIndex + 2],
true, out resolution))
1134 isUniverses = info[startIndex + 2].Equals(
"universes", StringComparison.InvariantCultureIgnoreCase);
1141 Log.
Debug($
"LeanData.TryParsePath(): Failed to parse '{fileName}' unexpected Resolution");
1153 var fileNameNoPath = info[info.Count - 1].Split(
'_').First();
1155 if (!DateTime.TryParseExact(fileNameNoPath,
1157 DateTimeFormatInfo.InvariantInfo,
1158 DateTimeStyles.None,
1162 ticker = fileNameNoPath;
1167 ticker = info[info.Count - 2];
1173 market = info[startIndex + 1];
1174 var components = info[startIndex + 3].Split(
'_');
1177 ticker = components[0];
1182 var dateIndex = securityType ==
SecurityType.FutureOption ? startIndex + 5 : startIndex + 4;
1188 var year =
int.Parse(components[1], CultureInfo.InvariantCulture);
1189 date =
new DateTime(year, 01, 01);
1201 var underlyingFuture =
Symbol.
CreateFuture(underlyingTicker, market, underlyingFutureExpiryDate);
1213 Type dataType =
null;
1214 if (isUniverses && info[startIndex + 3].
Equals(
"etf", StringComparison.InvariantCultureIgnoreCase))
1218 symbol = CreateSymbol(ticker, securityType, market, dataType, date);
1222 catch (Exception ex)
1224 Log.
Debug($
"LeanData.TryParsePath(): Error encountered while parsing the path {fileName}. Error: {ex.GetBaseException()}");
1249 private static Symbol CreateSymbol(
string ticker,
SecurityType securityType,
string market, Type dataType, DateTime mappingResolveDate =
default)
1258 return Symbol.
Create(ticker, securityType, market, baseDataType: dataType);
1262 private static List<string> SplitDataPath(
string fileName)
1264 var pathSeparators =
new[] {
'/',
'\\' };
1267 fileName = fileName.Replace(fileName.GetExtension(),
string.Empty);
1270 while (fileName.First() ==
'.' || pathSeparators.Any(x => x == fileName.First()))
1272 fileName = fileName.Remove(0, 1);
1276 return fileName.Split(pathSeparators, StringSplitOptions.RemoveEmptyEntries).ToList();
1355 if (potentialEnd.Date != endTime.Date)
1359 endTime = potentialEnd;
1362 var period = endTime - startTime;
1369 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1381 public static void ParseKey(
string key, out
string fileName, out
string entryName)
1393 var hashIndex = key.LastIndexOf(
"#", StringComparison.Ordinal);
1394 if (hashIndex != -1)
1396 entryName = key.Substring(hashIndex + 1);
1397 fileName = key.Substring(0, hashIndex);
1414 var getConsolidatedBar = () =>
1416 if (lastAggregated != consolidator.Consolidated && consolidator.Consolidated !=
null)
1419 lastAggregated = consolidator.Consolidated;
1420 lastAggregated.
Symbol = symbol;
1421 return lastAggregated;
1426 foreach (var dataPoint
in dataPoints)
1428 consolidator.Update(dataPoint);
1429 var consolidated = getConsolidatedBar();
1430 if (consolidated !=
null)
1432 yield
return (T)consolidated;
1437 consolidator.Scan(Time.EndOfTime);
1438 var lastConsolidated = getConsolidatedBar();
1439 if (lastConsolidated !=
null)
1441 yield
return (T)lastConsolidated;
1445 consolidator.DisposeSafely();