## July 3, 2008

### QuickAFL facts

QuickAFL(tm) is a feature that allows faster AFL calculation under certain conditions. Initially (since 2003) it was available for indicators only, as of version 5.14+ it is available in Automatic Analysis too.

Initially the idea was to allow faster chart redraws through calculating AFL formula only for that part which is visible on the chart. In a similar manner, automatic analysis window can use subset of available quotations to calculate AFL, if selected “range” parameter is less than “All quotations”.

So, in short QuickAFL works so it calculates only part of the array that is currently visible (indicator) or within selected range (Automatic Analysis).

Your formulas, under QuickAFL, may or may NOT use all data bars available, but only visible (or “in-range”) bars (plus some extra to ensure calculation of used indicators), so when you are using Close[ 0 ] it represents not first bar in entire data set but first bar in array currently used (which is just a bit longer than visible, or ‘in-range’ area).

The QuickAFL is designed to be transparent, i.e. do not require any changes to the formulas you are using. To achieve this goal, AmiBroker in the first execution of given formula “learns” how many bars are really needed to calculate it correctly.

To find out the number of bars required to calculate formula AmiBroker internally uses two variables ‘backward ref’ and ‘forward ref’.

‘backward ref’ describes how many PREVIOUS bars are needed to calculate the value for today, and ‘forward ref’ tells how many FUTURE bars are needed to calculate value for today.

If these numbers are known, during execution of given formula AmiBroker takes FIRST visible (or in-range) bar and subtracts ‘backward ref” and takes LAST visible (or in-range) bar and adds ‘forward ref’ to calculate first and last bar needed for calculation of the formula.

Now, how does AmiBroker know a correct “backward ref” and “forward ref” for the entire formula?

Well, every AmiBroker’s built-in function is written so that it knows its own requirements and adds them to global “backward ref” and “forward ref” each time given function is called from your formula.

The whole process starts with setting initial BackwardRef to 30 and ForwardRef to zero. These initial values are used to give “safety margin” for simple loops/scripts.

Next, when parser scans the formula like this:

Buy = C > Ref ( MA( C, 40 ), -1 );

it analyses it and “sees” the MA with parameter 40. It knows that simple moving average of period 40 requires 40 past bars and zero future bars to calculate correctly so it does the following (all internally):

BackwardRef = BackwardRef + 40; ForwardRef = ForwardRef + 0;

So now, the value of BackwardRef will be 70 (40+30(initial)), and ForwardRef will be zero.

Next the parser sees Ref( .., -1 );

It knows that Ref with shift of -1 requires 1 past bar and zero future bars so it “accumulates” requirements this way:

BackwardRef = BackwardRef + 1; ForwardRef = ForwardRef + 0;

So it ends up with:

BackwardRef = 71; ForwardRef = 0;

The BackwardRef and ForwardRef numbers are displayed by AFL Editor’s Tools->Check and Profile as well as on charts when “Display chart timing” is selected in the preferences.

If you use Check and Profile tool, it will tell you that the formula

Buy = C > Ref ( MA( C, 40 ), -1 );

requires 71 past bars and 0 future bars.

You can modify it to

Buy = C > Ref ( MA( C, 50 ), -2 );

and it will tell you that it requires 82 past bars (30+50+2) and zero future bars.

If you modify it to

Buy = C > Ref ( MA( C, 50 ), 1 );

It will tell you that it needs 80 past bars (30+50) and ONE future bar (from Ref).

Thanks to that your formula will use 80 bars prior to first visible (or in-range) bar leading to correct calculation result, while improving the speed of execution by not using bars preceding required ones.

**IMPORTANT NOTES**

It is very important to understand, that the above estimate requirements while fairly conservative,

and working fine in majority of cases, may NOT give you identical results with QuickAFL enabled, if your formulas use:

a) JScript/VBScript scripting

b) for/while/do loops using more than 30 past bars

c) any functions from external indicator DLLs

d) certain functions that use recursive calculation such as very long exponential averages or TimeFrame functions with much higher intervals than base interval

In these cases, you may need to use SetBarsRequired() function to set initial requirements to value higher than default 30. For example, by placing

SetBarsRequired( 1000, 0 );

at the **TOP** of your formula you are telling AmiBroker to add 1000 bars PRIOR to first visible (or in-range) bar to ensure more data to stabilise indicators.

You can also effectively turn OFF QuickAFL by adding:

SetBarsRequired( sbrAll, sbrAll );

at the top of your formula. It tells AmiBroker to use ALL bars all the time.

It is also worth noting that certain functions like cumulative sum (Cum()) by default request ALL past bars to guarantee the same results when QuickAFL is enabled. But when using such a function, you may or may NOT want to use all bars. So SetBarsRequired() gives you also ability to DECREASE the requirements of formula. This is done by placing SetBarsRequired at the **END** of your formula, as any call to SetBarsRequired effectively overwrites previously calculated estimate. So

if you write

x = Cum( 1 ); SetBarsRequired( 1000, 0 ); // use 1000 past bars DESPITE using Cum()

You may force AmiBroker to use only 1000 bars prior first visible even though Cum() by itself would require all bars.

It is also worth noting that when QuickAFL is used, BarIndex() function does NOT represent elements of the AFL array, but rather the indexes of ENTIRE quotation array. With QuickAFL turned on, an AFL array is usually shorter than quotation array, as illustrated in this picture:

**SPECIAL CASE: AddToComposite function**

Since AddToComposite creates artificial stock data it is desirable that it works the same regardless of how many ‘visible’ bars there are or how many bars are needed by other parts of the formula.

For this reason internally AddToComposite does this:

SetBarsRequired( sbrAll, sbrAll );

which effectivelly means “use all available bars” for the formula. AddToComposite function simply tells the AFL engine to use all available bars (from the very first to the very last) regardless of how formula looks like. This is to ensure that AddToComposite updates ALL bars of the composite

The side-effect is that “Check And Profile” feature will see that it needs to reference future bars and display a warning even though this is false alert because AddToComposite itself has no impact on trading system at all.

Now why this shows only when flag atcFlagEnableInBacktest is on ??

It is simple: this is so because it means that AddToComposite is ACTIVE in BACKTEST.

http://www.amibroker.com/guide/afl/afl_view.php?name=ADDTOCOMPOSITE

Since “Check And Profile” uses “BACKTEST” state you get such result.

If atcFlagEnableInBacktest is not specified AddToComposite is not enabled in Backtest and hence does not affect calculation of BackwardRef and ForwardRef during “Check And Profile”.

**BACKWARD COMPATIBILITY NOTES**

a) QuickAFL is available in Automatic Analysis in version 5.14.0 or higher

b) sbrAll constant is available in Automatic Analysis in version 5.14.0 or higher. If you are using older versions you should use numeric constant of: 1000000 instead.

Filed by Tomasz Janeczko at 5:33 am under AFL

4 Comments

The question from the list:

“Is the full array still passed to a DLL, or just the part of the array that Quick AFL is using?”

If you are using external plugins, any plugin function that you will call will see only the part of the array that QuickAFL is using. If you want to increase/decrease required bars, just use SetBarsRequired function.

One note:

in 5.14 – if your formula uses old-backtester (Equity() function), you can’t use QuickAFL.

Hi there, just became alert to your blog through Google, and found

that it is truly

informative. I am going to watch out for brussels. I will appreciate if you continue

this in future. Numerous people will be benefited from

your writing. Cheers!

Excellent post. Keep writing such kind of info on your blog.

Im really impressed by your site.

Hello there, You have performed an incredible job.

I will definitely digg it and personally recommend to my

friends. I’m confident they will be benefited from this website.