study(“The Echo Forecast [LUX]”,”ECHO [LuxAlgo]”,overlay=true,max_bars_back=1000,max_lines_count=200)
length = input(50,’Evaluation Window’,minval=0,maxval=200)
fcast = input(50,’Forecast Window’,minval=1,maxval=200)
fmode = input(‘Similarity’,’Forecast Mode’,options=[‘Similarity’,’Dissimilarity’])
cmode = input(‘Cumulative’,’Forecast Construction’,options=[‘Cumulative’,’Mean’,’Linreg’])
src = input(close)
fcast_col = input(#2157f3,’Forecast Style’,inline=’fcast_style’,group=’Style’)
fcast_style = input(‘· · ·’,”,options=[‘──’,’- – -‘,’· · ·’],inline=’fcast_style’,group=’Style’)
show_area = input(true,’Show Area’,inline=’areas’,group=’Style’)
fcast_area = input(color.new(#ff5d00,50),”,inline=’areas’,group=’Style’)
corr_area = input(color.new(#0cb51a,50),”,inline=’areas’,group=’Style’)
eval_area = input(color.new(color.gray,50),”,inline=’areas’,group=’Style’)
//—-
var lines = array.new_line(0)
if barstate.isfirst
for i = 0 to fcast-1
array.push(lines,line.new(na,na,na,na))
//—-
n = bar_index
d = change(src)
top = highest(src,length+fcast*2)
btm = lowest(src,length+fcast*2)
if barstate.islast
float val = na
k = 0
A = array.new_float(0)
X = array.new_int(0)
for i = 0 to fcast*2+length
array.push(A,src[i])
if cmode == ‘Linreg’
array.push(X,n[i])
a = array.slice(A,0,fcast-1)
for i = 0 to length-1
b = array.slice(A,fcast+i,fcast*2+i-1)
r = array.covariance(a,b)/(array.stdev(a)*array.stdev(b))
if fmode == ‘Similarity’
val := r >= nz(val,r) ? r : val
else
val := r <= nz(val,r) ? r : val
k := val == r ? i : k
prev = src
current = src
for i = 0 to fcast-1
e = d[fcast+k+(fcast-i-1)]
if cmode == ‘Mean’
current := array.avg(a) + e
else if cmode == ‘Linreg’
a = array.slice(A,0,fcast)
x = array.slice(X,0,fcast)
alpha = array.covariance(a,x)/array.variance(x)
beta = array.avg(a) – alpha*array.avg(x)
current := alpha*(n+i+1) + beta + e
else
current += e
l = array.get(lines,i)
line.set_xy1(l,n+i,prev)
line.set_xy2(l,n+i+1,current)
line.set_color(l,fcast_col)
if fcast_style == ‘- – -‘
line.set_style(l,line.style_dashed)
else if fcast_style == ‘· · ·’
line.set_style(l,line.style_dotted)
prev := current
if show_area
box.delete(box.new(n-length-fcast*2+1,top,n-fcast+1,btm,
border_color=na,
bgcolor=eval_area)[1])
box.delete(box.new(n-fcast+1,top,n,btm,
border_color=na,
bgcolor=fcast_area)[1])
box.delete(box.new(n-k-fcast*2+1,btm,n-k-fcast,top,
border_color=na,
bgcolor=corr_area)[1])