Your first backtest
Goal: from blank slate to a backtest with a non-zero Sharpe on your screen, in under 5 minutes.
Why
The backtest pipeline is the central artifact of every AlphaSwarm workflow. Every strategy gets backtested before paper, every paper run gets promoted on the back of backtest evidence, and every RL policy gets evaluated against the same engine. Understanding the backtest contract is prerequisite to understanding anything else.
Prerequisites
- The quickstart completed.
- An open terminal pointing at the repo root.
Step 1 — author the strategy
Create configs/strategies/my_first_strategy.yaml:
name: "My First Momentum"
description: >
Long the top-quantile of trailing returns, short the bottom quantile (or cash).
strategy:
class: FrameworkAlgorithm
module_path: alphaswarm.strategies.framework
kwargs:
universe_model:
class: StaticUniverse
module_path: alphaswarm.strategies.universes
kwargs:
symbols: [SPY, QQQ, IWM]
alpha_model:
class: MomentumAlpha
module_path: alphaswarm.strategies.momentum
kwargs:
lookback: 60
top_quantile: 0.3
bottom_quantile: 0.3
allow_short: false
portfolio_model:
class: EqualWeightPortfolio
module_path: alphaswarm.strategies.portfolio
kwargs:
max_positions: 2
risk_model:
class: BasicRiskModel
module_path: alphaswarm.strategies.risk_models
kwargs:
max_position_pct: 0.5
max_drawdown_pct: 0.15
execution_model:
class: MarketOrderExecution
module_path: alphaswarm.strategies.execution
kwargs: {}
backtest:
class: EventDrivenBacktester
module_path: alphaswarm.backtest.engine
kwargs:
initial_cash: 100000.0
commission_pct: 0.0005
slippage_bps: 2.0
start: "2024-01-01"
end: "2024-06-30"
Each class + module_path + kwargs block resolves to a registered
component (see the bundled
configs/strategies/momentum.yaml
for the reference shape). MomentumAlpha itself lives in
alphaswarm/strategies/momentum.py
and is registered via @register("MomentumAlpha") — AGENTS rule 6. See
AGENTS.md.
Step 2 — dispatch the backtest
docker compose exec alphaswarm-core alphaswarm-backtest \
--config configs/strategies/my_first_strategy.yaml \
--start 2024-01-01 \
--end 2024-06-30 \
--engine event_driven
The CLI returns a task_id. Tail its progress:
docker compose exec alphaswarm-core python -c "from alphaswarm.ws.broker import subscribe; \
[print(m) for m in subscribe('<task_id>')]"
You will see progress frames in the canonical
{task_id, stage, message, timestamp, **extras} shape.
Step 3 — inspect the ledger
docker compose exec alphaswarm-postgres psql -U alphaswarm -d alphaswarm -c \
"SELECT id, strategy_name, sharpe, total_return, max_drawdown
FROM backtest_runs ORDER BY created_at DESC LIMIT 5;"
The most recent row is your run. If sharpe is NULL, the backtest
failed — see Step 5.
Step 4 — render a tearsheet
curl -X POST http://localhost:3000/api/analytics/portfolio/tearsheet \
-H "Content-Type: application/json" \
-d '{"run_id": "<backtest_run_id_from_step_3>"}'
The endpoint returns another task_id; the resulting HTML tearsheet
lands at /analytics/portfolio/<run_id>/tearsheet.html once Celery
finishes rendering.
Open it in your browser. Or use the operator UI route /analytics/portfolio/:runId.
Step 5 — handle expected failures
InsufficientDataError — Alpha Vantage has not seeded the
universe yet. Run the ingest via the fetcher in
alphaswarm/data/fetchers/api/yfinance.py
(there is no standalone scripts/ingest_yfinance module — dispatch
ingestion through the alphaswarm-download CLI or the /data/* API
routes instead).
StrategyRegistryMissError — the YAML's class field
references a class that is not decorated with @register. Open
alphaswarm/strategies/momentum.py
and confirm MomentumAlpha is there. If you renamed the class,
update the YAML.
IcebergNamespaceError — your local Iceberg catalog has not
been migrated. There is no make iceberg-bootstrap target in the
current Makefile; re-run make generate-config ENV=local && make dev
and retry.
Verify
-
backtest_runsrow visible with non-NULLsharpe. - Tearsheet HTML renders.
- Strategy YAML committed under
configs/strategies/.
What next
- Concept: backtest engines —
what
event_drivenvsvbtprovshftactually does. - Recipe: run a backtest from YAML — the same thing, but as a how-to for repeated dispatch.
- Tutorial: first bot — wrap this strategy in a reusable bot spec.