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


I am looking at a formula that performs a ranking based on mulltiple criteria, including whether the S&P 500 is below its 200 DMA. These ranks must be available inside the Status("stocknum") == 0 code section as I generate buy/sell signals and position sizes inside a bar by bar loop for later loading via static variables.

The issue I have run into is tha tSetForeign("PY") loads SPY data up to the last bar of the first symbol being analyzed. This creates a problem when using a watchlist that includes delisted symbols (the famous survivorship bias issue) with a delisted symbol appearing at the top of the list.

The only idea I could com up with is to experiment with a second watchlist that only holds SPY. But it looks like Amibroker sorts all symbols alphabetically and starts with the first one, no matter what.

A solution would be to create a symbol AAAAA with SPY data, but I would consider that a last resort workaround.

Is there a simple solution or am I bumping up against an Amibroker design hurdle?

Thanks for any help,


if (  Status( "stocknum" ) == 0 )
    //--- calculate if the S&P500 is above or below its 200DMA
   SPYBelowMA = C < MA(C,200);

  // --- perform ranking ---
    for ( i = 0; ( symbol = StrExtract( watchlist, i ) )  != "";  i++ )
        SetForeign( symbol ); 
        RankValue = ... something that includes SPYBelowMA
   StaticVarGenerateRanks("Rank","RankValue", 0 , 1224);

   // --- generate buy/sell signals and offload them into static variables
   for( bar = 1; bar < BarCount; bar++ )

Not sure why you would generate signals in a loop like this, but without knowing more it's hard to say whether there's a more elegant solution. As for the SetForeign problem you mentioned, that can be easily solved using Pad & Align as described here: Change what stock gets processed first - #2 by mradtke. Many other forum posts on this topic exist as well. There's even a warning that pops up in AmiBroker when you try to use StaticVarGenerateRanks without enabling P&A: Generate ranks on Daily data but evaluate strategy on Hourly - #4 by fxshrat

1 Like

Thanks a lot! For some reason I assumed that the default ^DJI that appears in P&A worked. Changed it to SPY "et voilà". I am generating signals in the loop because I ran into limitations of the rotational backtest mode.

I strongly DISCOURAGE running loops with SetForeign like that because it is against multithreading principles.

Instead generate ranks as part of scan that goes before backtest. You can use #pragma sequence to have your ranks calculated before backtesting in fully multithreading mode without Status("stocknum") at all.

See this:


1 Like

Thanks Tomasz, was not aware of this possibility! Will investigate.

Examples already exist

After looking around I discovered that I needed to upgrade to 6.40.

Started to experiment and discovered an error in the documentation? In the section
*Running a sequence of actions" the code example starts with

#pragma sequence(scan,exploration)

which produces an error.

What works is

#pragma sequence(scan,explore)

Ok, I did a side-by-side test running the rank generation with SetForeign() and with #pragma. Observed a speed improvement of 30-40%. But the "heavy lifting" will still occur in side the bar by bar loop inside Status(stocknum) == 0 so in the end I don't think that I will not see much of an improvement.

Now my question: since #pragma only seems to run with the new "sequence" button my guess is that this way of working is not accessible for optimization? I.e. to perform optimization I will be forced to work with SefForeign() inside Status(stocknum) == 0 ?

Speed improvement depends on many factors. You can't make authoritative conclusions based on single case/use scenario and single computer that you use. With more symbols, more data in RAM and more CPU cores the advantage will grow.

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.