Overall Statistics
Total Trades
562
Average Win
0.46%
Average Loss
-0.97%
Compounding Annual Return
5.434%
Drawdown
8.300%
Expectancy
0.067
Net Profit
18.393%
Sharpe Ratio
0.594
Probabilistic Sharpe Ratio
20.858%
Loss Rate
28%
Win Rate
72%
Profit-Loss Ratio
0.48
Alpha
0.038
Beta
0.025
Annual Standard Deviation
0.067
Annual Variance
0.004
Information Ratio
-0.141
Tracking Error
0.213
Treynor Ratio
1.553
Total Fees
$562.00
Estimated Strategy Capacity
$17000.00
Lowest Capacity Asset
SPXW 325H5FB4N52SU|SPX 31
Portfolio Turnover
0.33%
# weekend effect of the selling options
# open - Fri 15:55
# close - Mon 9:45
# delta - 0.25
# 1 contract / account size 100,000 USD

import pandas as pd
import talib as ta
import numpy as np
from AlgorithmImports import *


class BasicTemplateSPXWeeklyIndexOptionsAlgorithm(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2020,1, 1)
        #self.SetEndDate(2022, 1, 14)
        self.SetCash(100000)
        self.SetTimeZone(TimeZones.NewYork)
        self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage,AccountType.Margin)
        
        self.spx = self.AddIndex("SPX", Resolution.Minute)
        self.SetBenchmark("SPX")


        # 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(-30, 30)
                                     .Expiration(3,3)
                                     .IncludeWeeklys()))

        self.spxw_option = spxw.Symbol      
        self.trade_run = 0
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.At(15, 55), self.Open)
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.At(9, 45), self.End)

 
    def OnData(self,slice):        
        try:
            if self.trade_run ==0:  
                return
            else:
                quantity = 1
                delta =0.25

            if self.call_contract == 1 and self.put_contract ==1:
                return
                    
            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
            call_contract = sorted(call,key = lambda x: abs(x.Greeks.Delta - delta))
            put_contract = sorted(put,key = lambda x: abs(abs(x.Greeks.Delta) - delta))
            
            
            if len(call_contract) == 0: 
                return
            else:
                if self.call_contract == 0:
                    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_, -quantity)
                    #self.MarketOrder(call_1, quantity)
                    self.call_contract = 1
            

            if len(put_contract) == 0:
                self.Debug('no put contract')
                return
            else:
                if self.put_contract == 0:
                    put_ = put_contract[0].Symbol
                    self.Debug('okay')
                    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_, -quantity)
                    #self.MarketOrder(put_1, quantity)
                    self.put_contract = 1
        except:
            pass

    def OnOrderEvent(self, orderEvent):
        self.Debug(str(orderEvent))
        self.Debug(self.spx.Price)
        self.Debug(self.Time)

    def End(self):
        self.Liquidate()
        self.trade_run = 0
 
    def Open(self):
        self.trade_run = 1
        self.call_contract = 0
        self.put_contract = 0