Step 3 of 7

Portfolio Build

Combines the winning slot from each feature set into one book, re-simulates everything at the full budget, and — the part that actually matters — lets you see whether the nine slots are nine edges or one edge wearing nine names.

What this stage does

build_allstar.py --engine lr --symbol XAUUSD --tf M5 --all9 --cores 14
Read every per-set result
Each <set>/summary.json and configs.json. A set with no output is skipped with a message — not an error, but it means the book will be smaller than you asked for.
Select one slot per set
The best-scoring slot from each set. Which sets participate depends on the mode — see below.
Re-simulate at full budget
Every selected slot is re-run at max_iter = 2000, so the portfolio's numbers describe the same models the EA will contain — not the 600-iteration versions the search ranked.
Sum the equity curves on a shared bar grid
The step with the actual subtlety in it — see the alignment section below.
Write the portfolio folder
Combined summary, per-slot configs, the combined equity curve, and each slot's own curve.

Modes

FlagFolderWhat it selects
--all9 all9 The canonical nine: base9, momentum, volatility, price_action, trend, full15, then micro, voltrend, meanrev. One slot each.
--all6 all6 The first six of those only — the "original" sets, before the three experimental additions.
(no flag) allstar The effective default. Ranks all slots from a preferred set list and takes the top 5, with at most one slot per set.
--topN topN The N best-scoring sets found on disk, one slot each.
--sets a b c custom An explicit set list. Overrides the mode flags.
--exclude x y best5 Drops the named sets and takes the rest.

Resolution order is first-match-wins: --topN--sets--exclude--all9--all6 → otherwise allstar.

The default mode is not all6 Running build_allstar.py with no mode flag produces an allstar build — five slots, one per preferred set. The GUI always passes an explicit flag, so this only bites when driving the script by hand.

How allstar differs from all9

all9 is a fixed roster: whatever each of those nine sets produced, take its best slot. allstar instead pools all slots from a preferred list of sets, ranks them by score, and takes the top 5 — but never two from the same set.

The one-per-set rule is a proxy, not a correlation test allstar's filter is implemented as "at most one slot per feature set", which is a reasonable stand-in for diversification but is not the same thing as the equity-correlation test the search applies within a set. Two slots from different sets can still be highly correlated, and the one-per-set rule will not catch it. This is exactly why the portfolio page shows per-slot curves.

Equity alignment — the part with the actual subtlety

Different slots can have different warmups, because training_bars is itself a searched parameter. A slot with training_bars = 1500 produces its first trade far later than one with training_bars = 500. Their equity curves therefore start at different bar indices.

Naively summing them would misalign every subsequent bar and produce a combined curve that is not any portfolio at all. So each slot's curve is offset by its own warmup before being added:

warmup = training_bars + 1
offset = warmup - 1                          # the bar its curve actually starts on

combined = zeros(max_offset + longest_curve)
for each slot:
    combined[offset : offset + len(curve)] += (curve - initial_balance)

Note what is being summed: the curve minus the initial balance, so each slot contributes only its own P&L rather than re-adding a $10,000 notional nine times.

The combined drawdown is then recomputed from the summed curve against its own running peak. Per-slot drawdowns and net profits are likewise recomputed from the raw equity arrays rather than trusted from summary.json — so the portfolio's numbers are internally consistent rather than a mixture of two computations.

Why this matters for reading the result The combined net profit is not the sum of the per-slot net profits you saw on the Optimize page. Each slot here is re-simulated at the full 2,000 iterations, and the curves are aligned differently. If you compare the two tables and find small discrepancies, that is the reason — and the portfolio's numbers are the correct ones.

Outputs

Under strategies_lr_m5/<folder>/, where folder is all9, all6, allstar, best5, custom or topN:

FileContents
summary.json The same shape as a per-set summary, plus a combined block with np and max_dd.
configs.json One parameter dict per slot with its magic number — the generator's input.
equity_combined.csv The combined portfolio curve.
equity_<magic>.csv Each slot's own curve, for the per-slot charts.

Progress output

mode=all9  slots selected: base9(magic 401), momentum(magic 411), volatility(magic 421), ...
re-simulating 9 slots @ max_iter=2000 ...
  magic= 401 base9          PF=1.062 NP=+9  T=142 (B70/S72) WR=... DD=-0.12% | sl=2.0 rr=1.5 la=3 tb=1000 ri=500 lr=0.01 th=0.55
  magic= 411 momentum       PF=1.048 NP=+7  T=131 (B64/S67) WR=... DD=-0.19% | ...
  ...

COMBINED (all9): NP=+57  MaxDD=-0.41%  final_balance=10057
wrote strategies_lr_m5/all9/  (summary.json configs.json equity_*.csv)

What to actually look at

The headline net profit is the least interesting number here It is in-sample, and it is the sum of nine separately-optimised components — which is the strongest possible case for it being optimistic. The question this stage answers is composition: are these nine genuinely different ways of earning, or nine correlated bets on the same behaviour?

Three things worth checking, in order:

Are the nine slots genuinely different?
Look at the per-slot equity curves, not just the table. If all nine rise and fall together, the book is one position with nine times the size — and it will draw down exactly as one position would, which defeats the entire purpose of holding nine.
Does any single slot dominate?
The page shows each slot's share of total net. A slot contributing most of the profit is a concentration risk: if that one behaviour stops working — regime change, a session that becomes efficient — the book loses its main earner, not one-ninth of it.
Is the drawdown a property of the book or of one slot?
Compare the combined maximum drawdown with each slot's own. If the combined drawdown is barely better than the worst single slot's, then diversification is not doing anything — the slots are losing at the same time, which is exactly what high correlation looks like in a drawdown.

The Portfolio page

Build controls
ALL9 or ALL6, the core count, and the exact command preview before it runs.
Headline KPIs
Net profit, max drawdown, trades, profit factor, win rate, slot count, net per day, and return-over-drawdown.
Combined equity and drawdown
The summed curve with its drawdown envelope underneath.
Slot table
Each slot's metrics, its share of total net, and its contribution to the worst drawdown.
Per-slot equity curves
Small multiples — the view that makes a single-slot blowup or a fully-correlated book visible rather than averaged away.
Rebuild from scratch
Re-runs the search then the build, for when the data file changed.

Checkpoint

Before moving to Step 4
  • The slot count matches what you asked for. Nine for ALL9 — unless a set produced nothing, in which case note which one.
  • No single slot contributes a majority of the net profit.
  • The per-slot curves are visibly different in shape, not scaled copies of one curve.
  • The combined drawdown is meaningfully better than the worst individual slot's drawdown.
  • Profit factor is above 1.0 for the book as a whole.
SymptomCauseFix
No per-set outputs under <root>; run feature_search.py first Step 2 was never run, or ran into a different output root. Run the search for this symbol and timeframe.
skip <set>: missing summary/configs That set produced no result — often because the search failed or was interrupted. Re-run that one set, then rebuild. The portfolio will be short one slot until you do.
Portfolio net is much lower than the sum of per-set nets Expected. Slots are re-simulated at full budget and aligned by warmup, so the arithmetic differs from a naive sum. Nothing to fix — read the portfolio's numbers as authoritative.
Combined drawdown ≈ worst slot drawdown The slots are highly correlated: they lose at the same time. Try a different mode, or accept that diversification is not helping on this data.