Using AFL intrinsic formula on a custom array inside back tester

Hi guys. I love Amibroker, and Amibroker AFL is a very powerful language, can do many things and can save us a lot of time. What I want to do is to utilize the power of AFL inside the back tester to help me calculate custom metrics, things like Kurtosis, Skewness, Median, etc. (on a custom array, not the intrinsic price array). So the first thing I do is test this out. I created a custom array of 8 elements, and I applied the AFL formula RSIa to this custom array: z = RSIa(y,8); see diagrams. And to my surprise, I can access the 1000th element of the resulting calculated array, when I only have 8 elements of data in my custom array. How is that possible. I can understand with a running total using 8 element of inputs, we can have a total of 64 element of output: 8*8. Anyone know why? Thanks.bactester code report

y and z have length BarCount just like all 1-dim arrays in AFL. Functions such as RSI operate on 1-dim arrays.
https://www.amibroker.com/guide/h_understandafl.html

Contrary to that a custom array such as this one

mat = Matrix(8,1);
length = MxGetSize(mat, 0);
_TRACEF( "length (rows): %g\n", length);
_TRACEF( "BarCount: %g", BarCount);

may have size 8x1 (while Barcount being e.g. 1000).

In addition such custom array of type Matrix is allowed to exceed BarCount length and AFL engine won't return error message, e.g.

BarCount being 1000 but your custom array being

mat = Matrix(100000,1);
length = MxGetSize(mat, 0);
_TRACEF( "length (rows): %g\n", length);
_TRACEF( "BarCount: %g", BarCount);

So your custom array may have size 100000x1 (or any other one) while BarCount being 1000 without any problem (well, not counting in hardware problems). But maximum possible size for custom arrays of type Matrix is 500 million elements.


BTW, important KB link about not making assumptions on number of available bars.
https://www.amibroker.com/kb/2014/09/22/do-not-make-assumptions-on-number-of-bars/

Hi fxshrat, thank you for the great knowledge as always. I like the Matrix arrays a lot better than the standard/default 1 dimensional arrays. However, if I want to make use of the power of AFL functions inside the back tester (and it appears that AFL only works on 1 dimensional, non-matrix arrays), is there a workaround way to make the AFL functions work on a matrix? I know in C++ standard STL we can come up with some adaptors to make this work. Is there a similar maneuver within the AFL/backtester environment? Thanks.

You can only convert matrix to 1-dim array via asArray argument of MxGetBlock function.

mat = Matrix(100000, 1, initial = 1);
length = MxGetSize(mat, 0);
_TRACEF( "length (rows): %g\n", length);
_TRACEF( "BarCount: %g\n", BarCount);

// converted to 1-dim array via asArray argument
block = MxGetBlock(mat, 0, length-1, 0, 0, asArray = True);
cs = Cum(block);// Cum being 1-dim array function

_TRACEF( "last element of block: %g\n", block[BarCount-1] );
_TRACEF( "last element of cs: %g", cs[BarCount-1] );

But then you operate on 1-dim array again. So if length of upper example exceeds 1-dim array size (BarCount) then block will be cut to BarCount length. If you try to use e.g. block[BarCount] you will get Error 10 message.

So if you want to calculate Stdev, MA, RSI, .... on 2-dim array (type Matrix and that array having larger size than 1-dim array) you would have to create your own function.

1 Like

Ok, got it, thank you!

After giving it a thought, the solution I sought is workable: when we are working behind the back tester, the base unit of measurement is the number of trades, which is always less than the number of bar returned by barcount. So check the number of trades and setup a 1 dimensional array with the upper bound not exceeding the max trade number (which again, is always less than the number of bars). And if we run the strategy over a portfolio of stocks, this won't crash the system. Thanks again.