Afl for relative volume scanner

I am looking for afl which scans for stocks which are showing following conditions

  1. If today's first 15 min volume is greater than past 3 days first 15min avg volume..
    New to Amibroker so don't know much about coding in it.
    Thanks,

Hi did you ever get a response to your question on relative volume?

I am looking for something similar.

If he did, the response would obviously be here.

The reason he didn't, was because OP didn't care to define the criteria more rigidly and show an inclined interest in getting it done.

Something doesnt classify as a good question.

A direction to proceed:

Vols = 0;             // Total Vol
LastNdays = 3;        // Last N occurrences
for (i = 1; i <= LastNdays; i++)
{
	Vols += ValueWhen( TimeNum() == 90000, V, i+1);	 
                // i=1 will be current day, Nth occurrence doesn't start with 0
}
VolToday = ValueWhen( TimeNum() == 90000, V, 1);
_TRACEF("Total = %.f Avg = %.f",Vols, Vols/LastNdays);

Filter = VolToday > Vols/LastNdays;

Today's first 15m Volume is very ambiguous statement, make sure the Correct TimeNum() value is set.
Doesn't make sense for me to spend more time writing generic code identifying first bar and what it means.

Many tickers have pre & post mkt data as well.

3 Likes

Thanks for your response travick. Like the OP I am also new to Amibroker and to coding for that matter. Forgive me in advance if my questions seems silly.

I was hoping you could clarify your response. If we start with a market like the ASX in Australia which does not trade pre and post market just to keep the example straight forward. I get what the OP was trying to ask. Say today is day 0. 1 = 1 day ago, 2 = 2 days ago, 3 = 3 days ago. If stock A had 10,000 in volume traded in the first 15 minutes of trading (3 days ago), 12,000 in volume 2 days ago, 9,000 in volume 1 day ago, then the average volume during the first 15 minutes of trading for the past 3 days ago would be 10,333. What I'm interested in is say if today's first 15 minute volume of Stock A has traded at greater than 2x the last 3 days' average, say for example it traded at 23,000 volume, then this is something I would want the AFL scan to pick up and alert me because it meets that criteria of being more than two times the 3 days average for the first 15 minutes.

How does the code you provided in your response capture my criteria?

Secondly, could you please clarify what the '90000' means in your code?

Thanks

  1. The code works just fine as described by OP and the way it is in your mind.

All you have to do is to make sure that the code runs in the correct timeframe, so you have to set the periodicity to 15min.

  1. When someone says first 15m bar, its a bit hazy although theoretically you can nail the 1st 15m bar easily, but I wasn't writing to code to identify that, rather how one can get the volumes at the specified interval bars.

  2. In your case, since you want "Twice the volume traded today" be greater, you can just multiply the Filter line with 2,

Filter = 2 * VolToday > Vols/LastNdays;

that's just how easy it is.

  1. In the AA window (if you don't know what AA means, search it), you need to have enough bars specified by the From-To Range fields.

  2. TimeNum(), again, read more about it in the Manual, its explained in detail.
    What I've done to cut short my effort, is to hard-code and specify the time of the First bar as 9 AM. so whatever is the time of you first bar, that's what it should match.
    To verify this, open a 15m chart, select that bar and see what time is displayed in the Title and use it.

  3. There are people who ask for first bar, and then few posts later they change their mind and want to try 2nd, 3rd and so on... this way, you can play with the time and suit yourself.

Edit for the previous post.
Line should read

Filter = VolToday > ( 2 * Vols / LastNdays );

No, the code is not correct.
Valuewhen() keeps state till next change and as such all states are summed up.

There isn't any loop required here.
Also since it is asked for first 15-min (bar) of day all that is needed is new day check.

/// INTRA-DAY code!
/// @link https://forum.amibroker.com/t/afl-for-relative-volume-scanner/6686/7
//if( Interval() != in15Minute )
//	Error( "Set to 15-Minute Interval since that one is what you asked for!" );
dn = DateNum();
newday = dn != Ref( dn, -1);
avgvol = SparseExpand(newday, SparseCompress(newday, Ref(MA(V,3),-1)));
first_bar_vol = IIf(newday, V, Null);
//
Filter = first_bar_vol > 2*avgvol;
//
Plot( avgvol, "Avg. First bar Volume", colorRed, styleHistogram, 0, 1, 0, 0, -60 );
Plot( first_bar_vol, "First session bar Volume", colorGreen, styleHistogram, 0, 1, 0, 0, -60 );
Plot( V, "Volume", colorGreen, styleHistogram, 0, 1, 0, 0, -60 );
PlotShapes( Filter * shapeSmallSquare, colorOrange, layer = 0, y = first_bar_vol, 12 );

154

6 Likes

That's why i'm here, to learn. I'm my test case it worked so posted but the learning curve for me is big.
Kudos to you,

@fxshrat above code without using SparseCompress.

dn = DateNum();
newday = dn != Ref( dn, -1);

avgvol=0;
for (i = 1; i <= 3; i++)
{
    avgvol += ValueWhen( newday, Ref(V,-i));     
}
avgvol = avgvol/3;
avgvol = IIf(newday, avgvol, Null);

first_bar_vol = IIf(newday, V, Null);
//
Filter = first_bar_vol > 2*avgvol;
//
Plot( avgvol, "Avg. First bar Volume", colorRed, styleHistogram, 0, 1, 0, 0, -60 );
Plot( first_bar_vol, "First session bar Volume", colorGreen, styleHistogram, 0, 1, 0, 0, -60 );
Plot( V, "Volume", colorGreen, styleHistogram, 0, 1, 0, 0, -60 );
PlotShapes( Filter * shapeSmallSquare, colorOrange, layer = 0, y = first_bar_vol, 12 );
1 Like

@Fossil,

thanks to your ValueWhen formula which is wrong (but is outputting same result as my Sparse* code) I realized that there is a mistake in there -> and it means that my Sparse* line is wrong also. By "wrong" I mean in the sense of doing unwanted calculation.


My Sparse line of upper code has been this one:

avgvol = SparseExpand(newday, SparseCompress(newday, Ref(MA(V,3),-1)));

So why is that one wrong?
Because it just compresses uncompressed calculation of MA(V,..) at newday bar and then expands it back to original position at new day. That's not what "we" want.

What it does is same one as this Iif() line:

avgvol = Iif(newday, Ref(MA(V,3),-1), Null);

So I think now you better understand why it is not correct calculation here.


And here comes correction:

So actually the Sparse* line should be like below one (which is correct one -> in the sense of calculating average of session start bars):

avgvol = SparseExpand(newday, Ref(MA(SparseCompress(newday, V),3),-1));

So that second Sparse line above now calculates MA of compressed Volume of newday bars and then expands it back to its original position in array. That's what "we" are looking for.

So here is full corrected Sparse* code:

/// @link https://forum.amibroker.com/t/afl-for-relative-volume-scanner/6686/10
/// INTRA-DAY code!
//if( Interval() != in15Minute )
//	Error( "Set to 15-Minute Interval as that one is what you asked for!" );
dn = DateNum();
newday = dn != Ref( dn, -1);
avgvol = SparseExpand(newday, Ref(MA(SparseCompress(newday, V),3),-1));
first_bar_vol = IIf(newday, V, Null);
//
Filter = first_bar_vol > 2*avgvol;
//
Plot( avgvol, "Avg. First bar Volume", colorRed, styleHistogram, 0, 1, 0, 0, -60 );
Plot( first_bar_vol, "First session bar Volume", colorPaleGreen, styleHistogram, 0, 1, 0, 0, -60 );
Plot( V, "Volume", colorGreen, styleHistogram, 0, 1, 0, 0, -60 );
PlotShapes( Filter * shapeSmallSquare, colorOrange, layer = 0, y = first_bar_vol, 12 );

Also it means that travick's ValueWhen is correct too (and outputs same result if using newday variable instead of Timenum() == 90000 or my one using Timenum() == 90000. In short, both (his Valuewhen code and my corrected Sparse* code) output same results if using same condition and same MA period). So it's not any problem for me saying sorry to travick for prematurely marking his code as incorrect one!

For comparison here is ValueWhen version (being correct also) and using same plot code of this post

/// INTRA-DAY code!
//if( Interval() != in15Minute )
//	Error( "Set to 15-Minute Interval as that one is what you asked for!" );
dn = DateNum();
newday = dn != Ref( dn, -1);
sumvol=0;
for (i = 1; i <= 3; i++)
    sumvol += ValueWhen(newday, V, i+1);     
avgvol = IIf(newday, sumvol/3, Null );
first_bar_vol = IIf(newday, V, Null);
//
Filter = first_bar_vol > 2*avgvol;
//
Plot( avgvol, "Avg. First bar Volume", colorRed, styleHistogram, 0, 1, 0, 0, -60 );
Plot( first_bar_vol, "First session bar Volume", colorPaleGreen, styleHistogram, 0, 1, 0, 0, -60 );
Plot( V, "Volume", colorGreen, styleHistogram, 0, 1, 0, 0, -60 );
PlotShapes( Filter * shapeSmallSquare, colorOrange, layer = 0, y = first_bar_vol, 12 );

Still, using Sparse* is preferred one (for me) -> loopless and one line.

5 Likes

No hard feelings Bro!
As I said before, i'm just here to Learn and help along the way :smiley:

1 Like

Hi fxshrat

How could you extend the ValueWhen version to all 15 min bars in the day? ie you are comparing each of today's 15 min bars to their respective 3-day MA. So for example the 9.45 to 10am bar with the 3-day MA of the 9.45 to 10am bars and so on for all bars.

Many thanks

2 Likes

Don't use ValueWhen but use Sparse*.
You iterate through bars of day of selected interval. That's the whole secret.

2 Likes

I have the same question with Ron. I actually have searched for many Amibroker forum as well as spend sometimes thinking of the code to accomplished that but can't find the solution. I am thinking about creating some kind of index for the bar during the day like this:

dn = DateNum();
tn = TimeNum();
dt = DateTime();

session = 090000 <= tn AND tn <= 144500;

//Create a series of barindex during the day for 5 minute chart (bar 0, bar 1, bar 2, ... bar 49)
Converter = (tn - 90000)/500; //Only use on 5 minute timeframe
Bar_pos	= Converter % 200;
//Filter = session;

AddColumn(Bar_pos,"index",1.0);

As I hit explore, it shows the index of each bar timenum during the day. Yet I still have no idea how to iterates through bars of day. Would you please clarify on how you would do that @fxshrat ?
Thanks so much.

I actually come accross this code in an Old Amibroker Achieve that solved the RVOL mystery.
However, it did not use the SparseCompress and SparseExpand function that @fxshrat mentioned.
I am looking forward to his approach.

But here is the code:

//RVOL: RELATIVE VOLUME WITH STANDARD DEVIATION BAND
//link: https://www.mail-archive.com/amibroker@yahoogroups.com/msg39758.html
//Note for Vietnamese market: 4 hour of trading total, each hour is 3600s

H1=V; //Use volume to calculate
dn = DateNum();
Avgvol=0;
sqsum=0;
relsd=0;

d=Param("d",20,2,50); //Select the number of period to do averaging

if (Interval()<inDaily) 
{
n = round(3600*4/Interval());  //number of bars in the day
barnum = BarsSince(dn!=Ref(dn,-1)); //bar number from start of the day
	for (i=0; i<n; i++) 
		{
			VarSet("vol"+i,IIf(i==barnum,H1,0));
			VarSet("vols"+i,IIf(i==barnum,H1*H1,0));
		}
	for (i=0; i<n; i++) 
	{ 
		Avgvol=IIf(barnum==i,Sum(VarGet("vol"+i),n*d)/d,Avgvol);
		sqsum=IIf(barnum==i,Sum(VarGet("vols"+i),n*d)/d,sqsum);
	}
relsd=sqrt(sqsum-(Avgvol*Avgvol));
}

// Z-Score
z=100*((H1-Avgvol)/relsd);

Plot(V,"Volume",colorGreen,styleHistogram);
Plot(Avgvol-relsd,"Lower",colorDarkRed,styleline|styleThick);
Plot(Avgvol,"Avg Vol",colorRed,styleHistogram|styleThick);
Plot(Avgvol+relsd,"Upper",colorPink,styleline|styleThick);
Plot(0,"ZeroLine",colorwhite,styleNoTitle|styleNoLabel);

That code is not proper one. Forget about it.
It is pretty imprecise e.g if number of bars is different one per session.
You won't get values at exactly same timenum per session to be summed up in that case.

As I said you have to use Sparse* functions.
Also you should rather iterate seconds not bars of session (using latter one is not precise one in general for this task). But don't increment like this i++.

2 Likes

Thanks for your reply @fxshrat. I see your points of iterating seconds not bars would be a better and more precise solution. Yet I am a noob at iterating intraday. Would you kindly share some examples or your solution?

Thank you very much in advance!