Troubleshooting Amibroker Performance

Here’s a question I received from Mugu M. about his local Amibroker performance and how long it takes him to run a backtest (shared with permission).


Mugu M.

I noticed in the email you sent to the group as a follow-up to your new computer acquisition that you can run a backtest across the entire market (1-minute bars) in 35 minutes in Amibroker.

This got me thinking, I could be missing a few setup tricks.

Here is a backtest I ran on S&P 500 constituents:

Completed in 23685.04 seconds. Number of rows: 134228
(Timings: data: 60.74, setup: 0.00, afl: 173816.18, job: 11.41, lock: 0.02, pbt: 530.50, UI thread: 591.24, worker threads: 173827.59/173827.56)

Does anything stand out? This backtest took 6.5 hours on 10-minute bars 2015 – 2019: 5 years. I have an Amibroker database in 1-minute granularity from 2009/2010 to date.

I can think of the extra compute from the for loops vs the Amibroker native way of handling array operations, but this gives us the benefit of predictive columns extraction from the backtest.


Dave:

There is some background I should review here for readers. Mugu was an early adopter of the forthcoming Amibroker course, which comes with a sample strategy showing you the right way to code a strategy in Amibroker.

Given how poor ChatGPT is at creating Amibroker code (it’s shockingly bad, but it thinks it’s great at it!), this sample strategy is a big head start for traders using Amibroker.

The sample strategy contains two sections that are very important to creating a profitable strategy in Amibroker.

One is a for loop that iterates through all the bars in your database.

Why is a for loop required? It’s required to add custom columns to your backtest.

Why are custom columns required? Because otherwise you’re going to be forever stuck in “backtest world” without figuring out how to make your strategy profitable and actually trade it live.

The other section turns on Amibroker’s “custom backtester” interface. This interface allows you to add custom columns to the resulting backtest.

Here’s what I suggest Mugu do to determine where the slowdown is.

Run a backtest with just this AFL code:

Buy = 0;
Sell = 0;
Short = 0;
Cover = 0;

This is the simplest backtest possible – no for loops – in fact, it won’t even take any trades, but it will iterate through all the bars in the database with minimal processing.

Measure how long it takes for this to complete.

The next step is to run another backtest with the same code, but with a simple for loop added:

Buy = 0;
Sell = 0;
Short = 0;
Cover = 0;

// adding a for loop that does nothing
for ( i = 0; i < BarCount; i++)
{
}

Measure this and compare.

There are a lot of technical details here, but they’re important. If you can get your backtest down to a smaller amount of time, your entire workflow is going to be faster, which will eventually translate into more profits.

I ultimately believe that Mugu’s performance issues are related to the number of trades in his backtest.

More on that tomorrow.

-Dave