Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

    Percent Price Oscillator conversion

    Indicators/Strategies/Analyzers
    3
    16
    107
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • A
      amit last edited by

      Hello,

      I am new to the backtrader community and need help with a specific indicator that I am trying to convert. Indicator is used for finding market tops and bottom based on the calculations.

      I am struggling to replicate those calculations in backtrader. Below is the specific function that I am not sure how to convert. As you can see in the function it used L0[1], I am not sure how to get this value. I was thinking of putting this value in an array but how would I reference it. or I should create an array the first time it will be zero and for the next candle it will have an value at index 1 and keep track of the candle number and use always candle-1. just thinking out loud

      lag(g, p) =>
      L0 = (1 - g)p+gnz(L0[1])
      L1 = -gL0+nz(L0[1])+gnz(L1[1])
      L2 = -gL1+nz(L1[1])+gnz(L2[1])
      L3 = -gL2+nz(L2[1])+gnz(L3[1])
      f = (L0 + 2L1 + 2L2 + L3)/6
      f

      Link to the Indicator
      https://www.tradingview.com/script/ngr0qRmw-CM-Laguerre-PPO-PercentileRank-Mkt-Tops-Bottoms/

      A 1 Reply Last reply Reply Quote 0
      • A
        ab_trader @amit last edited by

        @amit this looks like recursive indicator, so I would search docs and arcticles for this approach:
        https://backtrader.com/docu/
        https://backtrader.com/blog/

        Look on how the recursive built-in indicators are developed.
        https://github.com/mementum/backtrader/tree/master/backtrader/indicators

        Also search the forum, IIRC Laguerre indicators were discussed here.

        A 1 Reply Last reply Reply Quote 0
        • A
          amit @ab_trader last edited by

          @ab_trader Thank you for having a look. I will keep digging and share if I find anything

          1 Reply Last reply Reply Quote 0
          • A
            ab_trader last edited by

            https://backtrader.com/blog/posts/2018-01-27-recursive-indicators/recursive-indicator/

            1 Reply Last reply Reply Quote 1
            • A
              ab_trader last edited by

              https://community.backtrader.com/topic/204/laguerre-rsi/

              A 1 Reply Last reply Reply Quote 1
              • A
                amit @ab_trader last edited by

                @ab_trader Hello, thank you for the reference and apologies for late reply. I was trying to make the code changes and make it work.

                As in the suggested post I managed to get the array values correctly populated. thank you for that.

                Now I am stuck at PercentRank indicatot. its returning no value. and when I do next() on pctRankT it gives Divide by zero error. I looked in the lambda function, is it that it has to have all the lookback values before it can be used. I am using ccxtfeed to get the data from Binance.

                pctRankT = bt.indicators.PercentRank(ppoT, period=self.params.LookBackTop)
                pctRankB = bt.indicators.PercentRank(ppoB, period=self.params.LookBackBottom) * -1

                if(pctRankT >= self.params.ExtPercent or (pctRankT >= self.params.WarPercent and pctRankT < self.params.ExtPercent)):
                top = 1

                Thank you very much for your help.

                A 1 Reply Last reply Reply Quote 0
                • A
                  amit @amit last edited by

                  @ab_trader Just wanted to check, is there anywhere I can send you the code. I just need bit of guidance.

                  Regards

                  A 1 Reply Last reply Reply Quote 0
                  • A
                    ab_trader @amit last edited by

                    @amit said in Percent Price Oscillator conversion:

                    Just wanted to check, is there anywhere I can send you the code. I just need bit of guidance.

                    usually if somebody needs help, they post the scripts here.

                    A 1 Reply Last reply Reply Quote 0
                    • A
                      amit @ab_trader last edited by

                      @ab_trader hello, here is the full code.

                      import backtrader as bt
                      import math

                      class CustomStrategy(bt.Strategy):
                      # Moving average parameters
                      params = (('OscPeriod',50),('AdxPeriod',14), ('AtrPeriod',24),
                      ('ExtPercent',70),('WarPercent',90),
                      ('PPOShort',0.4),('PPOLong',0.8),
                      ('LookBackTop',200),('LookBackBottom',200),
                      ('AdxRange',20))

                      def log(self, txt, dt=None):
                      	dt = dt or self.datas[0].datetime.date(0)
                      	print(f'{dt.isoformat()} {txt}') # Comment this line when running optimization
                      
                      def __init__(self):
                      	self.L0S = [0,0]
                      	self.L1S=[0,0]
                      	self.L2S=[0,0]
                      	self.L3S=[0,0]
                      
                      	self.L0L = [0,0]
                      	self.L1L=[0,0]
                      	self.L2L=[0,0]
                      	self.L3L=[0,0]
                      
                      
                      	self.dataclose = self.datas[0].close
                      	
                      	# Order variable will contain ongoing order details/status
                      	self.order = None
                      
                      	# Adx values
                      	self.pDi = bt.indicators.AverageDirectionalMovementIndex(self.datas[0],period=self.params.AdxPeriod).DIplus
                      	self.mDi = bt.indicators.AverageDirectionalMovementIndex(self.datas[0],period=self.params.AdxPeriod).DIminus
                      
                      	# ATR values
                      	self.atr = bt.indicators.AverageTrueRange(self.datas[0],period=self.params.AtrPeriod)
                      
                      	#Calculate TP
                      	self.tpBuy = self.datas[0].close + self.atr *0.95
                      	self.tpSell = self.datas[0].close - self.atr *0.95
                      
                      	#calculate stop loss
                      	#self.fractal = bt.studies.contrib.fractal.Fractal(self.datas, period=2, bardist=0.01).lines
                      	#self.fup = self.fractal.fractal_bullish[0]
                      	#self.fdown = self.fractal.fractal_bearish[0]
                      	
                      	#Previous Day Close
                      	self.close = LastClose(self.datas[1])
                      
                      	#hl2
                      	self.hl2=(self.data.high+self.data.low)/2
                      	self.text =0
                      
                      
                      def notify_order(self, order):
                      	if order.status in [order.Submitted, order.Accepted]:
                      		# An active Buy/Sell order has been submitted/accepted - Nothing to do
                      		return
                      
                      	# Check if an order has been completed
                      	# Attention: broker could reject order if not enough cash
                      	if order.status in [order.Completed]:
                      		if order.isbuy():
                      			self.log(f'BUY EXECUTED, {order.executed.price:.2f}')
                      		elif order.issell():
                      			self.log(f'SELL EXECUTED, {order.executed.price:.2f}')
                      		self.bar_executed = len(self)
                      
                      	elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                      		self.log('Order Canceled/Margin/Rejected')
                      
                      	# Reset orders
                      	self.order = None
                      
                      def lagS(self,g,p):
                      
                      	self.L0S.insert(0,  (1 - g) * p + g * self.L0S[1] )
                      	self.L1S.insert(0,  -g * self.L0S[0] + self.L0S[1] + g * self.L1S[1])
                      	self.L2S.insert(0,  -g * self.L1S[0] + self.L1S[1] + g * self.L2S[1])
                      	self.L3S.insert(0,  -g * self.L2S[0] + self.L2S[1] + g * self.L3S[1])
                      	f  = (self.L0S[0] + 2 * self.L1S[0] + 2 * self.L2S[0] + self.L3S[0]) / 6
                      	return f
                      
                      def lagL(self,g,p):
                      
                      	self.L0L.insert(0,  (1 - g) * p + g * self.L0L[1] )
                      	self.L1L.insert(0,  -g * self.L0L[0] + self.L0L[1] + g * self.L1L[1])
                      	self.L2L.insert(0,  -g * self.L1L[0] + self.L1L[1] + g * self.L2L[1])
                      	self.L3L.insert(0,  -g * self.L2L[0] + self.L2L[1] + g * self.L3L[1])
                      	f  = (self.L0L[0] + 2 * self.L1L[0] + 2 * self.L2L[0] + self.L3L[0]) / 6
                      	return f
                      
                      
                      def next(self):
                      	
                      	lmas=0
                      	lmal=0
                      	top =0
                      	bottom =0
                      
                      
                          #Top & Bottom calculations
                      	lmal = self.lagL(self.params.PPOLong,self.hl2[0])
                      	lmas = self.lagS(self.params.PPOShort,self.hl2[0]) 
                      	
                          #Remove any data beyond 2 iterations
                      	del self.L0S[2:]
                      	del self.L1S[2:]
                      	del self.L2S[2:]
                      	del self.L3S[2:]
                      
                      	del self.L0L[2:]
                      	del self.L1L[2:]
                      	del self.L2L[2:]
                      	del self.L3L[2:]
                      
                      	
                      	pctileB = self.params.ExtPercent * -1
                      	wrnpctileB = self.params.WarPercent * -1
                      
                      	ppoT = (lmas-lmal)/lmal*100
                      	ppoB = (lmal - lmas)/lmal*100
                      
                      	pctRankT = bt.indicators.PercentRank(ppoT, period=self.params.LookBackTop)
                      	pctRankB =  bt.indicators.PrettyGoodOscillator .PercentRank(ppoB, period=self.params.LookBackBottom) * -1
                      
                      	if(pctRankT >= self.params.ExtPercent or (pctRankT >= self.params.WarPercent and pctRankT < self.params.ExtPercent)):
                      		top = 1
                      
                      	if(pctRankB <= pctileB or (pctRankB <= wrnpctileB and pctRankB > pctileB)):
                      		bottom = 1
                      
                      
                      	# Check for open orders
                      	if self.order:	
                      		return
                      
                      	# Check if we are in the market
                      	if not self.position:
                      
                      		# We are not in the market, look for a signal to OPEN trades
                      		#Calculate Top and Bottom if the Color on HMA is changed
                      		if(top == 1 and self.pdi > self.params.AdxRange):
                      			self.log(f'BUY CREATE {self.dataclose[0]:2f}')
                      			# Keep track of the	 created order to avoid a 2nd order
                      			self.order = self.buy()
                      		elif (bottom == 1 and self.mdi > self.params.AdxRange):
                      			self.log(f'SELL CREATE {self.dataclose[0]:2f}')
                      			# Keep track of the created order to avoid a 2nd order
                      			self.order = self.sell()
                      	else:
                      		if ( (self.position.size>0) and (self.dataclose[0] >= self.tpBuy) ):
                      			self.log(f'CLOSE CREATE {self.dataclose[0]:2f}')
                      			self.order = self.close()
                      		elif ( (self.position.size<0) and (self.dataclose[0] <= self.tpSell) ):
                      			self.log(f'CLOSE CREATE {self.dataclose[0]:2f}')
                      			self.order = self.close()
                      A 1 Reply Last reply Reply Quote 0
                      • A
                        amit @amit last edited by

                        @ab_trader hello, I have been trying to set it up from last few days, please help. Do I need to put the calcs as separate Indicator?

                        Regards

                        A 1 Reply Last reply Reply Quote 0
                        • A
                          ab_trader @amit last edited by

                          @amit i think it will be more convenient to have it as an indicator, but nobody prevents you from making calcs in the strategy. By the way, if you check the indicators in the docs, than you will find out that some of the indicators are already included in bt:

                          https://backtrader.com/docu/indautoref/#laguerrefilter
                          https://backtrader.com/docu/indautoref/#laguerrersi

                          A 1 Reply Last reply Reply Quote 0
                          • A
                            amit @ab_trader last edited by

                            @ab_trader thx for the reply. I will try to get the cals going in the strategy itself and then clean up the code as separate indicator. Could you please take a look why the PercentRank is not returning anything in the next call. This is where I am stuck. Very much appreciate your help.

                            Regards

                            A 1 Reply Last reply Reply Quote 0
                            • A
                              amit @amit last edited by

                              @ab_trader Sorry for not paying attention. I see the cals are already implemented in laguerrefilter. I will give it a go now, also it will be great full if you can share an example of Fractal use. I have tried using

                              self.fractal = bt.studies.contrib.fractal.Fractal(self.datas, period=2, bardist=0.01)

                              but get nan in the self.fractal.fractal_bearish[0]. what am I doing wrong? I am using fractals for StopLoss.

                              Regards

                              A 1 Reply Last reply Reply Quote 0
                              • A
                                ab_trader @amit last edited by

                                @amit said in Percent Price Oscillator conversion:

                                but get nan in the self.fractal.fractal_bearish[0]. what am I doing wrong? I am using fractals for StopLoss.

                                you are not trying to figure out what fractal indicator actually delivers and why it should deliver non-nanvalue. honestly i have no idea what does that indicator delivers, but simple fractal definition suggests that most of the bars should have nan and only rare fractal bars should deliver true or certain price values.

                                A 1 Reply Last reply Reply Quote 1
                                • A
                                  amit @ab_trader last edited by

                                  @ab_trader Thank you for the answer. Could you please suggest how should I look for the recent low or high, I want to use that as stop loss.

                                  Regards

                                  run-out 1 Reply Last reply Reply Quote 0
                                  • run-out
                                    run-out @amit last edited by

                                    @amit Have a look here for highest and lowest.

                                    1 Reply Last reply Reply Quote 1
                                    • 1 / 1
                                    • First post
                                      Last post
                                    Copyright © 2016, 2017, 2018 NodeBB Forums | Contributors
                                    $(document).ready(function () { app.coldLoad(); }); }