 Murder Algo Stats: last portion of Indices closing hour (S&P)
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/

// Stats regarding the 'murder algo' (last 10mins of the closing hour). Works on all sub-1hr timeframes. Best used on 10min timeframe
// Can be applied to other user input sessions alse
// © twingall

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

inputSess = input.session("1500-1600", "User Session", group = 'Statistics, Sessions, Timezones', inline = '5')
int sessStHr = math.round(str.tonumber(str.substring(inputSess,0,2)))
int sessStMn = math.round(str.tonumber(str.substring(inputSess,2,4)))
sessStart = timestamp("America/New_York", year, month, dayofweek, sessStHr, sessStMn, 00 )
int sessEndHr = math.round(str.tonumber(str.substring(inputSess,5,7)))
int sessEndMn = math.round(str.tonumber(str.substring(inputSess,7,9)))
sessEnd = timestamp("America/New_York", year, month, dayofweek, sessEndHr, sessEndMn, 00 )
timeframeInMins =timeframe.in_seconds(timeframe.period)/60
int sessLenBars = math.round((sessEnd-sessStart)/1000/(timeframe.in_seconds(timeframe.period)))
_avgMethod = input.string("sma(ohlc4)", "average method for 'Closing Hr minus last bar'", inline = '2', options = ["sma(ohlc4)", "sma(close)", "sma(low)", "sma(high)"])
tableTextCol = input.color(color.black, "table text color", inline = '3')
tabPos = input.string(position.top_right, "table position:", inline ='3', options = [ position.top_left, position.top_center, position.top_right, position.middle_left, position.middle_center, position.middle_right, position.bottom_left, position.bottom_center, position.bottom_right])

showAvLine = input.bool(true, "show Avg Line", inline = '4')
lineCol = input.color(color.fuchsia, "Color",  inline ='5')
lineStyleInput = input.string("Solid", "Style", options =["Dashed", "Dotted", "Solid"],  inline ='5')
lineWidth = input.int (3, "Width", minval =1, maxval =5, inline ='5')


string lineStyle = switch lineStyleInput
    "Dotted" => line.style_dotted
    "Dashed" => line.style_dashed
    "Solid"  => line.style_solid

float avgMethod = switch _avgMethod
    "sma(ohlc4)" => ohlc4
    "sma(close)" => close
    "sma(low)"   => low
    "sma(high)"  => high

userSess=time(timeframe.period, inputSess, "America/New_York")
bool inSess= nz(userSess)

bgcolor(inSess? color.new(color.blue, 80) : na)

roundToQuartDollar(float val)=>
    float roundVal = na
    float rem = val%0.25
    float invRem = 0.25-rem
    if rem  < 0.125
        roundVal:= math.round(val-rem,2)
    else 
        roundVal:=math.round(val+invRem, 2)
    roundVal


sessHighest = ta.highest(high[1],sessLenBars)
sessLowest = ta.lowest(low[1], sessLenBars)
sessRange =sessHighest -sessLowest

sessMinusMurHighest = ta.highest(high[2], sessLenBars-1)
sessMinusMurLowest = ta.lowest(low[2], sessLenBars-1)
sessRangeMinusMur = sessMinusMurHighest - sessMinusMurLowest

islastBarUpReach = sessHighest>sessMinusMurHighest?true:false
islastBarDnReach = sessLowest< sessMinusMurLowest? true:false
_lastBarUpReach = sessHighest- sessMinusMurHighest
_lastBarDnReach =sessMinusMurLowest -  sessLowest
lastBarUpReach=roundToQuartDollar(_lastBarUpReach)
lastBarDnReach=roundToQuartDollar(_lastBarDnReach)

AvgMethod_ExMur =ta.sma(avgMethod[2],sessLenBars-1)
_range = high[1]-low[1]

float _upReach1 = (AvgMethod_ExMur - high[1])<0 ? math.abs(AvgMethod_ExMur - high[1]):0
float _dnReach1 = (AvgMethod_ExMur - low[1])>0 ?  math.abs(AvgMethod_ExMur - low[1]):0
float _upReach = roundToQuartDollar(_upReach1)
float _dnReach = roundToQuartDollar(_dnReach1)

float _upReachPct = (_upReach / sessRange) *100
float _dnReachPct = (_dnReach / sessRange) *100

float _upReachLastBarPct =(lastBarUpReach/sessRange)*100
float _dnReachLastBarPct =(lastBarDnReach/sessRange)*100

var float murLow =0
var float murHigh =0
var float lastAvgExMur = 0
var float murAlgoRng = 0
var array<float> murAlgoRngArr = array.new<float>(1)
var float clHrRng = 0
var array<float> clHrRngArr = array.new<float>(1)
var float clHrRngMinusMur = 0
var array<float> clHrRngMinusMurArr = array.new<float>(1)
var float upReach =0
var float dnReach=0
var float upReachPct =0
var float dnReachPct =0
var float upReachLastBarPct =0
var float dnReachLastBarPct =0
var array<float> upReachArr = array.new<float>(1)
var array<float> dnReachArr = array.new<float>(1)
var array<float> upReachPctArr = array.new<float>(1)
var array<float> dnReachPctArr = array.new<float>(1)
var array<float> upReachLastBarPctArr = array.new<float>(1)
var array<float> dnReachLastBarPctArr = array.new<float>(1)
var float lastBarUpRch = 0
var array<float> lastBarUpRchArr = array.new<float>(1)
var float lastBarDnRch = 0
var array<float> lastBarDnRchArr = array.new<float>(1)
if inSess[1] and not inSess 
    if _upReach>_dnReach
        upReach:=_upReach
        array.push(upReachArr,upReach)
        upReachPct:= _upReachPct
        array.push(upReachPctArr, upReachPct)
    else 
        upReach:= _upReach
    if _dnReach>_upReach
        dnReach:=_dnReach
        array.push(dnReachArr, _dnReach)
        dnReachPct:=_dnReachPct
        array.push(dnReachPctArr, dnReachPct)
    else 
        dnReach:= _dnReach
    if islastBarUpReach 
        lastBarUpRch:= lastBarUpReach
        array.push(lastBarUpRchArr, lastBarUpRch)
        upReachLastBarPct:=_upReachLastBarPct
        array.push(upReachLastBarPctArr,upReachLastBarPct)
    else
        lastBarUpRch:=na
    if islastBarDnReach 
        lastBarDnRch:= lastBarDnReach
        array.push(lastBarDnRchArr, lastBarDnRch)
        dnReachLastBarPct:=_dnReachLastBarPct
        array.push(dnReachLastBarPctArr,dnReachLastBarPct)
    else
        lastBarDnRch:=na
    murLow := low[1]
    murHigh:= high[1]
    lastAvgExMur:=AvgMethod_ExMur
    murAlgoRng:= _range
    clHrRng:= sessRange
    clHrRngMinusMur:= sessRangeMinusMur
    array.push(murAlgoRngArr, murAlgoRng)
    array.push(clHrRngArr, clHrRng)
    array.push(clHrRngMinusMurArr,clHrRngMinusMur)

fct()=>
    int num = 0
    for i = 0 to sessLenBars
        if inSess[i]
            num+=1
        num

barsElapsed = fct()
dynamicAvgMethod = ta.sma(avgMethod, barsElapsed>0?barsElapsed:1)

line avgLine =na
if inSess and barsElapsed<sessLenBars and barsElapsed>0
    avgLine:=line.new(bar_index-barsElapsed+1, dynamicAvgMethod, bar_index, dynamicAvgMethod, color = lineCol, style = lineStyle, width =lineWidth)
    line.delete(avgLine[1])

avgMurRange = array.avg (murAlgoRngArr)
ArrSize = array.size (murAlgoRngArr)
lastMurRange = array.last(murAlgoRngArr)
avgClRange = array.avg (clHrRngArr)
lastRange = array.last(clHrRngArr)
lastRangeExMurder = array.last(clHrRngMinusMurArr)
avgRangeExMurder = array.avg(clHrRngMinusMurArr)

sizeupReachPctArr  = array.size(upReachPctArr)
sizednReachPctArr  = array.size(dnReachPctArr)
avgUP_reachPctArr  = array.avg(upReachPctArr)
avgDN_ReachPctArr  = array.avg(dnReachPctArr)
avgUP_ReachLastBarPctArr = array.avg(upReachLastBarPctArr)
avgDN_ReachLastBarPctArr = array.avg(dnReachLastBarPctArr)

sizeUpReachArr = array.size(upReachArr)
sizeDnReachArr = array.size(dnReachArr)
avgUpReachArr = array.avg(upReachArr)
avgDnReachArr = array.avg(dnReachArr)
modeUPreachArr = array.mode(upReachArr)
modeDNreachArr = array.mode(dnReachArr)
medianUPreachArr = array.median(upReachArr)
medianDNreachArr = array.median(dnReachArr)

lastBarUpRchArrSize = array.size(lastBarUpRchArr)
lastBarDnRchArrSize = array.size(lastBarDnRchArr)
lastBarUpRchAvg= array.avg(lastBarUpRchArr)
lastBarDnRchAvg= array.avg(lastBarDnRchArr)

lastBarUpRchMode= array.mode(lastBarUpRchArr)
lastBarDnRchMode= array.mode(lastBarDnRchArr)
lastBarUpRchMedian= array.median(lastBarUpRchArr)
lastBarDnRchMedian= array.median(lastBarDnRchArr)

lastBarUpRchStr = not na(lastBarUpRch)?str.tostring(lastBarUpRch,'0.00') + " $": "No Reach!"
lastBarDnRchStr = not na(lastBarDnRch)?str.tostring(lastBarDnRch,'0.00') + " $": "No Reach!"

lastUpReachFromAvgStr =  nz(upReach)?str.tostring(upReach,'0.00')+" $": "No Reach!"
lastDnReachFromAvgStr =  nz(dnReach)?str.tostring(dnReach,'0.00')+" $": "No Reach!"
//
var Table = table.new(tabPos, columns = 10, rows =24, bgcolor =color.new(color.gray, 74), border_width = 1)
table.cell(Table,0, 1, "History = "+str.tostring(ArrSize) +" days",  bgcolor = color.yellow, text_halign = text.align_center, text_color = tableTextCol)
table.cell(Table,0, 2, "session Bars = "+str.tostring(sessLenBars),  bgcolor = color.red, text_halign = text.align_center, text_color = tableTextCol)
table.cell(Table,1, 1, "Average Method(Session, without last bar):",  bgcolor = color.new(color.red, 20), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,2, 1, _avgMethod,  bgcolor = color.new(color.red, 20), text_halign = text.align_center, text_color = tableTextCol)

table.cell(Table,0, 3, "avg session Range = "+str.tostring(roundToQuartDollar(avgClRange))+" $",  bgcolor = color.orange, text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,0, 4, "avg Last Bar Range = "+str.tostring(roundToQuartDollar(avgMurRange))+" $",  bgcolor = color.orange, text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,0, 5, "avg session Range ex-last-bar = "+str.tostring(roundToQuartDollar(avgRangeExMurder))+" $",  bgcolor = color.orange, text_halign = text.align_right, text_color = tableTextCol)

table.cell(Table,0, 6, "previous session Range = "+str.tostring(roundToQuartDollar(lastRange))+" $",  bgcolor = color.new(color.blue, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,0, 7, "previous Last Bar range = "+str.tostring(roundToQuartDollar(lastMurRange))+" $",  bgcolor = color.new(color.blue, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,0, 8, "previous session range ex-last-Bar = "+str.tostring(roundToQuartDollar(lastRangeExMurder))+" $",  bgcolor = color.new(color.blue, 70), text_halign = text.align_right, text_color = tableTextCol)

table.cell(Table,1, 2, "~~ Last Bar Reach ~~",  bgcolor = color.new(color.blue, 50), text_halign = text.align_center, text_color = tableTextCol)
table.cell(Table,2, 2, "~~ Last Bar Reach from Average ~~",  bgcolor = color.new(color.blue, 50), text_halign = text.align_center, text_color = tableTextCol)

table.cell(Table,1, 3, "Is Up-Reach? : "+str.tostring(lastBarUpRchArrSize)+"/"+str.tostring(ArrSize) +" days ("+str.tostring(lastBarUpRchArrSize/ArrSize*100, '0.0')+ ") %",  bgcolor = color.new(color.lime, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,1, 4, "Mean Up-Reach(% of session) = "+str.tostring(avgUP_ReachLastBarPctArr,'0.0')+" %",  bgcolor = color.new(color.lime, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,1, 5, "Mean Up-Reach = "+str.tostring(roundToQuartDollar(lastBarUpRchAvg),'0.00')+" $",  bgcolor = color.new(color.lime, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,1, 6, "Mode Up-Reach = "+str.tostring(lastBarUpRchMode,'0.00')+" $",  bgcolor = color.new(color.lime, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,1, 7, "Median Up-Reach = "+str.tostring(lastBarUpRchMedian,'0.00')+" $",  bgcolor = color.new(color.lime, 70), text_halign = text.align_right, text_color = tableTextCol)

table.cell(Table,1, 8, "Is Down-Reach? : "+str.tostring(lastBarDnRchArrSize)+"/"+str.tostring(ArrSize)+" days ("+str.tostring(lastBarDnRchArrSize/ArrSize*100, '0.0')+ ") %",  bgcolor = color.new(color.lime, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,1, 9, "Mean Down-Reach(% of session) = "+str.tostring(avgDN_ReachLastBarPctArr,'0.0')+" %",  bgcolor = color.new(color.lime, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,1, 10, "Mean Down-Reach = "+str.tostring(roundToQuartDollar(lastBarDnRchAvg),'0.00')+" $",  bgcolor = color.new(color.lime, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,1, 11, "Mode Down-Reach = "+str.tostring(lastBarDnRchMode,'0.00')+" $",  bgcolor = color.new(color.lime, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,1, 12, "Median Down-Reach = "+str.tostring(lastBarDnRchMedian,'0.00')+" $",  bgcolor = color.new(color.lime, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,1, 13, "last Up-Reach = "+lastBarUpRchStr,  bgcolor = color.new(color.gray, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,1, 14, "last Down-Reach = "+lastBarDnRchStr,  bgcolor = color.new(color.gray, 70), text_halign = text.align_right, text_color = tableTextCol)

table.cell(Table,2, 3, "Is Up-Reach? : "+str.tostring(sizeUpReachArr)+"/"+str.tostring(ArrSize) +" days ("+str.tostring(sizeUpReachArr/ArrSize*100, '0.0')+ ") %",  bgcolor = color.new(color.green, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,2, 4, "Mean Up-Reach(% of session) = "+str.tostring(avgUP_reachPctArr,'0.0')+" %",  bgcolor =  color.new(color.green, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,2, 5, "Mean Up-Reach = "+str.tostring(roundToQuartDollar(avgUpReachArr),'0.00')+" $",  bgcolor = color.new(color.green, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,2, 6, "Mode Up-Reach = "+str.tostring(modeUPreachArr)+" $",  bgcolor = color.new(color.green, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,2, 7, "Median Up-Reach = "+str.tostring(roundToQuartDollar(medianUPreachArr),'0.00')+" $",  bgcolor = color.new(color.green, 70), text_halign = text.align_right, text_color = tableTextCol)

table.cell(Table,2, 8, "Is Down-Reach? : "+str.tostring(sizeDnReachArr)+"/"+str.tostring(ArrSize) +" days ("+str.tostring(sizeDnReachArr/ArrSize*100, '0.0')+ ") %",  bgcolor = color.new(color.green, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,2, 9, "Mean Down-Reach(% of session) = "+str.tostring(avgDN_ReachPctArr, '0.0')+" %",  bgcolor =  color.new(color.green, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,2, 10, "Mean Down-Reach = "+str.tostring(roundToQuartDollar(avgDnReachArr),'0.00')+" $",  bgcolor = color.new(color.green, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,2, 11, "Mode Down-Reach = "+str.tostring(modeDNreachArr,'0.00')+" $",  bgcolor = color.new(color.green, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,2, 12, "Median Down-Reach = "+str.tostring(roundToQuartDollar(medianDNreachArr),'0.00')+" $",  bgcolor = color.new(color.green, 70), text_halign = text.align_right, text_color = tableTextCol)
table.cell(Table,2, 13, "last Up-Reach = "+lastUpReachFromAvgStr,  bgcolor = color.new(color.gray, 70), text_halign = text.align_right, text_color = tableTextCol) 
table.cell(Table,2, 14, "last Down-Reach = "+lastDnReachFromAvgStr,  bgcolor = color.new(color.gray, 70), text_halign = text.align_right, text_color = tableTextCol) 