For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

Multiple Data Feeds (Instruments) on a single strategy



  • Hi All

    I am new to Back trader and I am in need of your help to test my strategy on multiple instrument data.
    I have pasted the code below, I am expecting the strategy to run for both the data feeds, but actually its running for only one data feed. Please let me know what I should be changing to make it run for both the instrument data feeds. Thanks in advance

    -- Satheesh Kumar

    from future import (absolute_import, division, print_function,
    unicode_literals)

    import argparse
    import backtrader as bt
    import backtrader.feeds as btfeeds
    import datetime as dt
    import pandas as p

    class TestStrategy(bt.Strategy):
    params = (
    ('smaPeriod', 10),
    )

    def __init__(self):
        
        #Retrieves Close price data from the object
        self.dataclose = self.data.close
        
        #To keep track of pending orders and buy price / commission.
        self.order = None
        self.buyprice = None
        self.commission = None
        
        #SMA Indicator
        self.sma = bt.indicators.MovingAverageSimple(self.data, period=self.params.smaPeriod)
    
        # Indicators for the plotting show
        bt.indicators.ExponentialMovingAverage(self.data, period=25)
        bt.indicators.WeightedMovingAverage(self.data, period=25).subplot = True
        bt.indicators.StochasticSlow(self.data)
        bt.indicators.MACDHisto(self.data)
        rsi = bt.indicators.RSI(self.data)
        bt.indicators.SmoothedMovingAverage(rsi, period=10)
        bt.indicators.ATR(self.data).plot = False
        
        
    def notify_order(self, order):
    
        #Check whether an order is Submitted or Accepted by the Broker
        if order.status in [order.Submitted, order.Accepted]:
            return
    
        #Check if an order is completed
        if order.status in [order.Completed]:
            if order.isbuy():
    
                print('Buy Executed Price: %.2f, Cost : %.2f, Commission : %.2f' % 
                      (order.executed.price,
                       order.executed.value,
                       order.executed.comm
                      ))
    
                self.buyprice = order.executed.price
                self.commission = order.executed.comm
    
    
            elif order.issell():
                print('Sell Executed Price: %.2f, Cost : %.2f, Commission : %.2f' % 
                      (order.executed.price,
                       order.executed.value, #for sell this is not working as expected
                       order.executed.comm
                      ))
    
            self.bar_executed = len(self)
    
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            print('Order Canceled/Margin/Rejected')
            
        
        self.order = None
        
    def notify_trade(self, trade):
            if not trade.isclosed:
                return
    
            print('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                 (trade.pnl, trade.pnlcomm))
    
        
    def next(self): 
       
        print('Date, %s, Close, %.2f' % (self.data.datetime.date(0), self.dataclose[0]))
    
        #Check if an order is in Pending state, if yes, we cannot send a 2nd one
        if self.order:
    
            print('An order already in Pending state')
            return
    
        #Check whether we have an open position already, if no, then we can enter a new position by entering a BUY trade
        if not self.position:
    
            if self.dataclose[0] > self.sma[0]:
                print('BUY Signal:, %.2f' % self.dataclose[0])
                self.order = self.buy()
      
        #if there is an existing position already, then we have to close it after 5 consecutive bars 
        else:
            if self.dataclose[0] < self.sma[0]:
                print('Sell Signal:, %.2f' % self.dataclose[0])
                self.order = self.sell() 
    

    if name == 'main':

    cerebro = bt.Cerebro() 
    cerebro.addstrategy(TestStrategy) #Adds the strategy
    
    orcl = p.read_csv('D:\Algoticks\Excercises\Data\orcl_price-history-05-21-2018.csv')
    orcl['datetime'] = orcl['datetime'].astype('datetime64[ns]')
    
    orcl_stg = bt.feeds.PandasData(dataname = orcl)
    
    hcl = p.read_csv('D:\Algoticks\Excercises\Data\hcl_price-history-05-21-2018.csv')
    hcl['datetime'] = hcl['datetime'].astype('datetime64[ns]')
    
    hcl_stg = bt.feeds.PandasData(dataname = hcl)
    
    cerebro.adddata(orcl_stg)   #Adds the data for the strategy
    cerebro.adddata(hcl_stg)
    
    #set the cash
    cerebro.broker.setcash(100000.0)
    #set broker commission
    cerebro.broker.setcommission(commission = 0.001) #.1 percentage
    #set the quantity
    cerebro.addsizer(bt.sizers.FixedSize, stake = 10)
    
    #cerebro.addwriter(bt.WriterFile, csv=True)
    
    print('Starting Portfolio Value : %.2f' % cerebro.broker.getvalue())
    cerebro.run()
    #data.head()
    print('Final Portfolio Value : %.2f' % cerebro.broker.getvalue())


  • Hi All

    Please ignore the previous code and please look at this code block. Sorry for the mistake

    from future import (absolute_import, division, print_function,
    unicode_literals)

    import argparse

    import backtrader as bt
    import backtrader.feeds as btfeeds
    import datetime as dt

    import pandas as p

    class TestStrategy(bt.Strategy):
    params = (
    ('smaPeriod', 10),
    )

    def __init__(self):
        
        #Retrieves Close price data from the object
        #self.dataclose = self.data.close
        
        #To keep track of pending orders and buy price / commission.
        self.order = None
        self.buyprice = None
        self.commission = None
        
    
        
    def notify_order(self, order):
    
        #Check whether an order is Submitted or Accepted by the Broker
        if order.status in [order.Submitted, order.Accepted]:
            return
    
        #Check if an order is completed
        if order.status in [order.Completed]:
            if order.isbuy():
    
                print('Buy Executed Price: %.2f, Cost : %.2f, Commission : %.2f' % 
                      (order.executed.price,
                       order.executed.value,
                       order.executed.comm
                      ))
    
                self.buyprice = order.executed.price
                self.commission = order.executed.comm
    
    
            elif order.issell():
                print('Sell Executed Price: %.2f, Cost : %.2f, Commission : %.2f' % 
                      (order.executed.price,
                       order.executed.value, #for sell this is not working as expected
                       order.executed.comm
                      ))
    
            self.bar_executed = len(self)
    
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            print('Order Canceled/Margin/Rejected')
            
        
        self.order = None
        
    def notify_trade(self, trade):
            if not trade.isclosed:
                return
    
            print('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                 (trade.pnl, trade.pnlcomm))
    
        
    def next(self): 
       
        
    
        for datafeed in self.getdatanames():
            print('Date, %s, Close, %.2f' % (self.getdatabyname(datafeed).datetime.date(0), self.getdatabyname(datafeed).close[0]))
            #Check if an order is in Pending state, if yes, we cannot send a 2nd one
            if self.order:
    
                print('An order already in Pending state')
                return
    
        #Check whether we have an open position already, if no, then we can enter a new position by entering a BUY trade
            if not self.position:
    
                if self.getdatabyname(datafeed).close[0] < self.getdatabyname(datafeed).close[-1]:
    
                    if self.getdatabyname(datafeed).close[-1] < self.getdatabyname(datafeed).close[-2]:
                        
                        print('BUY Signal:, %.2f' % self.getdatabyname(datafeed).close[0])
                        self.order = self.buy()
            
            elif self.position:
    
                 if len(self) >= (self.bar_executed + 4):
    
                    print('Sell Signal:, %.2f' % self.getdatabyname(datafeed).close[0])
                    self.order = self.sell()
    

    if name == 'main':

    cerebro = bt.Cerebro() 
    cerebro.addstrategy(TestStrategy) #Adds the strategy
    
    orcl = p.read_csv('D:\Algoticks\Excercises\Data\orcl_price-history-05-21-2018.csv')
    orcl['datetime'] = orcl['datetime'].astype('datetime64[ns]')
    
    orcl_stg = bt.feeds.PandasData(dataname = orcl)
    
    hcl = p.read_csv('D:\Algoticks\Excercises\Data\hcl_price-history-05-21-2018.csv')
    hcl['datetime'] = hcl['datetime'].astype('datetime64[ns]')
    
    hcl_stg = bt.feeds.PandasData(dataname = hcl)
    
    cerebro.adddata(orcl_stg)   #Adds the data for the strategy
    cerebro.adddata(hcl_stg)    
    
    #set the cash
    cerebro.broker.setcash(100000.0)
    #set broker commission
    cerebro.broker.setcommission(commission = 0.001) #.1 percentage
    #set the quantity
    cerebro.addsizer(bt.sizers.FixedSize, stake = 10)
    
    #cerebro.addwriter(bt.WriterFile, csv=True)
    
    print('Starting Portfolio Value : %.2f' % cerebro.broker.getvalue())
    cerebro.run()
    #data.head()
    print('Final Portfolio Value : %.2f' % cerebro.broker.getvalue())


  • @satheesh7134 Go through the multi data feeds example.

    You need to use enumerate(self.datas) to evaluate strategy on each data feed separately.