20 using System.Collections.Generic;
21 using System.Collections.ObjectModel;
23 using System.IO.Compression;
36 private readonly List<TradeBar> _dailyDataForEquity;
41 private readonly DateTime _lastDateFromEquityData;
56 _dailyDataForEquity = ReadDailyEquityData(pathForDailyEquityData);
57 _lastDateFromEquityData = _dailyDataForEquity.Last().Time;
67 var orderedDividendSplitQueue =
new Queue<BaseData>(
68 CombineIntraDayDividendSplits(dividendSplitList)
69 .OrderByDescending(x => x.Time));
71 var factorFileRows =
new List<CorporateFactorRow>
81 return RecursivlyGenerateFactorFile(orderedDividendSplitQueue, factorFileRows);
90 private static List<BaseData> CombineIntraDayDividendSplits(List<BaseData> splitDividendList)
92 var splitDividendCollection =
new Collection<BaseData>(splitDividendList);
94 var dateKeysLookup = splitDividendCollection.GroupBy(x => x.Time)
95 .OrderByDescending(x => x.Key)
96 .Select(group => group)
99 var baseDataList =
new List<BaseData>();
100 foreach (var kvpLookup
in dateKeysLookup)
102 if (kvpLookup.Count() > 1)
105 var dividend = kvpLookup.First(x => x.GetType() == typeof(
Dividend)) as
Dividend;
106 var split = kvpLookup.First(x => x.GetType() == typeof(
Split)) as
Split;
107 baseDataList.Add(
new IntraDayDividendSplit(split, dividend));
111 baseDataList.Add(kvpLookup.First());
124 private CorporateFactorProvider RecursivlyGenerateFactorFile(Queue<BaseData> orderedDividendSplits, List<CorporateFactorRow> factorFileRows)
127 if (!orderedDividendSplits.Any())
129 factorFileRows.Add(CreateLastFactorFileRow(factorFileRows, _dailyDataForEquity.Last().Close));
133 var nextEvent = orderedDividendSplits.Dequeue();
136 if (_lastDateFromEquityData > nextEvent.Time)
138 decimal initialReferencePrice = 1;
139 factorFileRows.Add(CreateLastFactorFileRow(factorFileRows, initialReferencePrice));
143 var nextFactorFileRow = CalculateNextFactorFileRow(factorFileRows, nextEvent);
145 if (nextFactorFileRow !=
null)
146 factorFileRows.Add(nextFactorFileRow);
148 return RecursivlyGenerateFactorFile(orderedDividendSplits, factorFileRows);
157 private CorporateFactorRow CreateLastFactorFileRow(List<CorporateFactorRow> factorFileRows, decimal referencePrice)
160 _dailyDataForEquity.Last().Time.Date,
161 factorFileRows.Last().PriceFactor,
162 factorFileRows.Last().SplitFactor,
176 var t = nextEvent.GetType();
181 nextCorporateFactorRow = CalculateNextDividendFactor(nextEvent, factorFileRows.Last());
184 nextCorporateFactorRow = CalculateNextSplitFactor(nextEvent, factorFileRows.Last());
186 case "IntraDayDividendSplit":
187 nextCorporateFactorRow = CalculateIntradayDividendSplit((IntraDayDividendSplit)nextEvent, factorFileRows.Last());
190 throw new ArgumentException(
"Unhandled BaseData type for FactorFileGenerator.");
193 return nextCorporateFactorRow;
205 var row = CalculateNextDividendFactor(intraDayDividendSplit.Dividend, last);
206 return CalculateNextSplitFactor(intraDayDividendSplit.Split, row);
217 var eventDayData = GetDailyDataForDate(dividend.
Time);
220 if (eventDayData ==
null)
225 TradeBar previousClosingPrice = FindPreviousTradableDayClosingPrice(eventDayData.Time);
228 var priceFactor = previousCorporateFactorRow.
PriceFactor *
232 previousClosingPrice.
Time,
233 priceFactor.RoundToSignificantDigits(7),
235 previousClosingPrice.
Close
247 var eventDayData = GetDailyDataForDate(split.
Time);
250 if (eventDayData ==
null)
255 TradeBar previousClosingPrice = FindPreviousTradableDayClosingPrice(eventDayData.Time);
258 previousClosingPrice.
Time,
260 (previousCorporateFactorRow.
SplitFactor / split.
Value).RoundToSignificantDigits(6),
261 previousClosingPrice.
Close
270 private TradeBar GetDailyDataForDate(DateTime date)
272 return _dailyDataForEquity.FirstOrDefault(x => x.Time.Date == date.Date);
280 private TradeBar FindPreviousTradableDayClosingPrice(DateTime date)
283 var lastDateforData = _dailyDataForEquity.Last();
285 while (previousDayData ==
null && date > lastDateforData.EndTime)
287 previousDayData = _dailyDataForEquity.FirstOrDefault(x => x.Time == date.AddDays(-1));
288 date = date.AddDays(-1);
291 return previousDayData;
299 private static List<TradeBar> ReadDailyEquityData(
string pathForDailyEquityData)
301 var dataReader =
new LeanDataReader(pathForDailyEquityData);
302 var bars = dataReader.Parse();
303 return bars.OrderByDescending(x => x.Time)
311 private class IntraDayDividendSplit :
BaseData
320 throw new ArgumentNullException(nameof(split));
323 if (dividend ==
null)
325 throw new ArgumentNullException(nameof(dividend));