Pivot Parallel Channel by [livetrend]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © livetrend

//@version=5

var MAX_BARS_BACK = 5000

indicator(title='Pivot Parallel Channel by [livetrend]', shorttitle='PPC', overlay=true, max_bars_back=MAX_BARS_BACK, max_labels_count=500,max_lines_count=500,format=format.price,precision=2)

hiddenChannel = input(false,group='Channel',inline='line')
lineWidth = input.int(1,minval=1,title="Width",group='Channel',inline='option')
threshold = input.float(5,title="Threshold(%)",minval=0,tooltip="Channel breakout threshold by percent",group='Channel',inline='option')/100
lineStyle = extend.right


res_line_col = hiddenChannel?na:input.color(color.new(#ff1100, 0), 'Down Trend Line',group='Style', inline='line')
sup_line_col = hiddenChannel?na:input.color(color.new(#0cb51a, 0), 'Up Trend Line',group='Style', inline='line')

res_col = hiddenChannel?na:input.color(color.new(#ff1100, 90), 'Down Trend',group='Style', inline='area')
sup_col = hiddenChannel?na:input.color(color.new(#0cb51a, 90), 'Up Trend',group='Style', inline='area')


baseMtf = input.int(2,title='Multiplier I',minval=1,tooltip="Pivot Length Multiplier")
baseMtf_htf = input.int(4,title='Multiplier II',minval=2,tooltip="Pivot Length Multiplier for Higher Time Frame")

if baseMtf_htf<baseMtf
    runtime.error("Multiplier II must be greater or equal than Multiplier I")

source = input.source(close, title='Source')
hl = input.string("High-Low", options=["High-Low","Source"])



gr="Left - Right Length"

leftLenH = input.int(title="Pivot High", defval=1, minval=1, inline="Pivot High",group=gr)
rightLenH = input.int(title="/", defval=1, minval=1, inline="Pivot High",group=gr)

leftLenL = input.int(title="Pivot Low", defval=1, minval=1, inline="Pivot Low", group=gr)
rightLenL = input.int(title="/", defval=1, minval=1, inline="Pivot Low",group=gr)



_high = hl=="High-Low"?high:source
_low = hl=="High-Low"?low:source


ph = ta.pivothigh(_high,leftLenH*baseMtf, rightLenH*baseMtf)
pl = ta.pivotlow(_low,leftLenL*baseMtf, rightLenL*baseMtf)

ph_htf = ta.pivothigh(_high,leftLenH*baseMtf_htf, rightLenH*baseMtf_htf)
pl_htf = ta.pivotlow(_low,leftLenL*baseMtf_htf, rightLenL*baseMtf_htf)


var float sup = na
var float res = na
var float prev_sup = na
var float prev_res = na
var int prev_res_index = 0
var int prev_sup_index = 0



var float sup_htf = na
var float res_htf = na
var float prev_sup_htf = na
var float prev_res_htf = na
var int prev_res_index_htf = 0
var int prev_sup_index_htf = 0





var line resline = na
var line supline = na
var line par_supline = na
var line par_resline = na



var line resline_htf = na
var line supline_htf = na
var line par_supline_htf = na
var line par_resline_htf = na


get_slope(xA, yA, xB, yB) =>
    (yB - yA) / math.max((xB - xA),1)


get_line_slope(l) =>
    x1 = line.get_x1(l)
    x2 = line.get_x2(l)
    y1 = line.get_y1(l)
    y2 = line.get_y2(l)
    get_slope(x1,y1,x2,y2)
    

var trend1 = 0
var trend2 = 0

var trend3 = 0
var trend4 = 0


var float pru = na
var float prl = na
var float psu = na
var float psl = na


var float pru_htf = na
var float prl_htf = na
var float psu_htf = na
var float psl_htf = na


var trend1_index  = 0
var trend2_index  = 0
var trend3_index  = 0
var trend4_index  = 0



if not na(ph_htf)

    prev_res_htf:=res_htf
    res_htf:=ph_htf
    
    
    if nz(res_htf[1])!=res_htf 
        prev_res_index_htf := bar_index[rightLenH*baseMtf_htf]
        
        if not (source<pru_htf and source>prl_htf)
        
            a = math.min(prev_res_index_htf[1],prev_sup_index_htf)
        
        
            resline_htf := line.new(prev_res_index_htf[1], res_htf[1]*(1+threshold), bar_index[rightLenH*baseMtf_htf], res_htf*(1+threshold), xloc=xloc.bar_index, color=res_line_col, extend=lineStyle, style=line.style_solid, width=2*lineWidth)    
    
            line.delete(resline_htf[1])
            
            m = get_line_slope(resline_htf)

            trend1:=m>0?1:-1
            
            par_resline_htf := line.new(prev_sup_index_htf, sup_htf*(1-threshold), prev_sup_index_htf+1, get_line_slope(resline_htf) + sup_htf*(1-threshold), xloc=xloc.bar_index, color=res_line_col, extend=lineStyle, style=line.style_solid, width=2*lineWidth)    
    
            line.delete(par_resline_htf[1])
            
            trend1_index:=prev_res_index_htf[1]
            
            
            line.set_x1(resline_htf,a)
            line.set_y1(resline_htf,res_htf[1]*(1+threshold)-m*(prev_res_index_htf[1]-a))
            
            line.set_x1(par_resline_htf,a)
            line.set_y1(par_resline_htf,sup_htf*(1-threshold)-m*(prev_sup_index_htf-a))
            
            linefill.new(resline_htf,par_resline_htf,m>0?sup_col:res_col)
            
            line.set_color(resline_htf, m>0?sup_line_col:res_line_col)
            line.set_color(par_resline_htf, m>0?sup_line_col:res_line_col)
            
            
pru_htf := line.get_price(resline_htf,bar_index)
prl_htf := line.get_price(par_resline_htf,bar_index)

if not (source<pru_htf and source>prl_htf)
    trend1:=0
    line.delete(resline_htf)
    line.delete(par_resline_htf)
       
            

if not na(pl_htf)

    prev_sup_htf:=sup_htf
    sup_htf:=pl_htf
    
    if nz(sup_htf[1])!=sup_htf 
        prev_sup_index_htf := bar_index[rightLenL*baseMtf_htf]

        if not (source<psu_htf and source>psl_htf)
        
            a = math.min(prev_sup_index_htf[1],prev_res_index_htf)
        

            supline_htf := line.new(prev_sup_index_htf[1], sup_htf[1]*(1-threshold), bar_index[rightLenL*baseMtf_htf], sup_htf*(1-threshold), xloc=xloc.bar_index, color=sup_line_col, extend=lineStyle, style=line.style_solid, width=2*lineWidth)
     
            line.delete(supline_htf[1])
    
            m = get_line_slope(supline_htf)
            
            trend2:=m>0?1:-1
            
            par_supline_htf := line.new(prev_res_index_htf, res_htf*(1+threshold), prev_res_index_htf+1, get_line_slope(supline_htf) + res_htf*(1+threshold), xloc=xloc.bar_index, color=sup_line_col, extend=lineStyle, style=line.style_solid, width=2*lineWidth)    
    
            line.delete(par_supline_htf[1]) 
            
            trend2_index:=prev_sup_index_htf[1]

            
            line.set_x1(supline_htf,a)
            line.set_y1(supline_htf,sup_htf[1]*(1-threshold)-m*(prev_sup_index_htf[1]-a))
            
            line.set_x1(par_supline_htf,a)
            line.set_y1(par_supline_htf,res_htf*(1+threshold)-m*(prev_res_index_htf-a))  
            
            linefill.new(supline_htf,par_supline_htf,m>0?sup_col:res_col)
            
            line.set_color(supline_htf, m>0?sup_line_col:res_line_col)
            line.set_color(par_supline_htf, m>0?sup_line_col:res_line_col)
            

psu_htf := line.get_price(par_supline_htf,bar_index)
psl_htf := line.get_price(supline_htf,bar_index)

if not (source<psu_htf and source>psl_htf)
    trend2:=0
    line.delete(supline_htf)
    line.delete(par_supline_htf)     




if not na(ph)

    prev_res:=res
    res:=ph
    
    if nz(res[1])!=res 
        prev_res_index := bar_index[rightLenH*baseMtf]
        
        if not (source<pru and source>prl)
        
            a = math.min(prev_res_index[1],prev_sup_index)
        
            resline := line.new(prev_res_index[1], res[1]*(1+threshold), bar_index[rightLenH*baseMtf], res*(1+threshold), xloc=xloc.bar_index, color=res_line_col, extend=lineStyle, style=line.style_solid, width=lineWidth)    
    
            line.delete(resline[1])
            
            m = get_line_slope(resline)
            
            par_resline := line.new(prev_sup_index, sup*(1-threshold), prev_sup_index+1, get_line_slope(resline) + sup*(1-threshold), xloc=xloc.bar_index, color=res_line_col, extend=lineStyle, style=line.style_solid, width=lineWidth)    
    
            line.delete(par_resline[1])
            
            trend3_index:=prev_res_index[1]

            
            trend3:=m>0?1:-1
            
            line.set_x1(resline,a)
            line.set_y1(resline,res[1]*(1+threshold)-m*(prev_res_index[1]-a))
            
            line.set_x1(par_resline,a)
            line.set_y1(par_resline,sup*(1-threshold)-m*(prev_sup_index-a))
            
            linefill.new(resline,par_resline,m>0?sup_col:res_col)
            
            line.set_color(resline, m>0?sup_line_col:res_line_col)
            line.set_color(par_resline, m>0?sup_line_col:res_line_col)

pru := line.get_price(resline,bar_index)
prl := line.get_price(par_resline,bar_index)

if not (source<pru and source>prl)
    trend3:=0
    line.delete(resline)
    line.delete(par_resline)
   

if not na(pl)
    
    prev_sup:=sup
    sup:=pl
    
    if nz(sup[1])!=sup 
        prev_sup_index := bar_index[rightLenL*baseMtf]

        if not (source<psu and source>psl)
        
            a = math.min(prev_sup_index[1],prev_res_index)
        

            supline := line.new(prev_sup_index[1], sup[1]*(1-threshold), bar_index[rightLenL*baseMtf], sup*(1-threshold), xloc=xloc.bar_index, color=sup_line_col, extend=lineStyle, style=line.style_solid, width=lineWidth)
     
            line.delete(supline[1])
            
            m = get_line_slope(supline)
            
            par_supline := line.new(prev_res_index, res*(1+threshold), prev_res_index+1, get_line_slope(supline) + res*(1+threshold), xloc=xloc.bar_index, color=sup_line_col, extend=lineStyle, style=line.style_solid, width=lineWidth)    
    
            line.delete(par_supline[1])
            
            trend4_index:=prev_sup_index[1]

            
            trend4:=m>0?1:-1
            
            line.set_x1(supline,a)
            line.set_y1(supline,sup[1]*(1-threshold)-m*(prev_sup_index[1]-a))
            
            line.set_x1(par_supline,a)
            line.set_y1(par_supline,res*(1+threshold)-m*(prev_res_index-a)) 
            
            
            linefill.new(supline,par_supline,m>0?sup_col:res_col)
            
            line.set_color(supline, m>0?sup_line_col:res_line_col)
            line.set_color(par_supline, m>0?sup_line_col:res_line_col)


psu := line.get_price(par_supline,bar_index)
psl := line.get_price(supline,bar_index)

if not (source<psu and source>psl)
    trend4:=0
    line.delete(supline)
    line.delete(par_supline)


var trend = 0


l1=trend1!=0?bar_index-trend1_index:0
l2=trend2!=0?bar_index-trend2_index:0
l3=trend3!=0?bar_index-trend3_index:0
l4=trend4!=0?bar_index-trend4_index:0


lx = math.max(l1,l2,l3,l4)


if lx!=0

    if l1 == lx
        trend:=trend1
        
    if l2 == lx
        trend:=trend2
        
    if l3 == lx
        trend:=trend3
        
    if l4 == lx
        trend:=trend4


up = trend!=nz(trend[1]) and trend>0
down = trend!=nz(trend[1]) and trend<0

plotshape(up,style=shape.triangleup,location=location.belowbar,color=color.green,size=size.small)
plotshape(down,style=shape.triangledown,location=location.abovebar,color=color.red,size=size.small)


alertcondition(up,title="Buy Alert!",message="It can be long condition :)")
alertcondition(down,title="Sell Alert!",message="It can be short condition :)")

//bgcolor(trend>0?color.green:trend<0?color.red:na, transp=90)