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

Detect new resampled price



  • I have a code that uses both a tick data and a resampled data, let's call it 5 min period. I have a set of logics that only need to occur when a NEW 5m candle comes in. This will save a ton of computation. In order to detect this new price, here's what I've been doing:

    (Lf = low frequency, meaning resampled data)

    class St(bt.Strategy)
        def __init__(self):
            self.Lf_dt = self.datas[1].datetime
            # memeory functionality
            self.__previous_Lf_dt = None
    
        def next(self):
            # Check to see if there's a new Lf candle printed this period
            self.__new_Lf_print   = (self.Lf_dt[0] != self.__previous_Lf_dt)
            self.__previous_Lf_dt = self.Lf_dt[0]
    
            if self.__new_Lf_print:
                execute_Lf_logics()
    

    Is there an easier way to do this? something built-in perhaps?


  • administrators

    Use the length of the data feed: len(data1). It will only change when new data is available.



  • Ahh yes that makes sense. Something like this.

    class St(bt.Strategy)
        def __init__(self):
            # memeory functionality
            self.__previous_Lf_len = 0
    
        def next(self):
    
            if len(data1) != self.__previous_Lf_len:
                execute_Lf_logics()
                self.__previous_Lf_len = len(data1)
    

  • administrators

    In any case I would recommend against prefixing your member attributes with __. But it is your code of course.



  • Yes fair enough. But you would agree this is the most efficient way to accomplish this?

    class St(bt.Strategy)
        def __init__(self):
            # memeory functionality
            self.previous_Lf_len = 0
    
        def next(self)
            if len(data1) != self.previous_Lf_len:
                self.new_Lf_print = True
                self.previous_Lf_len = len(data1)
    
            if self.new_Lf_print:
                execute_Lf_logics()
    

  • administrators

    Efficiency depends on your entire logic. If you simply want to act on a new bar, that's efficient enough for sure.



  • for reference - very similar issue here:

    Strategy execution on different timeframes and multi-data



  • This is the most efficient solution I've found.

    class St(bt.Strategy)
        def __init__(self):
            self.new_Lf_print = self.data1.datatime() != self.data1.datatime()(-1)
    
        def next(self)
            if self.new_Lf_print[0]:
                execute_Lf_logics()
    

    By putting the empty brackets after the line object (datetime) it creates a linecoupler that is coupled to the base sample rate. Documentation here.

    This slightly outperforms the len() calculation from the previous. I wasn't able to get len() as a line object in the init function, so datetime works well enough.

    I also like this solution because the code is clean. Only requires a single line in init.


  • administrators

    @algoguy235 said in Detect new resampled price:

    I wasn't able to get len() as a line object in the init function

    len is a builtin and cannot be overridden. Given it is only meant to check a single value (because it increase monotonically) it seems pointless to have a replacement function for it to deliver a lines object.