Backtesting API
Full reference for the Backtesting API — endpoints, request schema, response schema, metrics, and error codes.
Overview
The Backtesting API exposes two endpoints. You submit a strategy execution request and then poll for the result using the returned backtest ID.
Base URL: https://backtest.emidlabs.com/api/public/v1
x-api-key header with a valid API key. Keys are generated in the Console.#POST /backtest — Submit
/backtestSubmit a new backtest for execution.
The body must be application/json. The strategy is embedded as a nested JSON object inside strategySnapshotJson.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| strategySnapshotJson | object | Yes | Strategy object with configuration, inputs, conditions, score, decision, and (optional) riskManagement. |
| assetPair | string | Yes | Trading pair. E.g. "BTC-USDC", "ETH-USDC". |
| initialDate | string | Yes | Start date in ISO format: YYYY-MM-DD. |
| finalDate | string | Yes | End date in ISO format: YYYY-MM-DD. |
Supported asset pairs
For now, only crypto markets are supported, sourced from Coinbase and quoted in USDC. Examples:
BTC-USDCETH-USDCSOL-USDCXRP-USDCADA-USDCSee the Data Reference page for the full list of supported pairs and the assets available in the Console. Date ranges must fall within the available historical data for the selected asset.
Submit response
| Field | Type | Description |
|---|---|---|
| id | string (UUID) | Unique identifier for the backtest. |
| status | string | "Running" immediately after submission. |
| assetPair | string | The asset pair used. |
| initialDate | string | Start date of the backtest period. |
| finalDate | string | End date of the backtest period. |
| createdAtUtc | string | Timestamp of creation in UTC. |
| canViewResult | boolean | Whether the result is accessible (depends on credits). |
#GET /backtest/:id — Fetch Results
/backtest/{id}Fetch the status and results of a submitted backtest.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| includeTrades | boolean | false | When true, includes the full tradesDetail array in result. |
includeTrades or set it to false when you only need aggregate metrics. The trade list can be large for long date ranges, so only request it when you need per-trade analysis.Response fields
| Field | Type | Description |
|---|---|---|
| id | string | UUID of the backtest. |
| status | string | "Running", "Completed", or "Failed". |
| strategySnapshotJson | string | The strategy used, serialized. |
| assetPair | string | Asset pair. |
| initialDate / finalDate | string | Date range. |
| createdAtUtc | string | Creation timestamp (UTC). |
| errorMessage | string | null | Error details if status is "Failed". |
| canViewResult | boolean | Whether the result is accessible. |
| logsJson | string | null | Execution logs serialized as JSON string. |
| result | object | null | Full performance metrics when Completed. |
#Metrics Reference
When status is Completed, the result object contains:
Profitability metrics
| Field | Type | Description |
|---|---|---|
| pnlR | number | Net profit/loss in R-units. Sum of all trade PnLs. |
| grossProfitR | number | Sum of all winning trades in R-units. |
| grossLossR | number | Sum of all losing trades in R-units (negative). |
| profitFactor | number | grossProfitR / abs(grossLossR). >1 is profitable. |
| expectancyR | number | Average expected R per trade. (winRate × avgWinR) + (lossRate × avgLossR). |
| avgWinR | number | Average R on winning trades. |
| avgLossR | number | Average R on losing trades (-1.0 by default; varies if the strategy overrides riskManagement.stopLoss). |
Trade statistics
| Field | Type | Description |
|---|---|---|
| trades | number | Total number of trades executed. |
| wins | number | Number of winning trades. |
| losses | number | Number of losing trades. |
| winRate | number | wins / trades. Range: 0–1. |
| bothHit | number | Trades where both SL and TP were hit in the same candle (resolved as SL). |
Diagnostics
| Field | Type | Description |
|---|---|---|
| conditionsDistributionPct | object | For each condition: fraction of candles where it was true. |
| scoreDistributionPct | object | For each possible score value: fraction of candles with that score. |
conditionsDistributionPct and scoreDistributionPct fields are key for strategy quality analysis. A condition that is almost always true adds no discriminating power. Use these to diagnose and refine your strategy structure.Trade detail fields (with includeTrades=true)
| Field | Type | Description |
|---|---|---|
| number | number | Sequential trade number. |
| entryPrice | number | Price at which the trade was entered. |
| exitPrice | number | Price at which the trade was closed. |
| pnlR | number | +3.0 for a win, -1.0 for a loss with the default riskManagement; other values if the strategy configures its own stopLoss/takeProfit. |
| pnlPct | number | Percentage gain/loss on the trade. |
| totalScoreAtEntry | number | Total score that triggered the entry. |
| conditionsAtEntry | object | Which conditions were true at entry. |
| scoreBreakdownAtEntry | object | Score contributed by each condition at entry. |
#Error Codes
| Status | Code | Description |
|---|---|---|
| 400 | invalid_payload | The request body is malformed or missing required fields. |
| 400 | invalid_strategy | The strategySnapshotJson is invalid or references undefined variables. |
| 400 | invalid_date_range | The date range is outside available historical data for the asset. |
| 400 | unsupported_asset | The assetPair is not supported. |
| 401 | unauthorized | Missing or invalid API key. |
| 402 | insufficient_credits | Not enough credits to execute this backtest. |
| 429 | rate_limited | Too many requests. Back off and retry. |
| 500 | execution_failed | Server-side execution error. Check errorMessage field. |
When an error occurs at the execution level (after submission), the backtest status is set to Failed and the errorMessage field contains a description of what went wrong.