QuickAFL and Analysis Window

Hi

I am trying to test the quick AFL concept in an Analysis window. It seems that in the AW my code takes into account the entire database (as if I had set SetBarsRequired(sbrAll,sbrAll); ). Whereas the same code works as expected on a chart.

So in effect, both of the following lines report the same numbers in AW:
bi (local BarIndex)
Absolute Barindex from quickaflfirstdatabar

What am I doing wrong please?


SetBarsRequired(600,0);
part_diag_filename = "bbbtest0";
bi=BarIndex();


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

staticbi=StaticVarGet("AbsoluteBarindex");
msg="staticbi (static var)= "+NumToStr(staticbi,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 );

bi3 = staticbi - FirstBar;
msg="Local Barindex from static var = "+NumToStr(bi3,1.0);
printf(msg+"\n");
_MYTRACE( part_diag_filename, msg );

PS: _MYTRACE is a procedure that outputs to a text file, suitable for examining AW output.

No matter how many bars your base contain, you don't have to use all of them when performing a scan or exploration. If you have a large database and limit the number of bars the performance of exploration/scan may improve significantly.

  1. First of all you have to check "Use QuickAFL" in Backtester settings. For indicators QuickAFL is used by default but It is not the case for Analysis window. Of course range must be smaller than “All quotes”.

  1. Additionally you can reduce the number of bars required by a certain formula by adding SetBarsRequired() at the end of the formula. Most users know SetBarsRequired() function, but it is usually used to tell Amibroker to use more bars than would be needed by default. Usually it is placed at the top of the formula. For example SetBarsRequired(sbrall, sbrall) will force Amibroker to use all past and all future bars. But not everyone knows, that if he wants to limit the number of bars - SetBarsRequired() has to be placed at the end of the formula. Only then it overrides the default values. If you place SetBarsRequired (100, 100) at the end of the code, you will force Amibroker to use only 100 past and 100 future bars. Of course you have to pay attention when you override the default values, because the formula will not work properly if more bars are needed.

https://www.amibroker.com/guide/afl/setbarsrequired.html
http://www.amibroker.com/kb/2008/07/03/quickafl/

Regards

5 Likes

... to be precise. Use QuickAFL option in Backtester settings should be marked if you want to use QuickAFL in Analysis Window :wink:

Thank you very much for the info. I was not aware of it.

Strange that I need to place Setbarsrequired at the TOP if I want to increase the number of bars and at the END if I want to decrease them,

May I ask where this setting is?

Hi Milosz

I am still unable to turn quickAFL OFF in Analysis Window. Although I did follow your instructions.

Here is the script that works for a chart but not in an AW:

#include_once <myutils.afl>
SetChartOptions( 0, chartShowArrows | chartShowDates );
_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) );
Plot( C, "Close", ParamColor( "Color", colorDefault ), styleNoTitle | ParamStyle( "Style" ) | GetPriceStyle() );


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);

Again, _MYTRACE( part_diag_filename, msg ); just outputs to a text file.

Here is sample output, after a “bar replay”:

bi (local BarIndex)= 1,348
Absolute Barindex from quickaflfirstdatabar = 1,348
bi (local BarIndex)= 1,349
Absolute Barindex from quickaflfirstdatabar = 1,349
bi (local BarIndex)= 1,350
Absolute Barindex from quickaflfirstdatabar = 1,350
bi (local BarIndex)= 1,354
Absolute Barindex from quickaflfirstdatabar = 1,354
bi (local BarIndex)= 1,355
Absolute Barindex from quickaflfirstdatabar = 1,355
bi (local BarIndex)= 1,356
Absolute Barindex from quickaflfirstdatabar = 1,356
bi (local BarIndex)= 1,358
Absolute Barindex from quickaflfirstdatabar = 1,358

Can somebody send me a working example please?

It is not strange at all. It is very well explained by TJ here:
http://www.amibroker.com/kb/2008/07/03/quickafl/

Well Bob, if you ask me where Range setting is, than you probably lack some basic knowledge of how Analysis Window (ie. Exploration/Scan) works.

What sense does it make to use quickAFL and try to force Amibroker to use 100 bars instead of 500 000 using SetBarsRequired() at the end of the formula, if at the same time you set the Range to All quotes and force Amibroker to use all bars?

What do you mean? You wanted to turn it ON. Now you want to turn it OFF ???

I suggest you spend some more time reading about Analysis Window settings, Explorations etc. to gain some basic knowledge, instead of asking about everything on the forum. 90% of my knowledge comes from AmiBroker's documentation and examples already provided by other users :wink:

https://www.amibroker.com/guide/h_newanalysis.html
https://www.amibroker.com/guide/h_exploration.html
http://www.amibroker.com/kb/category/analysis/explorations/

2 Likes

Hi Milosz

Sorry, I meant how to turn quick AFL ON. That was a typo.

The Range is set to 1-Recent Bars as you suggested, so this was not a problem.

Truth is I am using the Analysis Window only as a means to run my script every 1sec. And through static vars I am passing values to other scripts. So I have not explored all the features of it.

Here is the .APX file I am using :

And the corresponding .AFL file:

I will try to look at all of the options later. But if those are the ones affecting QuickAFL, then I think I have covered all of them.

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.