Hello,
The code is inefficient because it repeats the sorting N*N times where N is
number of symbols, while
only N times is enough.
Ranking is a process that is done during first pass of backtest. It is
implemented efficiently.
We can use this built-in process easily using custom backtest procedure as
shown here:
Note that this formula will not produce output in AA directly. Instead it will
produce a HTML
file (output.html) that you can later import to AA using AA, File->Import
Also please be warned that produced files are huge and attempt to load such big
HTML file
into Internet Explorer instead will easily hang IE.
PositionScore = ROC( C, 14 ) + 1000; // WHAT YOU WANT TO RANK
SetOption("MaxOpenPositions", 10 );
SetBacktestMode( backtestRegularRaw );
Buy=1;
Sell=0;
SetCustomBacktestProc("");
if( Status("action")==actionPortfolio )
{
bo = GetBacktesterObject();
bo.PreProcess();
dt = DateTime();
fh = fopen("output.html", "w" );
fputs("<TABLE><TR><TH>Symbol</TH><TH>Date/Time</TH><TH>Rank</TH></TR>\n", fh
);
for( i = 0; i < BarCount; i++ )
{
k = 1;
for( sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) )
{
Line = "<TR><TD>" + sig.Symbol + "</TD><TD>" +
DateTimeToStr( dt[ i ] ) + "</TD><TD>" + k + "</TD></TR>\n";
fputs( Line, fh );
k++;
}
}
bo.PostProcess();
fputs( "</TABLE>", fh );
fclose( fh );
}
Best regards,
Tomasz Janeczko
amibroker.com
----- Original Message -----
From: Ken Close
To: [email protected]
Sent: Sunday, July 06, 2008 5:35 PM
Subject: [amibroker] Paul Ho: Memory Challenges with Great Ranking Tool
Paul:
my initial euphoria has turned somewhat downward as I attempt to apply the
code below (just two indicators) to larger Watchlists. You sounded (from other
messages) like someone who knows the ins and outs of memory management with AB,
and perhaps can comment on how to keep the code below from "bogging down".
In spite of my many years with AB and its array processing, my mind still has
a problem wrapping around what this code is doing and why (and whether) larger
populated Watchlists will ever be able to work.
I initially tested against the DJ-30 (30 symbols) and all went well, fairly
quickly, perhaps 10-15 seconds.
I then tried the NDX (100 symbols) and things went more slowly but finished.
I noticed the symbols appearing in the AA window more slowly.
I have not been able to nor wanted to wait for the SP-500, as the symbols
appear more and more slowly and the est time counter was saying something like
1 1/2 hours to complete 500 symbols.
I was assuming that the code had to collect or process all symbols before it
could make comparisons among them---this is probably false or else why would
processed symbols start to appear in the AA window while it is still accessing
symbols.
What suggestions can you make, given your understanding of the code and AB,
that would minimize the processing of large member watchlists?
Can adding a SetBarsRequired in the right place limit the number of lookback
bars that are processed, and thus speed up execution?
As the number of indicators I wish to process into a "Total Rank" score
increases, I imagine that executing this code will get slower and slower and
may not be possible at all. Would you agree?
Thanks for any added help.
Ken
------------------------------------------------------------------------------
From: [email protected] [mailto:[EMAIL PROTECTED] On Behalf Of Ken
Close
Sent: Saturday, July 05, 2008 10:47 AM
To: [email protected]
Subject: [amibroker] What a Great Ranking Tool
Paul Ho has come up with a supurb ranking tool. I have expanded it to two
indicators. Feel free to expand the code structure to any number of indicators.
Possible next step: stick the Tot_Rank values into the OI field for the
symbols, then Plot the Ranks for a visual representation of "where the symbol
is over time".
The possibilities are endless (or at least enlarged because of Paul's code
idea). Thanks Paul for your creative input.
Ken
// Ranking_Alt01.afl KSC 07/05/2008
// Original code by Paul Ho, Amibroker list 07/05/2008
// Modifications and expansions by Ken Close 07/05/2008
// Will ordinal rank every symbol in watchlist for every bar.
mOwnROC = ROC(C, 14);
mOwnRSI = RSIa(C, 14);
mRoc = 0;
mRSI = 0;
list = CategoryGetSymbols(categoryWatchlist, 16);
ROCcount[0] = rocrank[0] = 0;
RSIcount[0] = RSIrank[0] = 0;
for(i = 0; (sym = StrExtract(list, i)) != ""; i++)
{
SetForeign(sym);
mRoc = ROC(C, 14);
mRSI = RSIa(C, 14);
RestorePriceArrays();
n = !IsNull(mRoc);
m = !IsNull(mRSI);
roccount += n;
rsicount += m;
rocrank = IIf(Nz(mRoc) > mOwnROC, Rocrank + n, rocrank);
rsirank = IIf(Nz(mRsi) > mOwnRSI, Rsirank + m, rsirank);
Totrank = rocrank + rsirank;
}
ROCn = ROC(C, 14);
RSIn = RSIa(C, 14);
Filter = 1;
Buy = Sell = 0;
AddColumn(ROCn, "ROCn",1.2);
AddColumn(RSIn, "RSIn",1.2);
AddColumn(mRoc, "MROC", 1.2);
AddColumn(ROCrank, "ROCRank", 1.0);
AddColumn(RSIrank, "rsirank",1.0);
AddColumn(Totrank, "Totrank", 1.0);
// To check the sorting, run on a watchlist, then click once on the date
column,
// Then shift click on one of the indicators, ie, RSIn, and you will see the
// ordinal values in order.