Executing Buy Sell Strategy for PivotPoint



  • Trying to execute a strategy for buying at the first P and selling at the R1:

    class St(bt.SignalStrategy):
        params = ()
    
    def __init__(self):
        self.pp = bt.ind.PivotPoint(self.data1)
        pp1 = self.pp()  # couple the entire indicators
        self.buysignal = self.data0.close < pp1.p
        self.sellsignal = self.data0.close > pp1.r1
    
        self.signal_add(bt.SIGNAL_LONG, self.buysignal)
        self.signal_add(bt.SIGNAL_LONGEXIT, self.sellsignal)
    

    def runstrat():
    args = parse_args()

    cerebro = bt.Cerebro()
    data = use_clf_data()
    
    # Add commodity
    commCL= bt.CommissionInfo(commission=2.0, margin=1000.0, mult=1000.0)
    cerebro.broker.addcommissioninfo(commCL)
    cerebro.broker.setcash(100000.0)
    
    cerebro.signal_accumulate(True)
    
    # Add the data
    cerebro.adddata(data)
    cerebro.resampledata(data, timeframe=bt.TimeFrame.Months)
    
    cerebro.addstrategy(St)
    cerebro.run(runonce=False)
    if args.plot:
        #cerebro.plot(style='bar')
        cerebro.plot(style='line')
    

    However, I get this: plot

    I'm expecting a lot more buy and sell events. What did I do wrong?



  • How would I attach a Strategy to this to LONG when it crosses P and SHORT when it crosses R1?

    This does not work:

    class MySignal(bt.Indicator):
        lines = ('signal',)
    
    def __init__(self):
        self.lines.signal = self.data - bt.indicators.PivotPoint(self.data)


  • @SShepherd

    This can initiate the buy but only for the first datapoint:

        self.pp = bt.ind.PivotPoint(self.data1)
        pp1 = self.pp()  # couple the entire indicators
        self.buysignal = self.data0.close < pp1.r1
        self.sellsignal = self.data0.close > pp1.p
    
        self.signal_add(bt.SIGNAL_LONG, self.buysignal)
        self.signal_add(bt.SIGNAL_LONGEXIT, self.sellsignal)
    

    And here's my runstrat():

    cerebro.signal_accumulate(True)
    
    # Add the data
    cerebro.adddata(data)
    cerebro.resampledata(data, timeframe=bt.TimeFrame.Months)
    
    cerebro.addstrategy(St)

  • administrators

    The indicator depicted in the 1st post was obviously not working as you found out, because it wasn't checking for a "cross" and was only addressing p (1st line of PivotPoint)

    Your second approach is only checking if something is less than other thing and not checking a cross. It is unclear if you want to do that or really check for a crossing pattern.

    But without some printout of the data and values of the indicators or a reference to which data feed you are using, it is for sure not possible to say anything.


  • administrators

    All the related posts under the blog thread have been moved here.


  • administrators

    @SShepherd You are using a subclass of SignalStrategy and the accumulate you use is therefore not applied, because that applies only to the automatic addition of signals in cerebro. Set it in your subclass.

    (One possibility)



  • @backtrader Thanks for response, I uploaded the entire file and dataset

    Here is the full code: http://dpaste.com/0FYC29P

    Here is the dataset: http://dpaste.com/37EGH80 [same as 2005-2006-day-001.txt]

    I ideally want to buy once a month when it crosses the pivot after a certain day, but not sure how to do that



  • @SShepherd said in Executing Buy Sell Strategy for PivotPoint:

    @backtrader Thanks for response, I uploaded the entire file and dataset

    Here is the full code: http://dpaste.com/0FYC29P

    Here is the dataset: http://dpaste.com/37EGH80 [same as 2005-2006-day-001.txt]

    I ideally want to buy once a month when it crosses the pivot after a certain day, but not sure how to do that

    I'm copying the code into this forum for archival purposes:

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    
    import argparse
    
    import backtrader as bt
    import backtrader.feeds as btfeeds
    import backtrader.utils.flushfile
    
    
    class St(bt.SignalStrategy):
        params = (('usepp1', False),
                  ('plot_on_daily', False))
    
        def __init__(self):
            autoplot = self.p.plot_on_daily
            self.pp = pp = bt.ind.PivotPoint(self.data1, _autoplot=autoplot)
    
    
            ## Here is here I am trying to buy when the daily close is less than the
            ## pivot on the Xth day and sell whenever it crosses r1
            pp1 = self.pp()  # couple the entire indicators
            self.buysignal = self.data0.close < pp1.p
            self.sellsignal = self.data0.close > pp1.r1
    
            self.signal_add(bt.SIGNAL_LONG, self.buysignal)
            self.signal_add(bt.SIGNAL_LONGEXIT, self.sellsignal)
    
    
        def next(self):
            txt = ','.join(
                ['%04d' % len(self),
                 '%04d' % len(self.data0),
                 '%04d' % len(self.data1),
                 self.data.datetime.date(0).isoformat(),
                 '%04d' % len(self.pp),
                 '%.2f' % self.pp[0]])
    
            print(txt)
    
    
    def runstrat():
        args = parse_args()
    
        cerebro = bt.Cerebro()
        data = btfeeds.BacktraderCSVData(dataname=args.data)
        cerebro.adddata(data)
        cerebro.resampledata(data, timeframe=bt.TimeFrame.Months)
    
        cerebro.addstrategy(St,
                            plot_on_daily=args.plot_on_daily)
        cerebro.run(runonce=False)
        if args.plot:
            cerebro.plot(style='bar')
    
    
    def parse_args():
        parser = argparse.ArgumentParser(
            formatter_class=argparse.ArgumentDefaultsHelpFormatter,
            description='Sample for pivot point and cross plotting')
    
        parser.add_argument('--data', required=False,
                            default='../../datas/2005-2006-day-001.txt',
                            help='Data to be read in')
    
        parser.add_argument('--plot', required=False, action='store_true',
                            help=('Plot the result'))
    
        parser.add_argument('--plot-on-daily', required=False, action='store_true',
                            help=('Plot the indicator on the daily data'))
    
        return parser.parse_args()
    
    
    if __name__ == '__main__':
        runstrat()
    

  • administrators

    I ideally want to buy once a month when it crosses the pivot after a certain day

    The previous statement raises, at least, the following questions, which may help you into coding your strategy:

    • Which pivot?
    • Crossing to the upside? To the downside?
    • Which certain day?


  • @backtrader said in Executing Buy Sell Strategy for PivotPoint:

    I ideally want to buy once a month when it crosses the pivot after a certain day

    The previous statement raises, at least, the following questions, which may help you into coding your strategy:

    • Which pivot?

    The first pivot, and R1

    • Crossing to the upside? To the downside?

    Crossing to the upside

    • Which certain day?

    The 15th of the month


  • administrators

    In that case your friends are:

    • pivotpoint.lines.p and pivotpoint.lines.r1 (already in your 2nd version of the code)

      because p is the 1st line, any operation directly on the indicator will directly use p, but being specific about lines.p can help when later reading.

    • bt.indicators.CrossUp Indicator Reference

    • self.dataX.datetime.date() which gives you the current date of dataX (if you only have 1 data feed, you can simply use self.data) and can compare against the 15th. Although I'd be wary of such a fixed date: it may happen to be a Saturday, Sunday or Bank Holiday.



  • @backtrader Let me give it a shot!

    Also, side question, how are dataX automagically created? I don't see them defined anywhere -- I assume this is in the indicator?



  • OK, baby steps. I got the CrossUp and CrossDown signals generated but it doesn't do LONGEXIT

    See image: crossup and crossdown no LONGEXIT

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    
    import argparse
    
    import backtrader as bt
    import backtrader.feeds as btfeeds
    import backtrader.utils.flushfile
    
    
    class St(bt.SignalStrategy):
        params = (('usepp1', False),
                  ('plot_on_daily', False))
    
        def __init__(self):
            autoplot = self.p.plot_on_daily
            self.pp = pp = bt.ind.PivotPoint(self.data1, _autoplot=autoplot)
    
            ## Here is here I am trying to buy when the daily close is less than the
            ## pivot on the Xth day and sell whenever it crosses r1
            pp1 = self.pp()  # couple the entire indicators
            self.buysignal = bt.ind.CrossUp(self.data0.close, pp1)
            self.sellsignal = bt.ind.CrossDown(self.data0.close, pp1.r1)
    
            self.signal_add(bt.SIGNAL_LONG, self.buysignal)
            self.signal_add(bt.SIGNAL_LONGEXIT, self.sellsignal)
    
        def next(self):
            txt = ','.join(
                ['%04d' % len(self),
                 '%04d' % len(self.data0),
                 '%04d' % len(self.data1),
                 self.data.datetime.date(0).isoformat(),
                 '%04d' % len(self.pp),
                 '%.2f' % self.pp[0]])
    
            print(txt)
    
    
    def runstrat():
        args = parse_args()
    
        cerebro = bt.Cerebro()
        data = btfeeds.BacktraderCSVData(dataname=args.data)
        cerebro.adddata(data)
        cerebro.resampledata(data, timeframe=bt.TimeFrame.Months)
    
        cerebro.broker.setcash(100000.0)
        #cerebro.signal_accumulate(True)
    
        cerebro.addstrategy(St,
                            plot_on_daily=args.plot_on_daily)
        cerebro.run(runonce=False)
        if args.plot:
            cerebro.plot(style='bar')
    
    
    def parse_args():
        parser = argparse.ArgumentParser(
            formatter_class=argparse.ArgumentDefaultsHelpFormatter,
            description='Sample for pivot point and cross plotting')
    
        parser.add_argument('--data', required=False,
                            default='../../datas/2005-2006-day-001.txt',
                            help='Data to be read in')
    
        parser.add_argument('--plot', required=False, action='store_true',
                            help=('Plot the result'))
    
        parser.add_argument('--plot-on-daily', required=False, action='store_true',
                            help=('Plot the indicator on the daily data'))
    
        return parser.parse_args()
    
    
    if __name__ == '__main__':
        runstrat()
    

  • administrators

    You are passing a long indication to an EXIT signal handler, and this type expects a short indication., i.e.: you pass a signal which produce positive values (long) to something which is expecting negative values (short)

    Described here in Strategy with signals

    Quote:

    Signals indications
    The signals delivers indications when queried with signal[0] and the meaning is:

    • > 0 -> long indication
    • < 0 -> short indication
    • == 0 -> No indication

    LONGEXIT: short indications are taken to exit long positions

    This is how signals can be used for many different things. Multiply your signal by -1.0



  • Great! Now the chart is working. Here's what it looks like with your simple tweak:

            self.signal_add(bt.SIGNAL_LONGEXIT, -1.0*self.sellsignal)
    

    LONGEXIT works

    And I'd like to add that the community behind this software is fantastic!

    My next step will be to figure out the date time. I believe I need to create a new Signal class with an if statement to check the date, correct? Since I won't be using a CrossUp, I'll simply compare the date and data0-pp1.p


  • administrators

    One of the latest additions lets you do direct time comparisons directly to lines to generate signals. Probably nobody has used it yet. An example:

    class MySignal(bt.Indicator):
        lines = ('mysignal',)
    
        def __init__(self):
            self.lines.mysignal = self.data.datetime > datetime.time(10, 30)
    

    This generates an indicator which can be used as a signal to only execute orders when the daily time goes over 10:30.

    But since you are probably looking for day, you'll need to work it out in the next method comparing the self.data.datetime.date() (maybe even getting the weekday) against something of your choosing


Log in to reply
 

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