Category Archives: programming

Backtrader–notes about multiple data timeframes

I attempted to make a system that uses ATR based on a different time frame than the signal I was considering. Bottom line, that wasn’t successful for trading (at least so far) but I did discover some errors and figured out a way to correct some of them.

First of all, to use multiple time frames I had to include some additional inputs into the original data.

I collected the data using a class I wrote that gets data into a pandas dataframe named data frame, so that is the entry point for the following code:

data = bt.feeds.PandasData(dataname=dataframe, name=symbol, ) 

If I wanted to use a different time frame, I had to modify this code to the following:

data = bt.feeds.PandasData(dataname=dataframe, name=symbol, timeframe = bt.TimeFrame.Minutes, compression = _) 

Then to resample the data, I could use the following statements:

cerebro.adddata(data) #data0
cerebro.resampledata(data, timeframe=bt.TimeFrame.Minutes, compression = 720, name = '720m') # data1
cerebro.resampledata(data, timeframe=bt.TimeFrame.Days, compression = 1, name = '1d') # data2

This including this resampled data did cause some problems. I had an observer that intermittently caused errors when plotting which I removed to allow plotting to be reliable:

#cerebro.addobserver(bu.AcctValue)

Truth be told I didn’t really need that observer but it was in some code I copied when I was just getting started with backtrader.

I also had trouble with an analyzer, specifically the returns analyzer added with the following code.

cerebro.addanalyzer(bt.analyzers.Returns, _name="ret")

When I used the data feed that included “timeframe = bt.TimeFrame.Minutes” this analyzer would give a nonsensical answer. I don’t know why this subtle difference in the data that shouldn’t really change anything ruins the output of the analyzer but it seems to be the case.

Backtrader Reference Info

I found the following to be useful when working with the Backtrader testing/trading engine.

To get “self” variables from a strategy for inspection after the run is over:

...
strategies = cerebro.run()
...
strat = strategies[0]
# the strategy uses self.hypo_long_orders as a variable
strat.hypo_long_orders

To view orders from the system this approach should work:

# orders
orders = [str(order).splitlines() for order in strat._orders]
df = pd.DataFrame(orders)
df

#trades
trades = [str(trade).splitlines() for trade in list(strat._trades.values())[0][0]]
df1 = pd.DataFrame(trades)
df1

#raw data
# raw data
open = strat.data_open.array
high = strat.data_high.array

I adapted some of this from the following place in the backtrader community:

https://community.backtrader.com/topic/809/accessing-data-after-finished-run/6

With respect to using backtrader with IB the following appears to be useful:

https://community.backtrader.com/topic/1203/is-it-possible-to-retrieve-all-the-open-active-orders-from-interactive-broker

https://community.backtrader.com/topic/1146/is-there-way-to-track-open-orders-with-ib-broker

https://medium.com/@danjrod/interactive-brokers-in-python-with-backtrader-23dea376b2fc

https://community.backtrader.com/user/richard-o-regan

https://pypi.org/project/ibapi/

https://medium.com/codex/using-python-to-send-telegram-messages-in-3-simple-steps-419a8b5e5e2