Hi,
I wrote code that prints call and put options delta of SPY and I compare it to the values in optionet explorer (which I know are correct).
the call options delta are accurate, but the PUTs are not.
For example:
2020-01-02 09:31:00 SPY 200221P00316000, strike: 316.0, Delta: -0.21
while in optionet explorer the same option, at the same time, has 30.11 delta.
why there is such difference?
Thanks,
from QuantConnect.Securities.Option import OptionPriceModels
from datetime import timedelta
class LongStrangleAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2020, 1, 1)
self.SetEndDate(2020, 2, 1)
self.SetCash(100000)
equity = self.AddEquity("SPY", Resolution.Minute)
equity.SetDataNormalizationMode(DataNormalizationMode.Raw) # required when working with options
option = self.AddOption("SPY", Resolution.Minute)
self.symbol = option.Symbol
# set our strike/expiry filter for this option chain
option.SetFilter(-40, 40, timedelta(45), timedelta(55))
option.PriceModel = OptionPriceModels.CrankNicolsonFD() # both European & American, automatically
# this is needed for Greeks calcs
self.SetWarmUp(TimeSpan.FromDays(50)) #TODO: better understand how much time is required
def OnData(self,slice):
if self.IsWarmingUp: return
if not self.Portfolio.Invested:
self.OpenStrangle(slice)
def OpenStrangle(self, slice):
call_option = self.FindOptionByDelta(slice, OptionRight.Call, 0.2)
put_option = self.FindOptionByDelta(slice, OptionRight.Put, 0.2)
if call_option != None and put_option != None:
#self.PrintOptionContract(call_option)
#self.PrintOptionContract(put_option)
self.Sell(call_option.Symbol ,1)
self.Sell(put_option.Symbol ,1)
# find the option with the closest delta the input parameter
def FindOptionByDelta(self, slice, optionType, delta):
for i in slice.OptionChains:
if i.Key != self.symbol: continue
optionchain = i.Value
options_by_type = [x for x in optionchain if x.Right == optionType]
self.PrintOptionContracts(options_by_type)
contracts = sorted(options_by_type, key = lambda x: abs(x.Greeks.Delta - delta))
if len(contracts) == 0: return None #no option was found
return contracts[0]
def PrintOptionContract(self, contract):
self.Log(contract.Symbol.Value + ", strike: " + str(contract.Strike) + ", Delta: " + str(contract.Greeks.Delta) + ", Vega: " + str(contract.Greeks.Vega) +", AskPrice: " + str(contract.AskPrice) + ", Underlying Price: " + str(contract.UnderlyingLastPrice))
def PrintOptionContracts(self, contracts):
for contract in contracts:
self.PrintOptionContract(contract)
Shay Hazan
It seems like the problem comes from the vega that is also different (only on for PUTs) - but why?
Ernest Shaggleford
Hi Shay,
the difference may be due to the use of different option pricing models.
Are you using the same pricing model as is being used by optionet explorer ?
i.e. does optionet explorer use the CrankNicolsonFD model that the algo is using ?
re: "has 30.11 delta." vs "Delta: -0.21".
Normally Put option Delta is expressed as a -ve value between -1 and 0, so "30.11" as a +ve value for a Put doesn't look correct.
Another aspect to consider is that the warmup period for the pricing model can impact the accuracy of the option greeks.
Best,
ES.
Shay Hazan
Thanks.
When mentioning delta of 30.11, I mean 0.3011 (usually options traders talk about delta in tens :)). Both of them with negative delta (so it's ok).
Anyway, it means that there is 0.1 (i.e. 10) delta differece between the calculations, which is a lot.
Regarding the warmup period, you can see in the code above that it has 50 days, but also with 100 days I get the same results.
Optionet explorer uses B&S model, so I expect to have discrepancy, but not that big.
Since all trading platform (that I'm aware of) are using B&S model for calculating greeks, then having such discrepancy will cause the backtest to not simulate correctly what I will do in live.
I tried to set B&S model in QC code, but it doesn't work (return zeros if I'm not wrong).
Is there any way to make QC return greek values close to what I see on the different trading plaforms?
Thanks,
Ernest Shaggleford
Hi Shay,
For "B&S" I'm assuming you're referring to the Black-Scholes model and not the Bjerksund-Stensland model ?
My understanding is that Black-Scholes model is typically used for pricing European style, whereas the Bjerksund-Stensland model is typically used for pricing American style.
re: "Since all trading platform (that I'm aware of) are using B&S model for calculating greeks":
May I ask how you determined that all trading platforms are using B&S (Black-Scholes), as my understanding is that this can vary per platform, and that also some platforms support configuring the model to be used for pricing, such as ThinkOrSwim (TOS). I believe that the default for TOS is Bjerksund-Stensland with the mid price used for pricing input.
In your algo, did you select the CrankNicolsonFD European model in the expectation that it would be similar to Black-Scholes?
All I can suggest is to try using the following for comparison.
BinomialCoxRossRubinstein - Pricing engine for vanilla options using binomial trees
BaroneAdesiWhaley - Pricing engine for American options (1987)
BjerksundStensland - Pricing engine for American options (1993)
Best,
ES.
Ernest Shaggleford
Hi Shay,
btw BlackSholes is also available in the OptionPriceModels.
For the full set of supported models refer to
https://github.com/QuantConnect/Lean/blob/master/Common/Securities/Option/OptionPriceModels.cs
Best,
ES.
Shay Hazan
Hi,
Thanks for the respose.
You're correct, for B&S I meant "Black-Scholes".
I work with 3 different brokers and they all show the same delta value for all options, so I expect the QC will have the same value.
I tried changing the model to different models, but they all give the "wrong" value (0.21 instead of 0.30).
For "BlackScholes" I get delta and vega 0 - I don't know why it's different from the other models.
After checking it further, it seems that delta issue comes from vega, i.e. the vega is also different, so I assume that it effects the delta.
What do you think?
thanks,
Laurent Crouzet
Shay Hazan For SPY, there is a (rather big!) dividend on the 3rd Friday of March/June/September/December: around 1.4/1.5$, or almost 0.5%.
As the SPY options are American (not European) options, there could be a discrepancy on the Delta of put options that might explain the issue you are describing.
Shay Hazan
I thought about it, but why the brokers' plaforms show different delta?
thanks,
Ernest Shaggleford
Hi Shay,
I don't use BlackScholes, as I typically use BjerksundStensland, so out of interest, I ran a quick test using BlackScholes in one of my test algorithms, to find that when using the BlackScholes pricing model, only the following model attributes are populated in the contract:
underlyingSecurity.VolatilityModel.Volatility,
contract.ImpliedVolatility
The following pricing model attributes are not populated in the contract:
contract.TheoreticalPrice,
contract.Greeks.Delta,
contract.Greeks.Gamma,
contract.Greeks.Vega,
contract.Greeks.Rho,
contract.Greeks.Theta / 365.0m,
eg.
2017-06-01 15:45:00 : ---> chain: 6/1/2017 3:45:00 PM, key=?AAPL, value=?AAPL: ¤0.00
2017-06-01 15:45:00 : AAPL 170616C00148000,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=5.4500 Ask=5.5500 Last=5.0200 OI=279 σ=0.174 NPV=0.000 ΔD=0.000 ΓG=0.000 ν=0.000 ρ=0.00 ΘT=0.00 IV=0.175
2017-06-01 15:45:00 : AAPL 170616C00149000,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=4.6500 Ask=4.7000 Last=4.5000 OI=366 σ=0.174 NPV=0.000 ΔD=0.000 ΓG=0.000 ν=0.000 ρ=0.00 ΘT=0.00 IV=0.172
2017-06-01 15:45:00 : AAPL 170616C00150000,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=3.8500 Ask=3.9000 Last=3.8500 OI=58784 σ=0.174 NPV=0.000 ΔD=0.000 ΓG=0.000 ν=0.000 ρ=0.00 ΘT=0.00 IV=0.166
2017-06-01 15:45:00 : AAPL 170616C00152500,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=2.2000 Ask=2.2100 Last=2.1700 OI=4314 σ=0.174 NPV=0.000 ΔD=0.000 ΓG=0.000 ν=0.000 ρ=0.00 ΘT=0.00 IV=0.157
2017-06-01 15:45:00 : AAPL 170616C00155000,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=1.0800 Ask=1.0900 Last=1.0900 OI=89754 σ=0.174 NPV=0.000 ΔD=0.000 ΓG=0.000 ν=0.000 ρ=0.00 ΘT=0.00 IV=0.154
2017-06-01 15:45:00 : AAPL 170616C00157500,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=0.4800 Ask=0.4900 Last=0.4700 OI=5869 σ=0.174 NPV=0.000 ΔD=0.000 ΓG=0.000 ν=0.000 ρ=0.00 ΘT=0.00 IV=0.157
2017-06-01 15:45:00 : AAPL 170721C00150000,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=5.5000 Ask=5.6000 Last=5.5500 OI=35777 σ=0.174 NPV=0.000 ΔD=0.000 ΓG=0.000 ν=0.000 ρ=0.00 ΘT=0.00 IV=0.169
2017-06-01 15:45:00 : AAPL 170721C00155000,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=2.9000 Ask=2.9600 Last=2.8900 OI=42620 σ=0.174 NPV=0.000 ΔD=0.000 ΓG=0.000 ν=0.000 ρ=0.00 ΘT=0.00 IV=0.166
But using BjerksundStensland pricing model, all the Greeks and volatility model attributes are populated.
So it looks as though the BlackScholes pricing model is not supporting the pricing model attributes, only the volatility model attributes.
2017-06-01 15:45:00 : ---> chain: 6/1/2017 3:45:00 PM, key=?AAPL, value=?AAPL: ¤0.00
2017-06-01 15:45:00 : AAPL 170616C00148000,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=5.4500 Ask=5.5500 Last=5.0200 OI=279 σ=0.174 NPV=5.492 ΔD=0.832 ΓG=0.047 ν=7.796 ρ=5.00 ΘT=-0.05 IV=0.175
2017-06-01 15:45:00 : AAPL 170616C00149000,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=4.6500 Ask=4.7000 Last=4.5000 OI=366 σ=0.174 NPV=4.696 ΔD=0.779 ΓG=0.055 ν=9.198 ρ=4.70 ΘT=-0.06 IV=0.172
2017-06-01 15:45:00 : AAPL 170616C00150000,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=3.8500 Ask=3.9000 Last=3.8500 OI=58784 σ=0.174 NPV=3.958 ΔD=0.719 ΓG=0.063 ν=10.454 ρ=4.36 ΘT=-0.06 IV=0.166
2017-06-01 15:45:00 : AAPL 170616C00152500,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=2.2000 Ask=2.2100 Last=2.1700 OI=4314 σ=0.174 NPV=2.408 ΔD=0.544 ΓG=0.074 ν=12.293 ρ=3.32 ΘT=-0.07 IV=0.157
2017-06-01 15:45:00 : AAPL 170616C00155000,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=1.0800 Ask=1.0900 Last=1.0900 OI=89754 σ=0.174 NPV=1.311 ΔD=0.363 ΓG=0.070 ν=11.633 ρ=2.23 ΘT=-0.07 IV=0.154
2017-06-01 15:45:00 : AAPL 170616C00157500,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=0.4800 Ask=0.4900 Last=0.4700 OI=5869 σ=0.174 NPV=0.633 ΔD=0.211 ΓG=0.054 ν=8.951 ρ=1.30 ΘT=-0.05 IV=0.157
2017-06-01 15:45:00 : AAPL 170721C00150000,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=5.5000 Ask=5.6000 Last=5.5500 OI=35777 σ=0.174 NPV=5.659 ΔD=0.639 ΓG=0.038 ν=21.203 ρ=12.61 ΘT=-0.04 IV=0.169
2017-06-01 15:45:00 : AAPL 170721C00155000,Time=6/1/2017 3:45:00 PM ULPrice=152.9450 Bid=2.9000 Ask=2.9600 Last=2.8900 OI=42620 σ=0.174 NPV=3.094 ΔD=0.439 ΓG=0.040 ν=22.315 ρ=8.77 ΘT=-0.04 IV=0.166
I think you're raising a very interesting question as to why the QC Lean pricing models PUT Greeks are not even close to the Broker's Greeks. It may be related to the Dividend adjustment as mentioned by Laurent, but I'm no expert in the details of these models, so I can't confirm this.
I recently raised a question in the forum on why the Interactive Brokers option contract Greek values are ignored for Live mode and have not received any response. I asked the question in relation to being able to use the Greek values provided by the broker directly. This could then support contract selection via Greeks such as Delta, for example, when using the OptionChainProvider selection and filtering approach. This approach would also support keeping the live subscription under the 100 symbol default data lines allowance, and would also support trading options on different underlying stocks while keeping within the data lines allowance.
Of course, this doesn't help the back test situation, but I'd suggest for Live mode, that it would be preferrable to be able to select option trades using the Greeks provided directly by the broker, as this is how option traders typically select contracts to trade.
Best,
ES.
Derek Melchin
Hi Shay,
The OptionNet Explorer documentation shows their platform uses the Black-Scholes pricing model to calculate the greeks. We can specify our algorithm to use this model with the following line in Initialize:
option.PriceModel = OptionPriceModels.BlackScholes()
Although, it seems there is currently a bug with this model as the greeks always evaluate to 0. I've created a GitHub Issue to address this problem. Its progress can be viewed here.
Best,
Derek Melchin
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Shay Hazan
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!