Overall Statistics
Total Trades
104
Average Win
0.30%
Average Loss
-0.07%
Compounding Annual Return
58.147%
Drawdown
2.000%
Expectancy
1.808
Net Profit
6.170%
Sharpe Ratio
16.146
Probabilistic Sharpe Ratio
100%
Loss Rate
50%
Win Rate
50%
Profit-Loss Ratio
4.62
Alpha
0
Beta
0
Annual Standard Deviation
0.023
Annual Variance
0.001
Information Ratio
16.146
Tracking Error
0.023
Treynor Ratio
0
Total Fees
$65.00
Estimated Strategy Capacity
$0
Lowest Capacity Asset
SPXW Y5WEOAUNBDKE|SPX 31
# This is not a very good strategy.
#
from AlgorithmImports import *


pos_size = 5      # number of orders

class BasicTemplateSPXWeeklyIndexOptionsAlgorithm(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2023, 1, 1)
        self.SetEndDate(2023, 2, 18)
        self.SetCash(50000)
        self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
        self.spx = self.AddIndex("SPX", Resolution.Minute)


        # weekly option SPX contracts
        spxw = self.AddIndexOption(self.spx.Symbol, "SPXW")
        # set our strike/expiry filter for this option chain
        spxw.SetFilter(lambda u: (u.Strikes(-50,50)
                                     .Expiration(0,0)
                                     .IncludeWeeklys()))

        self.spxw_option = spxw.Symbol
        
        self.day_low = 10000
        self.day_high = 0
        self.Schedule.On(self.DateRules.EveryDay(),
                 self.TimeRules.At(9,30,00),
                 self.MarketOpen)
        
        self.day_high = self.MAX(self.spx.Symbol, 1000000, Resolution.Minute, Field.High)
        self.day_low =  self.MIN(self.spx.Symbol, 1000000, Resolution.Minute, Field.Low)
        
        self.SetWarmup(timedelta(2),Resolution.Minute)

    def OnData(self,slice):
        #day high and day low

        if self.IsWarmingUp: return

        current_price = self.spx.Price
        #self.Debug('Hello')
                
        self.Debug(f'current price is {current_price}')
        self.Debug(f'day high is {self.day_high}')
        self.Debug(f'day low is {self.day_low}')

        if (self.day_high.Current.Value - self.day_low.Current.Value) == 0: return
        else:
            ratio = (current_price-self.day_low.Current.Value)/(self.day_high.Current.Value - self.day_low.Current.Value)
        
        self.Debug(f'current ratio is {ratio}')

        if self.Portfolio.Invested: return
        if self.Time.hour <= 13: return 
        
        delta = 0.05

        chain = slice.OptionChains.GetValue(self.spxw_option)
        if chain is None:
            return
        call = [x for x in chain if x.Right == OptionRight.Call]
        put = [x for x in chain if x.Right == OptionRight.Put]

        # we sort the contracts to find contract with the right delta
        put_contract = sorted(put,key = lambda x: abs(abs(x.Greeks.Delta) - delta))
        call_contract = sorted(call,key = lambda x: abs(x.Greeks.Delta - delta))

        # if found, sell spread
        if len(put_contract) == 0: 
            return
        else:
            if ratio < 0.05:
                put_ = put_contract[0].Symbol
                strike = put_contract[0].Strike - 30
                put_1 = sorted(put,key = lambda x: abs(abs(x.Strike) - strike))
                put_1 = put_1[0].Symbol
                self.MarketOrder(put_,-pos_size)
                self.MarketOrder(put_1,pos_size)

        if len(call_contract) == 0: 
            return
        else:
            if ratio > 0.95:
                call_ = call_contract[0].Symbol
                strike = call_contract[0].Strike + 30
                call_1 = sorted(call,key = lambda x: abs(abs(x.Strike) - strike))
                call_1 = call_1[0].Symbol
                self.MarketOrder(call_,-pos_size)
                self.MarketOrder(call_1,pos_size)
     

    def OnOrderEvent(self, orderEvent):
        self.Debug(str(orderEvent))
    
    def MarketOpen(self):
        self.day_high = self.MAX(self.spx.Symbol, 1000000, Resolution.Minute, Field.High)
        self.day_low =  self.MIN(self.spx.Symbol, 1000000, Resolution.Minute, Field.Low)