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

help with indicator based on multiple data feeds not synchronised



  • Hi,

    I would like to implement an indicator that first calculates the bid-ask midpoint on two separate minute-bar data feeds, one for bid and the other for ask. These data feeds are not synchronised i.e. there are minutes when one has value and the other does not. Although the value of the indicator is correct, its length is not. When the second feed does not have a minute bar of the first feed, it just overwrites the indicator value.

    Many thanks for the help.

    import backtrader as bt
    import sys
    import os
    
    
    class StrategyBidAsk(bt.Strategy):
    
        def next(self):
            output_str = ""
            for i in range(len(self.datas)):
                output_str += "{}: {}, {}|".format(self.datas[i]._name, self.datas[i].datetime.datetime(0), self.datas[i].lines.close[0])
            output_str = output_str[:-1]
            print(output_str)
            for ind in self.getindicators_lines():
                line_names = ind.getlinealiases()
                for idx in range(len(line_names)):
                    print("{} {} {} {} {}".format(ind.plotinfo.plotname or ind.__class__.__name__,
                                            line_names[idx], ind.lines[idx][0], ind.lines[idx][-1], len(ind)))
    
    
    class MidPriceIndicator(bt.Indicator):
        lines = ('toy_mid',)
    
        def __init__(self):
            self.lines.toy_mid = (self.datas[0]+self.datas[1])/2
    
    
    def main(argv):
    
        folder = "data"
        files = [['Toy_Ask.csv', 'Toy_Bid.csv']]
        cash = 100000.0
    
        cerebro = bt.Cerebro()
        cerebro.broker.setcash(cash)
        cerebro.broker.set_shortcash(False)
        cerebro.broker.setcommission(commission=0)
        cerebro.broker.set_coc(False)
    
        for file in files:
            if not isinstance(file, list):
                file = [file]
            data_list = []
            for i, f in enumerate(file):
                data = bt.feeds.GenericCSVData(
                        dataname=os.path.join(folder, f),
                        dtformat='%Y-%m-%d %H:%M:%S', # default
                        datetime=0,         # default
                        time=-1,            # default
                        close=1,
                        high=-1,
                        low=-1,
                        open=-1,
                        volume=-1,           # default
                        openinterest=-1,    # default for not present
                        timeframe=bt.TimeFrame.Minutes,
                        compression=1)      # default
                if i != 0 and len(file) == 2:
                    data.compensate(data_list[0])
                data_list.append(data)
                cerebro.adddata(data, name=os.path.splitext(f)[0])
    
        idx = cerebro.addstrategy(StrategyBidAsk)
        cerebro.addsizer_byidx(idx, bt.sizers.SizerFix, stake=100)
        cerebro.addindicator(MidPriceIndicator, cerebro.datasbyname["Toy_Bid"]._getline("close"), cerebro.datasbyname["Toy_Ask"]._getline("close"))
        cerebro.run(runonce=False, preload=True)
        cerebro.plot(volume=False, numfigs=1)
    
    
    if __name__ == "__main__":
        main(sys.argv)
    
    # # Output
    # Toy_Ask: 2018-08-08 00:00:01, 3.0|Toy_Bid: 2018-08-08 00:00:01, 5.0
    # MidPriceIndicator toy_mid 4.0 4.0 1
    # Toy_Ask: 2018-08-08 00:02:01, 3.0|Toy_Bid: 2018-08-08 00:02:01, 6.0
    # MidPriceIndicator toy_mid 4.5 4.0 2
    # Toy_Ask: 2018-08-08 00:02:01, 3.0|Toy_Bid: 2018-08-08 00:03:01, 7.0
    # MidPriceIndicator toy_mid 5.0 4.5 3
    # Toy_Ask: 2018-08-08 00:04:01, 0.0|Toy_Bid: 2018-08-08 00:03:01, 7.0
    # MidPriceIndicator toy_mid 3.5 4.5 3
    # Toy_Ask: 2018-08-08 00:08:01, 1.0|Toy_Bid: 2018-08-08 00:08:01, 2.0
    # MidPriceIndicator toy_mid 1.5 3.5 4
    
    

  • administrators

    @momentum said in help with indicator based on multiple data feeds not synchronised:

    Although the value of the indicator is correct, its length is not. When the second feed does not have a minute bar of the first feed, it just overwrites the indicator value.

    The indicator has the right length and the right value. If the data feeds have different paces, the 1st data feed is the clock for the indicator and marks the tempo. The indicator cannot add the length of both data feeds because it would then have a greater length than the system itself.



  • Thanks for your reply and help. By system you mean the strategy? Because in this case, strategy will have length 5 while indicator length 4.

    # Toy_Ask: 2018-08-08 00:00:01, 3.0|Toy_Bid: 2018-08-08 00:00:01, 5.0
    # MidPriceIndicator toy_mid 4.0 4.0 1 1
    # Toy_Ask: 2018-08-08 00:02:01, 3.0|Toy_Bid: 2018-08-08 00:02:01, 6.0
    # MidPriceIndicator toy_mid 4.5 4.0 2 2
    # Toy_Ask: 2018-08-08 00:02:01, 3.0|Toy_Bid: 2018-08-08 00:03:01, 7.0
    # MidPriceIndicator toy_mid 5.0 4.5 3 3
    # Toy_Ask: 2018-08-08 00:04:01, 0.0|Toy_Bid: 2018-08-08 00:03:01, 7.0
    # MidPriceIndicator toy_mid 3.5 4.5 3 4
    # Toy_Ask: 2018-08-08 00:08:01, 1.0|Toy_Bid: 2018-08-08 00:08:01, 2.0
    # MidPriceIndicator toy_mid 1.5 3.5 4 5
    
    import backtrader as bt
    import sys
    import os
    
    
    class StrategyBidAsk(bt.Strategy):
    
        def next(self):
            output_str = ""
            for i in range(len(self.datas)):
                output_str += "{}: {}, {}|".format(self.datas[i]._name, self.datas[i].datetime.datetime(0), self.datas[i].lines.close[0])
            output_str = output_str[:-1]
            print(output_str)
            for ind in self.getindicators_lines():
                line_names = ind.getlinealiases()
                for idx in range(len(line_names)):
                    print("{} {} {} {} {} {}".format(ind.plotinfo.plotname or ind.__class__.__name__,
                                            line_names[idx], ind.lines[idx][0], ind.lines[idx][-1], len(ind), len(self)))
    
    
    class MidPriceIndicator(bt.Indicator):
        lines = ('toy_mid',)
    
        def __init__(self):
            self.lines.toy_mid = (self.datas[0]+self.datas[1])/2
    
    
    def main(argv):
    
        folder = "data"
        files = [['Toy_Ask.csv', 'Toy_Bid.csv']]
        cash = 100000.0
    
        cerebro = bt.Cerebro()
        cerebro.broker.setcash(cash)
        cerebro.broker.set_shortcash(False)
        cerebro.broker.setcommission(commission=0)
        cerebro.broker.set_coc(False)
    
        for file in files:
            if not isinstance(file, list):
                file = [file]
            data_list = []
            for i, f in enumerate(file):
                data = bt.feeds.GenericCSVData(
                        dataname=os.path.join(folder, f),
                        dtformat='%Y-%m-%d %H:%M:%S', # default
                        datetime=0,         # default
                        time=-1,            # default
                        close=1,
                        high=-1,
                        low=-1,
                        open=-1,
                        volume=-1,           # default
                        openinterest=-1,    # default for not present
                        timeframe=bt.TimeFrame.Minutes,
                        compression=1)      # default
                if i != 0 and len(file) == 2:
                    data.compensate(data_list[0])
                data_list.append(data)
                cerebro.adddata(data, name=os.path.splitext(f)[0])
    
        idx = cerebro.addstrategy(StrategyBidAsk)
        cerebro.addsizer_byidx(idx, bt.sizers.SizerFix, stake=100)
        cerebro.addindicator(MidPriceIndicator, cerebro.datasbyname["Toy_Bid"]._getline("close"), cerebro.datasbyname["Toy_Ask"]._getline("close"))
        cerebro.run(runonce=False, preload=True)
        cerebro.plot(volume=False, numfigs=1)
    
    
    if __name__ == "__main__":
        main(sys.argv)
    
    

  • administrators

    The system can be longer than the underlying elements. If not, it would impossible to operate with different timeframes simultaneously.

    But it cannot be shorter.


Log in to reply
 

});