Open endk17 opened 2 months ago
Additional comments:
OptionContract
model should be completly changed in case this path works, right? They seem to be different. The new endpoint response has the details in the details
property, but your models doesn't have that. Same for the OHLC, etc. values.
Hi @jhonabreul
Thanks for getting back to me and appreciate the detailed feedback.
Apologies, my initial described technical specification / requirements as noted in https://github.com/QuantConnect/Lean.DataSource.Polygon/issues/12#issuecomment-2088865996 didn't mention that using the new endpoint /v3/snapshot/options/{underlyingAsset}
would be for live trading only.
Currently, IBKR option datasets (US Equity and Options Add-On Streaming Bundle) are being used for historical and back testing purposes.
Would the below PR changes make sense, from your end of things, for this requirement:
/v3/snapshot/options/{underlyingAsset}
OptionContract
model in file OptionContract.cs
to a different naming convention
OptionContractQuery
/v3/reference/options/contracts
and /v3/snapshot/options/{underlyingAsset}
into a combined data model
OptionContract
model in file OptionContract.cs
as to adhere to the current LEAN syntaxOptionContractSnapshot
OptionContract
==> OptionContractQuery
PolygonOptionChainProvider : IOptionChainProvider
in file PolygonOptionChainProvider.cs
to perform two API requests
/v3/reference/options/contracts
/v3/snapshot/options/{underlyingAsset}
OptionContract
and populate it using data from both sources i.e. OptionContractQuery
+ OptionContractSnapshot
Ticker
and ExpirationDate
as keys to ensure data integrity var request1 = new RestRequest("/v3/reference/options/contracts", Method.GET);
var request2 = new RestRequest($"/v3/snapshot/options/{underlying.Value}", Method.GET);
Dictionary<string, CombinedOptionData> combinedOptions = new Dictionary<string, CombinedOptionData>();
foreach (var option in request1)
{
var key = $"{option.Ticker}-{option.ExpirationDate.ToString("yyyy-MM-dd")}";
combinedOptions[key] = new CombinedOptionData
{
Ticker = option.Ticker,
ContractType = option.Right,
ExerciseStyle = option.Style,
ExpirationDate = option.ExpirationDate,
StrikePrice = (double)option.StrikePrice
};
}
foreach (var snapshot in request2)
{
foreach (var result in snapshot.Results)
{
var key = $"{result.Details.Ticker}-{result.Details.ExpirationDate.ToString("yyyy-MM-dd")}";
if (!combinedOptions.TryGetValue(key, out var combinedOption))
{
combinedOption = new CombinedOptionData { Ticker = result.Details.Ticker };
combinedOptions[key] = combinedOption;
}
combinedOption.Greeks = result.Greeks;
combinedOption.LastQuote = result.LastQuote;
combinedOption.LastTrade = result.LastTrade;
}
}
Interested to get your thoughts on this approach
Many thanks Enda
Hi @endk17
The difference between those two endpoints is not just the data model they return. The one being currently used gets the option chain at a given date, that is, all the contracts available for a given underlying at a given date:
The endpoint you propose to use also gets an option chain (with more data like greeks and open interest) but in real time, that is, all contracts available literally today. The IOptionChainProvider.GetOptionContractList
method should be able to get the option chain for a given date, not only for today. And also, that date
argument is not the contracts expiration date; it is the point in time at which you want to get the option chain, which might be today or some past date.
There might be a way to keep using the original endpoint and then get the wanted data for each contract, maybe with another endpoint, but again, I did not find one that would allow us to do this.
Hi @jhonabreul,
I'm working with @endk17 and would like to make a few additions.
Firstly, we don't actually use the method OptionChainProvider.GetOptionContractList
in our algorithm.
We obtain the options chain data through QCAlgorithm.CurrentSlice.OptionChains.Get(<canonicalOptionSymbol>)
.
I'm not sure if this makes a difference, or if OptionChainProvider.GetOptionContractList
with the parameter time=utcNow
is then invoked in the background, but it does show that we only really need it for live trading.
Additionally, Polygon is not officially supported by QC as a data provider for backtesting yet. However, for live trading, Polygon is officially listed as a supported data provider (which is why I think the related GitHub issue should be classified as a bug). Therefore, I believe it makes sense to first ensure that this part of the API (live trading) is functioning flawlessly. For our use case, we only require live trading. For backtesting, we use the default data provider for index options which is Algoseek.
I think PolygonOptionChainProvider.cs
can remain unchanged. However, the data on open interest, Greeks, and IV still need to be feeded into the Slice
objects, and this is not happening at the moment. Hence the warning
Warning: USA IndexOption OpenInterest data not supported. Please consider reviewing the data providers selection.
As far as I can see, this can only be achieved through the API endpoint /v3/snapshot/options/{underlyingAsset}
.
I'm also wondering, when real-time data from Polygon comes in, how are fields/attributes like OptionContract.OpenInterest
updated? It seems that this is not currently being done.
I'm not sufficiently familiar with C# and the DataSource plugins of LEAN to implement these changes myself. I believe these adjustments would be better handled by experts like you or other developers from the QC team.
@jhonabreul Here is a simple algorithm that reproduces the bug:
# region imports
from AlgorithmImports import *
# endregion
class IndexOptionAlgorithm(QCAlgorithm):
def initialize(self):
self.set_start_date(2024, 1, 1)
self.set_end_date(2024, 5, 1)
self.set_cash(100000)
self.spx = self.add_index('SPX')
self.spx_option = self.add_index_option(self.spx.symbol)
self.spx_option.set_filter(-1, 1, 0, 100)
def on_data(self, data: Slice):
if self.algorithm_mode is not AlgorithmMode.LIVE:
return
chain = data.option_chains.get(self.spx_option.symbol)
if not chain:
return
for contract in chain:
self.log(f"{contract.symbol}| open interest: {contract.open_interest}; delta: {contract.greeks.delta}; implied volatility: {contract.implied_volatility}.")
When deploying this algorithm for live trading with QC + Polygon as data providers, the following logs are generated:
2024-05-10 17:37:48 Launching analysis for L-3ffd0d19687922fd9e89e48e6bdf8fea with LEAN Engine v2.5.0.0.16423
2024-05-10 17:37:54 Paper Brokerage account base currency: USD
2024-05-10 17:38:08 Warning: usa IndexOption OpenInterest data not supported. Please consider reviewing the data providers selection.
2024-05-10 17:39:00 SPX 240517C05215000| open interest: 0.0; delta: 0.532253383735248; implied volatility: 0.0920031928428969.
2024-05-10 17:39:00 SPX 240517C05220000| open interest: 0.0; delta: 0.505825425148433; implied volatility: 0.0918866720162672.
2024-05-10 17:39:00 SPX 240517P05215000| open interest: 0.0; delta: -0.470339109238199; implied volatility: 0.102137279946327.
2024-05-10 17:39:00 SPX 240517P05220000| open interest: 0.0; delta: -0.49415161757284; implied volatility: 0.101699571257173.
2024-05-10 17:39:00 SPX 240621C05215000| open interest: 0.0; delta: 0.558908042608909; implied volatility: 0.109208822620727.
2024-05-10 17:39:00 SPX 240621C05220000| open interest: 0.0; delta: 0.549011714694276; implied volatility: 0.108904994834179.
2024-05-10 17:39:00 SPX 240621P05215000| open interest: 0.0; delta: -0.442198760403517; implied volatility: 0.112071579867093.
2024-05-10 17:39:00 SPX 240621P05220000| open interest: 0.0; delta: -0.451815241524863; implied volatility: 0.111652211549492.
2024-05-10 17:39:00 SPX 240719C05215000| open interest: 0.0; delta: 0.571491234138189; implied volatility: 0.116239701209309.
2024-05-10 17:39:00 SPX 240719C05220000| open interest: 0.0; delta: 0.564330031525248; implied volatility: 0.115874306439842.
2024-05-10 17:39:00 SPX 240719P05215000| open interest: 0.0; delta: -0.427852489705179; implied volatility: 0.114750769139942.
2024-05-10 17:39:00 SPX 240719P05220000| open interest: 0.0; delta: -0.435078075633236; implied volatility: 0.114323583761875.
2024-05-10 17:39:00 SPX 240816C05220000| open interest: 0.0; delta: 0.575357028689254; implied volatility: 0.121746578619667.
2024-05-10 17:39:00 SPX 240816P05220000| open interest: 0.0; delta: -0.423570866189567; implied volatility: 0.1191776470517.
Here, I notice that it seems to work with delta and IV, and the problem is limited to the open interest.
Description
Related Issue
https://github.com/QuantConnect/Lean.DataSource.Polygon/issues/12
Motivation and Context
The original implementation of Polygon Options endpoint did not support parsing of data objects: open interest, greeks, Implied volatility, last pice + volume
Types of changes
Checklist:
bug-<issue#>-<description>
orfeature-<issue#>-<description>