pythonpandasdataframeback-testingpyalgotrade

Using Hour and Minute from pandas data frame index


First of all, I am a beginner to programming. I have been working on a Python algo trading program and have been using the backtesting.py library for backtesting. I need help with implementing a time-based exit (calling self.position.close()), such as using simple if statements. However, I am having trouble properly retrieving data from a pandas DataFrame. My data is in a 15-minute timeframe, and I want to exit my running trades at 15:15 hrs. I have stored my sample data in a DataFrame named 'symbol,' with time as the index (e.g., 2023-04-28 09:15:00+05:30). Can you help me implement it in below code?

class SmaCross(Strategy):
    # Define the two MA lags as *class variables*
    # for later optimization
    n1 = 10
    n2 = 20
    
    def init(self):
        # Precompute the two moving averages
        self.sma1 = self.I(SMA, self.data.Close, self.n1)
        self.sma2 = self.I(SMA, self.data.Close, self.n2)
        
        #TRYING TO RETRIEVE TIME DATA
        self.current_datetime = self.data.index 
        
        self.hourNow = self.current_datetime.hour
        self.minuteNow = self.current_datetime.minute

    
    def next(self):
        
        if (self.hourNow >= 15 and self.minuteNow >= 15):
            self.position.close()
            
        # If sma1 crosses above sma2, close any existing
        # short trades, and buy the asset
        if crossover(self.sma1, self.sma2):
            self.position.close()
            self.buy()

        # Else, if sma1 crosses below sma2, close any existing
        # long trades, and sell the asset
        elif crossover(self.sma2, self.sma1):
            self.position.close()
            self.sell()

bt = Backtest(symbol, SmaCross, cash=10_000, commission=.002)
stats = bt.run()

The above code is not working because self.hourNow, self.hourNow got a list of values. I also tried using self.current_datetime = self.data.index[-1] but it always using the last time instead of the testing time value.


Solution

  • From the documentation:

    In init(), the whole series of points was available, whereas in next(), the length of self.data and all declared indicators is adjusted on each next() call so that array[-1] (e.g. self.data.Close[-1] or self.sma1[-1]) always contains the most recent value, array[-2] the previous value, etc. (ordinary Python indexing of ascending-sorted 1D arrays).

    You need to move these lines to the top of next(), because in there self.data.index[-1] is the most recent time, as you wanted.

        self.current_datetime = self.data.index[-1]
    
        self.hourNow = self.current_datetime.hour
        self.minuteNow = self.current_datetime.minute