Oscillator overlay
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © mickes

//@version=5
indicator("Oscillator overlay", overlay = true)

_atrFactor = input.float(2, "ATR factor", tooltip = "Determines the limits for where the oscillator is shown", group = "General")
_changeBackground = input.bool(true, "Change background", group = "General")
_showLastValue = input.bool(true, "Show last value", group = "General")

_showPivots = input.bool(true, "Show", group = "Pivots")
_showPivotsOscillatorValue = input.bool(true, "Show oscillator value", group = "Pivots")
_pivotLength = input.int(10, "Length", group = "Pivots")

_oscillatorType = input.string("MFI", "Oscillator", ["MFI", "RSI", "Stochastic"], group = "Osciillator")
_length = input.int(14, "Length", group = "Osciillator")
_oversold = input.float(20, "Oversold", group = "Osciillator")
_overbougth = input.float(80, "Overbougth", group = "Osciillator")

type Oscillator
    float Value
type Drawing
    float Oversold
    float Overbought
    float Minimum
    float Maximum
    float Value
    float Price

var _lightTheme = color.r(chart.bg_color) == 255
var _oscillator = Oscillator.new()

switch _oscillatorType
    "MFI" => _oscillator.Value := ta.mfi(hlc3, _length)
    "RSI" => _oscillator.Value := ta.rsi(close, _length)
    "Stochastic" => _oscillator.Value := ta.sma(ta.stoch(close, high, low, _length), 3)

oscillate() =>
    atr = ta.atr(14)
    drawing = Drawing.new(low, high, low, high, ohlc4)
    if not na(atr)
        drawing.Minimum := low - ((atr * _atrFactor))
        drawing.Maximum := high + ((atr * _atrFactor))
        area = drawing.Maximum - drawing.Minimum
        drawing.Oversold := drawing.Minimum + (area * (_oversold / 100))
        drawing.Overbought := drawing.Maximum - (area * (1 - (_overbougth / 100)))
        drawing.Price := ((drawing.Maximum - drawing.Minimum) * (_oscillator.Value / 100)) + drawing.Minimum

    drawing
background() =>
    color background = na
    if _changeBackground
        if _oscillator.Value > _overbougth
            background := color.new(color.red, 80)
        else if _oscillator.Value < _oversold
            background := color.new(color.green, 80)

    background
showLastValue(drawing) =>
    if barstate.islast
        var l = label.new(bar_index, 0, color = color.new(color.purple, 30), style = label.style_label_lower_left, textcolor = color.white)
        label.set_text(l, str.format("{0,number,#.##}", _oscillator.Value))
        label.set_xy(l, bar_index, drawing.Price)
showPvots(drawing) =>
    pivotHigh = ta.pivothigh(_oscillator.Value, _pivotLength, _pivotLength)
    highPrice = drawing.Maximum[_pivotLength]
    pivotLow = ta.pivotlow(_oscillator.Value, _pivotLength, _pivotLength)
    lowPrice = drawing.Minimum[_pivotLength]
    
    if _showPivots
        if not na(pivotHigh)
            labelColor = pivotHigh > _overbougth ? color.new(color.red, 30) : color.new(color.red, 70)
            label.new(bar_index - _pivotLength, highPrice, str.format("{0}▼", _showPivotsOscillatorValue ? str.format("{0,number,#.##}\n", pivotHigh) : ""), color = labelColor, textcolor = color.white)

        if not na(pivotLow)
            labelColor = pivotLow < _oversold ? color.new(color.green, 30) : color.new(color.green, 70)
            label.new(bar_index - _pivotLength, lowPrice, str.format("▲{0}", _showPivotsOscillatorValue ? str.format("\n{0,number,#.##}", pivotLow) : ""), color = labelColor, textcolor = color.white, style = label.style_label_up)

drawing = oscillate()

plot(_oscillator.Value, "Value (for alerts)", display = display.none)

price = plot(drawing.Price, "Price", color = _oscillator.Value > _overbougth ? color.red : _oscillator.Value < _oversold ? color.green : color.purple, display = display.pane)
extremeTransparency = 90
oversold = plot(drawing.Oversold, "Oversold", color = _lightTheme ? color.new(color.black, extremeTransparency) : color.new(color.white, extremeTransparency), display = display.pane)
overbougth = plot(drawing.Overbought, "Overbougth", color = _lightTheme ? color.new(color.black, extremeTransparency) : color.new(color.white, extremeTransparency), display = display.pane)
fill(oversold, overbougth, color.new(color.purple, 90), "Background")
limitTransparency = 60
min = plot(drawing.Minimum, "Minimum", color = _lightTheme ? color.new(color.black, limitTransparency) : color.new(color.white, limitTransparency), display = display.pane)
max = plot(drawing.Maximum, "Maximum", color = _lightTheme ? color.new(color.black, limitTransparency) : color.new(color.white, limitTransparency), display = display.pane)

fill(price, overbougth, _oscillator.Value > _overbougth ? color.new(color.red, 80) : na)
fill(price, oversold, _oscillator.Value < _oversold ? color.new(color.green, 80) : na)

showPvots(drawing)

if _showLastValue
    showLastValue(drawing)

bgcolor(background())