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()