Using Multiple Datasets in Backtrader’s Strategies

Quite often, when you work on advanced strategies only prie is not enough for you. You might want to use correlations between stocks, sentiment data, fundamentals, and so on. In this article, I will show you how you can use multiple data sources in Backtrader Strategies.

So let’s assume I want to add additional conditions to my strategy. It’s pretty risky to buy stocks when volatility is high. So let’s add a filter on VIX Index and deprecate the position when VIX is too high.

It’s extremely easy to add more data to Backtrader backtests. You should just basically repeat the same code for the new dataset as for the initial. If you fro example trade Apple and added it to the engine with the following code:

data = bt.feeds.YahooFinanceData(dataname = 'AAPL', fromdate = datetime(2010, 1, 1), todate = datetime(2020, 1, 1))
cerebro.adddata(data)

You can add the VIX index to the engine with the following code:

vix = bt.feeds.YahooFinanceData(dataname = '^VIX', fromdate = datetime(2010, 1, 1), todate = datetime(2020, 1, 1))
cerebro.adddata(vix)

Next, you can use VIX data with the following code:

self.data1.close

The initial data you add to your strategy has a data0 variable name. After that datasets you’re adding will have increased names: data1, data2, data3, …

Here is the entire code for the strategy:

import backtrader as bt
import backtrader.analyzers as btanalyzers
import matplotlib
from datetime import datetime

class MaCrossStrategy(bt.Strategy):

    params = (
        ('fast_length', 5),
        ('slow_length', 25), 
        ('vix_level', 30)
    )
    
    def __init__(self):
        ma_fast = bt.ind.SMA(period = self.params.fast_length)
        ma_slow = bt.ind.SMA(period = self.params.slow_length)
        
        self.crossover = bt.ind.CrossOver(ma_fast, ma_slow)
        self.vix = self.data1.close

    def next(self):
        if not self.position:
            if self.crossover > 0 and self.vix < self.params.vix_level: 
                self.buy()
        elif self.crossover < 0: 
            self.close()

cerebro = bt.Cerebro()

data = bt.feeds.YahooFinanceData(dataname = 'AAPL', fromdate = datetime(2010, 1, 1), todate = datetime(2020, 1, 1))
cerebro.adddata(data)

vix = bt.feeds.YahooFinanceData(dataname = '^VIX', fromdate = datetime(2010, 1, 1), todate = datetime(2020, 1, 1))
cerebro.adddata(vix)

cerebro.addstrategy(MaCrossStrategy, fast_length = 5, slow_length = 25, vix_level = 999)
cerebro.broker.setcash(1000000.0)
cerebro.addsizer(bt.sizers.PercentSizer, percents = 50)

cerebro.addanalyzer(btanalyzers.SharpeRatio, _name = "sharpe")
cerebro.addanalyzer(btanalyzers.Returns,     _name = "returns")

back = cerebro.run()

cerebro.broker.getvalue()

back[0].analyzers.sharpe.get_analysis()['sharperatio']
back[0].analyzers.returns.get_analysis()['rnorm100']

Leave a Reply

Your email address will not be published. Required fields are marked *