Backtest your Trading Systems with Python — Multi Time Frame/Sources Analysis
This story is the sixth of the backtrader series. You can find the other stories here: Improve your Trading with Python. Also, there is a GitHub repo associated with this series, you can find it here if you want to follow the code in a clearer way: Backtrader Series.
Why Should I Use Multiple Time Frame/Sources Analysis
I know very few traders who trade using only one time frame. Indeed, most traders will look at larger time frames to identify the trend, and smaller time frames to adjust their entry.
Some traders also want to use different data sources in their strategies. For example, maybe they want to use an exponential moving average using the prices’ highs as a data source instead of the prices’ closes. Or maybe they want to take into consideration the quote of BTC-EUR before placing an order on ETH-EUR.
Adding Multiple Data Sources into Backtrader
Do you remember how we added data into our Cerebro in the previous stories? We used cerebro.adddata(data) .
Now, let me tell you one thing: there is no limit to the number of data you can add to a Cerebro. It means if you want to add other data, you can do it using the same method. For example, you can do this:
btc_eur = yf.Ticker("BTC-EUR")
btc_data = btc_eur.history(period="1y")
btc_pandas_data = btfeeds.PandasData(dataname=btc_data)
eth_eur = yf.Ticker("ETH-EUR")
eth_data = eth_eur.history(period="1y")
eth_pandas_data = btfeeds.PandasData(dataname=eth_data)
cerebro.adddata(btc_pandas_data)
cerebro.adddata(eth_pandas_data)Now you may wonder how to access the additional data from our strategy. Remember, to access our data, we used self.datas[0] . It allows us to access the first data feed added to our Cerebro. If we want to access the second data feed, we can just use self.datas[1] .
So, if I want to log the BTC and ETH prices from my strategy, I do it this way:
self.log("BTC Close: {}, ETH Close: {}".format(
self.datas[0].close[0], self.datas[1].close[0]))Now, what if I want to smooth my ETH prices using an EMA?
In each Backtrader indicator, we can specify the data we want the indicator to use to do the computing. For example, let’s create an ETH exponential moving average:
self.eth_ema = EMA(self.datas[1], period=10)We can log it to check:
2021-10-03 - BTC Close: 51189.44921875, ETH Close: 2945.1484375, ETH EMA: 2629.69794921875
2021-10-04 - BTC Close: 50313.38671875, ETH Close: 2909.7802734375, ETH EMA: 2680.622008167614It works! By the way, we see our ETH closes are correct too.
You can add any data to the Cerebro. You can even create your own data feeds if you want.
Custom Data Feeds
Let’s say you have a CSV File containing an additional column for the PE ratio and you want to use it in your strategy’s logic. I didn’t talk specifically about how data feeds work, but the code and the comments below talk by themselves.
from backtrader.feeds import GenericCSVData
class GenericCSV_PE(GenericCSVData):
# Add a 'pe' line to the inherited ones from the base class
lines = ('pe',)
# openinterest in GenericCSVData has index 7 ... add 1
# add the parameter to the parameters inherited from the base class
params = (('pe', 8),)When you want to add additional lines to a data feed, you can do it by creating a new data feed inheriting from GenericCSVData and by adding lines. Then, you must add your line index in params. The line index is the index of the column where your data is located in the CSV file.
You can check the Backtrader’s documentation for more information, I rarely use this feature and I don’t specifically know how it works.
Data Resampling
Data resampling is like adding new data sources, but these sources come from existing data. For example, let’s say your main source is BTC-EUR on a daily time frame. You can resample it to BTC-EUR on a weekly time frame.
So your weekly BTC-EUR data comes from the daily BTC-EUR data but is considered a new source.
In Backtrader, we don’t use adddata to resample data, we use resampledata :
btc_eur = yf.Ticker("BTC-EUR")
btc_data = btc_eur.history(period="1y")
btc_pandas_data = btfeeds.PandasData(dataname=btc_data)cerebro.adddata(btc_pandas_data)
cerebro.resampledata(btc_pandas_data, timeframe=bt.TimeFrame.Weeks, compression=1)So now, if we access self.datas[1] , we will get the weekly BTC-EUR data. It’s as simple as that.
Just be careful when you add multiple data because the order of the indexes corresponds to the order in which the data was added.
So, self.datas[0] accesses the first data added, self.datas[3] the fourth data added, etc…
Final Note
Multi Time Frame/Sources analysis allows you to build very complex trading systems. As you can see, it’s easy to implement in Backtrader. The hardest part is to design the strategy.
To find the other stories of this series and more about mixing trading and Python, check this: Improve your Trading with Python
To explore more of my Python stories, click here!
If you liked the story, don’t forget to clap and maybe follow me if you want to explore more of my content :)
You can also subscribe to me via email to be notified every time I publish a new story, just click here!
If you’re not subscribed to Medium yet and wish to support me or get access to all my stories, you can use my link:
A Message from InsiderFinance

Thanks for being a part of our community! Before you go:
- 👏 Clap for the story and follow the author 👉
- 📰 View more content in the InsiderFinance Wire
- 📚 Take our FREE Masterclass
- 📈 Discover Powerful Trading Tools




