|
22 | 22 | using QuantConnect.Research; |
23 | 23 | using QuantConnect.Logging; |
24 | 24 | using QuantConnect.Data.Fundamental; |
| 25 | +using System.Data; |
| 26 | +using QuantConnect.Securities.Future; |
| 27 | +using QuantConnect.Data; |
| 28 | +using NodaTime; |
| 29 | +using QuantConnect.Interfaces; |
| 30 | +using QuantConnect.Data.UniverseSelection; |
25 | 31 |
|
26 | 32 | namespace QuantConnect.Tests.Research |
27 | 33 | { |
@@ -179,6 +185,65 @@ public void CanonicalOptionIntradayQuantBookHistory() |
179 | 185 | } |
180 | 186 | } |
181 | 187 |
|
| 188 | + private static TestCaseData[] CanonicalOptionIntradayHistoryTestCases |
| 189 | + { |
| 190 | + get |
| 191 | + { |
| 192 | + var twx = Symbol.Create("TWX", SecurityType.Equity, Market.USA); |
| 193 | + var twxOption = Symbol.CreateCanonicalOption(twx); |
| 194 | + |
| 195 | + return |
| 196 | + [ |
| 197 | + new TestCaseData(twxOption, new DateTime(2014, 06, 05), (DateTime?)null), |
| 198 | + new TestCaseData(twxOption, new DateTime(2014, 06, 05), new DateTime(2014, 06, 05)), |
| 199 | + new TestCaseData(twxOption, new DateTime(2014, 06, 05), new DateTime(2014, 06, 06)), |
| 200 | + new TestCaseData(twxOption, new DateTime(2014, 06, 05, 0, 0, 0), new DateTime(2014, 06, 05, 15, 0, 0)), |
| 201 | + new TestCaseData(twxOption, new DateTime(2014, 06, 05, 10, 0, 0), new DateTime(2014, 06, 05, 15, 0, 0)), |
| 202 | + new TestCaseData(twxOption, new DateTime(2014, 06, 05, 10, 0, 0), new DateTime(2014, 06, 06)), |
| 203 | + new TestCaseData(twxOption, new DateTime(2014, 06, 05, 10, 0, 0), new DateTime(2014, 06, 06, 10, 0, 0)), |
| 204 | + new TestCaseData(twxOption, new DateTime(2014, 06, 05, 10, 0, 0), new DateTime(2014, 06, 06, 15, 0, 0)) |
| 205 | + ]; |
| 206 | + } |
| 207 | + } |
| 208 | + |
| 209 | + [TestCaseSource(nameof(CanonicalOptionIntradayHistoryTestCases))] |
| 210 | + public void CanonicalOptionIntradayQuantBookHistoryWithIntradayRange(Symbol canonicalOption, DateTime start, DateTime? end) |
| 211 | + { |
| 212 | + var quantBook = new QuantBook(); |
| 213 | + var historyProvider = new TestHistoryProvider(quantBook.HistoryProvider); |
| 214 | + quantBook.SetHistoryProvider(historyProvider); |
| 215 | + quantBook.SetStartDate((end ?? start).Date.AddDays(1)); |
| 216 | + |
| 217 | + var option = quantBook.AddSecurity(canonicalOption); |
| 218 | + var history = quantBook.OptionHistory(canonicalOption, start, end, Resolution.Minute); |
| 219 | + |
| 220 | + Assert.Greater(history.Count, 0); |
| 221 | + |
| 222 | + var symbolsInHistory = history.SelectMany(slice => slice.AllData.Select(x => x.Symbol)).Distinct().ToList(); |
| 223 | + Assert.Greater(symbolsInHistory.Count, 1); |
| 224 | + |
| 225 | + var underlying = symbolsInHistory.Where(x => x == canonicalOption.Underlying).ToList(); |
| 226 | + Assert.AreEqual(1, underlying.Count); |
| 227 | + |
| 228 | + var contractsSymbols = symbolsInHistory.Where(x => x.SecurityType == canonicalOption.SecurityType).ToList(); |
| 229 | + Assert.Greater(contractsSymbols.Count, 1); |
| 230 | + |
| 231 | + var expectedDates = new HashSet<DateTime> { start.Date }; |
| 232 | + if (end.HasValue && end.Value > end.Value.Date) |
| 233 | + { |
| 234 | + expectedDates.Add(end.Value.Date); |
| 235 | + } |
| 236 | + |
| 237 | + var dataDates = history.SelectMany(slice => slice.AllData.Where(x => contractsSymbols.Contains(x.Symbol)).Select(x => x.EndTime.Date)).ToHashSet(); |
| 238 | + CollectionAssert.AreEqual(expectedDates, dataDates); |
| 239 | + |
| 240 | + // OptionUniverse must have been requested for all dates in the range |
| 241 | + foreach (var date in Time.EachTradeableDay(option, start.Date, (end ?? start).Date)) |
| 242 | + { |
| 243 | + Assert.AreEqual(1, historyProvider.HistoryRequests.Count(request => request.DataType == typeof(OptionUniverse) && request.EndTimeLocal == date)); |
| 244 | + } |
| 245 | + } |
| 246 | + |
182 | 247 | [Test] |
183 | 248 | public void OptionContractQuantBookHistory() |
184 | 249 | { |
@@ -301,6 +366,57 @@ public void CanonicalFutureIntradayQuantBookHistory(int maxFilter, int numberOfF |
301 | 366 | } |
302 | 367 | } |
303 | 368 |
|
| 369 | + private static TestCaseData[] CanonicalFutureIntradayHistoryTestCases |
| 370 | + { |
| 371 | + get |
| 372 | + { |
| 373 | + var es = Symbol.Create(Futures.Indices.SP500EMini, SecurityType.Future, Market.CME); |
| 374 | + return |
| 375 | + [ |
| 376 | + new TestCaseData(es, new DateTime(2013, 10, 10), (DateTime?)null), |
| 377 | + new TestCaseData(es, new DateTime(2013, 10, 10), new DateTime(2013, 10, 10)), |
| 378 | + new TestCaseData(es, new DateTime(2013, 10, 10), new DateTime(2013, 10, 11)), |
| 379 | + new TestCaseData(es, new DateTime(2013, 10, 10, 0, 0, 0), new DateTime(2013, 10, 10, 15, 0, 0)), |
| 380 | + new TestCaseData(es, new DateTime(2013, 10, 10, 10, 0, 0), new DateTime(2013, 10, 10, 15, 0, 0)), |
| 381 | + new TestCaseData(es, new DateTime(2013, 10, 10, 10, 0, 0), new DateTime(2013, 10, 11)), |
| 382 | + new TestCaseData(es, new DateTime(2013, 10, 10, 10, 0, 0), new DateTime(2013, 10, 11, 10, 0, 0)), |
| 383 | + new TestCaseData(es, new DateTime(2013, 10, 10, 10, 0, 0), new DateTime(2013, 10, 11, 15, 0, 0)) |
| 384 | + ]; |
| 385 | + } |
| 386 | + } |
| 387 | + |
| 388 | + [TestCaseSource(nameof(CanonicalFutureIntradayHistoryTestCases))] |
| 389 | + public void CanonicalFutureIntradayQuantBookHistoryWithIntradayRange(Symbol canonicalFuture, DateTime start, DateTime? end) |
| 390 | + { |
| 391 | + var quantBook = new QuantBook(); |
| 392 | + var historyProvider = new TestHistoryProvider(quantBook.HistoryProvider); |
| 393 | + quantBook.SetHistoryProvider(historyProvider); |
| 394 | + quantBook.SetStartDate((end ?? start).Date.AddDays(1)); |
| 395 | + var future = quantBook.AddSecurity(canonicalFuture) as Future; |
| 396 | + future.SetFilter(universe => universe); |
| 397 | + |
| 398 | + var history = quantBook.FutureHistory(canonicalFuture, start, end, Resolution.Minute); |
| 399 | + Assert.Greater(history.Count, 0); |
| 400 | + |
| 401 | + var symbolsInHistory = history.SelectMany(slice => slice.AllData.Select(x => x.Symbol)).Distinct().ToList(); |
| 402 | + Assert.Greater(symbolsInHistory.Count, 1); |
| 403 | + |
| 404 | + var expectedDates = new HashSet<DateTime> { start.Date }; |
| 405 | + if (end.HasValue && end.Value > end.Value.Date) |
| 406 | + { |
| 407 | + expectedDates.Add(end.Value.Date); |
| 408 | + } |
| 409 | + |
| 410 | + var dataDates = history.SelectMany(slice => slice.AllData.Select(x => x.EndTime.Date)).ToHashSet(); |
| 411 | + CollectionAssert.AreEqual(expectedDates, dataDates); |
| 412 | + |
| 413 | + // FutureUniverse must have been requested for all dates in the range |
| 414 | + foreach (var date in Time.EachTradeableDay(future, start.Date, (end ?? start).Date)) |
| 415 | + { |
| 416 | + Assert.AreEqual(1, historyProvider.HistoryRequests.Count(request => request.DataType == typeof(FutureUniverse) && request.EndTimeLocal == date)); |
| 417 | + } |
| 418 | + } |
| 419 | + |
304 | 420 | [Test] |
305 | 421 | public void FutureContractQuantBookHistory() |
306 | 422 | { |
@@ -685,5 +801,30 @@ def getHistory(): |
685 | 801 | Assert.IsFalse(pyHistory.HasAttr("data")); |
686 | 802 | } |
687 | 803 | } |
| 804 | + |
| 805 | + private class TestHistoryProvider : HistoryProviderBase |
| 806 | + { |
| 807 | + private IHistoryProvider _provider; |
| 808 | + |
| 809 | + public List<HistoryRequest> HistoryRequests { get; } = new(); |
| 810 | + |
| 811 | + public override int DataPointCount => _provider.DataPointCount; |
| 812 | + |
| 813 | + public TestHistoryProvider(IHistoryProvider provider) |
| 814 | + { |
| 815 | + _provider = provider; |
| 816 | + } |
| 817 | + |
| 818 | + public override void Initialize(HistoryProviderInitializeParameters parameters) |
| 819 | + { |
| 820 | + } |
| 821 | + |
| 822 | + public override IEnumerable<Slice> GetHistory(IEnumerable<HistoryRequest> requests, DateTimeZone sliceTimeZone) |
| 823 | + { |
| 824 | + requests = requests.ToList(); |
| 825 | + HistoryRequests.AddRange(requests); |
| 826 | + return _provider.GetHistory(requests, sliceTimeZone); |
| 827 | + } |
| 828 | + } |
688 | 829 | } |
689 | 830 | } |
0 commit comments