declare lower;
# === INPUTS ===
input Number_Of_Bars_To_Be_Averaged = 5;
input Time_of_First_Bar = 0930;
input qty_of_bars = 4;
input percent_gain = 15.0;
input min_rvol_required = 2.0;
input Use_Range_Total = yes;
input Min_Range_Total_Gain = 90;
input Show_Chart_Bubble = no;
# === BASE DEFINITIONS ===
def v = volume;
def isFirstBar = SecondsTillTime(Time_Of_First_Bar) == 0;
# === INITIAL RANGE VOLUME CALC (for RVOL) ===
def RangeBar = if isFirstBar then 1
else if RangeBar[1] < Number_Of_Bars_To_Be_Averaged and RangeBar[1] then RangeBar[1] + 1
else 0;
def RangeTotal = if !RangeBar[1] and RangeBar then v
else if RangeBar then RangeTotal[1] + v
else RangeTotal[1];
def RangeAverage = if !RangeBar then RangeTotal / Number_Of_Bars_To_Be_Averaged else Double.NaN;
def RVOL = if !IsNaN(RangeAverage) then Round(v / RangeAverage, 2) else double.nan;
# === VOLUME SPIKE DETECTION ===
def gain = Round((fold l = 0 to qty_of_bars
with y
do y + (GetValue(v,l) - GetValue(v,l+1)) / GetValue(v,l+1))*100,0);
def cnt = if Use_Range_Total then
fold z = 0 to qty_of_bars
with u = 0
do if GetValue(v,z)>=GetValue(v,z+1) then u+1 else u
else
fold i = 0 to qty_of_bars
with x = 0
while GetValue(v, i) > ((1 + percent_gain / 100) * GetValue(v, i + 1))
do x + 1;
def vper = Round(100 * ((v - v[1]) / v[1]), 0);
# === TIER CONDITIONS (ALL TIED TO SINGLE RVOL FILTER) ===
def show1 = !Use_Range_Total && cnt == 1 && RVOL >= min_rvol_required && RangeAverage;
def show2 = !Use_Range_Total && cnt == 2 && RVOL >= min_rvol_required && RangeAverage;
def show3 = !Use_Range_Total && cnt == 3 && RVOL >= min_rvol_required && RangeAverage;
def show4 = !Use_Range_Total && cnt >= 4 && RVOL >= min_rvol_required && RangeAverage;
def show5 = Use_Range_Total && cnt > 1 && gain >= Min_Range_Total_Gain && RVOL >= min_rvol_required && RangeAverage;
#added due to NA condition when hiding afterhours;
def validateshow1= if isnan(show1[-1]) then 0 else if !show1[-1] then 0 else 1;
def validateshow2= if isnan(show2[-1]) then 0 else if !show2[-1] then 0 else 1;
def validateshow3= if isnan(show3[-1]) then 0 else if !show3[-1] then 0 else 1;
def validateshow4= if isnan(show4[-1]) then 0 else if !show4[-1] then 0 else 1;
def validateshow5= if isnan(show5[-1]) then 0 else if !show5[-1] then 0 else 1;
# === HISTOGRAM ===
plot volPlot = v;
volPlot.setPaintingStrategy(PaintingStrategy.HISTOGRAM);
volPlot.assignValueColor(if RangeBar then Color.YELLOW else if (show5 && !validateshow5) then Color.LIGHT_GREEN else if RVOL>1 then Color.DARK_GREEN else Color.DARK_GRAY);
volPlot.setLineWeight(2);
# === CHART BUBBLES ===
AddChartBubble((show1 && validateshow2) && Show_Chart_Bubble, v, "1\n" +vper+ "%", Color.LIGHT_GREEN, yes);
AddChartBubble((show2 && validateshow3) && Show_Chart_Bubble, v, "2\n" +vper+ "%", Color.GREEN, yes);
AddChartBubble((show3 && validateshow4) && Show_Chart_Bubble, v, "3\n" +vper+ "%", Color.YELLOW, yes);
AddChartBubble((show4 && validateshow4) && Show_Chart_Bubble, v, "4\n" +vper+ "%", Color.ORANGE, yes);
AddChartBubble((show5 && !validateshow5) && Show_Chart_Bubble, v, ">="+Min_Range_Total_Gain+ "%^\n"+"RVOL>="+min_rvol_required, Color.ORANGE, yes);
# === LABEL ===
AddLabel(!IsNaN(RangeAverage), "RVOL: " + AsText(RVOL,NumberFormat.TWO_DECIMAL_PLACES) + " | Avg Vol (first " + Number_Of_Bars_To_Be_Averaged + " bars): " + RangeAverage, Color.WHITE);