Mulit time frames: dont understand how to 'couple' (Pivot Points)



  • I followed the documentation regarding mixing and resampling time frames, but i still don't understand the behavior of my strategy:

    I have written my own implementation of Pivot Point Indicator and I want to use it for weekly and monthly data feeds:

    class PivotPointIndicator(bt.Indicator):
        lines =('r3', 'r2', 'r1', 'pp', 's1', 's2', 's3',)
       params = dict(withopen=False)
       plotinfo = dict(subplot=False)
    
        def __init__(self):
            h = self.data.high(-1)  # previous high
            l = self.data.low(-1)  # previous low
            c = self.data.close(-1)  # previous close
    
            if not self.p.withopen:
                self.lines.pp = pp = (h + l + c) / 3.0
            else:
                o = self.data.open(-1)
                self.lines.pp = pp = (o + h + l + c) / 4.0
    
            p2 = pp * 2.0
            self.lines.s1 = p2 - h  # (p x 2) - high
            self.lines.r1 = p2 - l  # (p x 2) - low
    
            hilo = h - l
            self.lines.s2 = pp - hilo  # p - (high - low)
            self.lines.r2 = pp + hilo  # p + (high - low)
    
            self.lines.r3 = h + 2 * (pp - l)
            self.lines.s3 = l - 2 * (h - pp)
    

    In my Strategy I want to instantiate two of my Pivot Point Indicators, one with a weekly and the other with monthly feed:

    def __init__(self):
        self.pivots_weekly = indis.PivotPointIndicator(self.datas[0])
        pm = indis.PivotPointIndicator(self.datas[1])
        self.pivots_monthly = pm() # coulpe    
    
    
    
    def next(self):
        self.log('PP Reversals: weekly: {}, monthly: {}'.format(self.pivots_weekly.l.pp[0],   self.pivots_monthly.l.pp[0]))
    

    I would expect that if I run my strategy it would print the weekly and monthly pivot reversal for each WEEK, because it is the first data feed that was added and because it has the shortest time frame:

    cerebro = bt.Cerebro(runonce=False)
    cerebro.resampledata(feed_daily, timeframe=bt.TimeFrame.Weeks)
    cerebro.resampledata(feed_daily, timeframe=bt.TimeFrame.Months)
    
    cerebro.run()
    

    It gives me not the expected values but the following:

    (...)
    2017-07-28T00:00:00, PP Reversals: weekly: 150.19333333333336, monthly: 151.51000000000002
    2017-07-28T00:00:00, PP Reversals: weekly: 150.19333333333336, monthly: 147.39999999999998
    2017-08-04T00:00:00, PP Reversals: weekly: 150.26333333333335, monthly: 147.39999999999998
    2017-08-11T00:00:00, PP Reversals: weekly: 154.75666666666666, monthly: 147.39999999999998
    2017-08-18T00:00:00, PP Reversals: weekly: 157.98000000000002, monthly: 147.39999999999998
    2017-08-25T00:00:00, PP Reversals: weekly: 158.91,             monthly: 147.39999999999998
    2017-08-25T00:00:00, PP Reversals: weekly: 158.91,             monthly: 148.63333333333333
    2017-09-01T00:00:00, PP Reversals: weekly: 158.57000000000002, monthly: 148.63333333333333
    2017-09-08T00:00:00, PP Reversals: weekly: 162.97333333333333, monthly: 148.63333333333333
    2017-09-15T00:00:00, PP Reversals: weekly: 160.47,             monthly: 148.63333333333333
    2017-09-22T00:00:00, PP Reversals: weekly: 160.58333333333334, monthly: 148.63333333333333
    2017-09-29T00:00:00, PP Reversals: weekly: 154.31666666666666, monthly: 148.63333333333333
    2017-09-29T00:00:00, PP Reversals: weekly: 154.31666666666666, monthly: 156.83333333333334
    2017-10-06T00:00:00, PP Reversals: weekly: 152.66666666666666, monthly: 156.83333333333334
    2017-10-13T00:00:00, PP Reversals: weekly: 154.41666666666669, monthly: 156.83333333333334
    2017-10-20T00:00:00, PP Reversals: weekly: 156.6966666666667,  monthly: 156.83333333333334
    2017-10-27T00:00:00, PP Reversals: weekly: 157.38,             monthly: 156.83333333333334
    2017-10-27T00:00:00, PP Reversals: weekly: 157.38,             monthly: 156.07333333333335
    2017-11-03T00:00:00, PP Reversals: weekly: 160.64000000000001, monthly: 156.07333333333335
    2017-11-10T00:00:00, PP Reversals: weekly: 170.16,             monthly: 156.07333333333335
    2017-11-17T00:00:00, PP Reversals: weekly: 174.21,             monthly: 156.07333333333335
    2017-11-24T00:00:00, PP Reversals: weekly: 171.01,             monthly: 159.70333333333335
    

    The monthly reversals are some kind of 'shiftet' and there are different values for the same date at the ending of a month (e.g. for 2017-08-25T00:00:00, 2017-09-29T00:00:00, 2017-10-27T00:00:00 there are two entries??).

    What do I have to do if I want to have monthly and weekly reversals on the same weekly time frame? That means i should have for every single week the corresponding and correct monthly and weekly value.



  • resampledata uses data available at the moment. So if you are going thru weeks of the current month then on monthly time frame the only prices available are the prices from the previous month. So your indicator gives you values based on previous month bar. Maybe that is why it seems 'shifted'.

    Rows with similar dates are two calls of the next() for two data feeds: 1st row - weekly bar call, monthly bar is not completed yet, so it uses previous month prices and indicator values. 2nd row - monthly bar call, monthly bar is completed now, prices and indicators are updated.

    If you will print out prices, this behavior will be clear.

    One other comment - if you use (-1) in the __init()__ you calculate your indicators not at the end of the current bar, but at the end of the previous bar. So indicators on EOD 12/1 are calculated based on prices from EOD 11/24. On the monthly bars it can be even 2-month shift.



  • @team172011 said in Mulit time frames: dont understand how to 'couple' (Pivot Points):

    i should have for every single week the corresponding and correct monthly and weekly value.

    If the week is in the middle of the month, then at the end of the week you can have current week prices and previous month prices. Only if your end of week corresponds with the end of the month you can have current week and current month prices.



  • To see the current values of the month ... the ideal would be to resample the weeks and replay the months from the weekly timeframe. But it would have to be tested.



  • @Paska-Houso With the use of replay (it works, I've played with this staff today a bit) monthly bars pivot point will be floating from week to week during the month. If it works for topic starter, it is ok. But I don't think that it can be called as a pivot point on monthly bars. :)



  • That's right.

    There is an additional obstacle: the end of a month doesn't have to meet the end of a week. Unlike in combinations like Days/Weeks and Days/Months in which it can be accounted for bank holidays by using trading calendars, there is no (imho) way to fully synchronize the combination Weeks/Months



  • Thank you very much for your answers!
    Like @ab_trader mentioned, this is not a classic usage of pivot points, because I am just using the prior week for 'weekly pivots' and the prior month for 'monthly pivots', actually it has to be a higher time frame for weekly or monthly reversals (e.g. for weeks it must be the prior year I think). I'm aware of that, and I want to calculate it this way.

    Like @Paska-Houso said it is not possible to sync weeks to month because a months ending is not always a weeks ending (by the way, sync weeks to year is even more difficult). So far I had re-sampled and calculated the pivots outside of backtrader on my own and it works perfectly:

    • If a week ends (mostly on Friday but it can be any other day because of hollidays etc) I took the pivots of the corresponding prior month,

      • E.g ends in November, take pivots of September, ends in December, take pivots of November...
    • Simple logic: On a weekly base we use priors week as weekly reversals and priors month as monthly reversals

    This way i had to write my own PadasFeed with additional columns for s3-r3 weekly and s3-r3 monthly. Later I discovered the mixed time frame handling of backtrader and the re-sampling function and thought

    • "nice, I would have much less code, maybe better performance and a smaller feed without all the additional lines"

    if using this functionality.

    Do you think my intentions are possible with backtraders in-build functionality? I will take a closer look at the replay function. So far I am a newbie regarding backtrader and still discovering all its functionality.



  • @ab_trader How should I use the replay function?



  • @team172011 Honestly I don't think that replay will give any benefits. You use completed monthly bars and replay delivers to you incompleted but updated based on the latest weekly prices "monthly" bar every week.

    What I would do in your case is start with daily data, resample it to weeks first and then resample the same daily data to months. It will give you correct monthly bars. But if you have no daily data available, then the way you do it now is an appropriate way.



  • @ab_trader this is exactly what I am doing. If you take a look at the top post, you see that i am feeding cerebro with weekly and daily data, resampled from daily data.



  • @team172011 I didn't find anything about daily data in your original post, piece of code with data resampling also doesn't have any reference to daily data.

    So in this case bt works as expected, I don't see any problems. Double rows with the sane date but different results are explainable, see my post above. I've run your code printing prices and got the following:

    end of week 11/17 - get weekly close from 11/10 (previous available week), monthly close from September (previous available month).
    end of week 11/10 - get weekly close from 11/03 (previous available week), monthly close from September (previous available month).
    ...
    

    It is correct based on the script you shown.



  • @ab_trader sorry, but I don't get it. My monthly calculations are not shifted anymore, but the monthly calculations are wrong and I even don't know where to search:

    • If I just add (daily) data resampled to weekly data my indicator calculates correct values.
    • Also if I just add (daily) data resampled to monthly data all calculations are like expected. (its possible to set up my kind of pivots in https://www.tradingview.com, so I can fast validate against it)

    But if I add both daily and monthly resampled data I get wrong results for the monthly pivots. My output also shows no difference between coupled (self.pivots_monthly = pm()) and not coupled (self.pivots_monthly = pm) monthly pivot indicator.



  • This is interesting, but not really clear why it is going the way it is going. I would keep daily, weekly and monthly data feeds in the system and put into the next() end of week condition to trigger trading rules.



  • @ab_trader

    I have added daily, weekly and monthly data to cerebro and let my Strategy1 just print the date and close:

    # get stored daily data from interactive brokers(2002-11-29-2017-11-24) 
    rawData = inout.getSymbolData(symbol) 
    feed_daily = PandasData(dataname=rawData)
    
    cerebro = bt.Cerebro(runonce=False)
    cerebro.addstrategy(Strategy1)
    cerebro.adddata(feed_daily)
    cerebro.resampledata(feed_daily, timeframe=bt.TimeFrame.Weeks)
    cerebro.resampledata(feed_daily, timeframe=bt.TimeFrame.Months)
    cerebro.run()
    
    #Strategy1 just prints the daily, weekly and monthly data in next() method:
        def next(self):
            print('daily:{} c: {} | weekly:{} c: {} | monthly:{} c: {}'\
                .format(bt.num2date(self.datas[0].datetime[0]), self.datas[0].close[0],\
                 bt.num2date(self.datas[1].datetime[0]), self.datas[1].close[0],\
                 bt.num2date(self.datas[2].datetime[0]), self.datas[2].close[0]))
    

    The output looks good, but the last two entries are duplicated. Maybe because there is a last monthly close (last date) but no more daily and weekly data?

    (...)
    daily:2017-10-30-166.72 | weekly:2017-10-27-163.05 | monthly:2017-09-29-154.12
    daily:2017-10-31-169.04 | weekly:2017-10-27-163.05 | monthly:2017-09-29-154.12
    daily:2017-11-01-166.89 | weekly:2017-10-27-163.05 | monthly:2017-10-31-169.04
    daily:2017-11-02-168.11 | weekly:2017-10-27-163.05 | monthly:2017-10-31-169.04
    daily:2017-11-03-172.5 | weekly:2017-10-27-163.05 | monthly:2017-10-31-169.04
    daily:2017-11-06-174.25 | weekly:2017-11-03-172.5 | monthly:2017-10-31-169.04
    daily:2017-11-07-174.81 | weekly:2017-11-03-172.5 | monthly:2017-10-31-169.04
    daily:2017-11-08-176.24 | weekly:2017-11-03-172.5 | monthly:2017-10-31-169.04
    daily:2017-11-09-175.88 | weekly:2017-11-03-172.5 | monthly:2017-10-31-169.04
    daily:2017-11-10-174.67 | weekly:2017-11-03-172.5 | monthly:2017-10-31-169.04
    daily:2017-11-13-173.97 | weekly:2017-11-10-174.67 | monthly:2017-10-31-169.04
    daily:2017-11-14-171.34 | weekly:2017-11-10-174.67 | monthly:2017-10-31-169.04
    daily:2017-11-15-169.08 | weekly:2017-11-10-174.67 | monthly:2017-10-31-169.04
    daily:2017-11-16-171.1 | weekly:2017-11-10-174.67 | monthly:2017-10-31-169.04
    daily:2017-11-17-170.15 | weekly:2017-11-10-174.67 | monthly:2017-10-31-169.04
    daily:2017-11-20-169.98 | weekly:2017-11-17-170.15 | monthly:2017-10-31-169.04
    daily:2017-11-21-173.14 | weekly:2017-11-17-170.15 | monthly:2017-10-31-169.04
    daily:2017-11-22-174.96 | weekly:2017-11-17-170.15 | monthly:2017-10-31-169.04
    daily:2017-11-24-174.97 | weekly:2017-11-17-170.15 | monthly:2017-10-31-169.04
    daily:2017-11-24-174.97 | weekly:2017-11-24-174.97 | monthly:2017-11-24-174.97
    

    How can I avoid this? I think this is my problem, if I calculate with this last values i get wrong results (or results I would not expected). This also happens if I 'shift' them, I mean if I take previous week and month [-1]:



  • Here is the approach - compare length of the daily data feed on each next() call. This will help to avoid excessive next() calls due to resampling. You might be able to come up with the only next() call at the end of the week.

    class MasterStrategy(bt.Strategy):
    
        def __init__(self):
    
            self.daily_length = 0
    
        def next(self):
    
            if len(self.datas[0]) > self.daily_length:
                print('daily:{} len: {} | weekly:{} len: {} | monthly:{} len: {}'\
                    .format(bt.num2date(self.datas[0].datetime[0]), len(self.datas[0]),\
                            bt.num2date(self.datas[1].datetime[0]), len(self.datas[1]),\
                            bt.num2date(self.datas[2].datetime[0]), len(self.datas[2])))
                self.daily_length = len(self.datas[0])
    

    Output:

    daily:2017-10-16 23:59:59.999989 len: 98 | weekly:2017-10-13 23:59:59.999989 len: 20 | monthly:2017-09-29 23:59:59.999989 len: 5
    daily:2017-10-17 23:59:59.999989 len: 99 | weekly:2017-10-13 23:59:59.999989 len: 20 | monthly:2017-09-29 23:59:59.999989 len: 5
    daily:2017-10-18 23:59:59.999989 len: 100 | weekly:2017-10-13 23:59:59.999989 len: 20 | monthly:2017-09-29 23:59:59.999989 len: 5
    daily:2017-10-19 23:59:59.999989 len: 101 | weekly:2017-10-13 23:59:59.999989 len: 20 | monthly:2017-09-29 23:59:59.999989 len: 5
    daily:2017-10-20 23:59:59.999989 len: 102 | weekly:2017-10-13 23:59:59.999989 len: 20 | monthly:2017-09-29 23:59:59.999989 len: 5
    daily:2017-10-23 23:59:59.999989 len: 103 | weekly:2017-10-20 23:59:59.999989 len: 21 | monthly:2017-09-29 23:59:59.999989 len: 5
    daily:2017-10-24 23:59:59.999989 len: 104 | weekly:2017-10-20 23:59:59.999989 len: 21 | monthly:2017-09-29 23:59:59.999989 len: 5
    daily:2017-10-25 23:59:59.999989 len: 105 | weekly:2017-10-20 23:59:59.999989 len: 21 | monthly:2017-09-29 23:59:59.999989 len: 5
    daily:2017-10-26 23:59:59.999989 len: 106 | weekly:2017-10-20 23:59:59.999989 len: 21 | monthly:2017-09-29 23:59:59.999989 len: 5
    daily:2017-10-27 23:59:59.999989 len: 107 | weekly:2017-10-20 23:59:59.999989 len: 21 | monthly:2017-09-29 23:59:59.999989 len: 5
    daily:2017-10-30 23:59:59.999989 len: 108 | weekly:2017-10-27 23:59:59.999989 len: 22 | monthly:2017-09-29 23:59:59.999989 len: 5
    daily:2017-10-31 23:59:59.999989 len: 109 | weekly:2017-10-27 23:59:59.999989 len: 22 | monthly:2017-09-29 23:59:59.999989 len: 5
    daily:2017-11-01 23:59:59.999989 len: 110 | weekly:2017-10-27 23:59:59.999989 len: 22 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-02 23:59:59.999989 len: 111 | weekly:2017-10-27 23:59:59.999989 len: 22 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-03 23:59:59.999989 len: 112 | weekly:2017-10-27 23:59:59.999989 len: 22 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-06 23:59:59.999989 len: 113 | weekly:2017-11-03 23:59:59.999989 len: 23 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-07 23:59:59.999989 len: 114 | weekly:2017-11-03 23:59:59.999989 len: 23 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-08 23:59:59.999989 len: 115 | weekly:2017-11-03 23:59:59.999989 len: 23 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-09 23:59:59.999989 len: 116 | weekly:2017-11-03 23:59:59.999989 len: 23 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-10 23:59:59.999989 len: 117 | weekly:2017-11-03 23:59:59.999989 len: 23 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-13 23:59:59.999989 len: 118 | weekly:2017-11-10 23:59:59.999989 len: 24 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-14 23:59:59.999989 len: 119 | weekly:2017-11-10 23:59:59.999989 len: 24 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-15 23:59:59.999989 len: 120 | weekly:2017-11-10 23:59:59.999989 len: 24 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-16 23:59:59.999989 len: 121 | weekly:2017-11-10 23:59:59.999989 len: 24 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-17 23:59:59.999989 len: 122 | weekly:2017-11-10 23:59:59.999989 len: 24 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-20 23:59:59.999989 len: 123 | weekly:2017-11-17 23:59:59.999989 len: 25 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-21 23:59:59.999989 len: 124 | weekly:2017-11-17 23:59:59.999989 len: 25 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-22 23:59:59.999989 len: 125 | weekly:2017-11-17 23:59:59.999989 len: 25 | monthly:2017-10-31 23:59:59.999989 len: 6
    daily:2017-11-24 23:59:59.999989 len: 126 | weekly:2017-11-17 23:59:59.999989 len: 25 | monthly:2017-10-31 23:59:59.999989 len: 6
    

Log in to reply
 

Looks like your connection to Backtrader Community was lost, please wait while we try to reconnect.