Phase Accumulation, Smoothed Williams %R Histogram [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="Phase Accumulation, Smoothed Williams %R Histogram [Loxx]", shorttitle="PAWPRSH [Loxx]", overlay=false, max_bars_back = 3000)
import loxx/loxxexpandedsourcetypes/3

greencolor = #2DD204
redcolor = #D2042D 

lightgreencolor = #96E881 
lightredcolor =  #DF4F6C

EMA(x, t) =>
    _ema = x
    _ema := na(_ema[1]) ? x : (x - nz(_ema[1])) * (2 / (t + 1)) + nz(_ema[1])
    _ema
    
calcComp(src, period)=>
    out = (
         (0.0962 * src +
         0.5769 * src[2] -
         0.5769 * src[4] -
         0.0962 * src[6]) * (0.075 * src[1] + 0.54))
    out

_a_jurik_filt(src, len, phase) =>
    //static variales
    volty = 0.0, avolty = 0.0, vsum = 0.0, bsmax = src, bsmin = src
    len1 = math.max(math.log(math.sqrt(0.5 * (len-1))) / math.log(2.0) + 2.0, 0)
    len2 = math.sqrt(0.5 * (len - 1)) * len1
    pow1 = math.max(len1 - 2.0, 0.5)
    div = 1.0 / (10.0 + 10.0 * (math.min(math.max(len-10, 0), 100)) / 100)

    //Price volatility
    del1 = src - nz(bsmax[1])
    del2 = src - nz(bsmin[1])
    volty := math.abs(del1) > math.abs(del2) ? math.abs(del1) : math.abs(del2)

    //Relative price volatility factor
    vsum := nz(vsum[1]) + div * (volty - nz(volty[10]))
    avolty := nz(avolty[1]) + (2.0 / (math.max(4.0 * len, 30) + 1.0)) * (vsum - nz(avolty[1]))
    dVolty = avolty > 0 ? volty / avolty : 0
    dVolty := math.max(1, math.min(math.pow(len1, 1.0/pow1), dVolty))
        
    //Jurik volatility bands
    bet = len2 / (len2 + 1)
    pow2 = math.pow(dVolty, pow1)
    Kv = math.pow(bet, math.sqrt(pow2))
    bsmax := del1 > 0 ? src : src - Kv * del1
    bsmin := del2 < 0 ? src : src - Kv * del2

    //Jurik Dynamic Factor
    phaseRatio = math.max(math.min(phase, 100), -100) / 100.0 + 1.5
    beta = 0.45 * (len - 1) / (0.45 * (len - 1) + 2)
    alpha = math.pow(beta, pow2)

    //1st stage - prelimimary smoothing by adaptive EMA
    jma = 0.0, ma1 = 0.0, det0 = 0.0, e2 = 0.0
    ma1 := (1 - alpha) * src + alpha * nz(ma1[1])
    
    //2nd stage - one more prelimimary smoothing by Kalman filter
    det0 := (src - ma1) * (1 - beta) + beta * nz(det0[1])
    ma2 = ma1 + phaseRatio * det0

    //3rd stage - final smoothing by unique Jurik adaptive filter
    e2 := (ma2 - nz(jma[1])) * math.pow(1 - alpha, 2) + math.pow(alpha, 2) * nz(e2[1])
    jma := e2 + nz(jma[1])
    jma
    
_pr(src, len) =>
	max = ta.highest(high, len)
	min = ta.lowest(low, len)
	temp = 50 + (-100) * (max - src) / (max - min)
    temp

_prout(src, mult, filt)=>
    Smooth = 0.00
    Detrender = 0.00
    I1 = 0.00
    Q1 = 0.00
    Period = 0.00
    DeltaPhase = 0.00
    InstPeriod = 0.00
    PhaseSum = 0.00
    Phase = 0.
    _period = 0.
    
    Smooth := bar_index > 5 ? (4 * src + 3 * nz(src[1]) + 2 * nz(src[2]) + nz(src[3])) / 10 : Smooth
    ts = calcComp(Smooth, Period)
    Detrender := bar_index > 5 ? ts : Detrender

    qs = calcComp(Detrender, Period)
    Q1 := bar_index > 5 ? qs : Q1
    I1 := bar_index > 5 ? nz(Detrender[3]) : I1
    
    I1 := .15 * I1 + .85 * nz(I1[1])
    Q1 := .15 * Q1 + .85 * nz(Q1[1])
    
    Phase := nz(Phase[1])
    Phase := math.abs(I1) > 0 ? 180.0 / math.pi * math.atan(math.abs(Q1 / I1)) : Phase
    
    Phase := I1 < 0 and Q1 > 0 ? 180 - Phase : Phase
    Phase := I1 < 0 and Q1 < 0 ? 180 + Phase : Phase
    Phase := I1 > 0 and Q1 < 0 ? 360 - Phase : Phase
    
    DeltaPhase := nz(Phase[1]) - Phase
    DeltaPhase := nz(Phase[1]) < 90 and Phase > 270 ? 360 + nz(Phase[1]) - Phase : DeltaPhase
    DeltaPhase := math.max(math.min(DeltaPhase, 60), 7)

    InstPeriod := nz(InstPeriod[1])
    PhaseSum := 0
    count = 0
    
    while (PhaseSum < mult * 360 and count < 4500)
        PhaseSum += nz(DeltaPhase[count])
        count := count + 1
    
    InstPeriod := count > 0 ? count : InstPeriod

    alpha = 2.0 / (1.0 + math.max(filt, 1))
    _period := nz(_period[1]) + alpha * (InstPeriod - nz(_period[1]))
    _period := math.floor(_period) < 1 ? 1 : math.floor(_period)
    math.floor(_period)
    
smthtype = input.string("AMA", "Heiken-Ashi Better Smoothing", options = ["AMA", "T3", "Kaufman"], group=  "Basic Settings")

srcoption = input.string("Median", "Source", group= "Basic 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)"])


smlen = input.int(35, title = "Smoothing Period", group=  "Basic Settings")

regcycles = input.float(5, title = "WR% Cycles", group=  "Basic Settings")
macycles = input.float(0.25, title = "Signal Cyles", group=  "Basic Settings")

regfilter = input.float(1, title = "WR% filter", group=  "Basic Settings")
mafilter = input.float(1, title = "Signal filter", group=  "Basic 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")

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


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
	
int fout = math.floor(_prout(src, regcycles, regfilter))
int sout = math.floor(_prout(src, macycles, mafilter))

pr = _pr(close, fout)
pr1 = _a_jurik_filt(pr, smlen, 0)

sig = EMA(pr1, sout)

colorout = 
     pr1 > sig and pr1 >= 0 ? greencolor :
     pr1 < sig and pr1 >= 0 ? lightgreencolor :
     pr1 < sig and pr1 < 0 ? redcolor :
     lightredcolor

plot(pr1, color = colorout , style = plot.style_histogram)
plot(sig, color = color.white)

barcolor(colorbars ? colorout : na)


goLong = ta.crossover(pr1, 0) 
goShort = ta.crossunder(pr1, 0)


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



alertcondition(goLong, title = "Long", message = "Phase Accumulation, Smoothed Williams %R Histogram [Loxx]: Long\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(goShort, title = "Short", message = "Phase Accumulation, Smoothed Williams %R Histogram [Loxx]: Short\nSymbol: {{ticker}}\nPrice: {{close}}")

























