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,
Robert
if ( Status( "stocknum" ) == 0 )
{
StaticVarRemove("*.*");
//--- calculate if the S&P500 is above or below its 200DMA
SetForeign("SPY");
SPYBelowMA = C < MA(C,200);
RestorePriceArrays();
// --- perform ranking ---
for ( i = 0; ( symbol = StrExtract( watchlist, i ) ) != ""; i++ )
{
SetForeign( symbol );
RankValue = ... something that includes SPYBelowMA
RestorePriceArrays();
}
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
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.
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.