Overall Statistics
Total Trades
2850
Average Win
0.71%
Average Loss
-0.69%
Compounding Annual Return
-28.870%
Drawdown
86.000%
Expectancy
-0.189
Net Profit
-85.710%
Sharpe Ratio
-1.396
Probabilistic Sharpe Ratio
0.000%
Loss Rate
60%
Win Rate
40%
Profit-Loss Ratio
1.03
Alpha
-0.205
Beta
0.04
Annual Standard Deviation
0.144
Annual Variance
0.021
Information Ratio
-1.398
Tracking Error
0.212
Treynor Ratio
-5.024
Total Fees
$47001.64
Estimated Strategy Capacity
$1900000.00
Lowest Capacity Asset
TQQQ UK280CGTCB51
# region imports
from AlgorithmImports import *
import datetime as dt
# endregion

class TimedTrader(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2017, 1, 1)  # Set Start Date
        self.SetEndDate(2022, 9, 17)
        self.SetCash(100000)  # Set Strategy Cash
        
        self.ticker = self.GetParameter('Ticker')
        self.symbol = self.AddEquity(self.ticker, Resolution.Minute).Symbol

        OpenTime = self.GetParameter('OpenTime') # Format: 'HH:MM'
        OpenTime = dt.datetime.strptime(OpenTime,'%H:%M').time()
        CloseTime = self.GetParameter('CloseTime') # Format: 'HH:MM'
        CloseTime = dt.datetime.strptime(CloseTime,'%H:%M').time()

        self.GreaterThanOpen = self.GetParameter('GreaterThanOpen') # Long, Short, Ignore
        self.GreaterThanClose = self.GetParameter('GreaterThanClose') # Long, Short, Ignore
        self.resolution = self.GetParameter('Resolution') # Minute, Second

        self.close = 0
        self.open = 0


        if self.resolution == 'Minute':
            self.symbol = self.AddEquity(self.ticker, Resolution.Minute).Symbol
        else:
            self.symbol = self.AddEquity(self.ticker, Resolution.Second).Symbol

        self.Schedule.On(self.DateRules.EveryDay(self.symbol),self.TimeRules.At(OpenTime.hour,OpenTime.minute),self.CheckInitiation)
        self.Schedule.On(self.DateRules.EveryDay(self.symbol),self.TimeRules.At(CloseTime.hour,CloseTime.minute),self.Close)
        self.Schedule.On(self.DateRules.EveryDay(self.symbol),self.TimeRules.AfterMarketOpen(self.symbol,1),self.RecordOpen)
        self.Schedule.On(self.DateRules.EveryDay(self.symbol),self.TimeRules.BeforeMarketClose(self.symbol,1),self.RecordClose)

    def CheckInitiation(self):
        if (self.open == 0) or (self.close==0):
            return

        current_price = self.SliceToPrice()
        open_trigger = self.GetOpenTrigger(current_price)
        close_trigger = self.GetCloseTrigger(current_price)

        signal = open_trigger + close_trigger
        quantity = max(-1, min(1, signal))
        self.SetHoldings(self.symbol,quantity,tag=f'O:{round(self.open,2)}|C:{round(self.close,2)}|P:{round(current_price,2)}')

    def Close(self):
        self.Liquidate()

    def RecordOpen(self):
        self.open = self.SliceToPrice()

    def RecordClose(self):
        self.close = self.SliceToPrice()

    def GetOpenTrigger(self, price):
        if self.GreaterThanOpen == 'Long':
            if price > self.open:
                return 1
            else:
                return -1
        elif self.GreaterThanOpen == 'Short':
            if price < self.open:
                return 1
            else:
                return -1       
        else:
            return 0   

    def GetCloseTrigger(self, price):
        if self.GreaterThanClose == 'Long':
            if price > self.close:
                return 1
            else:
                return -1
        elif self.GreaterThanClose == 'Short':
            if price < self.close:
                return 1
            else:
                return -1       
        else:
            return 0   
    
    def SliceToPrice(self):
        slice = self.CurrentSlice
        if slice.ContainsKey(self.symbol):
            if slice[self.symbol] is not None:            
                return self.CurrentSlice[self.symbol].Price
        
        return 0