CFB Adaptive MOGALEF Bands [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 MOGALEF Bands [Loxx]", overlay = true, shorttitle='CFBAMB [Loxx]', timeframe="", timeframe_gaps=true)

import loxx/loxxjuriktools/1

greencolor = #2DD204
redcolor = #D2042D 

_rngcalc(src, int BandsPeriod, rngper)=>
    lsum = (BandsPeriod + 1) * loxxjuriktools.jurik_filt(loxxjuriktools.jurik_filt(low, rngper, 0), rngper, 0)
    hsum = (BandsPeriod + 1) * loxxjuriktools.jurik_filt(loxxjuriktools.jurik_filt(high, rngper, 0), rngper, 0)
    sumw = (BandsPeriod + 1)
    lsum := math.sum(BandsPeriod * nz(loxxjuriktools.jurik_filt(loxxjuriktools.jurik_filt(low, rngper, 0), rngper, 0)), BandsPeriod)
    hsum := math.sum(BandsPeriod * nz(loxxjuriktools.jurik_filt(loxxjuriktools.jurik_filt(high, rngper, 0), rngper, 0)), BandsPeriod)
    sumw := BandsPeriod * BandsPeriod
    out = (hsum / sumw - lsum / sumw)
    out

src = input.source(close, "Source", group = "Basic Settings")
inpPeriod = input.int(8, "Period", group = "Basic Settings")
bandstype = input.string("CFB Adaptive Range", "Source", options = ["Standard Deviation", "CFB Adaptive Range"], group = "Basic Settings")
devup = input.int(2, "Level Up Multiplier", group = "Basic Settings")
devdn = input.int(2, "Level Down Multiplier", group = "Basic Settings")

inpDeviationsPeriod = input.int(7, "Deviation Period", group = "Basic Settings")
rangePeriod = input.int(5, "Range Period", 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(true, "Color bars?", group= "UI Options")
showfill = input.bool(true, "Fill Levels?", group = "UI Options")

linreg = ta.linreg(src, inpPeriod, 0)

levup = linreg
levdn = linreg
levmi = linreg

levup := nz(levup[1])
levdn := nz(levdn[1])
levmi := nz(levmi[1])

deviation = ta.stdev(linreg, inpDeviationsPeriod)

cfb_draft = loxxjuriktools.jcfb(src, 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_out_cfb = math.ceil(slim + ratio * (llim - slim))

rngout = bandstype == "Standard Deviation" ? deviation : _rngcalc(src, len_out_cfb, rangePeriod)

if (linreg > nz(levup[1]) or linreg < nz(levdn[1]))   
    levup := linreg + devup * rngout
    levdn := linreg - devdn * rngout
    levmi := linreg
    
up = plot(levup, "Level Up", color = greencolor)
dn = plot(levdn, "Level Down", color = redcolor)
mid = plot(levmi, "Mid", color = color.white)

fill(up, mid, color = showfill ? color.new(greencolor, 95) : na)
fill(dn, mid, color = showfill ? color.new(redcolor, 95) : na)

barcolor(colorbars ? close > levmi ? greencolor : redcolor : na)


















