The Backtests API is the computational core of the Hedge Fund platform. A backtest ties a trading strategy to a specific engine (vectorbt or Backtrader), an execution configuration (capital, commission, slippage, signal logic), and a date range. Once created, a backtest can be triggered synchronously for immediate results or dispatched to the Celery worker pool for non-blocking execution. After a run completes, the API surfaces structured performance, risk, and trading metrics, downloadable equity curves and trade lists, side-by-side multi-run comparison, and full grid-search parameter sweeps — all against a single persistent database record that advances throughDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/najmulhossainnj/Hedge-fund-backend/llms.txt
Use this file to discover all available pages before exploring further.
pending → running → completed (or failed).
CRUD
Create a Backtest
POST /api/v1/backtests
Creates a new backtest configuration record in pending status. The record is not executed until you call /execute. Returns the persisted BacktestRead object with a generated UUID you use in every subsequent call.
Request Body
UUID of the strategy this backtest is attached to. The strategy must already exist.
Execution engine. One of
"vectorbt" or "backtrader". Use GET /engines/available to confirm which engines are registered on this deployment.Starting portfolio value in base currency units (e.g. USD).
Per-trade commission as a fraction of notional (e.g.
0.0005 = 5 bps).Per-trade slippage as a fraction of price, applied symmetrically on entry and exit.
Full execution configuration. All fields below live inside this object.
Response — BacktestRead
Unique identifier for this backtest record.
Strategy this backtest belongs to.
Engine selected for this run (
"vectorbt" or "backtrader").Lifecycle status. One of
"pending", "running", "completed", "failed".Starting capital as persisted.
Per-trade commission fraction.
Per-trade slippage fraction.
The
BacktestRunConfig stored as JSONB.Empty at creation time; populated after a successful execution.
Storage URI for the trades parquet artifact.
null until completed.Storage URI for the equity-curve parquet artifact.
null until completed.ISO-8601 creation timestamp.
ISO-8601 last-update timestamp.
List Backtests
GET /api/v1/backtests
Returns a paginated list of backtest records. Optionally filter to a single strategy.
Query Parameters
When provided, only backtests belonging to this strategy are returned.
Number of records to skip (offset-based pagination).
Maximum records to return.
list[BacktestRead] (same schema as the create response).
Get a Backtest
GET /api/v1/backtests/{backtest_id}
Retrieves a single backtest by ID. When status is "completed", the response includes the structured_metrics block with typed sub-objects for performance, risk, and trading statistics (see Structured Metrics below).
Path Parameters
UUID of the backtest to retrieve.
BacktestResultResponse (superset of BacktestRead, adds structured_metrics).
Update a Backtest
PATCH /api/v1/backtests/{backtest_id}
Partially updates a backtest record. Intended primarily for administrative corrections; normal lifecycle transitions happen automatically during execution.
Path Parameters
UUID of the backtest to update.
Request Body
Override the status string (e.g. to reset a stuck
"running" record back to "pending").Replace the stored flat metrics dict.
Update the trades artifact storage URI.
Update the equity-curve artifact storage URI.
BacktestRead.
Delete a Backtest
DELETE /api/v1/backtests/{backtest_id}
Permanently deletes the backtest record. Artifact files stored at trades_uri and equity_curve_uri are not automatically removed from object storage; clean those up separately if needed.
Path Parameters
UUID of the backtest to delete.
204 No Content.
Execution
Execute a Backtest
POST /api/v1/backtests/{backtest_id}/execute
Triggers the full backtest pipeline against the configuration stored in the record. Supports both synchronous and asynchronous modes via the async_mode flag.
Path Parameters
UUID of the backtest to execute.
Request Body
When
false (default), the request blocks until the backtest completes and returns the full BacktestResultResponse including structured_metrics. When true, the run is dispatched to Celery and the endpoint immediately returns a task_id and "PENDING" status. Poll GET /api/v1/tasks/{task_id} for the result.Sync Response — BacktestResultResponse
Backtest UUID.
Parent strategy UUID.
Engine used (
"vectorbt" or "backtrader")."completed" on success, "failed" if the engine raised an error.Flat metrics dict with prefixed keys (e.g.
perf_sharpe_ratio, risk_max_drawdown).Typed breakdown of the flat
metrics dict. Only present when status == "completed". See Structured Metrics.Storage URI of the equity-curve artifact.
Storage URI of the trades artifact.
Creation timestamp.
Completion timestamp.
Async Response
Execute Async (dedicated endpoint)
POST /api/v1/backtests/{backtest_id}/execute/async
Convenience endpoint that always dispatches execution to the Celery worker pool — equivalent to calling /execute with async_mode: true. Returns 409 if the backtest is already running.
Path Parameters
UUID of the backtest to execute asynchronously.
List Available Engines
GET /api/v1/backtests/engines/available
Returns the list of backtest engines currently registered in the engine registry on this deployment.
Response
Results
All four result endpoints below require the backtest to be in"completed" status and to have non-null artifact URIs. They return 404 if the backtest ID does not exist and 409 if the backtest is not yet completed or the result artifacts are missing.
Get Equity Curve (JSON)
GET /api/v1/backtests/{backtest_id}/equity-curve
Returns the full equity curve as a JSON array of {date, equity} objects — one record per bar.
UUID of a completed backtest.
Download Equity Curve (Parquet)
GET /api/v1/backtests/{backtest_id}/equity-curve/parquet
Streams the equity curve as an Apache Parquet file with a date index and an equity column. The response has Content-Disposition: attachment; filename=equity_{backtest_id}.parquet.
UUID of a completed backtest.
Get Trade List (JSON)
GET /api/v1/backtests/{backtest_id}/trades
Returns the complete list of closed trades as a JSON array. Each object contains at minimum pnl, return_pct, and side columns as recorded by the engine adapter.
UUID of a completed backtest.
Download Trade List (Parquet)
GET /api/v1/backtests/{backtest_id}/trades/parquet
Streams the trade list as a Parquet file (no index). The response has Content-Disposition: attachment; filename=trades_{backtest_id}.parquet.
UUID of a completed backtest.
Structured Metrics
WhenGET /api/v1/backtests/{backtest_id} or a synchronous /execute returns a completed backtest, the structured_metrics field is populated. This is a typed decomposition of the flat metrics JSONB column into three namespaced sub-objects, computed by the engine-agnostic compute_metrics function so the numbers are identical regardless of which engine ran the backtest.
Cumulative return over the full backtest period as a decimal fraction.
0.25 = 25% total return.Number of bars where the strategy held a non-zero position. Refined by engine adapters if a position series is available.
Annualised risk-adjusted performance metrics.
Drawdown and tail-risk metrics.
Trade-level execution statistics.
metrics dict stores the same values with prefixed keys for direct database querying:
| Flat key | Structured path |
|---|---|
total_return | structured_metrics.total_return |
bars_in_market | structured_metrics.bars_in_market |
perf_cagr | structured_metrics.performance.cagr |
perf_sharpe_ratio | structured_metrics.performance.sharpe_ratio |
perf_sortino_ratio | structured_metrics.performance.sortino_ratio |
perf_calmar_ratio | structured_metrics.performance.calmar_ratio |
risk_max_drawdown | structured_metrics.risk.max_drawdown |
risk_max_drawdown_duration | structured_metrics.risk.max_drawdown_duration |
risk_var_95 | structured_metrics.risk.var_95 |
risk_cvar_95 | structured_metrics.risk.cvar_95 |
risk_var_99 | structured_metrics.risk.var_99 |
risk_cvar_99 | structured_metrics.risk.cvar_99 |
risk_volatility_annualised | structured_metrics.risk.volatility_annualised |
trade_total_trades | structured_metrics.trading.total_trades |
trade_win_rate | structured_metrics.trading.win_rate |
trade_profit_factor | structured_metrics.trading.profit_factor |
trade_avg_win | structured_metrics.trading.avg_win |
trade_avg_loss | structured_metrics.trading.avg_loss |
trade_expectancy | structured_metrics.trading.expectancy |
trade_turnover_annualised | structured_metrics.trading.turnover_annualised |
Comparison
Compare Multiple Backtests
POST /api/v1/backtests/compare
Side-by-side metric comparison of between 2 and 10 backtest runs. For every metric key found across any of the supplied runs, the response includes each run’s value and identifies the best-performing run based on whether higher or lower is better for that metric.
All requested backtest IDs must exist; the endpoint returns
404 if any are missing. Backtests do not need to be completed — the raw metrics dict is compared regardless of status, though absent metrics simply show null.Request Body
Between 2 and 10 backtest UUIDs to compare. Order does not affect results.
Response — BacktestCompareResponse
One entry per requested backtest.
Keyed by flat metric name (e.g.
"perf_sharpe_ratio"). Each value is a MetricDiff object.higher_is_better: true):
perf_cagr, perf_sharpe_ratio, perf_sortino_ratio, perf_calmar_ratio, total_return, trade_win_rate, trade_profit_factor, trade_expectancy, bars_in_market
Lower-is-better metrics (higher_is_better: false):
risk_max_drawdown, risk_max_drawdown_duration, risk_var_95, risk_cvar_95, risk_var_99, risk_cvar_99, risk_volatility_annualised
Parameter Sweep
Run a Parameter Grid Search
POST /api/v1/backtests/sweep
Submits a grid of backtest configurations to the Celery worker pool for parallel execution. Each entry in param_grid is merged (shallow) over base_config to produce one complete BacktestRunConfig, so only the fields you want to vary need to appear in each grid entry. The engine ranks all completed runs by rank_metric and returns the leaderboard when the task finishes.
The sweep endpoint always dispatches asynchronously. Poll
GET /api/v1/tasks/{task_id} to retrieve progress and the ranked leaderboard once all runs complete.Request Body
UUID string of the strategy to run the sweep against.
Engine to use for all runs in the grid. All entries share the same engine.
A complete
BacktestRunConfig-compatible dict. Every key not overridden by a param_grid entry will use this value.List of 1–50 override dicts. Each dict is merged over
base_config to produce one run’s configuration. Keys that appear in an entry replace the corresponding base_config key; all other base_config keys are inherited unchanged.Flat metric key used to rank completed runs in the leaderboard (e.g.
"perf_sharpe_ratio", "perf_calmar_ratio", "total_return").Response
Celery task UUID. Use with
GET /api/v1/tasks/{task_id} to poll for the ranked leaderboard.Always
"PENDING" immediately after dispatch.Number of backtest configurations dispatched (equals
len(param_grid)).