Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- fi(ki)=>'ra' // ©fikira - This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
- //@version=5
- indicator('Multiple Divergences (UDTs - objects)' , max_lines_count=500, max_labels_count=500, overlay=true) // max_bars_back=2000,
- // ––––––––––––––––––––––––––––––––––––––––––––––––––––––[ input's ]––––––––––––––––––––––––––––––––––––––––––––––––––––––
- int left = input.int ( 3, 'left' , minval= 1, maxval= 100)
- int right = input.int ( 1, 'right' , minval= 1, maxval= 100)
- int mx = input.int ( 750, 'max values', minval=100, maxval=2000)
- bool trsi = input.bool ( true, '' , inline='1', group='Oscillators (+ length)')
- int l_rsi = input.int ( 14, 'RSI' , minval= 1, maxval= 100, inline='1', group='Oscillators (+ length)')
- color bl1 = input.color (color.lime , '' , inline='1', group='Oscillators (+ length)')
- color br1 = input.color (#FF0000 , '' , inline='1', group='Oscillators (+ length)')
- bool tCci = input.bool ( true, '' , inline='2', group='Oscillators (+ length)')
- int l_cci = input.int ( 14, 'CCI' , minval= 1, maxval= 100, inline='2', group='Oscillators (+ length)')
- color bl2 = input.color (color.olive , '' , inline='2', group='Oscillators (+ length)')
- color br2 = input.color (color.red , '' , inline='2', group='Oscillators (+ length)')
- bool tMfi = input.bool ( true, '' , inline='3', group='Oscillators (+ length)')
- int l_mfi = input.int ( 14, 'MFI' , minval= 1, maxval= 100, inline='3', group='Oscillators (+ length)')
- color bl3 = input.color (color.yellow, '' , inline='3', group='Oscillators (+ length)')
- color br3 = input.color (color.orange, '' , inline='3', group='Oscillators (+ length)')
- // ––––––––––––––––––––––––––––––––––––––––––––––––––––––[ UDT's ]––––––––––––––––––––––––––––––––––––––––––––––––––––––
- // @type An object of highs and lows
- // @field b bar_index - right
- // @field h high[right]
- // @field l low [right]
- // @field isPh is Pivot High
- // @field isPl is Pivot Low
- type HLs
- int b = na
- float h = na
- float l = na
- bool isPh = false
- bool isPl = false
- // @type An object of oscillator values
- // @field b bar_index - right
- // @field o oscillator[right]
- // @field isPh is Pivot High
- // @field isPl is Pivot Low
- type Osc
- int b = na
- float o = na
- bool isPh = false
- bool isPl = false
- // ––––––––––––––––––––––––––––––––––––––––––––––––––––––[ array's ]––––––––––––––––––––––––––––––––––––––––––––––––––––––
- var HLs[] aHLs = array.new <HLs>()
- var Osc[] aRSI = array.new <Osc>()
- var Osc[] aCCI = array.new <Osc>()
- var Osc[] aMFI = array.new <Osc>()
- var line[] aLn = array.new <line>()
- // ––––––––––––––––––––––––––––––––––––––––––––––––––––––[ data ]––––––––––––––––––––––––––––––––––––––––––––––––––––––
- int sz = array.size ( aHLs )
- int ls = array.size ( aLn )
- float hi = nz(high [right])
- float lo = nz(low [right])
- int bx = nz(bar_index - right )
- // ––––––––––––––––––––––––––––––––––––––––––––––––––––––[ functions ]––––––––––––––––––––––––––––––––––––––––––––––––––––––
- // @function Fills Oscillator array
- aOsc(series bool osc_ph, series bool osc_pl, series float osc, Osc[] aOsc) =>
- max_bars_back(osc, 2000)
- os = nz(osc [right])
- switch
- osc_ph => get = Osc.new(bx, os, true , false), array.unshift(aOsc, get)
- osc_pl => get = Osc.new(bx, os, false, true ), array.unshift(aOsc, get)
- => get = Osc.new(bx, os, false, false), array.unshift(aOsc, get)
- // @function Checks for Regular Divergence (high/low)
- Reg_Div_Piv(series HLs getZ, series string BlBr) => // - - - - - // getZ = current Pivot point
- max_bars_back(time, 2000) // prevents "Pine cannot determine the referencing length of a series. Try using max_bars_back ..." error
- bull = BlBr == 'bl' // - - - - - - - - - - - - - // bullish/bearish divergence
- check = false // checks for a non-pierced DIV line
- int x1 = na, float y1 = na, int x2 = na, float y2 = na //
- if sz > right // - - - - - - - - - - - - - // if enough data in array
- //-{ //
- for i = 0 to sz - right //
- getA = array.get(aHLs, i) // - - - - - // getA = point in history
- if (bull ? getA.isPl : getA.isPh) // if getA is a Pivot point
- _x1 = getA.b, _y1 = (bull ? getA.l : getA.h) // collect data
- _x2 = getZ.b, _y2 = (bull ? getZ.l : getZ.h) //
- if (bull ? _y2 < _y1 : _y2 > _y1) // - - - - - // if condition for DIV is true
- testline = line.new(_x1, _y1, _x2, _y2) // create testline
- bix = bar_index - _x1 //
- //-{ //
- for j = right to bix // - - - - - // check if high/low pierces testline in between
- getY = array.get(aHLs, j) //
- if (bull ? getY.l < line.get_price(testline, getY.b) : //
- getY.h > line.get_price(testline, getY.b) ) //
- break // - - - - - - - - - - // if pierced -> break, check remains false
- if j == bix // if at end of loop
- check := true // - - - - - // else -> collect data for output
- x1 := getA.b, y1 := (bull ? getA.l : getA.h) //
- x2 := getZ.b, y2 := (bull ? getZ.l : getZ.h) //
- // }- //
- line.delete(testline) // - - - - - // deleted testline
- // }- //
- [check, x1, y1, x2, y2]// - - - - - - - - - - - - - // output
- // @function Checks for Regular Divergence (oscillator)
- Reg_Div_Osc(Osc[] aOsc, series int pv_x1, series int pv_x2, series string BlBr) => // aOsc = array of oscillator values
- max_bars_back(time, 2000) // prevents "Pine cannot determine the referencing length of a series. Try using max_bars_back ..." error
- bull = BlBr == 'bl' // - - - - - - - - - - - - - // bullish/bearish divergence
- check = false // checks for a non-pierced DIV line
- int x1 = na, float y1 = na, int x2 = na, float y2 = na //
- if sz > right and array.size(aOsc) > 0 // - - - - - // if enough data in array
- getZ = array.get (aOsc , 0) // get current oscillator data
- //-{ //
- for i = 0 to sz - right //
- getA = array.get(aOsc , i) // - - - - - // getA = point in history
- _x1 = getA.b, _y1 = getA.o, _x2 = getZ.b, _y2 = getZ.o //
- isPiv = (bull ? getA.isPl : getA.isPh) // if getA is a Pivot point
- if isPiv and math.abs(pv_x1 - _x1) < 3 and math.abs(pv_x2 - _x2) < 3 // if Piv high/low is not too far from Piv Oscillator
- if (bull ? _y2 > _y1 : _y2 < _y1) // - - - - - // if condition for DIV is true
- testline = line.new(_x1, _y1, _x2, _y2) // create testline
- bix = bar_index - _x1 //
- //-{ //
- for j = right to bix // - - - - - // check if oscillator pierces testline in between
- getY = array.get(aOsc, j) //
- if (bull ? getY.o < line.get_price(testline, getY.b) : //
- getY.o > line.get_price(testline, getY.b) ) //
- break // - - - - - - - - - - // if pierced -> break, check remains false
- if j == bix // if at end of loop
- check := true // - - - - - // else -> collect data for output
- x1 := getA.b, y1 := getA.o //
- x2 := getZ.b, y2 := getZ.o //
- // }- //
- line.delete(testline) // - - - - - // deleted testline
- // }- //
- [check, x1, y1, x2, y2]// - - - - - - - - - - - - - // output
- // @function Draws a line when divergence is spotted
- draw(series string BlBr, series bool toggle, Osc[] aOsc, series int x1, series float y1, series int x2, series float y2, series color col) =>
- int check = 0
- bool bull = BlBr == 'bl'
- if toggle
- [ch_osc, x1_o, y1_o, x2_o, y2_o] = Reg_Div_Osc(aOsc, x1, x2, bull ? 'bl' : 'br')
- if ch_osc
- check := 1
- array.unshift(aLn, line.new(x1, y1, x2, y2, color=col, width=1))
- check
- // @function Cleans array when full
- pop(arr) =>
- if array.size(arr) > mx
- array.pop(arr)
- // @function Lines are dotted when unconfirmed DIV, solid if confirmed
- setLine(series int n) =>
- line ln = ls > n ? array.get(aLn, n) : na
- line.set_style(ln, bar_index - line.get_x2(ln) <= right ? line.style_dotted : line.style_solid )
- // ––––––––––––––––––––––––––––––––––––––––––––––––––––––[ Action ]––––––––––––––––––––––––––––––––––––––––––––––––––––––
- // calculate values -{
- float rsi = ta.rsi (close , l_rsi)
- float cci = ta.cci (close , l_cci)
- float mfi = ta.mfi (close , l_mfi)
- ph = ta.pivothigh( left, right)
- pl = ta.pivotlow ( left, right)
- rsi_ph = ta.pivothigh(rsi , left, right)
- rsi_pl = ta.pivotlow (rsi , left, right)
- cci_ph = ta.pivothigh(cci , left, right)
- cci_pl = ta.pivotlow (cci , left, right)
- mfi_ph = ta.pivothigh(mfi , left, right)
- mfi_pl = ta.pivotlow (mfi , left, right)
- // }
- // add object (Osc.new) to array -{
- if trsi
- aOsc(rsi_ph, rsi_pl, rsi, aRSI)
- if tCci
- aOsc(cci_ph, cci_pl, cci, aCCI)
- if tMfi
- aOsc(mfi_ph, mfi_pl, mfi, aMFI)
- // }
- // add object (HLs.new) to array -{
- switch
- //
- ph =>
- getZ = HLs.new(bx, hi, lo, true , false), array.unshift(aHLs, getZ)
- [check, x1, y1, x2, y2] = Reg_Div_Piv(getZ, 'br')
- if check
- check1 = draw('br', trsi, aRSI, x1, y1, x2, y2, br1)
- check2 = draw('br', tCci, aCCI, x1, y1, x2, y2, br2)
- check3 = draw('br', tMfi, aMFI, x1, y1, x2, y2, br3)
- total = check1 + check2 + check3
- if total > 0
- label.new(
- bx, hi, style=label.style_label_down, text=str.tostring(total),
- color=color.new(#FF0000, 90), textcolor=#FF0000
- )
- //
- pl =>
- getZ = HLs.new(bx, hi, lo, false, true ), array.unshift(aHLs, getZ)
- [check, x1, y1, x2, y2] = Reg_Div_Piv(getZ, 'bl')
- if check
- check1 = draw('bl', trsi, aRSI, x1, y1, x2, y2, bl1)
- check2 = draw('bl', tCci, aCCI, x1, y1, x2, y2, bl2)
- check3 = draw('bl', tMfi, aMFI, x1, y1, x2, y2, bl3)
- total = check1 + check2 + check3
- if total > 0
- label.new(
- bx, lo, style=label.style_label_up , text=str.tostring(total),
- color=color.new(#00FF00, 90), textcolor=#00FF00
- )
- //
- => array.unshift(aHLs, HLs.new(bx, hi, lo, false, false))
- // }
- // ––––––––––––––––––––––––––––––––––––––––––––––––––––––[ ––––––––– ]––––––––––––––––––––––––––––––––––––––––––––––––––––––
- // clean array's
- pop(aHLs), pop(aRSI), pop(aCCI), pop(aMFI)
- // clean line array
- if ls > 500
- line.delete(array.pop(aLn))
- // set line style
- setLine(0), setLine(1), setLine(2)
- // ––––––––––––––––––––––––––––––––––––––––––––––––––––––[ ––––––––– ]––––––––––––––––––––––––––––––––––––––––––––––––––––––
Advertisement
Add Comment
Please, Sign In to add comment