hi, yes the volume is a good idea. I added it to my code. You are right that for certain futures the length of the days in bars are not always the same and therefor I use a percentage. If the number of bars is less than 8% of a regular day then I assume it is a "holiday" day.
The way I find the length of a regular day is maybe not very accurate. I did it this way because the code is intended for use in a tick database that has limited data. But I will think about a better way.
For the rest our results are sometimes the same and sometimes there is a difference. I think mine is correct because I calculated some number manually. I am not sure exactly why there is a difference but I think is is due to how you handled the separator. How you remove the Sunday does not seem correct, maybe you can have a look at that. See chart below I calculate it for ndays = 3 1/10/22 @ES# at 3:55PM. The average volume 90562, which I manually verified:
>>> (87302 + 83659 + 100617 )/ 3
90526.0
in your chart it is off. It is due to the handling of Sundays imo.

my updated code adding your volume solution:
//SetBarsRequired( sbrAll );
bi = BarIndex();
ndays = Param( "Number of Days", 10, 1, 20, 1 );
disp = ParamToggle( "Display Stats", "Off|On", 1 );
selectseparator = ParamList( "Select Separator", "Time|Day|expandPoint", 1 );
findholidays = ParamList( "Find Holdidays", "Use Bars|Use Volume", 0 );
cutoff = Param( "Bars Cutoff Percentage", 8, 1, 20, 0.1 ); // a holiday (low vol day) has at least the cutoff% less bars than regular a day.
minvollevel = Param( "Low Volume Cutoff (%)", 50, 0, 100, 5 ) * 0.01; // a holiday (low vol day) has at least the minvollevel% less volume than a regular day.
// various ways to calculate the separator between trading days
if( selectseparator == "Time" )
{
separator = TimeNum() >= 165900;
separator = separator - Ref( separator, -1 );
separator = IIf( Day() != Ref( Day(), -1 ) AND !( DayOfWeek() == 0 ), 0, separator );
separator_day = Day() != Ref( Day(), -1 );
}
else
if( selectseparator == "Day" )
{
separator = Day() != Ref( Day(), -1 ) AND DayOfWeek() != 0;// remove Sunday
separator_day = Day() != Ref( Day(), -1 );
}
else
if( selectseparator == "expandPoint" )
{
// version of Jorgen W., uses database time settings.
// For CME use
// Day 09:30 - 17:29, Night 17:30 - 09:29
// compression Day/Night checked
// First day of Week: Sunday
separator = Ref( Nz( TimeFrameExpand( 1, inDaily, expandPoint ) ), -1 );
separator_day = Day() != Ref( Day(), -1 );
}
// correct number of days used if not available in database
maxdays = LastValue( Cum( separator ) ) - 1; // check if ndays are available in database
ndays = Min( ndays, maxdays );
// find the index of days that are holidays / half trading days based on the number of bars OR the volume
if( findHolidays == "Use Bars" )
{
// find the length of a regular trading day
delta_index_of_separator = ValueWhen( separator, bi, 1 ) - ValueWhen( separator, bi, 2 );
ss = Sort( delta_index_of_separator, 0, -1, 0 );
ss = ss[BarCount - 1]; // length regular trading days stored in ss
holiday_index = IIf( ( ss - abs( ValueWhen( separator, bi, 1 ) - ValueWhen( separator, bi, 0 ) ) ) / ss * 100 > cutoff, 1, 0 );
holiday_index = IIf( bi >= LastValue( ValueWhen( separator, bi ) ), 0, holiday_index ); // last day is not complete keep this day
}
else
if( findholidays == "Use Volume" )
{
// code from alligator
TimeFrameSet( inDaily );
adv = AMA( V, 1 / ( ndays + 1 ) ); // average daily volume
Tmp = Cum( 1 );
LastDay = LastValue( Tmp ) == Tmp;
regular_day = ( V >= minvollevel * adv ) OR LastDay; // criterium for low vol: minvollevel% of average
TimeFrameRestore();
holiday_index = !TimeFrameExpand( regular_day, inDaily, expandFirst );
}
// exclude bars at the holiday_index using SparseCompress
volume_SparseCompress = SparseCompress( !holiday_index, V );
separator_SparseCompress = SparseCompress( !holiday_index, separator );
// add the volumes, creating the numerator
average_volume_array = 0;
for( i = 1; i <= ndays; i++ )
{
// use regular BarIndex() bi
delta_index_of_separator = ValueWhen( separator_SparseCompress, bi, 1 ) - ValueWhen( separator_SparseCompress, bi, ( i + 1 ) );
average_volume_array = average_volume_array + Ref( volume_SparseCompress, -delta_index_of_separator ); // numerator
}
// calculate the average, dividing it by ndays
average_volume_array = SafeDivide( average_volume_array, ndays );
// expand the average
average_volume_array_SparseExpand = SparseExpand( !holiday_index, average_volume_array );
Plot( V, "True Volume", IIf( C > O, ParamColor( "Up Color", colorBlue ), ParamColor( "Down Color", colorRed ) ), styleHistogram, Null, Null, 0, 0, 3 );
Plot( IIf( separator, 1, Null ), "", ColorRGB( 0, 255, 255 ), styleHistogram | styleOwnScale | styleNoLabel, 0, 1, 0, -1, 1 );
Plot( average_volume_array_SparseExpand, "Average Volume over the previous " + ndays + " days", colorGold, styleStaircase | styleNoLabel, Null, Null, 0, 1, 1 );
if( selectseparator != "Day" )
{
Plot( IIf( separator_day, 1, Null ), "", ColorRGB( 100, 100, 100 ), styleDashed | styleHistogram | styleOwnScale | styleNoLabel, 0, 1, 0, -1, 1 );
}
if( disp )
{
lastsep = LastValue( ValueWhen( separator, bi ) );
ymin = Status( "axisminy" );
ymax = Status( "axismaxy" );
dy = ymax - ymin;
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );
delta_index_of_separator = ValueWhen( separator, bi, 1 ) - ValueWhen( separator, bi, 2 );
dd = Day();
mm = Month();
yy = Year();
dow = DayOfWeek();
for( i = lvb; i > fvb; i-- )
{
if( ( separator[i] AND selectseparator == "Day" ) OR( separator_day[i] AND selectseparator != "Day" ) )
{
if( dow[i] == 0 )
dowstr = "Sunday";
if( dow[i] == 1 )
dowstr = "Monday";
if( dow[i] == 2 )
dowstr = "Tuesday";
if( dow[i] == 3 )
dowstr = "Wednesday";
if( dow[i] == 4 )
dowstr = "Thursday";
if( dow[i] == 5 )
dowstr = "Friday";
if( dow[i] == 6 )
dowstr = "Saturday";
holiday_status = "";
if( holiday_index[i] AND bi[i] != lastsep )
{
holiday_status = "+++ Holiday +++";
PlotTextSetFont( holiday_status, "Helvetica", 10, i + 4, ymax - dy / 3, colorGold, colorDefault, 0 );
}
else
if( bi[i] != lastsep )
{
holiday_status = "Regular Trading";
}
else
if( bi[i] == lastsep )
{
holiday_status = "Last Day";
}
PlotTextSetFont( "" + delta_index_of_separator[i] + " bars", "Helvetica", 12, i - delta_index_of_separator[i] / 1.75, ymax - dy / 4, colorAqua, colorDefault, 0 );
PlotTextSetFont( dowstr + ", " + mm[i] + "/" + dd[i] + "/" + yy[i], "Helvetica", 10, i + 4, ymax - dy / 4, colorGold, colorDefault, 0 );
}
}
}