Skip to content

Market data

Backtest a basket over the last 12 months

Simulate a weighted basket over 12 months, monthly rebalanced, against buy-and-hold SPY.

POST /api/backtest takes a weighted basket and returns its 12-month simulated performance against buy-and-hold SPY. It reads public equity history only — no inference, no user funds.

POST /api/backtest · public, no token required · 20 requests per 60 seconds per IP. Base URL, response envelope, and error shapes: conventions.

The engine starts at 100, renormalizes weights over the covered subset, drifts positions with daily closes, and rebalances every ~21 trading days.

application/json.

Field Type Required Description
allocations array yes 1 to 20 legs.
allocations[].symbol string yes A tradable ticker, for example AAPL. Unknown symbols return 400.
allocations[].weightPct number yes Positive, up to 100. Weights renormalize over the legs that have history.
Field Type Description
backtest object | null null when covered weight is below 50% or SPY history is missing.
backtest.period string Always "1Y".
backtest.rebalance string Always "monthly".
backtest.coveragePct number Share of basket weight that had real history to test (0 to 100).
backtest.excluded string[] Symbols left out because no honest public series exists.
backtest.portfolio object Simulated basket: returnPct, volPct, maxDrawdownPct, sharpe, curve (60 points, normalized to 100).
backtest.benchmark object Same stats for buy-and-hold SPY, plus symbol: "SPY".
Terminal window
curl https://monvera.best/api/backtest \
-H "Content-Type: application/json" \
-d '{
"allocations": [
{ "symbol": "AAPL", "weightPct": 35 },
{ "symbol": "NVDA", "weightPct": 25 },
{ "symbol": "SPY", "weightPct": 25 },
{ "symbol": "SGOV", "weightPct": 15 }
]
}'

The curve arrays hold 60 points each, trimmed here for space.

{
"backtest": {
"period": "1Y",
"rebalance": "monthly",
"coveragePct": 100,
"excluded": [],
"portfolio": {
"returnPct": 22.41,
"volPct": 18.9,
"maxDrawdownPct": 12.07,
"sharpe": 1.18,
"curve": [100, 101.3, 99.8, 104.2, 108.6, 115.9, 122.41]
},
"benchmark": {
"symbol": "SPY",
"returnPct": 14.22,
"volPct": 12.68,
"maxDrawdownPct": 8.31,
"sharpe": 1.05,
"curve": [100, 100.9, 100.1, 102.8, 105.4, 110.7, 114.22]
}
}
}
Status Body Cause
400 {"error":"Invalid request body."} Malformed JSON, non-array allocations, unknown symbol, or a weightPct outside 0 to 100.
200 {"backtest": null} Covered weight fell below 50%, or SPY history was missing. Check for null before reading stats.

On a non-null result, excluded names any legs dropped for having no public series.

© 2026 Aibora · Documentation interface. Original Monvera materials retain their upstream attribution andMIT license.