Pivottrend
// 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("Pivottrend", overlay = true, max_labels_count = 500)

_timeframe = input.timeframe("", "Timeframe")

_leftLength = input.int(10, "Left length")
_rightLength = input.int(3, "Right length")

_showLabels = input.bool(true, "Show labels")
_showPivots = input.bool(false, "Show pivots")
_showMarketStructureShift = input.bool(true, "Show MSS", tooltip = "Shows a line when pivot high/low is broken and trend changes. Almost the same as a Market Structure Shift (MSS).")

type Pivot
    float Price
    int Time
type Extreme
    float Price
    int BarIndex

_atr = ta.atr(14)

pivot(pivotExtreme) =>
    Pivot pivot = na
    if not na(pivotExtreme)
        pivot := Pivot.new(pivotExtreme, time[_rightLength])

    pivot
trend() =>
    var trend = 0
    pivotHigh = request.security(syminfo.tickerid, _timeframe, pivot(ta.pivothigh(high, _leftLength, _rightLength)), lookahead = barmerge.lookahead_on)
    pivotLow = request.security(syminfo.tickerid, _timeframe, pivot(ta.pivotlow(low, _leftLength, _rightLength)), lookahead = barmerge.lookahead_on)
    var Pivot latestPivotHigh = na 
    var Pivot latestPivotLow = na

    if not na(pivotHigh)
        latestPivotHigh := pivotHigh
        if _showPivots
            i = 0, extreme = Extreme.new(0)
            while true
                if time[i] < pivotHigh.Time
                    break

                if high[i] > extreme.Price
                    extreme.Price := high[i]
                    extreme.BarIndex := bar_index - i
                i += 1

            label.new(extreme.BarIndex, extreme.Price, "▲", color = color.new(color.green, 70))

    if not na(pivotLow)
        latestPivotLow := pivotLow
        if _showPivots
            i = 0, extreme = Extreme.new(2147483647)
            while true
                if time[i] < pivotLow.Time
                    break

                if low[i] < extreme.Price
                    extreme.Price := low[i]
                    extreme.BarIndex := bar_index - i
                i += 1

            label.new(extreme.BarIndex, extreme.Price, "▼", style = label.style_label_up, color = color.new(color.red, 70))

    if (trend == 0 or trend == 1)
      and not na(latestPivotLow)
        if high <= latestPivotLow.Price
          and high[1] > latestPivotLow.Price
            trend := -1
            if _showMarketStructureShift
                line.new(latestPivotLow.Time, latestPivotLow.Price, time, latestPivotLow.Price, color = color.red, xloc = xloc.bar_time)

    if (trend == 0 or trend == -1)
      and not na(latestPivotHigh)
        if low >= latestPivotHigh.Price
          and low[1] < latestPivotHigh.Price
            trend := 1
            if _showMarketStructureShift
                line.new(latestPivotHigh.Time, latestPivotHigh.Price, time, latestPivotHigh.Price, color = color.green, xloc = xloc.bar_time)

    trend

trend = trend()

bull = trend == 1 ? hl2 - (_atr * 2) : na
bear = trend == -1 ? hl2 + (_atr * 2) : na

bullStart = not na(bull) and na(bull[1])
bearStart = not na(bear) and na(bear[1])

middlePlot = plot(hl2, "Middle", na)
bullPlot = plot(bull, "Bull", not na(bull) ? color.green : na, style = plot.style_linebr, linewidth = 2)
bearPlot = plot(bear, "Bear", not na(bear) ? color.red : na, style = plot.style_linebr, linewidth = 2)

fill(middlePlot, bullPlot, color.new(color.green, 90))
fill(middlePlot, bearPlot, color.new(color.red, 90))

plotshape(bullStart ? bull : na, title="Uptrend Begins", location = location.absolute, style = shape.circle, size = size.tiny, color = color.green)
plotshape(bearStart ? bear : na, title="Downtrend Begins", location = location.absolute, style = shape.circle, size = size.tiny, color = color.red)

if bullStart
    alert("Trend turned bullish", alert.freq_all)
    if _showLabels
        label.new(bar_index, bull, "Buy", style = label.style_label_up, textcolor = color.white, color = color.green)
if bearStart
    alert("Trend turned bearish", alert.freq_all)
    if _showLabels
        label.new(bar_index, bear, "Sell", textcolor = color.white, color = color.red)