| Overall Statistics |
|
Total Trades 105 Average Win 6.60% Average Loss -1.20% Compounding Annual Return 47.653% Drawdown 49.200% Expectancy 3.740 Net Profit 609.746% Sharpe Ratio 1.234 Probabilistic Sharpe Ratio 50.436% Loss Rate 27% Win Rate 73% Profit-Loss Ratio 5.52 Alpha 0.213 Beta 1.796 Annual Standard Deviation 0.399 Annual Variance 0.159 Information Ratio 1.16 Tracking Error 0.29 Treynor Ratio 0.274 Total Fees $639.75 Estimated Strategy Capacity $0.0000000000000000000000000001 Lowest Capacity Asset SPY XRX5OFMJ9L5Y|SPY R735QTJ8XC9X |
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from datetime import timedelta
from QuantConnect.Securities.Option import OptionPriceModels
class DCAintoLEAPs(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2016, 6, 1)
self.SetEndDate(2021, 6, 10)
self.SetWarmUp(90, Resolution.Daily)
self.UniverseSettings.SetLeverage = 1
self.num_buys = 24
self.amt_per_txn = 500000//24
self.SetCash(500000)
self.AddEquity("SPY", Resolution.Daily)
option = self.AddOption("SPY")
option.PriceModel = OptionPriceModels.CrankNicolsonFD()
self.option_symbol = option.Symbol
# set our strike/expiry filter for this option chain
option.SetFilter(self.UniverseFunc)
# use the underlying equity as the benchmark
self.SetBenchmark("SPY")
self.contracts = None
self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.AfterMarketOpen("SPY", 10), self.OnDataTrade)
self.Schedule.On(self.DateRules.WeekStart("SPY"), self.TimeRules.AfterMarketOpen("SPY", 10), self.sell_expiring)
def UniverseFunc(self, universe):
return universe.IncludeWeeklys().Strikes(-100000, 100000).Expiration(timedelta(380), timedelta(545))
def OnData(self,slice):
if not (self.Time.hour == 9 and self.Time.minute == 38): return
for kvp in slice.OptionChains:
if kvp.Key != self.option_symbol: continue
chain = kvp.Value
chain = [x for x in chain if x.Right == OptionRight.Call and 380 <= (x.Expiry-self.Time).days <= 545]
closest_expiry_beyond_1y = sorted(chain,key = lambda x: x.Expiry)[0].Expiry
chain = [x for x in chain if x.Expiry == closest_expiry_beyond_1y]
contracts = sorted(chain, key = lambda x: abs(x.Greeks.Delta-0.4))
self.contracts = contracts
def sell_expiring(self):
# Sell calls that are expiring within a week
leaps = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.Option]
for x in leaps:
if (self.Securities[x].Expiry.date() - self.Time.date()).days <= 14:
self.Liquidate(x)
def OnDataTrade(self):
# Buy calls
if len(self.contracts) == 0: pass
symbol = self.contracts[0].Symbol
self.MarketOrder(symbol, (self.amt_per_txn/100)//self.contracts[0].AskPrice)
x = self.contracts[0]
columns=['idx', 'type(call 0, put 1)', 'strike', 'expiry', 'ask price', 'bid price', 'delta', x.Symbol.Value,\
x.Right,float(x.Strike),x.Expiry,float(x.BidPrice),float(x.AskPrice),float(x.Greeks.Delta)]
self.Log(str(columns))
def OnOrderEvent(self, orderEvent):
self.Log(str(orderEvent))