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