Skip to main content

Get Backtest Result

Retrieve the status and (when ready) the full result of a backtest job.

Endpoint

GET /v1/backtest/jobs/{id}

Weight: 2

Authentication: Required (signed)

Path parameters

NameTypeMandatoryDescription
idstringYesJob identifier returned by Create Job, e.g. bt_3c91ef.

Response

A successful response returns the full job object. The result payload is populated only when status is done.

{
"id": "bt_3c91ef",
"status": "done",
"config": {
"template_id": "tpl_grid",
"params": {
"grid_levels": 8,
"upper_price": "72000",
"lower_price": "60000"
},
"symbols": ["BTCUSDT"],
"timeframe": "1h",
"start": "2025-01-01T00:00:00Z",
"end": "2025-12-31T23:59:59Z",
"capital": "10000.00",
"leverage": 1,
"fee_model": "fixed_bps",
"fee_bps": "5"
},
"submitted_at": "2026-04-29T10:15:00Z",
"started_at": "2026-04-29T10:15:08Z",
"finished_at": "2026-04-29T10:17:42Z",
"progress": 1.0,
"result": {
"metrics": {
"sharpe": "1.84",
"sortino": "2.31",
"calmar": "1.12",
"max_drawdown": "-0.142",
"win_rate": "0.638",
"profit_factor": "1.92",
"cagr": "0.187",
"expected_value": "12.43",
"total_trades": 247,
"avg_trade_duration_seconds": 14820
},
"equity_curve": [
["2025-01-01T00:00:00Z", "10000.00"],
["2025-01-02T00:00:00Z", "10031.50"]
],
"trades": [
{
"id": 1,
"side": "buy",
"symbol": "BTCUSDT",
"entry_time": "2025-01-15T08:00:00Z",
"entry_price": "62100.00",
"exit_time": "2025-01-15T14:00:00Z",
"exit_price": "63250.00",
"qty": "0.0805",
"pnl": "92.58",
"fee": "10.18"
}
]
},
"error": null
}

While the job is queued or running, result is null and progress is fractional in [0, 1]. While failed, result is null and error carries the failure detail.

Response fields

FieldTypeDescription
idstringJob identifier.
statusenumqueued, running, done, failed, or cancelled. The latter three are terminal.
configobjectResolved configuration the job is running with. See Create Job for field meanings.
submitted_atstring (ISO 8601)When the job was accepted.
started_atstring (ISO 8601) | nullWhen the worker began processing.
finished_atstring (ISO 8601) | nullWhen the job entered a terminal state.
progressnumberFractional progress in [0, 1]. 1.0 when complete.
resultobject | nullPopulated only when status = "done".
result.metricsobjectPerformance metrics. See Metrics for definitions.
result.equity_curvearray<[ISO 8601, decimal string]>Equity samples; one entry per simulated day.
result.tradesarray<object>Closed trades. Each trade has id, side, symbol, entry_time, entry_price, exit_time, exit_price, qty, pnl, fee.
errorobject | null{ "code", "message" } when status = "failed".

Polling guidance

  • Poll at most once every 5 seconds per job. More aggressive polling is rate-limited.
  • Stop polling as soon as status reaches a terminal value (done, failed, cancelled).
  • For long-running jobs, prefer exponential backoff after the first few polls.

Pagination of large results

For very long backtests, result.equity_curve and result.trades may eventually be paginated to keep responses manageable. In the initial release the full arrays are always returned in a single response.

Future: opt-in pagination via ?expand=equity_curve&cursor=... (and expand=trades). The default response will then return only metrics and the first page of each array.

Errors

HTTPCodeCause
404NOT_FOUNDThe job ID does not exist or is not owned by the authenticated key.

See Errors for shared error semantics.

Example

curl -X GET https://api.pipai.example/v1/backtest/jobs/bt_3c91ef \
-H "X-PipAI-API-Key: $API_KEY" \
-H "X-PipAI-Timestamp: $TS" \
-H "X-PipAI-Signature: $SIG"