Overall Statistics |
Total Trades 8 Average Win 0.29% Average Loss -0.65% Compounding Annual Return -21.226% Drawdown 1.600% Expectancy -0.419 Net Profit -1.363% Sharpe Ratio -5.682 Probabilistic Sharpe Ratio 0.007% Loss Rate 60% Win Rate 40% Profit-Loss Ratio 0.45 Alpha -0.101 Beta 0.116 Annual Standard Deviation 0.036 Annual Variance 0.001 Information Ratio 3.142 Tracking Error 0.22 Treynor Ratio -1.774 Total Fees $20.00 Estimated Strategy Capacity $470000.00 Lowest Capacity Asset SPY 31BIVCUZR6WDI|SPY R735QTJ8XC9X |
from datetime import timedelta from datetime import datetime import math from QuantConnect.Securities.Option import OptionPriceModels class BullPutSpreadAlgorithm(QCAlgorithm): ordersList = list() def Initialize(self): self.SetStartDate(2020,2, 10) self.SetEndDate(2020,2, 29) self.SetCash(600000) self.SetWarmUp(30, Resolution.Minute) equity = self.AddEquity("SPY", Resolution.Minute) option = self.AddOption("SPY", Resolution.Minute) self.symbol = option.Symbol option.SetFilter(lambda universe: universe.WeeklysOnly().Strikes(-30, -5).Expiration(timedelta(0), timedelta(29))) # use the underlying equity SPY as the benchmark option.PriceModel = OptionPriceModels.CrankNicolsonFD() self.SetBenchmark(equity.Symbol) self.SetWarmUp(timedelta(45)) self.optionMuliplier = option.ContractMultiplier self.Schedule.On(self.DateRules.WeekStart(), self.TimeRules.At(9,35), self.OpenWeekTrade) def OnData(self,slice): optionchain = slice.OptionChains for i in slice.OptionChains: if i.Key != self.symbol: continue chains = i.Value contract_list = [x for x in chains] # if there is no contracts in this optionchain, pass the instance if (slice.OptionChains.Count == 0) or (len(contract_list) == 0): return self.options_data = optionchain def OnOrderEvent(self, orderEvent): order = self.Transactions.GetOrderById(orderEvent.OrderId) quantity = orderEvent.FillQuantity fill_price = orderEvent.FillPrice underlying = orderEvent.Symbol.Underlying sym = orderEvent.Symbol if order.Type == OrderType.OptionExercise: self.Debug("Assignment: " + str(orderEvent.Symbol) + " quan: " + str(quantity) + " time: " + str(self.Time) ) self.ExerciseOnAssignment(sym) def ExerciseOnAssignment(self, sym): ticket = None option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.Option] s_options = sorted(option_invested, key = lambda x: x.ID.StrikePrice, reverse=True ) self.Debug("Length of s_options: " + str(len(s_options))) for option in s_options: if (option.Underlying == sym ): self.Log( str(self.ExerciseOption(option, 20 )) + " : Exercised: " + str(self.Time.second ) ) self.Log("SPY Quan: " + str(self.Portfolio[sym].Quantity)) if self.Portfolio[sym].Quantity != 0: self.Log("Exercise failed: " + str(sym) + ":" + str(self.Portfolio[option.Underlying].Quantity ) ) self.Debug("Quantity after exercise " + str(self.Portfolio[option.Underlying].Quantity)) def OpenWeekTrade(self): for i in self.options_data: if i.Key != self.symbol: continue chain = i.Value expiry = sorted(chain,key = lambda x: x.Expiry)[0].Expiry put = [i for i in chain if i.Right == 1 and i.Greeks.Delta > -0.1 and i.Strike % 1 == 0 and (i.Expiry-self.Time).days == 3 ] put_contracts = sorted(put,key = lambda x: x.Strike, reverse=True) if len(put_contracts) == 0: continue #5 point wide spread self.long_put = put_contracts[5] self.short_put = put_contracts[0] self.Order(self.short_put.Symbol, -20) self.Order(self.long_put.Symbol, 20)