Overall Statistics
Total Trades
8047
Average Win
0.20%
Average Loss
-0.20%
Compounding Annual Return
-2.622%
Drawdown
30.300%
Expectancy
-0.023
Net Profit
-19.164%
Sharpe Ratio
-0.301
Loss Rate
51%
Win Rate
49%
Profit-Loss Ratio
1.00
Alpha
-0.028
Beta
0.117
Annual Standard Deviation
0.066
Annual Variance
0.004
Information Ratio
-0.498
Tracking Error
0.185
Treynor Ratio
-0.169
Total Fees
$14886.95
class ComblinedSeasonalityMarketSessionTrading(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2008, 1, 1)  # Set Start Date
        self.SetEndDate(2015, 12, 31) # Set End Date
        self.SetCash(100000)  # Set Strategy Cash
        
        future = self.AddFuture(Futures.Indices.SP500EMini) # S&P E-mini future contracts
        future.SetFilter(timedelta(0), timedelta(180)) # Filter according to Expiry date
        
        # Set benchmark
        benchmark = self.AddEquity("SPY")
        self.SetBenchmark(benchmark.Symbol)
        
        # Set season
        # Bullish Season: Nov - May; 
        # Bearish Season: Jun - Oct
        
        # self.bullSeason = {11, 12, 1, 2, 3, 4, 5} # Bullish Season
        
        self.bearSeason = {6, 7, 8, 9, 10} # Bearish Season
        
        # Overnight trading strategy
        
        
        # Bullish Season: buy at 18:00, sell at 5:30; buy at 13:15, sell at 15:15
        # Bearlish Season: buy at 18:00, sell at 5:30; buy at 13:15, sell at 14:00
        
        
        # Night: 1800 - 530
        # Afternoon: 1315 - 1400
        # Close: 1400 - 1515
        
        # Night session
        self.Schedule.On(self.DateRules.EveryDay('SPY'), self.TimeRules.At(18, 0), Action(self.Enter))
        self.Schedule.On(self.DateRules.EveryDay('SPY'), self.TimeRules.At(5, 30), Action(self.Exit))
        
        # Afternoon session
        self.Schedule.On(self.DateRules.EveryDay('SPY'), self.TimeRules.At(13, 15), Action(self.Enter))
        self.Schedule.On(self.DateRules.EveryDay('SPY'), self.TimeRules.At(14, 0), Action(self.ExitException))
        
        # Close session
        self.Schedule.On(self.DateRules.EveryDay('SPY'), self.TimeRules.At(14, 0), Action(self.EnterException))
        self.Schedule.On(self.DateRules.EveryDay('SPY'), self.TimeRules.At(15, 15), Action(self.Exit))


    def OnData(self, data):
        '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
            Arguments:
                data: Slice object keyed by symbol containing the stock data
        '''
        # self.Debug(f'Month: {self.Time.date().month}')
        self.data = data
        pass
    
    def Enter(self):
        if not self.Portfolio.Invested:
            
            for chain in self.data.FutureChains:
                contracts = list(filter(lambda x: x.Expiry < self.Time + timedelta(90), chain.Value))
                
                # self.Debug(f'Num of Contracts {self.Time}: {len(contracts)}')
                
                if len(contracts) == 0:
                    continue
                
                front = sorted(contracts, key = lambda x: x.Expiry, reverse = False)[0]

                # long
                self.MarketOrder(front.Symbol, 1)
    
    def Exit(self):
        if self.Portfolio.Invested:
            # short
            self.Liquidate()
            
    def EnterException(self):
        isBear = self.Time.date().month in self.bearSeason
        
        if (not self.Portfolio.Invested) and isBear:
            
            for chain in self.data.FutureChains:
                contracts = list(filter(lambda x: x.Expiry < self.Time + timedelta(90), chain.Value))

                if len(contracts) == 0:
                    continue
                
                front = sorted(contracts, key = lambda x: x.Expiry, reverse = False)[0]

                # long
                self.MarketOrder(front.Symbol, 1)
    
    def ExitException(self):
        isBear = self.Time.date().month in self.bearSeason
        
        if self.Portfolio.Invested and isBear:
            # short
            self.Liquidate()