Basic MultiTimeframe order
-
So I have been following along with multitimeframe indicators as shown by the Backtrader website however I am having issues with sending basic buy and sell orders through.
from __future__ import (absolute_import, division, print_function, unicode_literals) import argparse import backtrader as bt import backtrader.feeds as btfeeds import backtrader.indicators as btind from datetime import datetime class SMAStrategy(bt.Strategy): params = ( ('period', 10), ('onlydaily', False), ) def __init__(self): self.sma_small_tf = btind.MACDHisto(self.data, period_me1 = 12, period_me2 = 26, period_signal=9) if not self.p.onlydaily: self.sma_large_tf = btind.MACDHisto(self.data1, period_me1 = 12, period_me2 = 26, period_signal=9) def nextstart(self): print('--------------------------------------------------') print('nextstart called with len', len(self)) print('--------------------------------------------------') if not self.position: if self.sma_large_tf.histo > self.sma_large_tf.histo[-1] and self.sma_small_tf.histo > self.sma_large_tf.histo[-1]: self.buy() print("Orderbuy") else: if self.sma_large_tf.histo < self.sma_large_tf.histo[-1] and self.sma_small_tf.histo < self.sma_small_tf.histo[-1]: self.sell() super(SMAStrategy, self).nextstart() def runstrat(): args = parse_args() # Create a cerebro entity startcash = 10000 cerebro = bt.Cerebro(stdstats=False) # Add a strategy if not args.indicators: cerebro.addstrategy(bt.Strategy) else: cerebro.addstrategy( SMAStrategy, # args for the strategy period=args.period, onlydaily=args.onlydaily, ) # Load the Data datapath = args.dataname or '../../datas/2006-day-001.txt' data = bt.feeds.YahooFinanceData( dataname='SPY', fromdate = datetime(2020,1,1), todate = datetime(2020,4,1), timeframe = bt.TimeFrame.Days, buffered= True ) cerebro.adddata(data) # First add the original data - smaller timeframe tframes = dict(daily=bt.TimeFrame.Days, weekly=bt.TimeFrame.Weeks, monthly=bt.TimeFrame.Months) # Handy dictionary for the argument timeframe conversion # Resample the data if args.noresample: datapath = args.dataname2 or '../../datas/2006-week-001.txt' data2 = btfeeds.BacktraderCSVData(dataname=datapath) # And then the large timeframe cerebro.adddata(data2) else: cerebro.resampledata(data, timeframe=tframes[args.timeframe], compression=args.compression) # Run over everything cerebro.run() portvalue = cerebro.broker.getvalue() pnl = portvalue - startcash #Print out the final result print('Final Portfolio Value: ${}'.format(portvalue)) print('P/L: ${}'.format(pnl)) # Plot the result cerebro.plot(style='bar') def parse_args(): parser = argparse.ArgumentParser( description='Multitimeframe test') parser.add_argument('--dataname', default='', required=False, help='File Data to Load') parser.add_argument('--dataname2', default='', required=False, help='Larger timeframe file to load') parser.add_argument('--noresample', action='store_true', help='Do not resample, rather load larger timeframe') parser.add_argument('--timeframe', default='weekly', required=False, choices=['daily', 'weekly', 'monhtly'], help='Timeframe to resample to') parser.add_argument('--compression', default=1, required=False, type=int, help='Compress n bars into 1') parser.add_argument('--indicators', action='store_true', help='Wether to apply Strategy with indicators') parser.add_argument('--onlydaily', action='store_true', help='Indicator only to be applied to daily timeframe') parser.add_argument('--period', default=10, required=False, type=int, help='Period to apply to indicator') return parser.parse_args() if __name__ == '__main__':
I placed the order logic in nextstart() because if it is my understanding a nextstart() will initiate after the higher timeframe will close. Any guidance will be greatly appreciated
-
From Operating the Platform in the docs.
nextstart
Called exactly ONCE when the minimum period for the line iterator` has been met.
The default behavior is to forward the call to next, but can of course be overriden if needed.
Place your orders in next().
-
@run-out Ok I think I understand now. So nextstart() ensures that the higher time frame completes the bar before letting the program continue? Also indicators from a higher time frame have there current index equals to their previous, [0] becomes [-1]? I understand where self.data gets its data however I am a bit confused about self.data1, does it originate from the cerebor.resampledata?
Thank You!! Much appreciated
-
@Paul-Park said in Basic MultiTimeframe order:
So nextstart() ensures that the higher time frame completes the bar before letting the program continue?
nextstart()
has no relation to time frames. It is called once between lastprenext()
call and firstnext()
call - ref Docs - Strategy.
-
@ab_trader said in Basic MultiTimeframe order:
@Paul-Park said in Basic MultiTimeframe order:
So nextstart() ensures that the higher time frame completes the bar before letting the program continue?
nextstart()
has no relation to time frames.Ahh I see where my confusion was now. Thank you very much.