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?

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)

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:

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.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]
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: