17 using System.Collections.Generic;
34 private readonly
int? _chainContractsLookupLimit;
36 private readonly
int? _resultsLimit;
47 int? resultsLimit = 1) : base(TimeSpan.FromDays(1), futureChainSymbolSelector)
50 if (algorithm ==
null)
52 throw new ArgumentNullException(nameof(algorithm));
55 _algorithm = algorithm;
56 _resultsLimit = resultsLimit;
57 _chainContractsLookupLimit = chainContractsLookupLimit;
68 int? resultsLimit = 1) : this(algorithm, ConvertFutureChainSymbolSelectorToFunc(futureChainSymbolSelector), chainContractsLookupLimit, resultsLimit)
79 filter.DistinctBy(x => x).ToDictionary(x => x.Symbol, x => _marketHoursDatabase.GetEntry(x.ID.Market, x, x.ID.SecurityType))));
87 public IEnumerable<Symbol>
FilterByOpenInterest(IReadOnlyDictionary<Symbol, MarketHoursDatabase.Entry> contracts)
89 var symbols =
new List<Symbol>(_chainContractsLookupLimit.HasValue ? contracts.Keys.OrderBy(x => x.ID.Date).Take(_chainContractsLookupLimit.Value) : contracts.Keys);
90 var openInterest = symbols.GroupBy(x => contracts[x]).SelectMany(g => GetOpenInterest(g.Key, g.Select(i => i))).ToDictionary(x => x.Key, x => x.Value);
92 if (openInterest.Count == 0)
95 $
"{nameof(OpenInterestFutureUniverseSelectionModel)}.{nameof(FilterByOpenInterest)}: Failed to get historical open interest, no symbol will be selected."
97 return Enumerable.Empty<
Symbol>();
100 var filtered = openInterest.OrderByDescending(x => x.Value).ThenBy(x => x.Key.ID.Date).Select(x => x.Key);
101 if (_resultsLimit.HasValue)
103 filtered = filtered.Take(_resultsLimit.Value);
109 private Dictionary<Symbol, decimal> GetOpenInterest(
MarketHoursDatabase.
Entry marketHours, IEnumerable<Symbol> symbols)
111 var current = _algorithm.UtcTime;
112 var exchangeHours = marketHours.ExchangeHours;
113 var endTime = Instant.FromDateTimeUtc(_algorithm.UtcTime).InZone(exchangeHours.TimeZone).ToDateTimeUnspecified();
115 var requests = symbols.Select(
123 exchangeHours.TimeZone,
132 return _algorithm.HistoryProvider.GetHistory(requests, exchangeHours.TimeZone)
133 .Where(s => s.HasData && s.Ticks.Keys.Count > 0)
134 .SelectMany(s => s.Ticks.Select(x =>
new Tuple<Symbol, Tick>(x.Key, x.Value.LastOrDefault())))
135 .GroupBy(x => x.Item1)
136 .ToDictionary(x => x.Key, x => x.OrderByDescending(i => i.Item2.Time).LastOrDefault().Item2.Value);
145 private static Func<DateTime, IEnumerable<Symbol>> ConvertFutureChainSymbolSelectorToFunc(PyObject futureChainSymbolSelector)
147 if (futureChainSymbolSelector.TryConvertToDelegate(out Func<DateTime, IEnumerable<Symbol>> futureSelector))
149 return futureSelector;
155 throw new ArgumentException($
"FutureUniverseSelectionModel.ConvertFutureChainSymbolSelectorToFunc: {futureChainSymbolSelector.Repr()} is not a valid argument.");