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:
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)
-
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)
-
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 ofPivotPoint
)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.
-
All the related posts under the blog thread have been moved here.
-
@SShepherd You are using a subclass of
SignalStrategy
and theaccumulate
you use is therefore not applied, because that applies only to the automatic addition of signals incerebro
. 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()
-
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
-
In that case your friends are:
-
pivotpoint.lines.p
andpivotpoint.lines.r1
(already in your 2nd version of the code)because
p
is the 1st line, any operation directly on the indicator will directly usep
, but being specific aboutlines.p
can help when later reading. -
bt.indicators.CrossUp
Indicator Reference -
self.dataX.datetime.date()
which gives you the current date ofdataX
(if you only have 1 data feed, you can simply useself.data
) and can compare against the15th
. 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:
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()
-
You are passing a
long
indication to anEXIT
signal handler, and this type expects ashort
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 positionsThis 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)
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
-
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 theself.data.datetime.date()
(maybe even getting the weekday) against something of your choosing