R-sqrd Adapt. Fisher Transform w/ D. Zones & Divs. [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(title="R-sqrd Adapt. Fisher Transform w/ D. Zones & Divs. [Loxx]",
     shorttitle='RSAFTDZ [Loxx]', 
     overlay = false, 
     timeframe="", 
     timeframe_gaps = true)

import loxx/loxxexpandedsourcetypes/4
import loxx/loxxdynamiczone/3

greencolor = #2DD204  
redcolor = #D2042D 
darkGreenColor =  #1B7E02 
darkRedColor = #93021F

SM02 = 'Slope'
SM03 = 'Middle Crossover'
SM04 = 'Levels Crossover'

_iRsq(src, per)=>
    SumX  = 0., SumXX = 0., SumXY = 0., SumYY = 0., SumY  = 0.
    for k = 0 to per-1 by 1
        SumX  += SumX+(k+1)
        SumXX += SumXX+((k+1)*(k+1))
        SumXY += SumXY+((k+1)*src)
        SumYY += SumYY+(src*src)
        SumY  += SumY+src
    Q1 = SumXY - SumX*SumY/per
    Q2 = SumXX - SumX*SumX/per
    Q3 = SumYY - SumY*SumY/per
    iRsq= (Q1*Q1)/(Q2*Q3)
    iRsq
    
round_(val) => 
    val > .99 ? .999 : val < -.99 ? -.999 : val
    val
    
_iFish(src, per)=>
    high_ = ta.highest(src, per)
    low_ = ta.lowest(src, per)
    value = 0.0
    value := round_(.66 * ((src - low_) / (high_ - low_) - .5) + .67 * nz(value[1]))
    fish1 = 0.0
    fish1 := .5 * math.log((1 + value) / (1 - value)) + .5 * nz(fish1[1])
    fish1
    
smthtype = input.string("Kaufman", "Heiken-Ashi Better Smoothing", options = ["AMA", "T3", "Kaufman"], group=  "Source Settings")
srcoption = input.string("Median", "Source", group= "Source Settings", 
     options = 
     ["Close", "Open", "High", "Low", "Median", "Typical", "Weighted", "Average", "Average Median Body", "Trend Biased", "Trend Biased (Extreme)", 
     "HA Close", "HA Open", "HA High", "HA Low", "HA Median", "HA Typical", "HA Weighted", "HA Average", "HA Average Median Body", "HA Trend Biased", "HA Trend Biased (Extreme)",
     "HAB Close", "HAB Open", "HAB High", "HAB Low", "HAB Median", "HAB Typical", "HAB Weighted", "HAB Average", "HAB Average Median Body", "HAB Trend Biased", "HAB Trend Biased (Extreme)"])

per = input.int(9, minval=1, title="Period", group = "Basic Settings")
adaptfactor = input.float(0.25, "Adaptive Factor", step = 0.01, group = "Basic Settings")
adapt = input.bool(true, "Make it R-squared adaptive?", group = "Basic Settings")

dzper = input.int(70, "Dynamic Zone Period", group = "Levels Settings") 
buy1  = input.float(0.05, "Dynamic Zone Buy Probability Level 1", group = "Levels Settings")
sell1 = input.float(0.05, "Dynamic Zone Sell Probability Level 1", group = "Levels Settings")

sigtype = input.string(SM03, "Signal type", options = [SM02, SM03, SM04], group = "Signal Settings")

lbR = input(title="Pivot Lookback Right", defval=5, group = "Divergences Settings")
lbL = input(title="Pivot Lookback Left", defval=5, group = "Divergences Settings")
rangeUpper = input(title="Max of Lookback Range", defval=60, group = "Divergences Settings")
rangeLower = input(title="Min of Lookback Range", defval=5, group = "Divergences Settings")
plotBull = input(title="Plot Bullish", defval=true, group = "Divergences Settings")
plotHiddenBull = input(title="Plot Hidden Bullish", defval=false, group = "Divergences Settings")
plotBear = input(title="Plot Bearish", defval=true, group = "Divergences Settings")
plotHiddenBear = input(title="Plot Hidden Bearish", defval=false, group = "Divergences Settings")
bearColor = darkRedColor
bullColor = darkGreenColor
hiddenBullColor = color.new(darkGreenColor, 80)
hiddenBearColor = color.new(darkRedColor, 80)
textColor = color.white
noneColor = color.new(color.white, 100)

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

kfl=input.float(0.666, title="* Kaufman's Adaptive MA (KAMA) Only - Fast End", group = "Moving Average Inputs")
ksl=input.float(0.0645, title="* Kaufman's Adaptive MA (KAMA) Only - Slow End", group = "Moving Average Inputs")
amafl = input.int(2, title="* Adaptive Moving Average (AMA) Only - Fast", group = "Moving Average Inputs")
amasl = input.int(30, title="* Adaptive Moving Average (AMA) Only - Slow", group = "Moving Average Inputs")

haclose = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, close)
haopen = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, open)
hahigh = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, high)
halow = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, low)
hamedian = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, hl2)
hatypical = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, hlc3)
haweighted = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, hlcc4)
haaverage = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, ohlc4)

float src = switch srcoption
	"Close" => loxxexpandedsourcetypes.rclose()
	"Open" => loxxexpandedsourcetypes.ropen()
	"High" => loxxexpandedsourcetypes.rhigh()
	"Low" => loxxexpandedsourcetypes.rlow()
	"Median" => loxxexpandedsourcetypes.rmedian()
	"Typical" => loxxexpandedsourcetypes.rtypical()
	"Weighted" => loxxexpandedsourcetypes.rweighted()
	"Average" => loxxexpandedsourcetypes.raverage()
    "Average Median Body" => loxxexpandedsourcetypes.ravemedbody()
	"Trend Biased" => loxxexpandedsourcetypes.rtrendb()
	"Trend Biased (Extreme)" => loxxexpandedsourcetypes.rtrendbext()
	"HA Close" => loxxexpandedsourcetypes.haclose(haclose)
	"HA Open" => loxxexpandedsourcetypes.haopen(haopen)
	"HA High" => loxxexpandedsourcetypes.hahigh(hahigh)
	"HA Low" => loxxexpandedsourcetypes.halow(halow)
	"HA Median" => loxxexpandedsourcetypes.hamedian(hamedian)
	"HA Typical" => loxxexpandedsourcetypes.hatypical(hatypical)
	"HA Weighted" => loxxexpandedsourcetypes.haweighted(haweighted)
	"HA Average" => loxxexpandedsourcetypes.haaverage(haaverage)
    "HA Average Median Body" => loxxexpandedsourcetypes.haavemedbody(haclose, haopen)
	"HA Trend Biased" => loxxexpandedsourcetypes.hatrendb(haclose, haopen, hahigh, halow)
	"HA Trend Biased (Extreme)" => loxxexpandedsourcetypes.hatrendbext(haclose, haopen, hahigh, halow)
	"HAB Close" => loxxexpandedsourcetypes.habclose(smthtype, amafl, amasl, kfl, ksl)
	"HAB Open" => loxxexpandedsourcetypes.habopen(smthtype, amafl, amasl, kfl, ksl)
	"HAB High" => loxxexpandedsourcetypes.habhigh(smthtype, amafl, amasl, kfl, ksl)
	"HAB Low" => loxxexpandedsourcetypes.hablow(smthtype, amafl, amasl, kfl, ksl)
	"HAB Median" => loxxexpandedsourcetypes.habmedian(smthtype, amafl, amasl, kfl, ksl)
	"HAB Typical" => loxxexpandedsourcetypes.habtypical(smthtype, amafl, amasl, kfl, ksl)
	"HAB Weighted" => loxxexpandedsourcetypes.habweighted(smthtype, amafl, amasl, kfl, ksl)
	"HAB Average" => loxxexpandedsourcetypes.habaverage(smthtype, amafl, amasl, kfl, ksl)
    "HAB Average Median Body" => loxxexpandedsourcetypes.habavemedbody(smthtype, amafl, amasl, kfl, ksl)
	"HAB Trend Biased" => loxxexpandedsourcetypes.habtrendb(smthtype, amafl, amasl, kfl, ksl)
	"HAB Trend Biased (Extreme)" => loxxexpandedsourcetypes.habtrendbext(smthtype, amafl, amasl, kfl, ksl)
	=> haclose
	
rsq = _iRsq(src, per)
perout = adapt ? math.ceil(per + per * (rsq-adaptfactor)) : per
perout := perout < 2 ? 1 : perout
perout := nz(perout, 1)

fish1 = _iFish(src, perout)
fish2 = nz(fish1[1])

middle = 0.
bl1 = loxxdynamiczone.dZone("buy", fish1, buy1,  dzper)
sl1 = loxxdynamiczone.dZone("sell", fish1, sell1, dzper)
zli = loxxdynamiczone.dZone("sell", fish1, 0.5 , dzper)

state = 0.
if sigtype == SM02
    if (fish1<fish2) 
        state :=-1
    if (fish1>fish2) 
        state := 1
else if sigtype == SM03
    if (fish1<zli) 
        state :=-1
    if (fish1>zli)
        state := 1
else if sigtype == SM04
    if (fish1<bl1) 
        state :=-1
    if (fish1>sl1)
        state := 1

colorfish = state == -1 ? redcolor : state == 1 ? greencolor : color.gray
plot(fish1, color = colorfish, linewidth = 2)
plot(bl1, color =  greencolor)
plot(sl1, color =  redcolor)
plot(zli, color =  bar_index % 2 ? color.white : na)

barcolor(colorbars ? colorfish : na)

goLong = sigtype == SM02 ? ta.crossover(fish1, fish2) : sigtype == SM03 ? ta.crossover(fish1, zli) : ta.crossover(fish1, sl1)
goShort = sigtype == SM02 ? ta.crossunder(fish1, fish2) : sigtype == SM03 ? ta.crossunder(fish1, zli) :  ta.crossunder(fish1, bl1)

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)

osc = fish1

plFound = na(ta.pivotlow(osc, lbL, lbR)) ? false : true
phFound = na(ta.pivothigh(osc, lbL, lbR)) ? false : true
_inRange(cond) =>
	bars = ta.barssince(cond == true)
	rangeLower <= bars and bars <= rangeUpper

//------------------------------------------------------------------------------
// Regular Bullish
// Osc: Higher Low

oscHL = osc[lbR] > ta.valuewhen(plFound, osc[lbR], 1) and _inRange(plFound[1])

// Price: Lower Low

priceLL = low[lbR] < ta.valuewhen(plFound, low[lbR], 1)
bullCond = plotBull and priceLL and oscHL and plFound

plot(
     plFound ? osc[lbR] : na,
     offset=-lbR,
     title="Regular Bullish",
     linewidth=2,
     color=(bullCond ? bullColor : noneColor)
     )

plotshape(
	 bullCond ? osc[lbR] : na,
	 offset=-lbR,
	 title="Regular Bullish Label",
	 text="R",
	 style=shape.labelup,
	 location=location.absolute,
	 color=bullColor,
	 textcolor=textColor
	 )

//------------------------------------------------------------------------------
// Hidden Bullish
// Osc: Lower Low

oscLL = osc[lbR] < ta.valuewhen(plFound, osc[lbR], 1) and _inRange(plFound[1])

// Price: Higher Low

priceHL = low[lbR] > ta.valuewhen(plFound, low[lbR], 1)
hiddenBullCond = plotHiddenBull and priceHL and oscLL and plFound

plot(
	 plFound ? osc[lbR] : na,
	 offset=-lbR,
	 title="Hidden Bullish",
	 linewidth=2,
	 color=(hiddenBullCond ? hiddenBullColor : noneColor)
	 )

plotshape(
	 hiddenBullCond ? osc[lbR] : na,
	 offset=-lbR,
	 title="Hidden Bullish Label",
	 text="H",
	 style=shape.labelup,
	 location=location.absolute,
	 color=bullColor,
	 textcolor=textColor
	 )

//------------------------------------------------------------------------------
// Regular Bearish
// Osc: Lower High

oscLH = osc[lbR] < ta.valuewhen(phFound, osc[lbR], 1) and _inRange(phFound[1])

// Price: Higher High

priceHH = high[lbR] > ta.valuewhen(phFound, high[lbR], 1)

bearCond = plotBear and priceHH and oscLH and phFound

plot(
	 phFound ? osc[lbR] : na,
	 offset=-lbR,
	 title="Regular Bearish",
	 linewidth=2,
	 color=(bearCond ? bearColor : noneColor)
	 )

plotshape(
	 bearCond ? osc[lbR] : na,
	 offset=-lbR,
	 title="Regular Bearish Label",
	 text="R",
	 style=shape.labeldown,
	 location=location.absolute,
	 color=bearColor,
	 textcolor=textColor
	 )

//------------------------------------------------------------------------------
// Hidden Bearish
// Osc: Higher High

oscHH = osc[lbR] > ta.valuewhen(phFound, osc[lbR], 1) and _inRange(phFound[1])

// Price: Lower High

priceLH = high[lbR] < ta.valuewhen(phFound, high[lbR], 1)

hiddenBearCond = plotHiddenBear and priceLH and oscHH and phFound

plot(
	 phFound ? osc[lbR] : na,
	 offset=-lbR,
	 title="Hidden Bearish",
	 linewidth=2,
	 color=(hiddenBearCond ? hiddenBearColor : noneColor)
	 )

plotshape(
	 hiddenBearCond ? osc[lbR] : na,
	 offset=-lbR,
	 title="Hidden Bearish Label",
	 text="H",
	 style=shape.labeldown,
	 location=location.absolute,
	 color=bearColor,
	 textcolor=textColor
	 )

alertcondition(goLong, title="Long", message="R-squared Adaptive Fisher Transform w/ Dynamic Zones [Loxx]: Long\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(goShort, title="Short", message="R-squared Adaptive Fisher Transform w/ Dynamic Zones [Loxx]: Short\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(hiddenBearCond, title="Hidden Bear Divergence", message="R-squared Adaptive Fisher Transform w/ Dynamic Zones [Loxx]: Hidden Bear Divergence\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(bearCond, title="Regular Bear Divergence", message="R-squared Adaptive Fisher Transform w/ Dynamic Zones [Loxx]: Regular Bear Divergence\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(hiddenBullCond, title="Hidden Bull Divergence", message="R-squared Adaptive Fisher Transform w/ Dynamic Zones [Loxx]: Hidden Bull Divergence\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(bullCond, title="Regular Bull Divergence", message="R-squared Adaptive Fisher Transform w/ Dynamic Zones [Loxx]: Regular Bull Divergence\nSymbol: {{ticker}}\nPrice: {{close}}")














