Overall Statistics
Total Trades
2613
Average Win
0.46%
Average Loss
-0.49%
Compounding Annual Return
20.245%
Drawdown
9.100%
Expectancy
0.062
Net Profit
44.931%
Sharpe Ratio
1.2
Probabilistic Sharpe Ratio
58.495%
Loss Rate
45%
Win Rate
55%
Profit-Loss Ratio
0.95
Alpha
0.151
Beta
-0.06
Annual Standard Deviation
0.118
Annual Variance
0.014
Information Ratio
-0.11
Tracking Error
0.192
Treynor Ratio
-2.351
Total Fees
$4216.10
Estimated Strategy Capacity
$18000000.00
Lowest Capacity Asset
SPY R735QTJ8XC9X
# Opening Range Breakout

# ------------------------------------------------------------
STOCK = "SPY"; PERIOD = 30; WAIT = 0; SL = -0.005; TP = 0.005;
# ------------------------------------------------------------

class OpeningRangeBreakout(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2020, 5, 1)  
        self.SetEndDate(2022, 5, 5)  
        self.SetCash(100000) 
        self.stock = self.AddEquity(STOCK, Resolution.Minute).Symbol
        self.hh = self.MAX(self.stock, PERIOD, Resolution.Minute, Field.High)
        self.ll = self.MIN(self.stock, PERIOD, Resolution.Minute, Field.Low)
        self.hh_d = IndicatorExtensions.Of(Delay(1), self.hh)
        self.ll_d = IndicatorExtensions.Of(Delay(1), self.ll)
        self.SetWarmUp(PERIOD + 1, Resolution.Minute)
        self.first_30_min_HH = 0
        self.first_30_min_LL = 0
        self.wait = WAIT
        self.Schedule.On(self.DateRules.EveryDay(self.stock), self.TimeRules.AfterMarketOpen(self.stock, 31), 
            self.DailyCheck)
        

    def DailyCheck(self):
        if self.IsWarmingUp: return
        if not (self.hh_d.IsReady or self.ll_d.IsReady): return
    
        self.first_30_min_HH = self.hh_d.Current.Value
        self.first_30_min_LL = self.ll_d.Current.Value
        
    
    def OnData(self, data):
        if self.IsWarmingUp: return
        if not (self.hh_d.IsReady or self.ll_d.IsReady): return
        if self.Time.hour < 10 or self.Time.hour >= 16: return
        if (self.first_30_min_HH ==0 or self.first_30_min_LL == 0): return
    
        self.wait += 1
        if not self.wait > WAIT: return
    
        price = self.Securities[self.stock].Price
        pnl = self.Securities[self.stock].Holdings.UnrealizedProfitPercent

        if not self.Portfolio[self.stock].Invested:
            if price > self.first_30_min_HH:
                self.SetHoldings(self.stock, 1)
                
            elif price < self.first_30_min_LL:
                self.SetHoldings(self.stock, -1)
                
        elif self.Portfolio[self.stock].Invested:
            if pnl >= TP: 
                self.Liquidate(self.stock, "Take Profit") 
                self.wait = 0
                
            elif pnl < SL: 
                self.Liquidate(self.stock, "Stop Loss") 
                self.wait = 0
                

    def OnEndOfDay(self, symbol): 
        if self.Portfolio[self.stock].Invested:
            self.Liquidate(self.stock, "EOD")  
        self.wait = WAIT