Apply buing conditions only for selected symbols from WL

Hello,

in my AFL strategy I have trading conditions to buy stocks. This strategy I apply on the watchlist that consists of 100 stocks. I would like add another condition that the buy conditions will be applied only for TOP 10 (measured by ROC(20) indicator) stocks from watchlist.

How can I do it?

Thank you

In AB it is called "Ranking"

There are 3 broad ways defined here https://www.amibroker.com/guide/h_ranking.html
There is one to Rank by ROC.

Some examples are given here as well:
https://www.amibroker.com/guide/h_portfolio.html

1 Like

Thank you for your response.

I know the function PositionScore and i use it in my swing EOD strategies but it cannot be used for this purpose as usual. I´ll try to explain my problem.

I have buying condition1 = RSI(5) < 30. This condition meets eg. 50 stocks. And I want to buy only stocks, that is by ROC(20) in TOP10. The order is executed by LMT order, so buyprice is under Close and the next day does not have to be filled respectively filled can be orders in stocks which is not in TOP10.

So simply condition2 could be PositionScore, but i don´t know how to incorporate to the strategy.

Thanks and have I nice day.

You may use StaticVarGenerateRanks() (also see examples there) and then incorporate called rank variable into your Buy rule.

e.g.

/// INCOMPLETE CODE SNIPPET
/// See manual for staticvargenerateranks
/// @link https://www.amibroker.com/guide/afl/staticvargenerateranks.html

/// e.g. 4 open positions of tickers with rank <= 10
SetOption("MaxOpenPositions", 4);

rank = StaticVarGet("RankValuesToSort" + Name());

condition1 = RSI(5) < 30;
Buy = condition1 and rank < 11;

///

Besides of AB manual there are StaticVarGenerateRanks examples in forum also.
(1. Rank via Scan, 2. then run backtest by calling ranks)


Or if you want to enter the top N then you may just use PositionScore.

/// e.g. 4 open positions being top N ranked (top 4)
SetOption("MaxOpenPositions", 4);

PositionScore = 10000 + Roc(C, 20);

condition1 = RSI(5) < 30;
Buy = condition1;
1 Like

Hello, thanks a lot for your help.

I've gotten here so far:

List = CategoryGetSymbols( categoryWatchlist, 0 );
SetOption("MaxOpenPositions", 3);

if ( Status("stocknum") == 0 ) // Generate ranking when we are on the very first symbol
{
     StaticVarRemove( "values*" );

     for ( n = 0; ( Symbol = StrExtract( List, n ) )  != "";  n++    )
     {
         SetForeign ( symbol );

         // value used for scoring
         values = 100 - RSI();
         RestorePriceArrays();
         StaticVarSet (  "values"  +  symbol, values );
         _TRACE( symbol );
     }

     StaticVarGenerateRanks( "rank", "values", 0, 1224 );
}

symbol = Name();
values = StaticVarGet ( "values" +  symbol );
rank = StaticVarGet ( "rankvalues" +  symbol );

PositionScore = values;

BuySignal = Cross( Close, MA(Close, 100 ) );

// buy on the next bar
Buy = Ref( BuySignal, -1);
BuyLimitPrice = Ref( Close, -1) * 0.999;

// now we check if limit was hit for the symbols ranked as top 3
Buy = Buy AND L < BuyLimitPrice AND rank <= 3;
BuyPrice = Min( Open, BuyLimitPrice );

// sample exit rules
Sell = 1;

It looks promising but now I have problem with the function: "List = CategoryGetSymbols( categoryWatchlist, 0 );"... in this case the backtest is applied only for the this specific watchlist.

Is possible not to specify the watchlist?

watchlistNumber = GetOption("FilterIncludeWatchlist");
watchlist = CategoryGetSymbols(categoryWatchlist, watchlistNumber);

Trendsurfer,

I have a strategy that trades QQQ and SPY. I these symbols in a watchlist I named "QQQ_SPY" and when I fuse the "apply to" ,"filter" and select the watchlist all is well.
I would like to run the strategy on other lists of names but if possible would prefer not to physically create and name 10 different watchlists and then each time I want to run it another set of symbols manually change the "apply to" settings. Ideally I could name the symbols as Parameters or name the watchlist as a parameter so I could change in the Parameter settings.
I can't understand how to use your suggestion above to point specifically to my watchlist "QQQ_SPY" or how to call the specific symbols "QQQ" and "SPY" if that is more straightforward.

I can always continue to manually create the Watchlists and then apply to, filter, etc. but thought your "watchlistNumber", "watchlist" suggestion seemed very close and flexible.

Thank you,

Mike

I'm not 100% sure what you're trying to accomplish, but perhaps you could do something like this:

sym1 = ParamStr("1st Symbol", "QQQ");
sym2 = ParamStr("2nd Symbol", "SPY");

if (Name() == sym1)
{
    // Your entry and exit logic for sym 1 here
}
else if (Name() == sym2)
{
    // Your entry and exit logic for sym2 here
}

Also, if you want to get someone's attention, you should "at" them, like this: @reds. Most forum members don't read every single post, so if you just use their name without an "at" symbol, then they may not see it.

@mradtke
Hi Matt,

Thank you. I will clean up the code and post. What I am trying to do is have the ability to run the script on a Watchlist that contains a 100 ETFs but only execute trades for the QQQ and SPY, skipping all other symbols in the Watchlist.

Thank you,

Mike

@mradtke
@TrendSurfer

Hi Matt & Michael,

Below is the code. As posted, if I run it on a large Watchlist of 100 ETFs, it will only take trades on QQQ. If I uncomment the two lines I have commented out and then comment out the logic below, and run on a Watchlist only containing SPY & QQQ, the code will take and size all trades correctly.

What I would like it to do is have the ability to run on a Watchlist of 100 ETFs, and only take trades for QQQ & SPY. This will allow me not to have to create specific, small Watchlists that are subsets of a larger Watchlist. Tomasz and Michael helped me with some array errors I had in a previous script and I think this is a legacy issue but I cannot get to the root of it.

Thanks,

Mike

Max_SPY_Exposure = Param("Max SPY Exposure", 70, 0, 100);
Min_SPY_Exposure = Param("Min SPY Exposure", 30, 0, 100);

Safe_Asset_Trigger = ParamStr("Safe Asset Symbol", "SPY");
Risky_Asset_Trigger = ParamStr("Risky Asset Symbol", "QQQ");

Symbol_Name_1 = ParamStr("Investment - Symbol Name 1", "SPY");
Symbol_Name_2 = ParamStr("Investment - Symbol Name 2", "QQQ");

SPY_Close = Foreign(Safe_Asset_Trigger, "C");
QQQ_Close = Foreign(Risky_Asset_Trigger, "C");

ShortTerm=ROC(SPY_Close,20);
LongTerm= ROC(QQQ_Close,20);

Buy1=ShortTerm  >= Longterm;
Buy2=ShortTerm  <= Longterm;

Sell1=ShortTerm < Longterm;
Sell2=ShortTerm > Longterm;

BuyPrice=SellPrice=C;
SPY_Max=Max_SPY_Exposure;
SPY_Min=Min_SPY_Exposure;
QQQ_Max=100-SPY_Min;
QQQ_Min=100-SPY_Max;

n = Name();
//if (n== Symbol_Name_1)   SetPositionSize( IIF( Buy1, SPY_Min, SPY_Max ),spsPercentOfEquity);
//if (n== Symbol_Name_2)   SetPositionSize( IIF( Buy1, QQQ_Max, QQQ_Min ),spsPercentOfEquity);
if (n== Symbol_Name_1 OR n== Symbol_Name_2 ) 
{
   if (n== Symbol_Name_1)  SetPositionSize( IIF( Buy1, SPY_Min, SPY_Max ),spsPercentOfEquity);
   if (n== Symbol_Name_2)  SetPositionSize( IIF( Buy1, QQQ_Max, QQQ_Min ),spsPercentOfEquity);
 
    Buy= IIf(Buy1, Buy1, Buy2);
    Sell=IIf(Ref(Buy1,-1), Sell1,Sell2);
}

ApplyStop( stopTypeNBar, stopModeBars, 1);

http://www.amibroker.com/kb/2015/09/28/symbol-selection-when-positionscore-is-not-defined/

If PositionScore is not defined or it has the same value for two or more symbols, then AmiBroker will use the following rules:

  1. transaction with greater PositionSize is preferred – the comparison method depends on the position sizing approach used in our code:
  • If we use SetPositionSize( dollarvalue, spsValue) – then $ value is compared.
  • If we use SetPositionSize( shares, spsShares) – then number of shares is used for comparison.
  • If we use SetPositionSize( perc, spsPercentOfEquity) – then % equity matters.
  1. alphabetical order
  2. long trades rather than short trades, if both occur at the same time for the same symbol.
SetOption("MaxOpenPositions", 2);
SetOption("AllowPositionShrinking", 1);

Max_SPY_Exposure = Param("Max SPY Exposure", 70, 0, 100);
Min_SPY_Exposure = Param("Min SPY Exposure", 30, 0, 100);

Safe_Asset_Trigger = ParamStr("Safe Asset Symbol", "SPY");
Risky_Asset_Trigger = ParamStr("Risky Asset Symbol", "QQQ");

Symbol_Name_1 = ParamStr("Investment - Symbol Name 1", "SPY");
Symbol_Name_2 = ParamStr("Investment - Symbol Name 2", "QQQ");

SPY_Close = Foreign(Safe_Asset_Trigger, "C");
QQQ_Close = Foreign(Risky_Asset_Trigger, "C");

ShortTerm=ROC(SPY_Close,20);
LongTerm= ROC(QQQ_Close,20);

Buy1=ShortTerm  >= Longterm;
Buy2=ShortTerm  <= Longterm;

Sell1=ShortTerm < Longterm;
Sell2=ShortTerm > Longterm;

BuyPrice=SellPrice=C;
SPY_Max=Max_SPY_Exposure;
SPY_Min=Min_SPY_Exposure;
QQQ_Max=100-SPY_Min;
QQQ_Min=100-SPY_Max;

n = Name();
//if (n== Symbol_Name_1)   SetPositionSize( IIF( Buy1, SPY_Min, SPY_Max ),spsPercentOfEquity);
//if (n== Symbol_Name_2)   SetPositionSize( IIF( Buy1, QQQ_Max, QQQ_Min ),spsPercentOfEquity);
if (n== Symbol_Name_1 OR n== Symbol_Name_2 ) 
{
   if (n== Symbol_Name_1)  SetPositionSize( IIF( Buy1, SPY_Min, SPY_Max ),spsPercentOfEquity);
   if (n== Symbol_Name_2)  SetPositionSize( IIF( Buy1, QQQ_Max, QQQ_Min ),spsPercentOfEquity);
 
    Buy= IIf(Buy1, Buy1, Buy2);
    Sell=IIf(Ref(Buy1,-1), Sell1,Sell2);
}

ApplyStop( stopTypeNBar, stopModeBars, 1);

14

I ran your code as posted against a watchlist containing 655 symbols including QQQ and SPY. My trade list has trades for both those symbols.

Try running a Scan to see if you're generating signals, and then if so, run with the Detailed Log turned on so you can see the details of which trades AB is taking and which it is skipping.

@fxshrat @mradtke

Hi Matt & fxshrat,

All is good and all trades being taken. I had pointed to my "All" symbols and it contains 10'of of thousands of S&P and VIX options so the code ran on QQQ first, and then started to cycle through all the S&P options. I just ran on a small list of a hundred ETFs and it ran on QQQ & SPY.

Thanks for all your help!

Mike

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