Most pythonic way of backtesting a range of values for an indicator
-
Greetings all,
I am trying to find the most efficient and effective way of backtesting a range of values for an indicator. Take for example, two simple moving averages, I would like to backtest the first moving average against the second moving average values x , x+2 , x+3... x+30 and then once that is done increment the first moving average by y+1 and repeat the process until I have reached y+30. Essentially I'm testing every value of one MA against the other within the range I have specified.
The following code shows this,
pslowVal = 10 pfastVal = 11 for y in range(30): for x in range(30): data = bt.feeds.GenericCSVData( dataname = "da15m-data.csv", nullvalue=0.0, dtformat=('%Y-%m-%d %H:%M:%S'), datetime=0, high=2, low=3, open=1, close=4, volume=5, openinterest=-1, ) class SmaCross(bt.Strategy): # list of parameters which are configurable for the strategy params = dict( pfast=pfastVal, # period for the fast moving average pslow=pslowVal # period for the slow moving average ) def __init__(self): sma1 = bt.ind.SMA(self.data.close,period=self.p.pfast,plotname=" fast moving average") # fast moving average sma2 = bt.ind.SMA(self.data.close,period=self.p.pslow,plotname=" slow moving average") # slow moving average self.crossover = bt.ind.CrossOver(sma1,sma2) # crossover signal def next(self): if not self.position: # not in the market if self.crossover > 0: # if fast crosses slow to the upside self.buy() # enter long elif self.crossover < 0: # in the market & cross to the downside self.close() # close long position cerebro = bt.Cerebro() cerebro.adddata(data) cerebro.addstrategy(SmaCross) cerebro.broker.set_cash(1000) print('Starting portfolio value: %.2f' % cerebro.broker.getvalue()) start_time = time.time() cerebro.run() print('Final portfolio value: %.2f' % cerebro.broker.getvalue() + " with fast value of ",pfastVal ," and slow of " , pslowVal) print("--- %s seconds ---" % (time.time() - start_time)) txtFile = open(",txt","a") txtFile.write(str('Final: %.2f' % cerebro.broker.getvalue() + " Fast " + str(pfastVal) + " Slow " + str(pslowVal))) txtFile.write("\n") txtFile.close() pfastVal = pfastVal + 1 pslowVal = pslowVal + 1
With the following parameters, around 900 lines of results will be written to the .txt. The problem however comes due to the fact that each run takes on average 12 seconds to compute. Putting the range of values for my parameters aside and soley focusing on computation time and I guess "effeciency", I have two questions to ask.
- Is there a more pythonic way of writing/structuring my code that can decrease computation time?
- Is there a more pythonic way of looping through the range of values for the moving averages?
The CSV file during the testing had 50k candles to backtest.
-