CFB-Adaptive Trend Cipher Candles [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 Trend Cipher Candles [Loxx]', 
     shorttitle = "CFBATCC [Loxx]",
     timeframe="", 
     timeframe_gaps=true, 
     overlay = true)
     
import loxx/loxxjuriktools/1 as jf
import loxx/loxxexpandedsourcetypes/4

_corrrelation(x, y, len)=> 
    float meanx = math.sum(x, len) / len
    float meany = math.sum(y, len) / len
    float sumxy = 0
    float sumx = 0
    float sumy = 0
    for i = 0 to len - 1
        sumxy := sumxy +    (nz(x[i]) - meanx) * (nz(y[i]) - meany)
        sumx  := sumx  + math.pow(nz(x[i]) - meanx, 2)
        sumy  := sumy  + math.pow(nz(y[i]) - meany, 2)
    sumxy / math.sqrt(sumy * sumx)
    
smthtype = input.string("Kaufman", "Heiken-Ashi Better Smoothing", options = ["AMA", "T3", "Kaufman"], group=  "Source Settings")
srcoption = input.string("Close", "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)"])

nlen = input.int(20, "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(8, "CFB Short Limit", minval = 1, group = "CFB Ingest Settings")
llim = input.int(48, "CFB Long Limit", minval = 1, group = "CFB Ingest Settings")
jcfbsmlen = input.int(5, "Post CFB Jurik Smooth Period", minval = 1, group = "CFB Ingest Settings")
jcfbsmph = input.float(0, "Post CFB Jurik Smooth Phase", group = "CFB Ingest Settings")
CfbSmoothDouble = input.bool(true, "CFB Double Juirk Smoothing?", group = "CFB Ingest Settings")

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

cfb_draft = jf.jcfb(src, cfb_len, smth)
cfb_pre = 
     CfbSmoothDouble ? jf.jurik_filt(jf.jurik_filt(cfb_draft, jcfbsmlen, jcfbsmph), jcfbsmlen, jcfbsmph) :
     jf.jurik_filt(cfb_draft, 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
out = math.ceil(slim + ratio * (llim - slim))

correlate = _corrrelation(src, bar_index, out)

colorCorrelate = 
     correlate > 0.95 ?  #FFF300 : 
     correlate > 0.9 ?  #80ff5f : 
     correlate > 0.8 ?   #58ff2e : 
     correlate > 0.6 ?  #33fc00 : 
     correlate > 0.4 ?   #29cc00 : 
     correlate > 0.2 ?  #1f9b00 : 
     correlate > 0.0 ?   #156a00 : 
     correlate < -0.95 ? #FF0EF3 : 
     correlate < -0.9 ? #ff2e57 : 
     correlate < -0.8 ?  #fc0031 : 
     correlate < -0.6 ? #cc0028 : 
     correlate < -0.4 ?  #9b001e : 
     correlate < -0.2 ? #6a0014 : 
     #6a0014 

color_out = color.new(colorCorrelate, 0)
barcolor(color_out)
