QuickAFL and Analysis Window

Bob, I didn’t analyse your code(s), but I have noticed that you include some other file(s) using #include_once <myutils.afl>. In that case, you may want to analyse how many bars does the included formula use. You can try limiting this number using SetBarsRequired() at the end of the (original) included code.

… But if you only need analysis window to run a formula every 1 second, I would consider using charts instead. Analysis window is meant to run a code less often then charts. Every 1 second is very often. For example this formula (applied on a chart), runs some part of the code only every n-seconds :

[code]_SECTION_BEGIN( “Timer” );
TimerON = ParamToggle( “Timer”, “Off|On”, 1 );
HowOften = Param( “How often (seconds)”, 10, 1, 180 );
OnlyWhenVisible = ParamToggle( “Only when visible”, “No|Yes”, 1 );
RequestTimedRefresh( HowOften, OnlyWhenVisible );

if( TimerON AND Status( “RedrawAction” ) )
{
GfxTextOut( “This part of the code is executed every " + HowOften + " seconds”, 5, 25 );
Say( “This part of the code is executed every " + HowOften + " seconds”, 1 );
}

_SECTION_END();[/code]

Selected part of the code above is not executed when you click on a chart, or when a chart is refreshed by regular AmiBroker refresh, but only when the chart is refreshed by RequestTimedRefresh() function every n-seconds.

https://www.amibroker.com/guide/afl/requesttimedrefresh.html
https://www.amibroker.com/guide/afl/status.html

1 Like

A slightly improved version - there’s no need to use RequestTimedRefresh() if the timer is off:

[code]_SECTION_BEGIN( “Timer” );
TimerON = ParamToggle( “Timer”, “Off|On”, 1 );
HowOften = Param( “How often (seconds)”, 10, 1, 180 );
OnlyWhenVisible = ParamToggle( “Only when visible”, “No|Yes”, 1 );

if( TimerON )
{
RequestTimedRefresh( HowOften, OnlyWhenVisible );
GfxTextOut( "Timer is ON ", 5, 30 );

if( Status( “RedrawAction” ) )
{
GfxTextOut( “This part of the code is executed every " + HowOften + " seconds”, 5, 45 );
Say( “This part of the code is executed every " + HowOften + " seconds”, 1 );
}
}
else GfxTextOut( "Timer is OFF ", 5, 30 );

_SECTION_END();[/code]

1 Like

Hi

[quote=“Milosz, post:8, topic:1157”]
Bob, I didn’t analyse your code(s), but I have noticed that you include some other file(s) using #include_once <myutils.afl>. In that case, you may want to analyse how many bars does the included formula use. [/quote]

I made the code more simple by removing the external file <myutils.afl>.

Yes, I was already doing this.

procedure _MYTRACE( part_diag_filename, msg )
{
    local fh, fullpath;

    fullpath = "c:\\broker-error\\debug" + part_diag_filename + ".txt";

    msg = msg + "\n";
    fh = fmkdir( "c:\\broker-error\\" );  //  make dir in case it is not already there.
    fh = fopen( fullpath, "a" ); // open file for Append

    if( fh )
    {
        fputs( msg, fh );
        fclose( fh );
    }
    else
    {
        printf( "Error_message failed:  Error opening " + fullpath );
        _TRACE( "Error_message failed:  Error opening " + fullpath );
        _TRACE( msg );
    }
}

part_diag_filename = "bbbtest3";
bi=BarIndex();

msg="bi (local BarIndex)= "+NumToStr(bi,1.0);
printf(msg+"\n");
_MYTRACE( part_diag_filename, msg );

FirstBar = Status( "quickaflfirstdatabar" );
AbsBarIndex = FirstBar + bi;
msg="Absolute Barindex from quickaflfirstdatabar = "+NumToStr(AbsBarIndex,1.0);
printf(msg+"\n");
_MYTRACE( part_diag_filename, msg );

SetBarsRequired(300,0);

The above code runs as expected in a chart (quickAFL is ON). However it still runs with quickAFL OFF in the Analysis Window I posted.

A long time ago I had tried the RequestTimedRefresh() approach. If I remember well, the chart needs to be in focus, minimized or not, in order to refresh. What I want is a script to run in the background no matter what.

FYI, this is my setup: I have 4 scripts (in 4 Analysis windows) processing online data in 4 different TimeFrames. Then I have 4 charts in the same 4 TimeFrames, taking data from the 4 analysis windows, through Static Vars.

… 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.

4 Likes

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.

@Milosz
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.

@Milosz

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?


bi=BarIndex();

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

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

SetBarsRequired(300,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

http://www.amibroker.com/kb/2014/09/22/do-not-make-assumptions-on-number-of-bars/

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.

2 Likes

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:

Regards