| Overall Statistics |
|
Total Trades 146 Average Win 0.09% Average Loss -0.08% Compounding Annual Return -9.975% Drawdown 18.100% Expectancy -0.589 Net Profit -5.149% Sharpe Ratio -0.329 Probabilistic Sharpe Ratio 17.349% Loss Rate 81% Win Rate 19% Profit-Loss Ratio 1.14 Alpha 0.02 Beta -0.512 Annual Standard Deviation 0.23 Annual Variance 0.053 Information Ratio -0.392 Tracking Error 0.668 Treynor Ratio 0.148 Total Fees $145.00 |
class QuantumParticleAtmosphericScrubbers(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2019, 12, 8) # Set Start Date
self.SetCash(100000) # Set Strategy Cash
self.spy_symbol = self.AddEquity("SPY", Resolution.Minute).Symbol
self.Securities[self.spy_symbol].SetDataNormalizationMode(DataNormalizationMode.Raw)
self.SetSecurityInitializer(self.CustomSecurityInitializer)
self.straddleTickets = {}
def OnData(self, data):
if not data.Bars.ContainsKey(self.spy_symbol):
return
if not self.Portfolio.Invested:
price = data.Bars[self.spy_symbol].Close;
expiry = self.Time + timedelta(days = 14)
call_symbol, put_symbol = self.GetStraddleContracts(self.spy_symbol, price, expiry)
call = self.AddOptionContract(call_symbol, Resolution.Minute)
put = self.AddOptionContract(put_symbol, Resolution.Minute)
call_tickets, put_tickets = self.TradeStraddle(call, put, 2)
self.straddleTickets[self.spy_symbol] = [call_tickets, put_tickets]
def GetStraddleContracts(self, symbol, strike, expiry):
contracts = self.OptionChainProvider.GetOptionContractList(symbol, self.Time)
expiry_sorted = sorted(contracts, key=lambda k: abs(k.ID.Date - expiry), reverse=False)
closest_expiry = expiry_sorted[0].ID.Date
contracts_with_desired_expiry = [symbol for symbol in contracts if symbol.ID.Date == closest_expiry]
calls = [symbol for symbol in contracts_with_desired_expiry if symbol.ID.OptionRight == OptionRight.Call]
puts = [symbol for symbol in contracts_with_desired_expiry if symbol not in calls]
sorted_calls = sorted(calls, key=lambda k: abs(k.ID.StrikePrice - strike), reverse=False)
sorted_puts = sorted(puts, key=lambda k: abs(k.ID.StrikePrice - strike), reverse=False)
return sorted_calls[0], sorted_puts[0]
def TradeStraddle(self, call, put, quantity):
call_entry= call.AskPrice
call_entry_ticket = self.MarketOrder(call.Symbol, quantity)
call_take_profit = call_entry * 1.10
call_stop_loss = call_entry * 0.90
call_profit_ticket = self.LimitOrder(call.Symbol, -quantity, call_take_profit)
call_loss_ticket = self.StopMarketOrder(call.Symbol, -quantity, call_stop_loss)
put_entry = put.AskPrice
put_entry_ticket = self.MarketOrder(put.Symbol, quantity)
put_take_profit = put_entry * 1.10
put_stop_loss = put_entry * 0.90
put_profit_ticket = self.LimitOrder(put.Symbol, -quantity, put_take_profit)
put_loss_ticket = self.StopMarketOrder(put.Symbol, -quantity, put_stop_loss)
return (call_profit_ticket, call_loss_ticket), (put_profit_ticket, put_loss_ticket)
def CustomSecurityInitializer(self, security):
bar = self.GetLastKnownPrice(security)
security.SetMarketPrice(bar)
def OnOrderEvent(self, orderevent):
if orderevent.Status != OrderStatus.Filled:
return
orderId = orderevent.OrderId
for underlying, order_pairs in self.straddleTickets.items():
for order_pair in order_pairs:
order_one = order_pair[0]
order_two = order_pair[1]
if orderId == order_one.OrderId:
order_two.Cancel()
elif orderId == order_two.OrderId:
order_one.Cancel()