Swing Point Oscillator with Trend Filter [Quantigenics]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Quantigenics

//@version=5
indicator("Swing Point Oscillator with Trend Filter",overlay = false)
OscLength       = input.int(defval = 9, title = "Oscillator Length" )
TrendFiltLength = input.int(defval = 18, title = "Trend Filter Length")
TopLine         = input(defval = .85, title = "Top Line")
MidHigh         = input(defval = .4, title = "Mid High")
MidLow          = input(defval = -.4, title = "Mid Low")
Bottom          = input(defval = -.85, title = "Bottom")
showZone        = input.bool(defval = true,title = "Show Zones")
UpZoneColor     = input.color(defval = color.rgb(255, 58, 222, 90),title = "Up Zone Color")
DownZoneColor   = input.color(defval = color.rgb(255, 58, 222, 90),title = "Down Zone Color")
OscColor        = input.color(defval = color.yellow, title = "Osc Color")
TopLineColor    = input.color(defval = color.rgb(255,0,255), title = "Top Line Color")
MidHighColor    = input.color(defval = color.rgb(24, 255, 24), title = "Mid High Color")
MidLineColor    = input.color(defval = color.blue, title = "Mid Line Color")
MidLowColor     = input.color(defval = color.rgb(24, 255, 24))
BottomColor     = input.color(defval = color.rgb(255,0,255), title = "Bottom Color")

var oFastK = 0.
var oFastD = 0.
var oSlowK = 0.
var oSlowD = 0.
var phase = 25
var upbox = box.new(bar_index,TopLine,bar_index,MidHigh,border_width = 0,bgcolor = showZone ? UpZoneColor: #00000000)
var downbox = box.new(bar_index,MidLow,bar_index,Bottom,border_width = 0,bgcolor = showZone ? DownZoneColor: #00000000)
box.set_right(upbox,bar_index)
box.set_right(downbox,bar_index)

Cum(series float price)=>
    var res = 0
    res[1]+price 


Num2 = 0.  
Den2 = 0. 
BarsToGo1 = 0 
BarsToGo2 = 0  


LL = ta.lowest( low, OscLength ) 
HH = ta.highest( high, OscLength ) 
Num1 = close - LL 
Den1 = HH - LL 

if( Den1 > 0) 
    oFastK := Num1 / Den1 * 100 
else 
    oFastK := 0 

CurrentBar = bar_index+1

BarsToGo1 := 1 - CurrentBar 

Num2 := Num1
Den2 := Den1 

if (Den2 > 0) 
    oFastD := Num2 / Den2 * 100 
else
    oFastD := 0 

BarsToGo2 := 3 - CurrentBar 
oFastDCum = Cum( oFastD )
if (BarsToGo2 > 0 and CurrentBar > 0) 
    oSlowD := ( oFastDCum + BarsToGo2 * oFastD[ CurrentBar - 1 ] ) / 3 
else
    oSlowD := (oFastD+oFastD[1]+oFastD[2])/ 3 
oSlowK := oFastD 
 
int Length = math.round(math.sqrt(phase))


Value2 = .1 * (oFastK - 50)
xavg = ta.ema(Value2, Length)
Value3 = ta.ema(xavg, Length)
Osckk = (math.exp(1 * Value3) - 1) / (math.exp(1 * Value3) + 1)

RE = (high-high[2])+(low-low[2])
REABS = math.abs(high-high[2])+math.abs(low-low[2])

SUM = 0.
SUMABS = 0.

for Z=0 to OscLength*.5-1   
    SUM += RE[Z] 
    SUMABS += REABS[Z]


OscB= SUMABS > 0 ? SUM/SUMABS : 0
OscA=OscB

CCIValue = (ta.cci( high + low + close, OscLength ))/100 

MainOsc = Osckk+OscA+CCIValue
var MaxMainOsc = 0.
MaxMainOsc := MaxMainOsc > math.abs(MainOsc)?MaxMainOsc:math.abs(MainOsc) //Keep track of maximum absolute value of MainOsc

if (MaxMainOsc != 0 )
    MainOsc := MainOsc / MaxMainOsc //Normalize MainOsc

plot(MainOsc, title = "Swing Point Oscillator",color = OscColor)
plot(TopLine,title = "Top",color = TopLineColor)
plot(MidHigh,title = "Mid High", color = (bar_index%2==0?MidHighColor:color.rgb(0, 0, 0, 100)))
plot(0,     title = "Mid Line",color = MidLineColor)
plot(MidLow,title = "Mid Low",color = (bar_index%2==0?MidLowColor:color.rgb(0, 0, 0, 100)))
plot(Bottom,title = "Bottom",color = BottomColor)

TrendFilt = ta.sma(MainOsc, TrendFiltLength)

var TrendColor = color.red
if (TrendFilt>MidHigh or TrendFilt<MidLow) 
    TrendColor := color.red
else 
    TrendColor := color.rgb(150, 150, 150)

plot(TrendFilt, title = "Trend Filter", color = TrendColor)