From 291aeb9f03c46240d9e528e5525776457662b14f Mon Sep 17 00:00:00 2001 From: Jhonathan Abreu Date: Fri, 23 Feb 2024 16:57:05 -0400 Subject: [PATCH] Return null on unsupported history requests --- .../TradierBrokerageHistoryProviderTests.cs | 29 +++++++------- .../TradierBrokerage.HistoryProvider.cs | 38 ++++++++++--------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/QuantConnect.TradierBrokerage.Tests/TradierBrokerageHistoryProviderTests.cs b/QuantConnect.TradierBrokerage.Tests/TradierBrokerageHistoryProviderTests.cs index 6db3e73..de2d562 100644 --- a/QuantConnect.TradierBrokerage.Tests/TradierBrokerageHistoryProviderTests.cs +++ b/QuantConnect.TradierBrokerage.Tests/TradierBrokerageHistoryProviderTests.cs @@ -43,9 +43,6 @@ private static TestCaseData[] TestParameters { get { - var seasEquity = Symbol.Create("SEAS", SecurityType.Equity, Market.USA); - var seasOptionSymbol = Symbol.CreateOption(seasEquity, Market.USA, OptionStyle.American, OptionRight.Call, 50, new DateTime(2022, 8, 19)); - return new[] { // valid parameters @@ -55,17 +52,15 @@ private static TestCaseData[] TestParameters new TestCaseData(Symbols.AAPL, Resolution.Hour, false, 7 * 2, TickType.Trade), new TestCaseData(Symbols.AAPL, Resolution.Daily, false, 6, TickType.Trade), - // invalid data type, returns empty response - new TestCaseData(Symbols.AAPL, Resolution.Minute, false, 0, TickType.Quote), - new TestCaseData(Symbols.AAPL, Resolution.Minute, false, 0, TickType.OpenInterest), - - new TestCaseData(seasOptionSymbol, Resolution.Daily, false, 0, TickType.Trade), + // invalid tick type, null result + new TestCaseData(Symbols.AAPL, Resolution.Minute, true, 0, TickType.Quote), + new TestCaseData(Symbols.AAPL, Resolution.Minute, true, 0, TickType.OpenInterest), - // invalid canonical symbo, throws "System.ArgumentException : Invalid symbol, cannot use canonical" + // canonical symbol, null result new TestCaseData(Symbols.SPY_Option_Chain, Resolution.Daily, true, 0, TickType.Trade), - // invalid security type, throws "System.ArgumentException : Invalid security type: Forex" - new TestCaseData(Symbols.EURUSD, Resolution.Daily, true, 0, TickType.Trade), + // invalid security type, null result + new TestCaseData(Symbols.EURUSD, Resolution.Daily, true, 0, TickType.Trade) }; } } @@ -90,7 +85,7 @@ public void TearDown() } [Test, TestCaseSource(nameof(TestParameters))] - public void GetsHistory(Symbol symbol, Resolution resolution, bool throwsException, int expectedCount, TickType tickType) + public void GetsHistory(Symbol symbol, Resolution resolution, bool unsupported, int expectedCount, TickType tickType) { if (_useSandbox && (resolution == Resolution.Tick || resolution == Resolution.Second)) { @@ -104,9 +99,9 @@ public void GetsHistory(Symbol symbol, Resolution resolution, bool throwsExcepti var request = new HistoryRequest(startUtc, endUtc, LeanData.GetDataType(resolution, tickType), symbol, resolution, mhdb.ExchangeHours, mhdb.DataTimeZone, null, false, false, DataNormalizationMode.Adjusted, tickType); - if (throwsException) + if (unsupported) { - Assert.Throws(() => GetHistoryHelper(request)); + Assert.IsNull(_brokerage.GetHistory(request)); } else { @@ -197,7 +192,11 @@ private int GetHistoryHelper(HistoryRequest request) { var count = 0; BaseData previous = null; - foreach (var data in _brokerage.GetHistory(request)) + var history = _brokerage.GetHistory(request); + + Assert.IsNotNull(history); + + foreach (var data in history) { Assert.AreEqual(request.Resolution.ToTimeSpan(), data.EndTime - data.Time); diff --git a/QuantConnect.TradierBrokerage/TradierBrokerage.HistoryProvider.cs b/QuantConnect.TradierBrokerage/TradierBrokerage.HistoryProvider.cs index 8600450..d25c334 100644 --- a/QuantConnect.TradierBrokerage/TradierBrokerage.HistoryProvider.cs +++ b/QuantConnect.TradierBrokerage/TradierBrokerage.HistoryProvider.cs @@ -32,6 +32,8 @@ namespace QuantConnect.Brokerages.Tradier public partial class TradierBrokerage { private bool _loggedTradierSupportsOnlyTradeBars; + private bool _loggedUnsupportedAssetForHistory; + private bool _loggedInvalidTimeRangeForHistory; /// /// Gets the history for the requested security @@ -40,19 +42,26 @@ public partial class TradierBrokerage /// An enumerable of bars covering the span specified in the request public override IEnumerable GetHistory(HistoryRequest request) { - if (request.Symbol.ID.SecurityType != SecurityType.Equity && request.Symbol.ID.SecurityType != SecurityType.Option) + if (!CanSubscribe(request.Symbol)) { - throw new ArgumentException($"Invalid security type: {request.Symbol.ID.SecurityType}"); + if (!_loggedUnsupportedAssetForHistory) + { + _loggedUnsupportedAssetForHistory = true; + _algorithm?.Debug("Warning: Tradier does not support this asset for history requests."); + Log.Error("TradierBrokerage.GetHistory(): Unsupported asset: " + request.Symbol.Value); + } + return null; } if (request.StartTimeUtc >= request.EndTimeUtc) { - throw new ArgumentException("Invalid date range specified start time can not be after end time"); - } - - if (request.Symbol.IsCanonical()) - { - throw new ArgumentException("Invalid symbol, cannot use canonical symbols for history request"); + if (!_loggedInvalidTimeRangeForHistory) + { + _loggedInvalidTimeRangeForHistory = true; + _algorithm?.Debug("Warning: The request start date must precede the end date, no history returned."); + Log.Error("TradierBrokerage.GetHistory(): Invalid date range."); + } + return null; } if (request.TickType != TickType.Trade) @@ -63,13 +72,12 @@ public override IEnumerable GetHistory(HistoryRequest request) _algorithm?.Debug("Warning: Tradier history provider only supports trade information, does not support quotes."); Log.Error("TradierBrokerage.GetHistory(): Tradier only supports TradeBars"); } - yield break; + return null; } var start = request.StartTimeUtc.ConvertTo(DateTimeZone.Utc, TimeZones.NewYork); var end = request.EndTimeUtc.ConvertTo(DateTimeZone.Utc, TimeZones.NewYork); - IEnumerable history; switch (request.Resolution) { @@ -97,13 +105,9 @@ public override IEnumerable GetHistory(HistoryRequest request) throw new ArgumentException("Invalid date range specified"); } - foreach (var bar in history.Where(bar => bar.Time >= request.StartTimeLocal && bar.EndTime <= request.EndTimeLocal)) - { - if (request.ExchangeHours.IsOpen(bar.Time, bar.EndTime, request.IncludeExtendedMarketHours)) - { - yield return bar; - } - } + return history.Where(bar => bar.Time >= request.StartTimeLocal && + bar.EndTime <= request.EndTimeLocal && + request.ExchangeHours.IsOpen(bar.Time, bar.EndTime, request.IncludeExtendedMarketHours)); } private IEnumerable GetHistoryTick(HistoryRequest request, DateTime start, DateTime end)