| Overall Statistics |
|
Total Trades 184 Average Win 0.40% Average Loss -0.26% Compounding Annual Return 4.129% Drawdown 2.100% Expectancy 0.079 Net Profit 1.880% Sharpe Ratio 0.73 Probabilistic Sharpe Ratio 41.196% Loss Rate 58% Win Rate 42% Profit-Loss Ratio 1.54 Alpha 0 Beta 0 Annual Standard Deviation 0.058 Annual Variance 0.003 Information Ratio 0.73 Tracking Error 0.058 Treynor Ratio 0 Total Fees $164.00 |
import clr
clr.AddReference("System")
clr.AddReference("QuantConnect.Algorithm")
clr.AddReference("QuantConnect.Indicators")
clr.AddReference("QuantConnect.Common")
import numpy as np
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
from QuantConnect.Securities.Option import OptionPriceModels
from datetime import datetime, timedelta
import decimal as d
class EODOptions(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2020, 8, 1) # Set Start Date
self.SetEndDate(2021, 1, 19) # Set End Date
self.SetCash(30000) # Set Strategy Cash
self.spy = self.AddEquity("SPY", Resolution.Minute)
self.spy.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage)
options = self.AddOption("SPY")
options.SetFilter(lambda universe: universe.IncludeWeeklys().Strikes(-3, 3).Expiration(timedelta(1), timedelta(3)))
#Pricemodel for Options
options.PriceModel = OptionPriceModels.CrankNicolsonFD()
# set the warm-up period for the pricing model
self.SetWarmUp(TimeSpan.FromDays(6))
# set the benchmark to be the initial cash
self.SetBenchmark(lambda x: 30000)
#####Execution model
def OnData(self, data):
underlying_symbol = "SPY"
if not data.Bars.ContainsKey("SPY"): return
##########Sell 2nd Candle of Day
if data.Time.hour == 9 and data.Time.minute == 32:
self.Liquidate()
##########Buy the next closest expiry that isn't today at the EOD
if data.Time.hour == 15 and data.Time.minute == 58:
contract_call_symbol = self.OptionsFilter (underlying_symbol, 1, OptionRight.Call)
if contract_call_symbol is None:
return
self.MarketOrder(contract_call_symbol.Symbol, 1)
###########Options Selection
def OptionsFilter(self, underlying_symbol, expiry_days, option_right):
for kvp in self.CurrentSlice.OptionChains:
chain = kvp.Value
key = kvp.Key # which chain it is
contracts = [i for i in chain]
if len(contracts) == 0: continue
contracts_filtered_for_right = [i for i in contracts if i.Right == option_right]
Greater_than_one_dollar = [i for i in contracts_filtered_for_right if (i.AskPrice + i.BidPrice)/2 > .25 and (i.AskPrice + i.BidPrice)/2 < 1.75]
if len(Greater_than_one_dollar) == 0: return
desired_expiration = self.Time + timedelta(days = expiry_days)
at_least_one_day_out = [i for i in Greater_than_one_dollar if desired_expiration < i.Expiry]
closest_expiry = sorted(at_least_one_day_out, key=lambda c : abs(c.Expiry - desired_expiration), reverse=False)
if len(closest_expiry) == 0: return
closest_expiry_date = closest_expiry[0].Expiry
contracts_with_desired_expiry = [i for i in Greater_than_one_dollar if i.Expiry == closest_expiry_date]
if len(contracts_with_desired_expiry) == 0: return
Sorted_by_Highest_leverage = sorted(contracts_with_desired_expiry, key=lambda x: x.Greeks.Gamma, reverse = True)
if len(Sorted_by_Highest_leverage) == 0: return
if len(Sorted_by_Highest_leverage) > 0:
contract = Sorted_by_Highest_leverage[0]
return contract