avatarEsteban Thilliez

Summary

The article provides guidance on using Python's Backtrader framework for multi-time frame and multi-source analysis in trading strategy development, including the addition of custom data feeds and data resampling.

Abstract

The sixth installment in a series about improving trading strategies with Python, this article focuses on the practical application of multi-time frame and multi-source analysis within the Backtrader framework. It explains how to add multiple data sources, access additional data feeds, and create custom data feeds by extending GenericCSVData. The article also covers data resampling to derive new time frames from existing data, emphasizing the ease of implementation in Backtrader. The author acknowledges the complexity of designing strategies with multiple time frames and data sources but demonstrates that Backtrader simplifies the technical aspect of this process.

Opinions

  • The author believes that most traders use multiple time frames to identify trends and refine entry points.
  • There is an emphasis on the flexibility of Backtrader, allowing for an unlimited number of data feeds to be added to a strategy.
  • The author suggests that traders may want to use different data sources, such as exponential moving averages based on high prices or BTC-EUR quotes for ETH-EUR trading decisions.
  • Custom data feeds are presented as a powerful feature for incorporating additional data like PE ratios into trading logic.
  • The author admits to having limited experience with creating custom data feeds but directs readers to Backtrader's documentation for further information.
  • A cautious note is made about the order of data feeds, reminding readers to keep track of the indexes when accessing different data sources.
  • The article concludes by highlighting the potential for building complex trading systems with multi-time frame/source analysis in Backtrader, while also noting that strategy design remains the most challenging aspect.

Backtest your Trading Systems with Python — Multi Time Frame/Sources Analysis

Photo by Ishant Mishra on Unsplash

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.622008167614

It 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:

Finance
Trading
Algorithmic Trading
Python
Programming
Recommended from ReadMedium