True Adaptive-Lookback Phase Change Index [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("True Adaptive-Lookback Phase Change Index [Loxx]", 
     shorttitle="TALBPCI [Loxx]", 
     overlay = false, 
     timeframe="", 
     timeframe_gaps = true)
     
import loxx/loxxjuriktools/1
import loxx/loxxexpandedsourcetypes/4

greencolor = #2DD204  
redcolor = #D2042D 
SM02 = 'Slope'
SM03 = 'Middle Crosses'

_albper(swingCount, speed, mmin, mmax)=>
    swing = 0.
    if bar_index > 3
        if (high > nz(high[1]) and 
             nz(high[1]) > nz(high[2]) and
             nz(low[2]) < nz(low[3]) and 
             nz(low[3]) < nz(low[4]))
            swing := -1
            
        if (low < nz(low[1]) and 
             nz(low[1]) < nz(low[2]) and 
             nz(high[2]) > nz(high[3]) and 
             nz(high[3]) > nz(high[4]))
            swing :=  1
    
    swingBuffer = swing
    k = 0, n = 0
    while (k < bar_index) and (n < swingCount)
        if(swingBuffer[k] != 0) 
            n += 1
        k += 1
    albPeriod = math.min(mmin - swingCount + math.max(math.round(k/swingCount/speed), 1), mmax)
    albPeriod
    

src = input.source(close, "Source", group = "Basic Settings")
MinimalLength = input.int(25, "Minimum ALB Period", group = "Basic Settings")
MaximalLength = input.int(45, "Maximum ALB Period", group = "Basic Settings")

swingCount = input.int(5, "ALB Swing Count", group = "Adaptive Lookback Settings")
speed = input.float(1, "ALB Speed", minval = 0., step = 0.01, group = "Adaptive Lookback Settings")

smthper = input.int(5, "Jurik Smoothing Period", group = "Jurik Settings")
smthphs = input.float(0., "Jurik Smoothing Phase", group = "Jurik Settings")

LevelHigh = input.int(80, "Oversold Leve", group = "Levels Settings")
LevelLow = input.int(20, "Overbought Level", group = "Levels Settings")

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

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


MinimalLength := math.max(MinimalLength, swingCount)
alb = _albper(swingCount, speed, MinimalLength, MaximalLength)

momentum = src - nz(src[alb])
sumUpDi  = 0.
sumDnDi  = 0.
for j = 1 to alb 
    gradient = nz(src[alb]) + momentum * (alb - j) / alb
    deviation = nz(src[j]) - gradient
    if (deviation > 0)
        sumUpDi += deviation
    else  
        sumDnDi -= deviation
pci = 0. 
if ((sumUpDi+sumDnDi) !=0)
    pci := loxxjuriktools.jurik_filt(loxxjuriktools.jurik_filt((100.0*sumUpDi)/(sumUpDi+sumDnDi), smthper, smthphs), smthper, smthphs)
else  
    pci := loxxjuriktools.jurik_filt(0, smthper, smthphs)  

sig = pci[1]
mid = 50

state = 0.
if sigtype == SM02
    if (pci<sig) 
        state := 1
    if (pci>sig) 
        state :=-1
else if sigtype == SM03
    if (pci<mid) 
        state :=1
    if (pci>mid)
        state := -1

colorout = state == -1 ? redcolor : state == 1 ? greencolor : color.gray

plot(LevelHigh, "Oversold", color = bar_index % 2 ? color.gray : na)
plot(LevelLow, "Overbought", color = bar_index % 2 ? color.gray : na)
plot(mid, "Middle", color = bar_index % 2 ? color.gray : na)

plot(pci, "PCI", color = colorout, linewidth = 3)

barcolor(colorbars ? colorout : na)

goLong = sigtype == SM02 ? ta.crossunder(pci, sig) :  ta.crossunder(pci, mid)  

goShort = sigtype == SM02 ? ta.crossover(pci, sig) :  ta.crossover(pci, mid) 

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="True Adaptive-Lookback Phase Change Index [Loxx]: Long\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(goShort, title="Short", message="True Adaptive-Lookback Phase Change Index [Loxx]: Short\nSymbol: {{ticker}}\nPrice: {{close}}")









