FLEX KDJ IND
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © shakibsharifian

//@version=5
indicator("FLEX KDJ IND",max_bars_back=400,overlay=true)

bcwsma(s,l,m) => _bcwsma=0.00, _bcwsma:= (m*s+(l-m)*nz(_bcwsma[1]))/l, _bcwsma

myKDJ(param,fast,ma1,ma2) =>
    h = ta.highest(high, fast)
    l = ta.lowest(low,fast)
    RSV = 100*((param-l)/(h-l))
    pK = bcwsma(RSV, ma1, 1)
    pD = bcwsma(pK, ma2, 1)
    pJ = 3 * pK-2 * pD

    [pD,pJ]

LONG = input.int(9, minval=1, title='PERIOD Length: ', group='TRADE SETTINGS', inline='k')
ma1 = input.int(3, minval=1, title='MA1 length: ', group='TRADE SETTINGS', inline='k')
ma2 = input.int(3, minval=1, title='MA2 length: ', group='TRADE SETTINGS', inline='k')

src =input.source(defval=ohlc4,title='SOURCE: ', group='TRADE SETTINGS', inline='l')

string optTopo1="AVG"
string optTopo2="MEDIAN"
string optTopo3="MAX"
string optTopo4="MIN"
string optTopo5="WIDE"
string optTopo6="NARROW"
string optTopo7="FIX"
string optTopo8="GAUSS"
string optTopo9="UPPER BOND"
string optTopo10="LOWER BOND"

string i_TopoType = input.string(defval="NARROW", title="Topology", options = [optTopo1, optTopo2,optTopo3,optTopo4,optTopo5,optTopo6,optTopo7,optTopo8,optTopo9,optTopo10],group='BOND Def.',inline='a')

leftBars=input.int(3,title='LEFT RANGE: ', group='BOND Def.', inline='b')
rightBars=input.int(3,title='RIGHT RANGE: ', group='BOND Def.', inline='b')
fix_H = input.int(80, minval=0, title='MAX BOND: ', group='BOND Def.', inline='c')
fix_L = input.int(20, minval=0, title='MIN BOND: ', group='BOND Def.', inline='c')

MEMORY = input.int(10, minval=1, title='MEMORY: ', group='BOND Def.', inline='d')
_multH = input.float(1.96, title='Mult. Max BOND', group='BOND Def.', inline='e')
_multL = input.float(-1.96, title='Mult. Min BOND', group='BOND Def.', inline='e')

[_pD,_pJ]=myKDJ(src,LONG,ma1,ma2)


pL = ta.pivotlow(_pJ, leftBars, rightBars)
pH = ta.pivothigh(_pJ, leftBars, rightBars)
//
var allBoundsL=array.new_float()
var allBoundsH=array.new_float()
//
if na(pH)==false
    array.push(allBoundsH,pH)
if na(pL)==false
    array.push(allBoundsL,pL)
    
if bar_index>LONG and array.size(allBoundsH)>MEMORY
    clnH=array.shift(allBoundsH)
if bar_index>LONG and array.size(allBoundsL)>MEMORY
    clnL=array.shift(allBoundsL)

float HvL = switch i_TopoType
	optTopo1 =>        array.avg(allBoundsH)
	optTopo2 =>     array.median(allBoundsH)
	optTopo3 =>        array.max(allBoundsH)
	optTopo4 =>        array.min(allBoundsH)
	optTopo5 =>        array.max(allBoundsH)
	optTopo6 =>        array.min(allBoundsH)
	optTopo7 =>        fix_H
	optTopo8 =>        array.avg(allBoundsH)+(_multH*array.stdev(allBoundsH))
	optTopo9 =>        array.max(allBoundsH)
	optTopo10 =>       array.max(allBoundsL)
	
float LvL = switch i_TopoType
	optTopo1 =>        array.avg(allBoundsL)
	optTopo2 =>     array.median(allBoundsL)
	optTopo3 =>        array.max(allBoundsL)
	optTopo4 =>        array.min(allBoundsL)
	optTopo5 =>        array.min(allBoundsL)
	optTopo6 =>        array.max(allBoundsL)
	optTopo7 =>        fix_L
	optTopo8 =>        array.avg(allBoundsL)+(_multL*array.stdev(allBoundsL))
	optTopo9 =>        array.min(allBoundsH)
	optTopo10 =>        array.min(allBoundsL)

h2 = plot(HvL,color=color.new(color.silver,0),title='High BOND',style=plot.style_cross,linewidth=1)
h3 = plot(LvL,color=color.new(color.silver,0),title='Low BOND',style=plot.style_cross,linewidth=1)
plot(_pD, color=color.orange,title='D')
plot(_pJ, color=color.new(color.white,0),title='J')
bgcolor(0.97*_pJ>_pD? color.new(#306318,0) : color.new(#6e1010,0))

_preUnder=ta.barssince(ta.crossunder(0.97*_pJ,_pD))
_preOver=ta.barssince(ta.crossover(0.97*_pJ,_pD))

var barUnderC=array.new_int()

_delUnder=ta.crossunder(0.97*_pJ,_pD)?(_preOver-_preUnder):na
if bar_index>LONG and ta.crossunder(0.97*_pJ,_pD)
    array.push(barUnderC,_delUnder)

if bar_index>LONG and array.size(barUnderC)>MEMORY
    clnUC=array.shift(barUnderC)

_CU=int(array.avg(barUnderC))
CUstd=int(array.stdev(barUnderC))
_multSTD975=1.96
var t = table.new(position.bottom_right, 1, 2, color.olive)
table.cell(t, 0, 0, str.tostring(_CU)+'|+-'+str.tostring(CUstd)+'| '+str.tostring(int(_CU-(_multSTD975*CUstd))<0?na:int(_CU-(_multSTD975*CUstd)))+'~'+str.tostring(int(_CU+(_multSTD975*CUstd))),bgcolor=color.new(color.black,0),text_color=color.new(color.yellow,0))
table.cell(t, 0, 1, 'C: '+str.tostring(_preUnder),bgcolor=color.new(color.black,0),text_color=color.new(color.white,0))

