CFB Adaptive Fisher Transform [Loxx]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © loxx

//@version=5
indicator("CFB Adaptive Fisher Transform [Loxx]", 
     overlay = false, 
     shorttitle="CFBAFT [Loxx]",
     timeframe="", 
     timeframe_gaps=true, 
     max_bars_back = 3000)

import loxx/loxxjuriktools/1

greencolor = #2DD204
redcolor = #D2042D 

SM02 = 'Zero-Line Cross'
SM03 = 'Signal Crossover'

signalMode = input.string(SM02, 'Signal Type', options=[SM02, SM03], group = "Basic Settings")

fisherOb1 = input.float(2, minval=1, step = 0.1, title='Overbought Level', group = "Basic Settings")
fisherOs1 = input.float(-2, maxval=-1, step = 0.1,  title='Oversold Level', group = "Basic Settings")

nlen = input.int(50, "CFB Normal Period", minval = 1, group = "CFB Ingest Settings")
cfb_len = input.int(10, "CFB Depth", maxval = 10, group = "CFB Ingest Settings")
smth = input.int(8, "CFB Smooth Period", minval = 1, group = "CFB Ingest Settings")
slim = input.int(10, "CFB Short Limit", minval = 1, group = "CFB Ingest Settings")
llim = input.int(20, "CFB Long Limit", minval = 1, group = "CFB Ingest Settings")
jcfbsmlen = input.int(10, "CFB Jurik Smooth Period", minval = 1, group = "CFB Ingest Settings")
jcfbsmph = input.float(0, "CFB Jurik Smooth Phase", group = "CFB Ingest Settings")

colorbars = input.bool(false, "Color bars?", group = "UI Options")
showsignals = input.bool(false, "Show signals?", group = "UI Options")

cfb_draft = loxxjuriktools.jcfb(hl2, cfb_len, smth)
cfb_pre = loxxjuriktools.jurik_filt(loxxjuriktools.jurik_filt(cfb_draft, jcfbsmlen, jcfbsmph), jcfbsmlen, jcfbsmph) 

max = ta.highest(cfb_pre, nlen)
min = ta.lowest(cfb_pre, nlen)
denom = max - min
ratio = (denom > 0) ? (cfb_pre - min) / denom : 0.5
len = math.ceil(slim + ratio * (llim - slim))


high_ = ta.highest(hl2, len)
low_ = ta.lowest(hl2, len)

round_(val) => val > .99 ? .999 : val < -.99 ? -.999 : val
value = 0.0
value := round_(.66 * ((hl2 - low_) / (high_ - low_) - .5) + .67 * nz(value[1]))
fish1 = 0.0
fish1 := .5 * math.log((1 + value) / (1 - value)) + .5 * nz(fish1[1])
fish2 = fish1[1]

hth = fisherOb1
lth = fisherOs1

middle = 0.

plot(hth+1.5, color = color.new(color.white, 100), title = "Upper UI Constraint")
plot(lth-1.5, color = color.new(color.white, 100), title = "Lower UI Constraint")

tl = plot(hth+1, color=color.rgb(0, 255, 255, 100), style=plot.style_line, title = "OB Level 2")
tl1 = plot(hth, color=color.rgb(0, 255, 255, 100), style=plot.style_line, title = "OB Level 1")

plot(middle, color=color.new(color.gray, 30), linewidth=1, style=plot.style_circles, title = "Zero")

bl1 = plot(lth, color=color.rgb(255, 255, 255, 100), style=plot.style_line, title = "OS Level 1")
bl = plot(lth-1, color=color.rgb(255, 255, 255, 100), style=plot.style_line, title = "OS Level 2")

fill(tl, tl1, color=color.new(color.gray, 85), title = "Top Boundary Fill Color")
fill(bl, bl1, color=color.new(color.gray, 85), title = "Bottom Boundary Fill Color")

color_out = 
     signalMode == SM03 ? (fish1 > fish2 ? greencolor : redcolor) : 
     (fish1 >= 0 and fish1 > fish2 ? greencolor : 
     fish1 < 0 and fish1 < fish2 ? redcolor : color.gray)

plot(fish1, color = color_out, title='Fisher', linewidth = 3)
plot(fish2, color = color.white, title = "Signale")

barcolor(colorbars ? color_out : na)

goLong = signalMode == SM03  ? ta.crossover(fish1, fish2) : ta.crossover(fish1, 0)
goShort = signalMode == SM03  ? ta.crossunder(fish1, fish2) : ta.crossunder(fish1, 0)

plotshape(goLong and showsignals, title = "Long", color = greencolor, textcolor = greencolor, text = "L", style = shape.triangleup, location = location.bottom, size = size.auto)
plotshape(goShort and showsignals, title = "Short", color = redcolor, textcolor = redcolor, text = "S", style = shape.triangledown, location = location.top, size = size.auto)

alertcondition(goLong, title="Long", message="CFB Adaptive Fisher Transform [Loxx]: Long\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(goShort, title="Short", message="CFB Adaptive Fisher Transform [Loxx]: Short\nSymbol: {{ticker}}\nPrice: {{close}}")
