Skip to content

Commit

Permalink
Add support for index historical data
Browse files Browse the repository at this point in the history
  • Loading branch information
jhonabreul committed Jan 8, 2024
1 parent 7fa1fab commit 7e5f655
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 8 deletions.
24 changes: 24 additions & 0 deletions QuantConnect.Polygon.Tests/PolygonDataDownloaderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,30 @@ public void DownloadsHistoricalData(Symbol symbol, Resolution resolution, TimeSp
PolygonHistoryTests.AssertHistoricalDataResults(data, resolution);
}

private static TestCaseData[] IndexHistoricalDataTestCases => PolygonHistoryTests.IndexHistoricalDataTestCases;

[TestCaseSource(nameof(IndexHistoricalDataTestCases))]
[Explicit("This tests require a Polygon.io api key, requires internet and are long.")]
public void DownloadsIndexHistoricalData(Resolution resolution, TimeSpan period, TickType tickType, bool shouldBeEmpy)
{
var symbol = Symbol.Create("SPX", SecurityType.Index, Market.USA);
var request = PolygonHistoryTests.CreateHistoryRequest(symbol, resolution, tickType, period);

var parameters = new DataDownloaderGetParameters(symbol, resolution, request.StartTimeUtc, request.EndTimeUtc, tickType);
var data = _downloader.Get(parameters).ToList();

Log.Trace("Data points retrieved: " + data.Count);

if (shouldBeEmpy)
{
Assert.That(data, Is.Empty);
}
else
{
PolygonHistoryTests.AssertHistoricalDataResults(data, resolution);
}
}

[Test]
[Explicit("This tests require a Polygon.io api key, requires internet and are long.")]
public void DownloadsDataFromCanonicalOptionSymbol()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class PolygonDataQueueHandlerIndicesTests : PolygonDataQueueHandlerBaseTe
[TestCase(Resolution.Hour, 3)]
[Explicit("Tests are dependent on network and take long. " +
"Also, this test will only pass if the subscribed securities are liquid enough to get data in the test run time.")]
public void StreamsDataForDifferentResolutions(Resolution resolution, int period)
public override void StreamsDataForDifferentResolutions(Resolution resolution, int period)
{
base.StreamsDataForDifferentResolutions(resolution, period);
}
Expand Down
43 changes: 43 additions & 0 deletions QuantConnect.Polygon.Tests/PolygonHistoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,49 @@ internal static void AssertHistoricalDataResults(List<BaseData> history, Resolut
}
}

internal static TestCaseData[] IndexHistoricalDataTestCases
{
get
{
return new[]
{
// Trades
new TestCaseData(Resolution.Tick, TimeSpan.FromMinutes(5), TickType.Trade, true), // Tick data is not available for indexes
new TestCaseData(Resolution.Second, TimeSpan.FromMinutes(30), TickType.Trade, false),
new TestCaseData(Resolution.Minute, TimeSpan.FromDays(15), TickType.Trade, false),
new TestCaseData(Resolution.Hour, TimeSpan.FromDays(180), TickType.Trade, false),
new TestCaseData(Resolution.Daily, TimeSpan.FromDays(3650), TickType.Trade, false),

// Quotes: quote data is not available for indexes
new TestCaseData(Resolution.Tick, TimeSpan.FromMinutes(5), TickType.Quote, true),
new TestCaseData(Resolution.Second, TimeSpan.FromMinutes(5), TickType.Quote, true),
new TestCaseData(Resolution.Minute, TimeSpan.FromMinutes(5), TickType.Quote, true),
new TestCaseData(Resolution.Hour, TimeSpan.FromMinutes(5), TickType.Quote, true),
new TestCaseData(Resolution.Daily, TimeSpan.FromMinutes(5), TickType.Quote, true),
};
}
}

[TestCaseSource(nameof(IndexHistoricalDataTestCases))]
[Explicit("This tests require a Polygon.io api key, requires internet and are long.")]
public void GetsIndexHistoricalData(Resolution resolution, TimeSpan period, TickType tickType, bool shouldBeEmpty)
{
var symbol = Symbol.Create("SPX", SecurityType.Index, Market.USA);
var requests = new List<HistoryRequest> { CreateHistoryRequest(symbol, resolution, tickType, period) };
var history = _historyProvider.GetHistory(requests, TimeZones.Utc).ToList();

Log.Trace("Data points retrieved: " + history.Count);

if (shouldBeEmpty)
{
Assert.That(history, Is.Empty);
}
else
{
AssertHistoricalDataResults(history.Select(x => x.AllData).SelectMany(x => x).ToList(), resolution, _historyProvider.DataPointCount);
}
}

[Test]
[Explicit("This tests require a Polygon.io api key, requires internet and are long.")]
public void GetsSameBarCountForDifferentResponseLimits()
Expand Down
7 changes: 2 additions & 5 deletions QuantConnect.Polygon/PolygonSymbolMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ public string GetBrokerageSymbol(Symbol symbol)
brokerageSymbol = ticker;
break;


case SecurityType.Index:
brokerageSymbol = $"I:{ticker}";
break;
Expand Down Expand Up @@ -208,18 +207,16 @@ private Symbol GetLeanOptionSymbol(string polygonSymbol)
var underlying = IndexOptionSymbol.IsIndexOption(ticker)
? Symbol.Create(IndexOptionSymbol.MapToUnderlying(ticker), SecurityType.Index, Market.USA)
: Symbol.Create(ticker, SecurityType.Equity, Market.USA);
var symbol = Symbol.CreateOption(underlying, ticker, Market.USA, OptionStyle.American, optionRight, strike, expirationDate);

return symbol;
return Symbol.CreateOption(underlying, ticker, Market.USA, OptionStyle.American, optionRight, strike, expirationDate);
}

/// <summary>
/// Gets the Lean index symbol for the specified Polygon symbol
/// </summary>
private Symbol GetLeanIndexSymbol(string polygonSymbol)
{
var symbol = Symbol.Create(polygonSymbol.Substring(2), SecurityType.Index, Market.USA);
return symbol;
return Symbol.Create(polygonSymbol.Substring(2), SecurityType.Index, Market.USA);
}
}
}
4 changes: 2 additions & 2 deletions QuantConnect.Polygon/PolygonWebSocketClientWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ public void Subscribe(SubscriptionDataConfig config, out bool usingAggregates)
/// </summary>
private void TrySubscribe(string ticker, SubscriptionDataConfig config, out bool usingAggregates)
{
usingAggregates = false;

// We'll try subscribing assuming the highest subscription plan and work our way down if we get an error
using var subscribedEvent = new ManualResetEventSlim(false);
using var errorEvent = new ManualResetEventSlim(false);
Expand Down Expand Up @@ -193,8 +195,6 @@ void ProcessMessage(object? _, WebSocketMessage wsMessage)
throw new Exception($"PolygonWebSocketClientWrapper.Subscribe(): Failed to subscribe to {ticker}. " +
$"Make sure your subscription plan allows streaming {config.TickType.ToString().ToLowerInvariant()} data.");
}

usingAggregates = false;
}

/// <summary>
Expand Down

0 comments on commit 7e5f655

Please sign in to comment.