Single-Symbol Thinking versus Portfolio Reality
There is a specific and very common experience: a system tests beautifully symbol by symbol, and then the portfolio backtest of the identical rules produces something much less interesting. The temptation is to assume something is broken.
Nothing is broken. The two tests answer different questions, and the second one is the question you actually care about.
What an individual backtest is really simulating
Section titled “What an individual backtest is really simulating”AmiBroker’s Analysis window offers an Individual backtest alongside the ordinary portfolio backtest. It runs each symbol in its own account.
Read that again, because the consequence is larger than it sounds: the initial equity figure is applied per symbol. Run an individual backtest over 200 symbols with £100,000 of initial equity and you have simulated an account with £20,000,000 in it — one that never has to choose between two signals, never runs out of cash, and never holds two correlated positions in the same account, because there is no single account.
That is a legitimate thing to compute. It is a good way to ask “do these rules behave sensibly on this instrument?” It is not a simulation of trading.
The four things that change
Section titled “The four things that change”1. The capital constraint
Section titled “1. The capital constraint”At portfolio level there is one cash balance. Signals beyond your slots or your cash are refused,
and the refusal is not random — it is decided by PositionScore, which means the trades you
actually get are a selected subset, not a sample.
The selection is often systematically different from the whole. Rank by liquidity and you get the biggest names. Rank by lowest RSI and you get the most beaten-down candidates. Whatever your score prefers, that preference is now baked into every performance figure you read.
2. Signal collisions
Section titled “2. Signal collisions”Systems built on market-wide conditions fire on many symbols at once, because the condition is market-wide. A breakout system generates a cluster of breakouts on the day the market surges.
So the bar where your rules produce twenty candidates is exactly the bar where you can take five. And the bars where you have plenty of free slots are the quiet bars where the rules produce two candidates you are not excited about. The constraint binds hardest precisely when the opportunity set is largest.
3. Correlation between positions
Section titled “3. Correlation between positions”Ten positions is ten positions. Ten positions in the same sector, on the same signal, on the same day, is closer to one position ten times the size.
An individual backtest cannot see this at all, because each symbol has its own account and its own drawdown. At portfolio level the drawdowns add up on the days they coincide — and they coincide much more often than an average correlation figure suggests, because correlations rise in exactly the conditions that produce large moves.
The practical symptom: the portfolio’s maximum drawdown is far larger than the average of the individual symbols’ drawdowns, and the equity curve has fewer, deeper valleys rather than many shallow independent ones. Part 34’s concentration lesson is where this is measured.
4. Exposure
Section titled “4. Exposure”This is the one that most often produces a wrong conclusion, and it is purely arithmetic.
Exposure % in the backtest report is the fraction of the period during which capital was actually at work. An individual backtest of a selective system typically shows low exposure per symbol, and the portfolio run shows something quite different depending on whether signals were spread out or clustered.
Two systems with different exposure cannot be compared on return alone. A system that is in the market 30% of the time and returns 8% a year is doing something quite different from one that is in the market 90% of the time and returns 10%. The report’s Risk Adjusted Return % exists precisely to normalise for this — it is the annual return divided by exposure — and it is the figure to compare when exposures differ.
The comparison, run properly
Section titled “The comparison, run properly”Complete runnable AFL
// same-rules-two-ways.afl// Part 28 - Single-Symbol Thinking versus Portfolio Reality//// One rule set, two ways of paying for it. Nothing about the signals changes// between the two runs; everything about the money does.//// HOW TO RUN IT// Run A - unconstrained. Set TestStyle = 1. In the Analysis window use the// Backtest button's INDIVIDUAL backtest. Each symbol is simulated in// its own account, with its own copy of the initial equity, and no// symbol ever competes with another for cash or for a slot.// Run B - portfolio. Set TestStyle = 2. Use the ordinary (portfolio)// Backtest. One account, one cash balance, PosQty slots, and a rank// deciding who gets them.// Run C - the signal count. Run the formula as a SCAN over the same universe// and the same range. That gives the number of entry signals the// rules produced, independent of whether any of them was affordable.//// Then compare three numbers across the three runs: signals generated, trades// taken, and Exposure %. The gap between run A and run B is not an error in// either one. It is the cost of having a finite account.//// ASSUMPTIONS// Fill price Next bar's open, no slippage or spread modelled here.// Delays One bar on every signal.// Costs Whatever is in Settings. Keep them IDENTICAL across runs, or// the comparison measures your settings instead of the effect.// Equity In an Individual backtest the initial equity figure is applied// PER SYMBOL. Ten symbols therefore start with ten times the// capital of the portfolio run, which is exactly the unrealistic// thing this comparison exists to expose.
TestStyle = 2; // 1 = unconstrained single-symbol, 2 = portfolioPosQty = 10; // portfolio slots, used by TestStyle 2 only
// ---------------------------------------------------------- 1. the accountSetOption( "InitialEquity", 100000 );SetOption( "AllowPositionShrinking", True );SetOption( "MinPosValue", 1000 );RoundLotSize = 1;
if( TestStyle == 1 ){ // Every symbol gets the whole of its own account. There is no competition // to model, so there is nothing for a rank to do. SetOption( "MaxOpenPositions", 1 ); SetPositionSize( 100, spsPercentOfEquity );}else{ // One account, PosQty equal slots. Signals beyond the free slots are // refused, and the refusal is decided by PositionScore. SetOption( "MaxOpenPositions", PosQty ); SetPositionSize( 100 / PosQty, spsPercentOfEquity );}
SetTradeDelays( 1, 1, 1, 1 );
BuyPrice = Open;SellPrice = Open;ShortPrice = Open;CoverPrice = Open;
// ------------------------------------------------------------ 2. the rules// Identical in both runs. If you change anything here, change it once.MinTurnover = 2000000;
Tradeable = MA( Close * Volume, 50 ) >= MinTurnover AND Close >= 2;Regime = Close > MA( Close, 200 );
Setup = Regime AND Tradeable;Trigger = Cross( Close, Ref( HHV( High, 50 ), -1 ) );
Buy = Setup AND Trigger;Sell = Cross( Ref( LLV( Low, 25 ), -1 ), Close );
// ------------------------------------------------------------- 3. the rank// Ignored entirely in run A, because nothing is ever refused there. That is the// point: a single-symbol test cannot tell you whether your selection rule is// any good, because it never has to select.PositionScore = MA( Close * Volume, 50 );
// -------------------------------------------------------- 4. what to record// For each run write down: number of trades, Exposure %, Annual Return %,// Risk Adjusted Return %, Max. system % drawdown, and Avg. Bars Held. Compare// Annual Return % only after you have compared Exposure %, because a system// that is in the market half as often is not comparable on return alone.One rule set. Nothing about the signals changes between the runs; everything about the money does.
The three runs
Section titled “The three runs”Run A — unconstrained. TestStyle = 1. Use the Individual backtest. One position at a
time per symbol, 100% of that symbol’s own account, no competition, no rank.
Run B — portfolio. TestStyle = 2. The ordinary portfolio backtest. One account, PosQty
slots, PositionScore deciding who gets them.
Run C — the signal count. Run the same formula as a Scan over the same universe and range. That gives you the number of entry signals the rules produced, independent of whether any of them was affordable.
Keep costs, delays and the date range identical across all three, or the comparison measures your settings rather than the effect.
What to record
Section titled “What to record”| Run A (individual) | Run B (portfolio) | Run C (scan) | |
|---|---|---|---|
| Entry signals generated | |||
| Trades taken | — | ||
| Exposure % | — | ||
| Annual Return % | — | ||
| Risk Adjusted Return % | — | ||
| Max. system % drawdown | — | ||
| Avg. Bars Held | — |
Reading the gap honestly
Section titled “Reading the gap honestly”The difference between Run A and Run B is not an error in either. It is the cost of having a finite account, and it decomposes into things you can name:
- Signals you could not afford. Compare trades taken in A and B. This is the raw size of the constraint.
- Whether your score picked well. Is Run B’s average profit per trade better than Run A’s? If yes, the selection rule earned something. If no, your score is picking the worse candidates and is worth replacing.
- The skipped-signal cascade. In
backtestRegular, a signal skipped for affordability silences that symbol until an exit. Some of the gap is this mechanism rather than the constraint itself — re-run inbacktestRegularRawto separate the two. - Correlation. Compare drawdowns. If Run B’s drawdown is much worse than Run A’s typical symbol drawdown, your positions are not independent.
Only the first is inevitable. The other three are design feedback.
When a single-symbol test is the right tool
Section titled “When a single-symbol test is the right tool”Individual backtests are not a beginner’s mistake to be outgrown. They are the right tool for a specific job:
- Debugging. One symbol, one trade list, checked by hand against the chart. This is how you confirm your delays, fills and stops do what you think.
- Asking whether rules behave sensibly on an instrument before committing to a universe test.
- Testing something that genuinely trades one instrument — a single futures contract, one index ETF. Here the individual backtest is not an approximation; it is the correct model.
What they cannot do is produce a performance figure you should ever quote for a multi-symbol system.
An individual backtest gives every symbol its own copy of your capital, so it never chooses, never
runs out of cash and never holds correlated positions in one account. A portfolio backtest adds
the constraint, and with it a selected — not sampled — subset of your signals, chosen by
PositionScore; collisions that bind hardest on exactly the bars with most opportunity;
correlated drawdowns that add up; and an exposure figure that must be read before any return
figure. Run both, plus a scan for the raw signal count, with everything else identical, and the
gap between them decomposes into a constraint you cannot avoid and three pieces of design feedback
you can act on.
Check your understanding
Sources for this lesson
4 verified · checked 2026-08-31
- 01AmiBroker User's Guide — Portfolio-level backtestingamibroker.com/guide/h_portfolio.html2026-08-31
- 02AmiBroker User's Guide — Back-testing your trading ideasamibroker.com/guide/h_backtest.html2026-08-31
- 03AmiBroker User's Guide — Backtest reportamibroker.com/guide/w_report.html2026-08-31
- 04AFL Function Reference — SetOptionamibroker.com/guide/afl/setoption.html2026-08-31
Every technical claim on this page was checked against the official AmiBroker documentation on the date shown. Where the course disagrees with folklore, the source is how you can tell which one to trust.