Simple Ultimate Oscillator
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © RozaniGhani-RG

//@version=5
indicator('Simple Ultimate Oscillator', 'SUO', false, format.price, precision=2, timeframe="", timeframe_gaps=true)

// 0. Inputs
// 1. Type
// 2. Custom Function
// 3. Variables
// 4. Constructs

//#region ———————————————————— 0. Inputs
lenFast = input.int( 7,   'Fast', minval = 1)
lenMid  = input.int(14, 'Middle', minval = 1)
lenSlow = input.int(28,   'Slow', minval = 1)
//#endregion

//#region ———————————————————— 1. Type
// @type      Used for hl
// @field max float value for max
// @field min float value for min
// @field  bp float value for bp
// @field  tr float value for tr
type hl
    float max = na
    float min = na
    float  bp = na
    float  tr = na
//#endregion

//#region ———————————————————— 2. Custom Function
// @function calculate average price from UO variable
// @param    common, len
// @returns  average price from UO variable
createUoVar(hl common = na, int len = na) =>
    math.sum(common.bp, len) / math.sum(common.tr, len)
//#endregion

//#region ———————————————————— 3. Variables
common      = hl.new()
common.max := math.max(high, close[1])
common.min := math.min( low, close[1])
common.bp  :=      close - common.min
common.tr  := common.max - common.min
uoFast      = createUoVar(common, lenFast)
uoMid       = createUoVar(common, lenMid)
uoSlow      = createUoVar(common, lenSlow)
uo          = 100 * (4*uoFast + 2*uoMid + uoSlow) / 7
//#endregion

//#region ———————————————————— 4. Constructs
p_UO  = plot(  uo,          'UO', chart.fg_color, 2)
UO050 = hline( 50, 'Middle Line', color.silver, hline.style_dashed, 2, false)
OB100 = hline(100,  'OVERBOUGHT',    color.red, hline.style_solid,  1, false, display.none)
OB070 = hline( 70,  'OVERBOUGHT',    color.red, hline.style_solid,  1, false, display.none)
OS030 = hline( 30,    'OVERSOLD',    color.red, hline.style_solid,  1, false, display.none)
OS000 = hline(  0,    'OVERSOLD',    color.red, hline.style_solid,  1, false, display.none)
fill(OB070, OB100, color.new(color.red,  90), 'OVERBOUGHT')
fill(OS000, OS030, color.new(color.lime, 90), 'OVERSOLD')
//#endregion