QuickAFL and Analysis Window

… and I have just shown you how you can execute a selected part of the code only every n-seconds when using charts …

If I remember well” - that’s the key quote! Apparently you didn’t read the documentation that I have mentioned. Additionally I have provided you with a ready to use code, and you didn’t find it appropriate to analyse it well. You can choose in the chart’s Parameters if the code is executed when the chart is minimized or not. Check out this line:

Sorry, but I won’t spend all day in this thread. I think I gave you enough information. Good luck!

1 Like
  1. Apply my code to the chart,
  2. In the chart’s Parameters select - “Only when visible” - “No”
  3. Minimize the chart
  4. Minimize the whole AmiBroker
  5. Start browsing the Net or watching “House of Cards”
  6. I can assure you, your chart is not in focus :wink:
  7. You will hear if your formula is executed or not …

I did it about half an hour ago (my AmiBroker is minimized) and still can hear that: “This part of the code is executed every n seconds” …

1 Like

Hello Milosz

Yes, I believe you. However please check out the following:

I tried sevral different combinations but mainly I focused on this:
OnlyWhenVisible : NO
TimerON : Off

I placed the script on SHEET1. Then I clicked on SHEET2. The script seemed not to run at all, as I could not hear the voice any more. Have you experienced the same? So this means that RequestTimedRefresh cannot force a script to run if it is not in the main visible window of AmiBroker? If this is the case then this was the problem I had faced a long time ago.

Even if this was a viable solution, I would still examine every piece of the documentation you sent me to determine why my .APX file did not run as expected. However, I need time for this.

Bob, you must be joking. Right? Tell me why did you turn my whole script OFF by selecting Timer : Off - It is even turned ON by default. How is this script supposed to work if you turn it OFF :flushed: :grey_question::grey_question::grey_question:

No, that was a typo. The correct settings I focused on are:

OnlyWhenVisible : NO
TimerON : On

When I switch to a different SHEET, the sound stops.

There is misunderstanding between two of you.

@Milosz Milosz means 'sheet' as the MDI tab (UPPER tab).
@bobptz apparently means LOWER tab, i.e. chart sheets.

And it works in @Milosz setup only.

Why? One has to understand that MDI tabs (the upper tabs) represent actual windows that still exist when they are hidden or partially obscured by other windows.

Lower tabs however (so called "chart sheets") don't represent windows.

They represent "chart sets" that can be switched quickly but they are NOT physical windows. Instead physical windows are created/destroyed when you select/deselect given sheet (in lower tab). Deselected chart sheet (in lower tab) does NOT exist physically. It is only tab. Only if you click on tab actual windows are created. If they were physical windows all the time resource and CPU consumption would be enormous and you won't be able to open that many actual charts as you do now because Windows has LIMITS on number of windows open and CPU also has limits. So in order to fit within Windows limits AND allow so many sheets AmiBroker in many places uses smart optimizations and dynamic creation to keep window count and CPU use as small as possible.

Thanks to this optimization having ANY number of chart sheets (lower tab) costs NOTHING in terms of resources and CPU.

MDI tabs however, consume resources even if they are obscured by other windows. But because they actually exist, they can receive timer refreshes.


Yes, this is what I mean.

And I confirm that if you just switch MDI Tab, the script works.

@Tomasz, thank you for the clarification and providing additional useful insights :slight_smile:

@bobptz, You might have one more problem with regards to Say() function in my example code. If you set the same interval of how often a selected part of the formula should be executed (in both charts’ Parameters) - for example: HowOften = 10 seconds , than you may not hear both notifications as the Synthesizer may speak it at the same time. To avoid this you can:

  1. Change how often a selected part of each formula is executed (in chart’s Parameters) - for example every 10 seconds for the first chart and every 15 seconds for the second one,

or (a much better solution):

  1. Change the line with Say() into:

When somebody uses Say() function:

I usually recommend setting purge parameter to False (or 0). If you leave the default setting - True (1) and your AFL generates a couple of synthesiser requests one after another (in a short period of time), you might not hear all the messages/notifications (especially if they are long) - because each request will clear/purge all queued speak requests and as a result, you might hear only the last one.

A quote from https://www.amibroker.com/guide/afl/say.html :

When purge is set to True (the default) - any call to Say() purges all previous speak requests (queued or in-progress) and speaks specified text immediatelly. When purge is set to False - speak request is queued and will be spoken right after previous requests are done.

Thank you for the tips. Now I do consider your solution a viable alternative. I could use different MDI tabs, I do not really need different chart Sheets.

However, I prefer to troubleshoot the problem I had with the Analysis Windows and Quick AFL, as this seems to be a minor mistake from my part, and not a major design flaw.


I did read all the documentation you sent me. I made a very simple script that does use QuickAFL in a chart. However QuickAFL is still OFF when I use Analysis Window.

Can somebody make a simple (APX) file with the following code, that does demonstrates the QuickAFL effect?


msg="bi (local BarIndex)= "+NumToStr(bi,1.0);

FirstBar = Status( "quickaflfirstdatabar" );
AbsBarIndex = FirstBar + bi;
msg="Absolute Barindex from quickaflfirstdatabar = "+NumToStr(AbsBarIndex,1.0);


As @Milosz wrote - it simply works.

You are probably making assumptions and expecting things that are not going to happen. For example you may be expecting to get less bars for the very first ticker. You won’t get that because it is the VERY FIRST ticker symbol that is executed with ALL bars so QuickAFL can figure out how many bars are needed for subsequent symbols. As we can read in http://www.amibroker.com/kb/2008/07/03/quickafl/

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.

As described in the Knowledge Base the formula needs to be EXECUTED first to find out required bars. And this means execution on very first symbol always uses all bars.

I said that dozens of times and would repeat again: it is not enough to just “scan” the docs. The docs are written in concise style. This means that every sentence in the Knowledge Base has important information in it and should not be skipped or scanned only. It should be read and understood.

By the way You should NEVER EVER be doing ANY assumptions on number of bars see


Your formula may be executed with different number of bars depending on zoom factor, QuickAFL settings, the symbol that is used and dozens of other factors that usually you don’t have any idea of. So your best bet is to never assume that you will get given number of bars. The formulas need to be written so they accept ANY number of bars.


Hello Tomasz

Thank you for the info, I did study the documentation you posted, however I do not think this is what I need.

I have the impression I have not communicated very clearly what I want, or maybe nobody tried to test my code. So to make it as simple as possible, my problem is this:

I cannot make QuickAFL work in an Analysis Window. Whenever I test Status( “quickaflfirstdatabar” );, it ALWAYS gives me 0.

Can somebody test really quick this for me please? Is it only me?

Again: it simply works. Here are easy steps:

  1. Open AFL Editor, copy-paste this:
Filter = Status("firstbarinrange");
AddColumn( Status("quickaflfirstdatabar"), "first" );
  1. Click Send to Analysis

  2. In Analysis window, select Apply to: All symbols and Range to 1 recent bar

  3. Go to Settings, make sure Use Quick AFL is checked

  4. Press Explore button and here is what you would see:

Hi Tomasz

Thank you for the very detailed steps, that I could follow.

Here is a video of me reproducing them:

I still see 0 as a result of Status( “quickaflfirstdatabar” );. Is there any other parameter that I might have missed?

I have AB pro, ver 6.21.0 64bit.

Use MORE symbols than one with ENOUGH data (like > 10000 bars).

You are just trying on TWO symbols. As I wrote previously, but you ignored it, that first symbol always uses all bars. Second symbol is ~~~EQUITY which may simply be very short.

@Tomasz, I thought, that all bars are used for the very first Symbol in the watchlist no matter how many threads are used by the Analysis window, but I have noticed, that this happens for the very first Symbol for each thread.

Can we expect that in some very specific cases (a database with a very long history - 500 000+ bars) if we perform an exploration (using QuickAFL) on a watchlist containing ie. 16 Symbols and our processor has 16 threads (or more) our exploration might be actually performed quicker when we run it using only one thread ( #pragma maxthreads 1;) ? In this scenario only one symbol in a watchlist is executed with all bars - all others are executed using QuickAFL. If our watchlist contains 16 symbols and 16 threads are used, even all 16 symbols might be executed using all bars. I know that is a rather unusuall situation, but it seemed interesting to me :wink:


Hi Tomasz

You are right. As I was reading your phrase “it is the VERY FIRST ticker symbol that is executed with ALL bars” I just passed it by. I did not think it applies to me as I only use one symbol (EURUSD), the other one is just garbage.

Also my interest is to make it work with BAR REPLAY. So again I thought that this “first time execution” does not affect me, as I could concentrate on later executions.


  1. Could it be that during bar replay, every new step, every new bar is considered the FIRST execution? So the very first symbol uses ALL the bars ALL the time?

  2. Maybe the workaroud would be to add a dummy symbol (with around 10500 bars) BEFORE the EURUSD, in order for EURUSD to be 2nd and have the quickAFL effect?

The thing is that QuickAFL must execute formula in order to find out bar requirements. Depending on your formula one or more threads can be started at once. If more than one thread is started initially it will use all bars, but if, for example, your formula has

if( Status("stocknum") == 0 )

then only one thread will be started for the very first symbol and subsequent threads will be started when first one finished, so the other threads will use less bars.

As I wrote many times in this thread already - one should never assume certain number of bars because this is internal AmiBroker thing. Reliance on undocumented inner workings is bad idea because your assumptions may be invalidated by future software changes/updates.

I also wrote many times that whenever formula benefits from multi-threading depends on how complex the formula is from computational point of view. CPU-heavy (CPU bound) algorithms like Percentile/Sorting/Trigonometric/Transcendental functions are likely to benefit much more than memory bound algorithms that are limited by RAM speed, not CPU.

As I wrote: assumptions are bad. There are dozens of factors that affect the speed and there is no “one-fits-all” recipe.


2. Maybe the workaround would be to add a dummy symbol BEFORE the EURUSD, in order for EURUSD to be 2nd and have the quickAFL effect?

Tomasz, thank you very much for the clarification.

I have checked and indeed:

  1. without if( Status("stocknum") == 0 ) { }
    in my code, all threads use all bars for the first/initial run (so with n-threads running, n-first symbols are executed using all bars),
  2. with if( Status(“stocknum”) == 0 ) { }
    in my code (even if this line is commented and begins with //)
    only 1 Symbol in a watchlist is executed using all bars, and all others are executed using QuickAFL even if Analysis window uses many threads…

Now I see, that if( Status("stocknum") == 0 ) { } might be used not only to perform some operations that should be done only once (like reading/writing StaticVariables etc.) but can be used just to change the behaviour of the Analysis window engine.

I really appreciate those tips and insights of yours :slight_smile: