Is that possible to read csv file for parameter by each symbol?

Example I have 100 symbols with all different parameters.

Symbol A, Buy = Cross(EMA(C,5), EMA(C,10))

Symbol B, Buy = Cross(EMA(C,10),EMA(C,15))

Symbol C, Buy = Cross(EMA(C,15),EMA(C,20))

I want to create csv file look like this.

Symbol EMA1 EMA2
A 5 10
B 10 15
C 15 20

and my AFL will use parameter in this csv file instead of type all parameters one by one.

Please help me write this code in AFL

Thank you

I will outline a solution. Read the csv file into a Matrix on the first bar. Use the OLE object to get the ordinal number for each symbol and store its parameters in the location corresponding to the ordinal number. Then in your strategy code use Status("stocknum") to find the current symbol's ordinal number and lookup the Matrix for indicator computation.


Status("stocknum") does not seem to correspond to ordinal number because during an Analysis execution it will be assigned at run-time depending on the scrips in the watchlist.
This may work in only one specific scenario when you use all the symbols and run it against the entire DB which may become very counter-productive.

Also you can not access the number when you may want to access data from chart.

Then ordinal number may change every time you add/delete symbols or some larger DB level change. I haven't checked this but it can happen.

Bearing all the above in mind, the most flexible way is to create a comma-separated string with all the symbols and look up the index with StrFind().
Then you can maintain similar number of strings for the param and retrieve the param at that index. Looking up strings will not really be slow and it will work in all scenarios especially when the number of symbols is just 100 or so.
see the implementation here.

Then you can store the strings in a static variable and use it everywhere or from as many formula files as needed.

Even the order of scrips wont matter, so you can add symbols at the end and drop from the middle.


Damn. In previous post there was matstr variable of include file AFL missing after copying the code of linked thread over to here and after modifying it in editor it got accidentally removed without noticing. Removed post not confuse.

So here is update of previous post and adding some further modifications such as checking for matstr existence etc.

So first code has to be saved to Include folder by file name e.g.
And the second code calls that include file and its data and extracts matrix block according to index of symbol in sorted Watchlist.

Note: Watchlist should have same number of symbols as number of Param rows of Include file.
Also you should check whether the symbols of watchllst are the ones you look for.

Include file code (name of that file and saved to Include folder of Formulas):

/// THIS is supposed to be an INCLUDE FILE with sample name ""
/// File has to be put to "...\Formulas\Include" (for example)
/// Read more about include files here
/// @link

matstr	=

// Set param set per row
// Sort it by symbol name
"{" +

"{5,10}," +  // Symbol A e.g. QQQ
"{10,15}," + // Symbol B e.g. SHY
"{15,20}" +  // Symbol C e.g. SPY
// etc.


This is main AFL (e.g. saved to Custom folder of Formulas) calling upper include file's code.
Note: Alternativally to using CategoryGetSymbols you may hardcode the list, e.g:

watchlist = "QQQ,SHY,SPY";
/// @link
/// @link
Version( 6.10 ); // AmiBroker 6.10 or higher required!

// File has to exist in Include folder !!!
#include <>

wlnum = 0; //watchlist number
watchlist = CategoryGetSymbols(categoryWatchlist, wlnum);
// OR you may hardcode the list e.g.
// watchlist = "QQQ,SHY,SPY";

// Sort list
// The order after sorting has to be like this
// Symbol A, Symbol B, symbol C
// So e.g.
// So same symbols as of Include file
watchlist = StrSort(watchlist);
printf("Watchlist: %s\n", watchlist);
nm = Name();
symcount = StrCount(watchlist, ",")+1;
for ( i = 0; i < symcount; i++ )
	if (StrMatch(nm, StrExtract(watchlist, i)))
extraced_ticker = StrExtract(watchlist, i);	
printf("\ni: %g, ticker: %s\n\n", i, extraced_ticker);
if ( extraced_ticker != "" ) {
	set = i;
	if ( typeof(matstr) == "undefined" )
		mat = Matrix(symcount, 2, default_param = 1);
		mat	= MxFromString(matstr);
	printf("Param Set:\n");

	row = Max(0, Min(MxGetSize(mat,0)-1, set));

	param1 = mat[row][0];
	param2 = mat[row][1];
	printf( "\n\nParams of symbol %s:\n", extraced_ticker);
	printf( "Param1: %g, Param2: %g", param1, param2);

	indicator = MACD(param1, param2);
	Plot( indicator, StrFormat("MACD(%g,%g) from Set", param1, param2), colorRed );
} else {
	ticker_check = WriteIf(extraced_ticker=="", "Ticker %s is NOT watchlist member!", "%s");
	printf(ticker_check, nm);
	Title = StrFormat(ticker_check, nm);

Tested and working now.




@nsm51: Yes, the solution I outlined only works for Analysis with entire database and it does not work in chart.

@fxshrat: Thank you for the code! With less than two weeks into AB, I have learnt a lot by reading your many pearls in the forum. Two questions since the evaluation model for AFL is not fully clear to me after all the reading:

(1) Is the for loop that contains the if with StrMatch run only once or does it run on each bar?

(2) I would appreciate a pointer to anything that describes what code runs on each bar and what runs only once.


It is explained in detail here. How AFL works.

As a general thumb rule, look at the syntax in the manual.
If a function accepts array parameter, it will process all bars in a single call when called. Like HHV()

If a function accepts only scalar ( not an array but a single variable like string or number ), then you should not supply an Array. Like StrMatch()
Some functions like LastValue(), SelectedValue(), End/Begin can help with this or use access Elements at Array index with [ ]
This is where For / if-else / while can also be used more often.

Some functions like IIF() can accept both and based on what is passed, will return appropriate array or scalar value.

After reading posts here it is clear that one should not use Array Functions in For/While Loops. It is not wrong syntactically but it will be very slow and wrong way of writing code. In some cases a few iterations are ok but not with large iterations.

Just remember that AB is an Array or Vector Language so you can read more on the internet.

Hi @nsm51:

I have gone through the AB user guide twice and am familiar with the content of the link you provided. I have also read the following which talks about how to make a piece of code run only once:

However, none of these answer my question as to how many times that for loop with if in the code by @fxshrat will run. Say you have that code for realtime trading of a portfolio of N symbols with 1 minute bars and M ticks arrive (total for the N symbols), is the for loop executed (a) 0 times (because it was executed once on initial load of strategy), (b) N times (given N symbols), (c) M times (given M ticks)?

Just to clarify my background: I am very comfortable with array processing languages having done extensive development with numpy and Pandas. I have also done extensive work with C++ and with Multicharts (MC) and totally understand how tick and array processing work in MC. I came over to AB is because MC is slow compared to AB.

I would greatly appreciate help with understanding how many times that for loop is executed in the context I have described in this post. Thanks.

It does not run per bar but per AFL (refresh) e.g per chart refresh or per analysis run (in latter case per symbol e.g. if "Current" then 1 time per run, if "Filter" and 3 symbols then 3 times). The loop does not iterate bars but iterates the symbol list to find/return the location of the selected symbol within that symbol list (if it is part of that list). If is found then the loop stops (till next refresh).

If you want to run the loop just once (at some event) then you may use a trigger (e.g. ParamTrigger or new bar event etc.) to store result to static variable.

:grin: :grin: :grin: :+1:

Thank you @fxshrat. I now understand how to make that code run once at the time the strategy is loaded.

I would have to guard it with Status("stocknum") == 0 and load the results into static variables so that the AFL threads for other N-1 symbols can find their parameters in the global static area.

Your reply triggered one more question that will help me get clarity with the workings of AFL. You mentioned that in general code that is unguarded is run per "refresh". Am I correct in equating "refresh" with "tick arrival" in the context of realtime portfolio autotrading? Thanks,

Add this code to chart pane then you will see in which intervals the chart will refresh.

/// @link
/// "redrawaction" - returns 0 (zero) for regular refreshes, 
/// and 1 for refreshes triggered via RequestTimedRefresh().
if( Status("redrawaction") == 0 ) 

Also see Tools - Preferences - Intraday - Realtime chart refresh interval where you can set refresh interval in seconds.

Also chart refreshes when you click on chart. Etc.

For more see below KB link by @nsm51.


There is a KB article which explains nicely.


Thank you @nsm51. That explained it nicely. Somehow I had missed that article.

I am using more than 3 symbols, which part should change ?


Sorry no response from me with such attitude. I am tired of people just coming here copy & pasting and demanding without any sign of appreciation.

What about helping yourself?
Here are the tools:

If you don't get it done yourself then send email to fxshrat at gmail dot com. Then you may get special help with included service fee plus coffee and cakes.

And BTW no one is sitting in front of your PC!
Please read pinned threads first.

E.g. is point 2. fulfilled in your post? Double check before responding.