Articles ·
How a Metrand basket backtest adds markets into one account
A basket trades one strategy on several markets at once, from one account. Each market is replayed as an ordinary backtest of the same window, on the same account size and costs, and kept in the ledger with the basket's id. The basket then adds them into one account.
The account, bar by bar
For every bar it replays, the engine gives the account's lowest, highest and closing equity inside that bar, over both ways the bar could have run, and the notional it held. The basket's account at any moment is the starting capital plus what every market had made by then:
account = start + Σ (market equity − start)
A market not listed yet, or finished, holds its last equity. When several markets mark the same bar, they are taken to reach their lows together and their highs together — a candle does not say which came first, so the basket keeps the worse case, as the engine does inside one market.
Drawdown, a year, Sharpe
- Drawdown is the deepest fall from a high to a later low of the account; inside one bar the high is taken to come first. It is reported in USDT and as a share of the high it fell from.
- A year is what the account made a year on the capital it started with:
net result / start × 365 days / span. Positions are sized from the starting capital and do not grow with what they made, so a year is weighed against it. It needs half a year of history. - Year by year is what the account made in each calendar year (UTC), as a share of the starting capital. A year the history did not span whole — the first or the one still running — is marked partial.
- Sharpe is computed from the account at the end of every UTC day, a day without a bar holding the last value, and annualised by √365.
One balance, one margin
The markets share one balance. Each market's maintenance margin is taken from its own margin schedule at the notional it holds. When the account's equity at a bar's low reaches the sum of them, the account is liquidated: it ends at zero there and stays there, whatever the markets did next.
Held at once is the largest notional the markets held together, and when; the result also gives the most markets holding at once. A basket whose markets held more at once than the starting capital times its leverage is marked: on the exchange some of those positions would have been refused.
What a basket does not model
- Each market sizes its positions as if it alone had the starting capital. A strategy that sizes from the account's equity sizes each market from its own result, not the account's.
- One market's loss does not shrink another market's buying power before the account as a whole is liquidated.
- Markets are added at their bars' extremes together, which can make a basket's drawdown deeper than the moment-by-moment account would have been, never shallower.
In the API
POST /backtest with "marks": true returns, beside the report, every traded bar's marks:
"marks": {"t": [1735689600000, …], "low": [1000.0, …], "high": [1000.0, …], "close": [1000.0, …], "held": [0.0, …]}
The last close is the account's final equity, after closing what was still held. Adding several backtests' marks this
way gives the basket's account; the platform's basket answer returns it as portfolio (net_pnl, return_pct,
max_drawdown_quote, max_drawdown_pct, per_year_pct, sharpe, peak_notional, peak_positions, over_margin,
ruined_at, years, curve).