21 using System.Collections.Generic;
44 _securityManager = securityManager;
54 var random =
new Random();
56 if (_settings.RandomSeedSet)
58 random =
new Random(_settings.RandomSeed);
65 if (_settings.SymbolCount > maxSymbolCount)
67 Log.
Error($
"RandomDataGenerator.Run(): Limiting Symbol count to {maxSymbolCount}, we don't have more {_settings.SecurityType} tickers for {_settings.Market}");
68 _settings.SymbolCount = maxSymbolCount;
71 Log.
Trace($
"RandomDataGenerator.Run(): Begin data generation of {_settings.SymbolCount} randomly generated {_settings.SecurityType} assets...");
76 var previousMonth = -1;
78 foreach (var (symbolRef, currentSymbolGroup) in symbolGenerator.GenerateRandomSymbols()
79 .GroupBy(s => s.HasUnderlying ? s.Underlying : s)
80 .Select(g => (g.Key, g.OrderBy(s => s.HasUnderlying).ToList())))
82 Log.
Trace($
"RandomDataGenerator.Run(): Symbol[{++count}]: {symbolRef} Progress: {progress:0.0}% - Generating data...");
84 var tickGenerators =
new List<IEnumerator<Tick>>();
85 var tickHistories =
new Dictionary<Symbol, List<Tick>>();
87 foreach (var currentSymbol
in currentSymbolGroup)
89 if (!_securityManager.
TryGetValue(currentSymbol, out var security))
93 new List<SubscriptionDataConfig>(),
94 underlying: underlyingSecurity);
95 _securityManager.
Add(security);
98 underlyingSecurity ??= security;
101 new TickGenerator(_settings, tickTypesPerSecurityType[currentSymbol.SecurityType].ToArray(), security, randomValueGenerator)
111 while (sync.MoveNext())
113 var dataPoint = sync.Current;
114 if (!_securityManager.
TryGetValue(dataPoint.Symbol, out var security))
116 Log.
Error($
"RandomDataGenerator.Run(): Could not find security for symbol {sync.Current.Symbol}");
120 tickHistories[security.Symbol].Add(dataPoint as
Tick);
121 security.Update(
new List<BaseData> { dataPoint }, dataPoint.GetType(),
false);
124 foreach (var (currentSymbol, tickHistory) in tickHistories)
126 var symbol = currentSymbol;
129 var delistDate = GetDelistingDate(_settings.Start, _settings.End, randomValueGenerator);
130 var willBeDelisted = randomValueGenerator.NextBool(1.0);
133 if (willBeDelisted && tickHistory.Select(tick => tick.Time.Month).Distinct().Count() <= 6)
135 willBeDelisted =
false;
141 randomValueGenerator,
148 var renamedSymbols =
new Dictionary<Symbol, DateTime>();
152 dividendsSplitsMaps.GenerateSplitsDividends(tickHistory);
156 dividendsSplitsMaps.DividendsSplits.Add(
new CorporateFactorRow(
new DateTime(2050, 12, 31), 1m, 1m));
158 if (dividendsSplitsMaps.MapRows.Count > 1)
161 dividendsSplitsMaps.MapRows.RemoveAt(dividendsSplitsMaps.MapRows.Count - 1);
163 dividendsSplitsMaps.MapRows.Add(
new MapFileRow(
new DateTime(2050, 12, 31), dividendsSplitsMaps.CurrentSymbol.Value));
167 if (symbol != dividendsSplitsMaps.CurrentSymbol)
171 foreach (var renameEvent
in dividendsSplitsMaps.MapRows.Skip(1))
176 renamedSymbols.Add(symbol, renameEvent.Date);
178 Log.
Trace($
"RandomDataGenerator.Run(): Symbol[{count}]: {symbol} will be renamed on {renameEvent.Date}");
184 renamedSymbols.Add(symbol,
new DateTime(9999, 12, 31));
187 symbol = dividendsSplitsMaps.CurrentSymbol;
190 var factorFile =
new CorporateFactorProvider(symbol.Value, dividendsSplitsMaps.DividendsSplits, _settings.Start);
191 var mapFile =
new MapFile(symbol.Value, dividendsSplitsMaps.MapRows);
193 factorFile.WriteToFile(symbol);
194 mapFile.WriteToCsv(_settings.Market, symbol.SecurityType);
196 Log.
Trace($
"RandomDataGenerator.Run(): Symbol[{count}]: {symbol} Dividends, splits, and map files have been written to disk.");
201 renamedSymbols.Add(symbol,
new DateTime(9999, 12, 31));
205 var aggregators = CreateAggregators(_settings, tickTypesPerSecurityType[currentSymbol.SecurityType].ToArray()).ToList();
206 Symbol previousSymbol =
null;
207 var currentCount = 0;
208 var monthsTrading = 0;
210 foreach (var renamed
in renamedSymbols)
212 var previousRenameDate = previousSymbol ==
null ?
new DateTime(1, 1, 1) : renamedSymbols[previousSymbol];
213 var previousRenameDateDay =
new DateTime(previousRenameDate.Year, previousRenameDate.Month, previousRenameDate.Day);
214 var renameDate = renamed.Value;
215 var renameDateDay =
new DateTime(renameDate.Year, renameDate.Month, renameDate.Day);
217 foreach (var tick
in tickHistory.Where(tick => tick.Time >= previousRenameDate && previousRenameDateDay != TickDay(tick)))
220 if (TickDay(tick) > renameDateDay)
225 if (tick.Time.Month != previousMonth)
227 Log.
Trace($
"RandomDataGenerator.Run(): Symbol[{count}]: Month: {tick.Time:MMMM}");
228 previousMonth = tick.Time.Month;
232 foreach (var item
in aggregators)
234 tick.Value = tick.Value / dividendsSplitsMaps.FinalSplitFactor;
235 item.Consolidator.Update(tick);
238 if (monthsTrading >= 6 && willBeDelisted && tick.Time > delistDate)
240 Log.
Trace($
"RandomDataGenerator.Run(): Symbol[{count}]: {renamed.Key} delisted at {tick.Time:MMMM yyyy}");
247 progress = 100 * (2 * count - 1) / (2.0 * _settings.SymbolCount);
249 Log.
Trace($
"RandomDataGenerator.Run(): Symbol[{count}]: {renamed.Key} Progress: {progress:0.0}% - Saving data in LEAN format");
252 foreach (var item
in aggregators)
260 writer.Write(item.Flush().Where(data => data.Time > previousRenameDate && previousRenameDateDay != DataDay(data)));
264 progress = 100 * (2 * count) / (2.0 * _settings.SymbolCount);
265 Log.
Trace($
"RandomDataGenerator.Run(): Symbol[{count}]: {symbol} Progress: {progress:0.0}% - Symbol data generation and output completed");
267 previousSymbol = renamed.Key;
273 Log.
Trace(
"RandomDataGenerator.Run(): Random data generation has completed.");
275 DateTime TickDay(
Tick tick) =>
new(tick.
Time.Year, tick.
Time.Month, tick.
Time.Day);
279 public static DateTime GetDateMidpoint(DateTime start, DateTime end)
281 TimeSpan span = end.Subtract(start);
282 int span_time = (int)span.TotalMinutes;
283 double diff_span = -(span_time / 2.0);
284 DateTime start_time = end.AddMinutes(Math.Round(diff_span, 2, MidpointRounding.ToEven));
290 public static DateTime GetDelistingDate(DateTime start, DateTime end, RandomValueGenerator randomValueGenerator)
292 var mid_point = GetDateMidpoint(start, end);
293 var delist_Date = randomValueGenerator.NextDate(mid_point, end,
null);
299 public static IEnumerable<TickAggregator> CreateAggregators(RandomDataGeneratorSettings settings,
TickType[] tickTypes)
302 foreach (var tickAggregator
in TickAggregator.ForTickTypes(settings.SecurityType, settings.Resolution, tickTypes))
304 yield
return tickAggregator;
309 if (settings.IncludeCoarse && settings.Resolution !=
Resolution.Daily)
312 if (tickTypes.Contains(
TickType.Trade))
314 yield
return TickAggregator.ForTickTypes(settings.SecurityType,
Resolution.Daily,
TickType.Trade).Single();
318 yield
return TickAggregator.ForTickTypes(settings.SecurityType,
Resolution.Daily,
TickType.Quote).Single();