AlexD Intraday market footprint
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Aleksey Demchenko / AlexD 

//@version=5
indicator(title="AlexD Intraday market footprint", shorttitle="IMF", format=format.price, precision=2, max_bars_back=5000)

//Init
DaysN      = input.int(30, title="Number of days", minval=1, maxval=128)
FilterK    = input.int(10, title="SMA filter period", minval=1, maxval=64)
Smooth     = input.int(2, title="IMF smooth period", minval=1, maxval=64)
SignalLine = input.int(6, title="IMF predict period", minval=1, maxval=64)
Preshift   = input.int(8, title="Skip N hours in days(optimisation)", minval=0, maxval=23)

i              = FilterK
DaysChecked    = 0
ReversalsFound = 0
IMF_Base       = 0.0
IMF_Predict    = 0.0

PrevDayBarIndex    = 0
PrevDayIMF_Base    = 0.0
PrevDayIMF_Predict = 0.0

//Levels
hline(1.0,  "Maximum level",   color=color.gray)
hline(0.9,  "Linearity level", color=color.green)
hline(0.5,  "Middle level",    color=color.gray)
hline(0.33, "Reversal level",  color=color.maroon)

//Chart filter
price_signal = ta.sma((high+low+close)/3, FilterK)

if((timeframe.isminutes) and (timeframe.multiplier < 61))
    //IMF calculation
    while( (DaysChecked < DaysN) and (i < 4999 - (FilterK+Smooth+Preshift)*(60/timeframe.multiplier)) )
        i += 1
        if( (hour == hour[i]) and (minute == minute[i]) )
            if(DaysChecked == 0)
                PrevDayBarIndex := bar_index[i]
            DaysChecked += 1
            if( ((price_signal[i-int(FilterK/2.0)] > price_signal[i-int(FilterK/2.0)+1]) and (price_signal[i-int(FilterK/2.0)+1] > price_signal[i-int(FilterK/2.0)+2])) or
              ((price_signal[i-int(FilterK/2.0)] < price_signal[i-int(FilterK/2.0)+1]) and (price_signal[i-int(FilterK/2.0)+1] < price_signal[i-int(FilterK/2.0)+2])) )
                ReversalsFound += 1
            i += int(60/timeframe.multiplier*Preshift) 
    IMF_Base := ta.sma(ReversalsFound/DaysChecked, Smooth)

    //IMF Predict calculation
    IMF_Predict := IMF_Base
    i := 1
    while i < SignalLine
        IMF_Predict *= IMF_Base[i]
        i += 1
    
    //Drawing the first values according to the data of the previous day
    if(bar_index > last_bar_index-SignalLine-int(Smooth/2.0))
        PrevDayIMF_Predict := IMF_Predict[bar_index-PrevDayBarIndex-SignalLine-int(Smooth/2.0)+1]
        if(bar_index > last_bar_index-int(Smooth/2.0)-1)
            PrevDayIMF_Base := IMF_Base[bar_index-PrevDayBarIndex-int(Smooth/2.0)]
        else
            PrevDayIMF_Base := na
    else
        PrevDayIMF_Predict := na
        PrevDayIMF_Base    := na
else if barstate.islastconfirmedhistory
    //TIMEFRAME ERROR
    label.new(bar_index, 0, style=label.style_label_right,
         size=size.normal, color=color.black, textcolor=color.white, 
         text="Invalid timeframe! Choose a chart from 1M to 1H.")



//Indicator view
plot(IMF_Base, title="IMF", color=color.silver, offset=-int(Smooth/2.0))
plot(IMF_Predict, title="IMF Predict", color=color.fuchsia, offset=-SignalLine-int(Smooth/2.0)+1)

plot(PrevDayIMF_Base, title="Prev day IMF", color=color.red, style=plot.style_line)
plot(PrevDayIMF_Predict, title="Prev day IMF Predict", color=color.red, style=plot.style_line)