How to test system „always in market“ on several thousands of stock

Hello,

I would like to get backtested results of individual stocks of a system that is always in the market applied on several thousands of stocks (like Russell 2000).

I was trying to use custom backtester and Add Custom Metrics to receive basics performance metrics of individual stocks. But I run into the limit of 1000 of simultaneously opened positions I understand Amibroker has.

What is my goal: bactest stock in the index and sort them into individual watchlists based on their performance (my intention was to do that using CategoryAddSymbol inside custom backtester).

What is the way to achieve my task and not be limited by number of opened positions?

The simple system I am trying to test on all of Russell 2000 stocks:

SetOption("InitialEquity", 1000000 );
SetOption("MaxOpenPositions", 1000 );
SetPositionSize(1000,spsValue);
SetOption( "AllowPositionShrinking", True );
BuyPrice=Close;
SellPrice=Close;
ShortPrice=Close;
CoverPrice=Close;

F_SAR = SAR(0.02,0.2); 

Buy = Cross(C,F_SAR); 
Short = Cross(F_SAR,C); 
Sell=Short;
Cover=Buy;

Buy=ExRem(Buy,Sell);
Sell=ExRem(Sell,Buy);
Short=ExRem(Short,Cover);
Cover=ExRem(Cover,Short);

Thank you for any tip.

I have never run into an AB limit of 1000 open positions, but the options you have set in your code will definitely impose that kind of limit. You set your max open positions to 1000, and also have position size of 1000 with initial equity of 1M, effectively limiting you to around 1000 open positions.

Another option would be to simply test each symbol individually so that you wouldn't need to calculate all the summary metrics yourself.

Thank you for the replay.

What would be the way to test each symbol individually? Is there some automatic way that would run the backtest on all the symbols in watchlist and saved for example cvs with the results?

The limit 1000 max. positions is used in manual Backtestsetting tab. So I am not sure if using SetOption("MaxOpenPositions", 1000 ); I can work with bigger number.

I would however prefer to test each symbol individually. But did not find the right way yet.

Try Ranking your stocks by the performance metrics. Your goal was to sort them which is easily done after ranking.

1 Like

@portfoliobuilder my goal is to sort stocks by peformance metrics from the trading strategy (like total PnL over backested period etc).

Is this possible with ranking? If so, do you have any example? I am aware of this page https://www.amibroker.com/guide/h_ranking.html however I am not sure if I can rank stocks also with results of my own strategy (which I published earlier as example).

Peter

The limit is only in User Interface (to protect from beginners entering absurd numbers by "mistake").

There is NO limit (other than available memory) when you set MaxOpenPositions from the code.

Although AmiBroker is super efficient and hand optimized in terms of memory usage, keep in mind that you need large amounts of RAM to backtest say 10K stocks (approx 40 (per signal) * max open positions * number of bars bytes), If you have 10K stocks and you have only 10 years of EOD (2600 bars per symbol) you would need to have 40 * 10000 * 2600 = 1GB (gigabyte) of RAM to just generate and temporarily keep signals alone.

1 Like

@peterfin it looks like Tomasz has answered your initial question.

But with regards to ranking and sorting, I am on my phone so can not try out any code, but yes I think it is possible for you to run an Explore to accumulate the performance metrics. Your system rules are fairly straightforward and perhaps something like this would work,

inLong = Cross(C,F_SAR);
inShort = Cross(F_SAR,C);

And then you sum up the bar by bar cumulative changes while inLong and while inShort are true. StaticVarGenerateRanks might be of use for generating the ranking and doing the sorting.

With regards to @mradtke suggestion about individual symbol tests, these articles may be of use

http://www.amibroker.com/kb/2014/12/05/how-to-backtest-symbols-individually/

http://www.amibroker.com/kb/2014/10/13/per-symbol-profitloss-in-a-portfolio-backtest/

Good luck!

2 Likes

@peterfin, the first link from @portfoliobuilder shows you one way to do a symbol-by-symbol analysis. Another way is to use an optimization, similar to this untested snippet:

numSymbols = 2000;      // Set this to the number of symbols in your watchlist
currStockNum = Optimize("Stock #", 0, numSymbols-1, 1);
...
Buy = currStockNum == Status("stocknum") AND
           <your Buy logic here>

Sell= currStockNum == Status("stocknum") AND
           <your Sell logic here>

The nice thing about this approach is that you will end up with a single optimization report where each line contains all the performance metrics for a single symbol. Note that you'll probably want to add a custom report metric with the ticker symbol, since your optimization variable will just show the stock number.

Thank you for the tips.

I am exploring all the ways.

I am currently testing the optimization aproach, but I am not sure how to add the symbol using custom report metric. I have tried:

if( Status("action") == actionPortfolio ) 
{ 
    bo = GetBacktesterObject(); 
    bo.Backtest(); // run default backtest procedure  
    trade = bo.GetFirstTrade();
    Symbol = trade.Symbol;
    bo.AddCustomMetric( "Symbol", Symbol ); 
}

It works sometimes, but on larger tests I get error:

    trade = bo.GetFirstTrade();

    Symbol = trade.Symbol;
-------------------------^

Error 18.
COM object variable is not initialized or has invalid type (valid COM object handle required)

What is proper way to get Symbol into custom metric?

Thank you,
Peter

That call is probably failing when you have no closed trades.

Wow about just doing something like this in your Phase 1 AFL:

if (currStockNum == Status("stocknum"))
{
     StaticVarSetText("currSym", Name());
}

and then in your CBT just retrieve that static variable.

1 Like