Intraday predictive High Volume Activity sessions [BEA]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Badshah.E.Alam

//@version=5
indicator('Intraday predictive High Volume Activity sessions [BEA]',shorttitle="HVAS [BEA]",max_boxes_count=500,max_lines_count=500)
// High Volume Activity sessions [BEA] (HVAS [BEA])
////////////////////////////// No display if No volume of Chart TF is not Intraday{
var cumVol = 0.
cumVol += nz(volume)
if (barstate.islast and cumVol == 0)
    runtime.error("No volume is provided by the data vendor.")

if (not timeframe.isintraday)
    runtime.error("Only Intraday chart Timeframe works for this indicator.")
//}

////////////////////////////// Date range selection for the volume data to be captured{
rangeType = input.string(defval="30 Days", title="Date range:", options=["Custom", "30 Days", "90 Days", "180 Days", "Year to Date"], group="Limit by date")

startDate = input.time(title="Start Date (YYYY/DD/MM)",
     defval=timestamp("1 Mar 2022 9:30 -0400"), group="Limit by date")
endDate =   input.time(title="End Date (YYYY/DD/MM)  ",
     defval=timestamp("31 Dec 2200 16:00 -0400"), group="Limit by date")

// subtract number of days (in milliseconds) from current time
startDate := rangeType == "Custom" ? startDate :
     rangeType == "30 Days" ? timenow - 2592000000 :   
     rangeType == "90 Days" ? timenow - 7776000000 :    
     rangeType == "180 Days" ? timenow - 15552000000 :
     rangeType == "Year to Date" ? timestamp(syminfo.timezone, year(timenow), 01, 01, 00, 01) : na

inDateRange = (time >= startDate) and (time < endDate)

//}

////////////////////////////// Identify Today for plotting of Predictive volume only for current Day{
isToday = false
if time>= timenow - 86400000//year(timenow) == year(time) and month(timenow) == month(time) and dayofmonth(timenow) == dayofmonth(time)) 
    isToday := true
//}

////////////////////////////// Defining the size of matrix and arrays used {
// getting Daily change to calculate data only on day change 
// getting Number of bars in a day for matrix size 

d_change=timeframe.change("D")
intraday_bar_count=ta.barssince(d_change)
var int count_day=0

if d_change and inDateRange
    count_day:=math.round(ta.cum(d_change?1:0))

dt =not d_change? time - time[1]:time[1] - time[2]

startCounting = false
startCounting := nz(startCounting[1], false)

if bar_index==0 and not nz(startCounting[1])
    startCounting := true

if d_change and nz(startCounting[1])
    startCounting := false

condCnt = startCounting ? 1 : 0
//}

////////////////////////////// Volume MA{
VolAvgLenght = input.int(title='MA Average Periods', defval=50, minval=0,group="MA period")
VolMa = ta.sma(volume, VolAvgLenght)
plot(VolMa, color=color.new(color.white, 0))
pred_vol_true = close>open?color.lime:color.red
plot(volume, color=pred_vol_true, style=plot.style_columns, title='Volume')
//}

////////////////////////////// Table positioning {
TablePos = input.string(title="Table Location", defval="Top Right", 
     options=["Top Right",  "Middle Right",  "Bottom Right", 
              "Top Center", "Middle Center", "Bottom Center", 
              "Top Left",   "Middle Left",   "Bottom Left"], group='Display')

_TablePos= TablePos== "Top Right"    ? position.top_right: 
           TablePos== "Middle Right" ? position.middle_right:  
           TablePos== "Bottom Right" ? position.bottom_right: 
           TablePos== "Top Center"   ? position.top_center: 
           TablePos== "Middle Center"? position.middle_center:
           TablePos== "Bottom Center"? position.bottom_center:
           TablePos== "Top Left"     ? position.top_left: 
           TablePos== "Middle Left"  ? position.middle_left:position.bottom_left

size = input.string(title="Table Size", defval="Small", 
     options=["Auto",  "Huge",  "Large", "Normal", "Small", "Tiny"], group='Display')

_size= size == "Auto" ? size.auto:  size == "Huge"  ? size.huge: 
       size == "Large"? size.large: size == "Normal"? size.normal: 
       size == "Small"? size.small: size.tiny


var t = table.new(
     position=_TablePos, columns=5, rows=500, bgcolor=color.silver, 
     frame_color=color.gray, frame_width=2, border_color=color.black, border_width=1)
//}

////////////////////////////// Main Part begins{
//Calculate everything on bar close and only once on change of Day , the data will be same for the rest of the day
// lets enter the calculation if we are within the selected range and at least two days of data is there
var bool[] array_start_time_alert = array.new_bool()
number_of_bar_count_intraday=math.round(ta.cum(condCnt))

if inDateRange and count_day>=2 and d_change and barstate.isconfirmed //and session.islastbar_regular

    // Definging marix , arrays 
    var matrix<float> matrix_v_data =matrix.new<float>(count_day-2, number_of_bar_count_intraday)
    var float[]    array_row_data = array.new_float( number_of_bar_count_intraday,na)
    var box[]    box_vol = array.new_box( number_of_bar_count_intraday,na)

    var matrix<float> matrix_ma_data =matrix.new<float>(count_day-2, number_of_bar_count_intraday)
    var float[]    array_ma_row_data = array.new_float( number_of_bar_count_intraday,na)
    var line[]    line_ma = array.new_line( number_of_bar_count_intraday,na)
    array_start_time_alert:=array.new_bool(number_of_bar_count_intraday,false)

    // setting every day volume and volume MA data in the array and then to the matrix
    for i=0 to number_of_bar_count_intraday-1
        array.set(array_row_data, i, volume[i+1])
        array.set(array_ma_row_data, i, VolMa[i+1])
    
    // adding Data arrays to the matrix
    matrix.add_row(matrix_v_data, count_day-2, array_row_data)
    matrix.add_row(matrix_ma_data, count_day-2, array_ma_row_data)
    
    //getting number of rows and coulmn in the matrix
    r_=matrix.rows(matrix_v_data)
    c_=matrix.columns(matrix_v_data)
    
    var float avg_of_vol_col=na
    var float avg_of_ma_col=na
    
    if r_>1
        for i=1 to c_
            //extracting column for Volume average calculation for each bar of the day
            subM1 =matrix.submatrix(matrix_v_data, 0, r_,  i-1, i)
            avg_of_vol_col= matrix.avg(subM1)
            
            //extracting column for VolumeMA average calculation for each bar of the day
            subM2 =matrix.submatrix(matrix_ma_data, 0, r_, i-1, i)
            avg_of_ma_col= matrix.avg(subM2)

            color_Vbar=avg_of_vol_col<avg_of_ma_col?color.new(color.blue,80):color.new(#0cbfe9,50)
            color_ma=avg_of_vol_col<avg_of_ma_col?color.blue:#0cbfe9
            array.set(array_start_time_alert,i-1,avg_of_vol_col>avg_of_ma_col)

            //plotting Predictive Volume boxes for whole day ( Today and live market only)            
            //plotting Predictive VolumeMA lines for current whole day             
            if isToday
                box.new(time+(math.abs(i-c_)*dt), avg_of_vol_col, time+(math.abs(i-c_-1)*dt), 0,xloc=xloc.bar_time, border_color=color_ma, border_style=line.style_dotted,border_color=color.red, bgcolor=color_Vbar)
                line.new(time+(math.abs(i-c_)*dt), avg_of_ma_col, time+(math.abs(i-c_-1)*dt), avg_of_ma_col,xloc=xloc.bar_time, color=color_ma, style=line.style_solid,width=2)

//}
bar_col_high_volume=(array.size(array_start_time_alert)>0 and math.abs(array.size(array_start_time_alert)-intraday_bar_count-1)<array.size(array_start_time_alert)?array.get(array_start_time_alert,math.abs(array.size(array_start_time_alert)-intraday_bar_count-1)):false)
barcolor(bar_col_high_volume?color.new(color.fuchsia,0):na,title="Predictive Volume Barcolor")    
////////////////////////////// Displaying some data in the table{
is_realtime=barstate.isrealtime?"Market Open":"Market Not open"
is_realtime_color=barstate.isrealtime? color.green: color.red

if barstate.islast and inDateRange
    table.cell(t, 0, 0, "Title", bgcolor = color.blue,text_size=_size)
    table.cell(t, 0, 1, "Bars in Intraday",text_size=_size)
    table.cell(t, 0, 2, "Days of data used",text_size=_size)
    table.cell(t, 0, 3, "Market Status",text_size=_size)

    table.cell(t, 1, 0, "Value", bgcolor = color.blue,text_size=_size)
    table.cell(t, 1, 1, str.tostring(number_of_bar_count_intraday ) , width = 15, bgcolor = color.green,text_size=_size)
    table.cell(t, 1, 2, str.tostring(count_day ), width = 15, bgcolor = color.green,text_size=_size)
    table.cell(t, 1, 3, is_realtime, width = 15, bgcolor =is_realtime_color,text_size=_size,tooltip="No Data will be plotted if Market is closed")
//}