Skip to content

Commit

Permalink
Historical data when symbol was restructured (renamed) (#7)
Browse files Browse the repository at this point in the history
* feat: volatile for prevent spamming flags

* test:feat: Download Historical Data when ticker had another name
  • Loading branch information
Romazes committed Mar 18, 2024
1 parent cbacfbb commit 2d68eb5
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 11 deletions.
29 changes: 29 additions & 0 deletions QuantConnect.AlphaVantage.Tests/AlphaVantageDataDownloaderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System.Linq;
using NUnit.Framework;
using QuantConnect.Util;
using QuantConnect.Tests;
using QuantConnect.Securities;
using QuantConnect.Data.Market;
using System.Collections.Generic;
Expand Down Expand Up @@ -57,6 +58,7 @@ public static IEnumerable<TestCaseData> DownloaderValidCaseData
{
get
{
TestGlobals.Initialize();
var AAPL = new Symbol(SecurityIdentifier.GenerateEquity("AAPL", Market.USA, false), "AAPL");
yield return new TestCaseData(AAPL, Resolution.Minute, new DateTime(2024, 1, 1, 5, 30, 0), new DateTime(2024, 2, 1, 20, 0, 0), TickType.Trade);
yield return new TestCaseData(AAPL, Resolution.Minute, new DateTime(2024, 1, 8, 9, 30, 0), new DateTime(2024, 1, 12, 16, 0, 0), TickType.Trade);
Expand Down Expand Up @@ -122,6 +124,33 @@ public void DownloadDataWithDifferentInvalidParameters(Symbol symbol, Resolution
Assert.IsNull(_downloader.Get(downloadParameters)?.ToList());
}

[TestCase("GOOG", "2014/04/01", "2014/06/02", "GOOG", Description = "GOOCV before 2014/04/02, GOOG")]
[TestCase("GOOGL", "2015/10/3", "2015/12/29", "GOOGL", Description = "October 2, 2015. [GOOG -> GOOGL]")]
[TestCase("META", "2021/11/3", "2022/1/2", "META", Description = "October 28, 2021. [FB -> META]")]
public void DownloadHistoricalDataBeforeSymbolWasRestructured(string ticker, DateTime startUtc, DateTime endUtc, string expectedTicker)
{
var symbol = Symbol.Create(ticker, SecurityType.Equity, Market.USA);
//var symbol = new Symbol(SecurityIdentifier.GenerateEquity(ticker, Market.USA, false), ticker);
var downloadParameters = new DataDownloaderGetParameters(symbol, Resolution.Daily, startUtc, endUtc, TickType.Trade);

var baseData = _downloader.Get(downloadParameters).ToList();

Assert.IsNotEmpty(baseData);
Assert.IsTrue(baseData.First().Time >= ConvertUtcTimeToSymbolExchange(symbol, startUtc));
Assert.IsTrue(baseData.Last().Time <= ConvertUtcTimeToSymbolExchange(symbol, endUtc));

foreach (var data in baseData)
{
Assert.IsTrue(data.DataType == MarketDataType.TradeBar);
var tradeBar = data as TradeBar;
Assert.Greater(tradeBar.Open, 0m);
Assert.Greater(tradeBar.High, 0m);
Assert.Greater(tradeBar.Low, 0m);
Assert.Greater(tradeBar.Close, 0m);
Assert.IsTrue(tradeBar.Period.ToHigherResolutionEquivalent(true) == Resolution.Daily);
}
}

private DateTime ConvertUtcTimeToSymbolExchange(Symbol symbol, DateTime dateTimeUtc)
{
var exchangeTimeZone = _marketHoursDatabase.GetExchangeHours(symbol.ID.Market, symbol, symbol.SecurityType).TimeZone;
Expand Down
24 changes: 13 additions & 11 deletions QuantConnect.AlphaVantage/AlphaVantageDataDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,22 @@ public class AlphaVantageDataDownloader : IDataDownloader, IDisposable
/// <summary>
/// Indicates whether the warning for invalid history <see cref="TickType"/> has been fired.
/// </summary>
private bool _invalidHistoryDataTypeErrorFired;
private volatile bool _invalidHistoryDataTypeErrorFired;

/// <summary>
/// Indicates whether the warning for invalid <see cref="SecurityType"/> has been fired.
/// </summary>
private bool _invalidSecurityTypeWarningFired;
private volatile bool _invalidSecurityTypeWarningFired;

/// <summary>
/// Indicates whether a warning for an invalid <see cref="Resolution"/> has been fired, where the resolution is neither daily nor minute-based.
/// </summary>
private bool _invalidResolutionWarningFired;
private volatile bool _invalidResolutionWarningFired;

/// <summary>
/// Indicates whether a warning for an invalid start time has been fired, where the start time is greater than or equal to the end time in UTC.
/// </summary>
private bool _invalidStartTimeErrorFired;
private volatile bool _invalidStartTimeErrorFired;

/// <summary>
/// Represents a mapping of symbols to their corresponding time zones for exchange information.
Expand Down Expand Up @@ -136,8 +136,8 @@ public AlphaVantageDataDownloader(IRestClient restClient, string apiKey)
{
if (!_invalidStartTimeErrorFired)
{
Log.Error($"{nameof(AlphaVantageDataDownloader)}.{nameof(Get)}:InvalidDateRange. The history request start date must precede the end date, no history returned");
_invalidStartTimeErrorFired = true;
Log.Error($"{nameof(AlphaVantageDataDownloader)}.{nameof(Get)}:InvalidDateRange. The history request start date must precede the end date, no history returned");
}
return null;
}
Expand All @@ -146,9 +146,9 @@ public AlphaVantageDataDownloader(IRestClient restClient, string apiKey)
{
if (!_invalidHistoryDataTypeErrorFired)
{
_invalidHistoryDataTypeErrorFired = true;
Log.Error($"{nameof(AlphaVantageDataDownloader)}.{nameof(Get)}: Not supported data type - {tickType}. " +
$"Currently available support only for historical of type - TradeBar");
_invalidHistoryDataTypeErrorFired = true;
}
return null;
}
Expand All @@ -157,17 +157,18 @@ public AlphaVantageDataDownloader(IRestClient restClient, string apiKey)
{
if (!_invalidSecurityTypeWarningFired)
{
Log.Trace($"{nameof(AlphaVantageDataDownloader)}.{nameof(Get)}: Unsupported SecurityType '{symbol.SecurityType}' for symbol '{symbol}'");
_invalidSecurityTypeWarningFired = true;
Log.Trace($"{nameof(AlphaVantageDataDownloader)}.{nameof(Get)}: Unsupported SecurityType '{symbol.SecurityType}' for symbol '{symbol}'");
}
return null;
}

var request = new RestRequest("query", DataFormat.Json);
request.AddParameter("symbol", symbol.Value);
// Always obtain the most relevant ticker symbol based on the current time.
request.AddParameter("symbol", SecurityIdentifier.Ticker(dataDownloaderGetParameters.Symbol, DateTime.UtcNow));
request.AddParameter("datatype", "csv");

IEnumerable<TimeSeries> data = null;
IEnumerable<TimeSeries> data;
switch (resolution)
{
case Resolution.Minute:
Expand All @@ -180,8 +181,8 @@ public AlphaVantageDataDownloader(IRestClient restClient, string apiKey)
default:
if (!_invalidResolutionWarningFired)
{
Log.Trace($"{nameof(AlphaVantageDataDownloader)}.{resolution} resolution not supported by API.");
_invalidResolutionWarningFired = true;
Log.Trace($"{nameof(AlphaVantageDataDownloader)}.{resolution} resolution not supported by API.");
}
return null;
}
Expand All @@ -206,7 +207,8 @@ private IEnumerable<TimeSeries> GetDailyData(RestRequest request, DateTime start
request.AddParameter("function", "TIME_SERIES_DAILY");

// The default output only includes 100 trading days of data. If we want need more, specify full output
if (GetBusinessDays(startUtc, endUtc, symbol) > 100)
// Compare with Today, because request doesn't contain specific DateTime range
if (GetBusinessDays(startUtc, DateTime.UtcNow, symbol) > 100)
{
request.AddParameter("outputsize", "full");
}
Expand Down

0 comments on commit 2d68eb5

Please sign in to comment.