Hey Martin, I'll post a block of code of a base algorithm as the next post in this series. (cant post backtest because it never completed!)
Â
This isn't exactly my code, but a much reduced version just to replicate the error. Hope it helps! Let me know how I can further improve/assist <3
Â
Best,
Â
JM
Â
from datetime import datetime
from collections import *
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Orders import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Selection import *
from QuantConnect.Algorithm.Framework.Execution import *
from QuantConnect.Algorithm.Framework.Risk import *
from Execution.StandardDeviationExecutionModel import StandardDeviationExecutionModel
import decimal as d
class ETFSimple(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2021,3,1)
self.SetCash(1000000)
self.SetPortfolioConstruction(InsightWeightingPortfolioConstructionModel()) #we want our portfolio to be made up of insights
self.SetExecution(StandardDeviationExecutionModel(5, 1, Resolution.Daily))
self.SetBrokerageModel(BrokerageName.AlphaStreams) #required brokerage model
self.STRIKES = 30 # no of strikes around ATM => for uni selection
self.MIN_EXPIRY = 75 # min num of days to expiration => for uni selection
self.MAX_EXPIRY = 175 # max num of days to expiration => for uni selection
self.SC_MIN_DELTA = d.Decimal(0.15)
self.SC_MAX_DELTA = d.Decimal(0.35)
self.MIN_PREMIUM = d.Decimal(0.05)
equity = self.AddEquity("SPY", Resolution.Minute)
option = self.AddOption("SPY", Resolution.Minute)
self.optionSymbol = option.Symbol
# set strike/expiry filter for this option chain
option.SetFilter(-self.STRIKES, self.STRIKES, timedelta(self.MIN_EXPIRY), timedelta(self.MAX_EXPIRY))
# for greeks and pricer (needs some warmup) - https://github.com/QuantConnect/Lean/blob/21cd972e99f70f007ce689bdaeeafe3cb4ea9c77/Common/Securities/Option/OptionPriceModels.cs#L81
option.PriceModel = OptionPriceModels.CrankNicolsonFD() # both European & American, automatically
# this is needed for Greeks calcs
self.SetWarmUp(TimeSpan.FromDays(self.MAX_EXPIRY))
def OnData(self, slice):
if (self.IsWarmingUp): return
self.shortCall(slice)
def shortCall(self,slice):
chain = slice.OptionChains.get(self.optionSymbol, None)
if not chain:
return
# filter the put options contracts
calls = [x for x in chain if x.Right == OptionRight.Call and abs(x.Greeks.Delta) > self.SC_MIN_DELTA and abs(x.Greeks.Delta) < self.SC_MAX_DELTA and x.BidPrice > self.MIN_PREMIUM]
# sorted the contracts according to the lowest price and the shortest expiry
contracts = sorted(sorted(calls, key = lambda x: x.BidPrice),
key = lambda x: x.Expiry)
if len(contracts) == 0: return
scCall = contracts[0].Symbol
self.EmitInsights(Insight.Price(scCall, timedelta(self.MIN_EXPIRY), InsightDirection.Down, None, None, None, .015))