20 using System.Threading.Tasks;
22 using System.Collections.Generic;
32 protected static Dictionary<Symbol, Dictionary<DateTime, decimal>> _dividendYieldRateProvider;
33 protected static Task _cacheClearTask;
34 private static readonly
object _lock =
new();
36 private DateTime _firstDividendYieldDate =
Time.
Start;
37 private decimal _lastDividendYield = -1;
38 private readonly
Symbol _symbol;
54 if (dueTime > TimeSpan.FromMinutes(10))
57 return dueTime - TimeSpan.FromMinutes(10);
70 if (_cacheClearTask ==
null)
75 if (_cacheClearTask ==
null)
86 private static void StartExpirationTask(TimeSpan cacheRefreshPeriod)
91 _dividendYieldRateProvider =
new();
93 _cacheClearTask = Task.Delay(cacheRefreshPeriod).ContinueWith(_ => StartExpirationTask(cacheRefreshPeriod));
103 Dictionary<DateTime, decimal> symbolDividend;
106 if (!_dividendYieldRateProvider.TryGetValue(_symbol, out symbolDividend))
113 if (symbolDividend ==
null)
118 if (!symbolDividend.TryGetValue(date.Date, out var dividendYield))
120 if (_lastDividendYield == -1)
122 _firstDividendYieldDate = symbolDividend.OrderBy(x => x.Key).First().Key;
123 _lastDividendYield = symbolDividend.OrderBy(x => x.Key).Last().Value;
125 return date < _firstDividendYieldDate
127 : _lastDividendYield;
130 return dividendYield;
140 var corporateFactors = factorFileProvider
143 .Where(corporateFactor => corporateFactor !=
null);
146 if (symbolDividends.Count == 0)
151 _firstDividendYieldDate = symbolDividends.Keys.Min();
152 var lastDate = symbolDividends.Keys.Where(x => x !=
Time.
EndOfTime).Max();
156 for (var date = _firstDividendYieldDate; date <= lastDate; date = date.AddDays(1))
158 if (!symbolDividends.TryGetValue(date, out var currentRate))
160 symbolDividends[date] = _lastDividendYield;
163 _lastDividendYield = currentRate;
166 return symbolDividends;
177 var dividendYieldProvider =
new Dictionary<DateTime, decimal>();
180 var subsequentRate = 0m;
181 foreach (var row
in corporateFactors.Where(x => x.Date !=
Time.
EndOfTime).OrderByDescending(corporateFactor => corporateFactor.Date))
183 var dividendYield = 1 / row.PriceFactor - 1 - subsequentRate;
184 dividendYieldProvider[row.Date] = dividendYield;
185 subsequentRate = dividendYield;
189 var yearlyDividendYieldProvider =
new Dictionary<DateTime, decimal>();
190 foreach (var date
in dividendYieldProvider.Keys.OrderBy(x => x))
193 var yearlyDividend = dividendYieldProvider.Where(kvp => kvp.Key <= date && kvp.Key > date.AddDays(-350)).Sum(kvp => kvp.Value);
195 yearlyDividendYieldProvider[date] = Convert.ToDecimal(Math.Log(1d + (
double)yearlyDividend));
198 if (yearlyDividendYieldProvider.Count == 0)
200 Log.
Error($
"DividendYieldProvider.FromCsvFile({symbol}): no dividend were loaded");
203 return yearlyDividendYieldProvider;