Automatically replace watchlist in Exploration in ranked order

Hello everyone,

I run a batch every day after my end of day data is available which runs several explorations and uses the ReplaceWatchlist command to replace the exploration's designated watchlist with the new findings.

All of them are ranked in one way or another and of course they are ordered by rank in the exploration output.

However using ReplaceWatchlist enters the symbols into the watchlist in alphabetical order. Therefore I have to take the exploration output, right click and choose "Replace Watchlist with the results...", and then it stores them in ranked order in the watchlist. Since I run several screens, this becomes problematic and time-consuming. The whole point of the batch is to reduce my work to reviewing charts for buying opportunities.

Is there an AFL equivalent to this manual action? I've searched this forum and the internet without any luck.

Sorry if this seems easy for most of you but I can't see a log of how to to do it anywhere nor can I find any equivalent afl command or sequence of commands that replaces the manual steps.

Thanks!
Mike

Here is one of my more basic screens to see how I'm using code to generate a watchlist.

#include "C:\Users\mamus\Dropbox\Michael\Documents\AmiBroker Files\In Test\Cassiopeia\FuncLib.afl"

// Find stocks with good RS that are making new RS line new highs
RS		= GetRS(Name());  // Call custom function to determine stock relative strength
RSgood 	= RS >= 85;

RSL = RSLine(C);	// custom function to generate the relative strength line
num = 100;
HV  = HHV(RSL, num);

// Determine whether stock's RS line has crossed into new high territory
RSNewHigh = Cross(RSL, Ref(HV, -1));

// determine how long (up to num) that a stock took to make such an RS line new high
newhighwait = BarsSince(Ref(RSNewHigh,-1));
if (newhighwait[BarCount-1] > num)
	RSNewHigh = 0;

// filter on liquid stocks with high RS and has taken at least 5 periods to make a new RS line high
Filter = Liquidity(C, V) AND RSgood AND RSNewHigh AND newhighwait > 4;

// Rank by the length it took to make an RS line new high
Ranking = newhighwait;

// custom function to add my standard columns to exploration output
ExploreOutput(Ranking);

// replace designated watchlist with the new exploration results
// ISSUE: Stores them alphabetically instead of by rank
ReplaceWatchlist("7_RSNewHighs", Filter);

// Add ranking as a column
AddColumn(newhighwait, "Length");

Thanks
Mike

1 Like

@rocketPower, welcome to the forum.

Maybe I'm missing it, but "ReplaceWatchlist" does not seems to be a standard AFL function.

I see that in your code, you use an include file. Is that function defined there? In such a case could you post the code snippet?

By the way, when I write and execute this code :

CategoryAddSymbol( "SPY", categoryWatchlist, 1 );
CategoryAddSymbol( "QQQ", categoryWatchlist, 1 );
CategoryAddSymbol( "DIA", categoryWatchlist, 1 );

The resultig watchlist (that was empty before runnig the code) is in the correct order:

immagine

Ciao Beppe,

Yes it's been such a long time I wrote my library I'm not even sure what's mine or native to AB...

here's the code:

function ReplaceWatchlist(WLName, Flt)
{
		listnum = CategoryFind(WLName, categoryWatchlist);
		if ( Status( "stocknum" ) == 0 )
	{
		oldlist = CategoryGetSymbols( categoryWatchlist, listnum );
		for ( i = 0; ( sym = StrExtract( oldlist, i ) ) != ""; i++ )
		{
			CategoryRemoveSymbol( sym, categoryWatchlist, listnum );
		}
	}
	
	if ( LastValue( Cum( Flt AND Status( "barinrange" ) ) )  )
		CategoryAddSymbol( "", categoryWatchlist, listnum );
		
	// return nothing
}

I understand the example you give works, but I'm not sure that will work after I rank the list of stocks.

My whole process I thought I was executing in my example is:

  1. Filter on stocks making RS line new highs
  2. Rank them in order how long the line has been consolidating
  3. Create a watchlist of these stocks in ranked order

Thanks!
Mike

1 Like

Mike,
You would need to export the ranked/sorted exploration results first then read from the file and assign symbols to watchlist. I tried importing ascii as a final batch step but for some reason could not make it work. However you can do that in afl so there would not be a problem there.

Note that SetSortColumns function sorts columns AFTER exploration is complete. Your formula is NOT running at that point. Instead your code adds symbols in the order they are executed, i.e. alphabetical. If you wanted to programmatically add symbols in other order than alphabetical you would need to do the sorting/ranking yourself, within the formula. This can be done using http://www.amibroker.com/guide/afl/staticvargenerateranks.html

Alternatively I could add "AddSymbolsToWatchlist" to the batch commands and then you could just run two step batch (exploration and addsymbolstowatchlist)

4 Likes

"Replace watchlist with results" command would be useful too.

2 Likes

Thanks Tomasz, I would use the batch solution since I already use a batch to run all my scripts.

I'll look into the staticvargenerateranks option.

Thanks also to everyone else for their suggestions as well!

Regards,
Mike

@aron, agreed, this would save me a step of deleting the watchlist contents in afl.

Thanks!

You can save this as apx and use as final step in your batch after exporting the exploration results with "export to file" command

function import2watchlist( file, wlnum , rank_column )
{
	//file - full path to exported results form main exploration
	//wlnum -  number of watchlist you need to populate
	//rank_column - rank column location form your main exploration 
	
	global Filter ; 
	id = "importsymbols"; 
	
    if( status( "stocknum" ) == 0 )
    {
		
        list = CategoryGetSymbols( categoryWatchlist, wlnum );

        for( i = 0; ( symbol = StrExtract( list, i ) ) != ""; i++ )
        {
            CategoryRemoveSymbol( symbol, categoryWatchlist, wlnum );
        }

        fh = fopen( file, "r" );

        if( fh )
        {
            while( ! feof( fh ) )
            {
                line = fgets( fh ); // read a line of text
                symbol = StrExtract( line , 0 );
                rank = StrExtract( line , rank_column );
                StaticVarSet( id +  symbol , StrToNum( rank ) );
                CategoryAddSymbol( symbol , categoryWatchlist, 0 );
            }

            fclose( fh );
        }
        else
        {
            Error( "ERROR: file can not be open" );
        }


    }

    Filter = InWatchList( wlnum ) ;
    AddColumn( StaticVarGet( Name() ), "rank" );
    SetSortColumns ( 3 );
    StaticVarRemove ( id + "*") ;

}

filename = "C:\\....\\{filename.ext}"; 
wlnum = ...; 
rank_column = ...; 
import2watchlist( filename, wlnum, rank_column );
5 Likes

@rocketPower As an alternative to @aron's solution, you can also try mine - utilizing StaticVarGenerateRanks(). It ranks the symbols (in this example according to their rate of change values), erases the output watchlist and adds symbols to this watchlist in sorted/ranked order in one pass. It imports name(s) of the watchlists used by Automatic Analysis window (Filter settings) so you just need to provide the name (not number) of the existing output watchlist.

Period = 10;
MinimumPrice = 20;

if( Status( "stocknum" ) == 0 )
{
    StaticVarRemove( "ValuesToSort*" );

    InputWatchlistNum = GetOption( "FilterIncludeWatchlist" ); // Import watchlist(s) from Backtester Filter settings
    InputSymList = CategoryGetSymbols( categoryWatchlist, InputWatchlistNum );

    OutputWatchlistName = "Roc10Top50"; // Name of the existing output watchlist
    OutputWatchlistNum = CategoryFind( OutputWatchlistName, categoryWatchlist );
    OutputSymList = CategoryGetSymbols( categoryWatchlist, OutputWatchlistNum );

	// Erasing the output watchlist
    if( OutputSymList != "" ) for( i = 0; ( symbol = StrExtract( OutputSymList, i ) ) != ""; i++ ) CategoryRemoveSymbol( symbol, categoryWatchlist, OutputWatchlistNum );
	
	// Sorting
    for( i = 0; ( symbol = StrExtract( InputSymList, i ) ) != ""; i++ )
    {
        SetForeign( symbol );

        if( LastValue( C ) > MinimumPrice ) // Example Filter
        {
            ValuesToSort = ROC( C, Period ); // Example values to sort
            RestorePriceArrays();
            StaticVarSet( "ValuesToSort_" + symbol, ValuesToSort );
        }

        else RestorePriceArrays();
    }

    StaticVarGenerateRanks( "top", "ValuesToSort_", 50, 1234 ); // Top 50
    SymList = StaticVarGetRankedSymbols( "top", "ValuesToSort_", LastValue( DateTime() ) );

	// Adding sorted symbols to the output watchlist
    for( i = 0; ( symbol = StrExtract( SymList, i ) ) != ""; i++ ) CategoryAddSymbol( symbol, categoryWatchlist, OutputWatchlistNum );
}

ValuesToSort = ROC( C, Period ); // // Example values to sort
Filter = LastValue( C )  > MinimumPrice; // Example Filter

AddColumn( ValuesToSort, "ROC "+ Period, 1.3 );
SetSortColumns( -3 );

Note that this or similar solution, after slight modification (especially implementing conditional execution - with for example ParamTrigger() ) can be easily used in Indicator/chart window instead of AA.

Regards

12 Likes

@aron, @milosz, much thanks for the handy code, I will try em all out as soon as I get some time this weekend!

I'll let you know how it goes.

Really helpful stuff. Much thanks!
Mike

1 Like

Hi Tomasz,
I am trying to learn how to use Batch for the 2 Operations (1) Explore and (2) Replace Watchlist with the Results but I don't find "Replace Watchlist with the Results" as a Basic operation listed in Batch. So for doing that I request more inputs from you please.Thanks.
Manmohan

Hi Tomasz,
Also If I want to run Auto-Repeat Explore every 1 min , then Scheduler does not have facility to autorun batch to Replace watchlist with the Results every 1 min ?
Thanks

You can add/modify/clear watch lists programmatically using
CategoryAddSymbol(), CategoryRemoveSymbol(), CategoryGetSymbols()
directly from the formula.

Scroll UP in this thread and you will see @aron code doing just that

2 Likes

Thank you very much. I will try formula . Wonder if batch would make it easy

Hi,
With reference to your suggested solution for "Automatically replace watchlist in exploration in ranked order" I have still difficulty to use the Batch function because when I want to start New Batch >> Insert >> Edit Batch Step select Action, Then there is no predefined action "Replace Watchlist with Results" so I am stuck up. Will you please elaborate how do I proceed. Thanks a lot. Manmohan

ERROR

This post has been very helpful. I have been trying to automate my gainers and losers via code by @Milosz , However, I was still not getting results in the ranked order in the watchlist. After a week of struggle, I figured that "Show Watchlist in Original watchlist order" needed to be checked for this to work. Posting this if someone in future has this problem. Cheers!

4 Likes