Overall Statistics
Total Trades
6
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
0
Tracking Error
0
Treynor Ratio
0
Total Fees
$6.00
Estimated Strategy Capacity
$160000000.00
Lowest Capacity Asset
SPY R735QTJ8XC9X
# region imports
from AlgorithmImports import *
# endregion

class HipsterRedBull(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2022, 11 , 22)  # Set Start Date
        self.SetEndDate(2022, 11, 22)
        self.SetCash(100000)  # Set Strategy Cash
        self.symbol = self.AddEquity("SPY", Resolution.Minute).Symbol
        self.Consolidate("SPY", timedelta(minutes=30), self.CustomBarHandler)
        self.window = RollingWindow[TradeBar](2)
        self.entryTicket = None
        self.StopMarketTicket = None
        self.TPTicket = None
        self.entryTime = datetime.min
        self.exitTime = datetime.min
        self.bias = 0

        self.Schedule.On(self.DateRules.EveryDay(self.symbol), self.TimeRules.BeforeMarketClose(self.symbol, 1) , self.onMarketClose)
        
    def onMarketClose(self):
        self.Liquidate()
        self.window.Reset()
        self.exitTime = self.Time
    
    def CustomBarHandler(self, bar):
        if self.Time.hour == 10:
            self.window.Add(bar)

    def OnData(self, data):
        if self.Time.date() == self.exitTime.date() or not self.window.IsReady or self.Portfolio.Invested:
            return
        # wait at least 1 day before last exit before making another trade
        # if rollingwindow is ready and portfolio is not invested
        # if close price is above or below opening range high or low, send market order
        # record entry time 

        maxprice = max(self.window[0].High, self.window[1].High)
        minprice = min(self.window[0].Low, self.window[1].Low)

        self.Plot("Opening Range","OR Max", maxprice)
        self.Plot("Opening Range","OR Min", minprice)

        if self.entryTicket is not None:
            return

        if data[self.symbol].Close > maxprice:
            self.entryTicket = self.MarketOrder(self.symbol, 100)
            self.bias = 1
            self.entryTime = self.Time
    
        if data[self.symbol].Close < minprice:
            self.entryTicket = self.MarketOrder(self.symbol, -100)
            self.bias = -1
            self.entryTime = self.Time
    
    def OnOrderEvent(self, orderEvent):

        if orderEvent.Status != OrderStatus.Filled:
            return
           
        if self.Portfolio.Invested:
            self.StopMarketTicket = self.StopMarketOrder(self.symbol, -orderEvent.Quantity, orderEvent.FillPrice - self.bias * 5)
            self.TPTicket = self.LimitOrder(self.symbol, -orderEvent.Quantity, orderEvent.FillPrice + self.bias * 5)

        # Stop market order and take profit order should not be filled immediately, so it is safe if we use the instance as indicator
        if self.StopMarketTicket is not None and self.StopMarketTicket.OrderId == orderEvent.OrderId:
            self.exitTime = self.Time
            self.entryTicket = None

        if self.TPTicket is not None and self.TPTicket.OrderId == orderEvent.OrderId:
            self.exitTime = self.Time
            self.entryTicket = None
# region imports
from AlgorithmImports import *
# endregion

class HipsterRedBull(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2022, 11 , 22)  # Set Start Date
        self.SetEndDate(2022, 11, 22)
        self.SetCash(100000)  # Set Strategy Cash
        self.symbol = self.AddEquity("SPY", Resolution.Minute).Symbol
        self.Consolidate("SPY", timedelta(minutes=30), self.CustomBarHandler)
        self.window = RollingWindow[TradeBar](2)
        self.entryTicket = None
        self.StopMarketTicket = None
        self.TPTicket = None
        self.entryTime = datetime.min
        self.exitTime = datetime.min
        self.bias = 0

        self.Schedule.On(self.DateRules.EveryDay(self.symbol), self.TimeRules.BeforeMarketClose(self.symbol, 1) , self.onMarketClose)
        
    def onMarketClose(self):
        self.Liquidate()
        self.window.Reset()
        self.exitTime = self.Time
    
    def CustomBarHandler(self, bar):
        if self.Time.hour == 10:
            self.window.Add(bar)

    def OnData(self, data):
        if self.Time.date() == self.exitTime.date() or not self.window.IsReady or self.Portfolio.Invested:
            return
        # wait at least 1 day before last exit before making another trade
        # if rollingwindow is ready and portfolio is not invested
        # if close price is above or below opening range high or low, send market order
        # record entry time 

        maxprice = max(self.window[0].High, self.window[1].High)
        minprice = min(self.window[0].Low, self.window[1].Low)

        self.Plot("Opening Range","OR Max", maxprice)
        self.Plot("Opening Range","OR Min", minprice)

        if data[self.symbol].Close > maxprice:
            self.entryTicket = self.MarketOrder(self.symbol, 100)
            self.bias = 1
            self.StopMarketTicket = self.StopMarketOrder(self.symbol, -self.entryTicket.QuantityFilled, self.entryTicket.AverageFillPrice - self.bias * 0.5)
            self.TPTicket = self.LimitOrder(self.symbol, -self.entryTicket.QuantityFilled, self.entryTicket.AverageFillPrice + self.bias * 0.5)
            self.entryTime = self.Time
            
    
        if data[self.symbol].Close < minprice:
            self.entryTicket = self.MarketOrder(self.symbol, -100)
            self.bias = -1
            self.StopMarketTicket = self.StopMarketOrder(self.symbol, -self.entryTicket.QuantityFilled, self.entryTicket.AverageFillPrice - self.bias * 0.5)
            self.TPTicket = self.LimitOrder(self.symbol, -self.entryTicket.QuantityFilled, self.entryTicket.AverageFillPrice + self.bias * 0.5)
            self.entryTime = self.Time
    
    def OnOrderEvent(self, orderEvent):

        if orderEvent.Status != OrderStatus.Filled:
            return
       
        # if entry ticket exists send out stop market order for stop loss
        # if entry ticket exists send out limit order to take profits
        # if either take profits or stop loss is hit, record time of order fill

        if self.StopMarketTicket is not None and self.StopMarketTicket.OrderId == orderEvent.OrderId:
            self.exitTime = self.Time

        if self.TPTicket is not None and self.TPTicket.OrderId == orderEvent.OrderId:
            self.exitTime = self.Time