Getting Started

Get your API key, make your first request, and receive your first backtest result in minutes.

Prerequisites

To use the EmidLabs Backtesting API you need:

  • An EmidLabs account — create one at the Console.
  • An API key generated from the Console.
  • Any HTTP client — curl, fetch, Python requests, or any language SDK.

#Authentication

All API requests must include your API key in the x-api-key header. There are no other authentication methods.

Authentication header
x-api-key: em_YOUR_API_KEY
Never expose your API key in client-side code, public repositories, or logs. Always use server-side code or environment variables to make API calls.

Generating an API key

1

Open the Console

Navigate to console.emidlabs.com and sign in to your account.
2

Go to API Keys

In the Console sidebar, select "API Keys" to access key management.
3

Create a key

Click "Generate New Key". Give it a descriptive name. The key is shown once — copy and store it securely.
4

Set an expiry (optional)

You can set an expiry date for the key for better security hygiene.

#Your First Backtest

A backtest is submitted as a POST request. The body includes the asset pair, date range, and a strategy definition serialized as a JSON string.

Step 1 — Define the strategy

The strategy is a JSON object that describes what the engine should look for. Here is a simple EMA crossover with RSI confirmation:

strategy.json
{
  "configuration": {
    "timeframe": "1H"
  },
  "inputs": {
    "emaFast": "ema(close, 9)",
    "emaSlow": "ema(close, 21)",
    "rsiValue": "rsi(close, 14)"
  },
  "conditions": {
    "trendUp": "emaFast > emaSlow",
    "rsiHealthy": "rsiValue > 40 AND rsiValue < 65"
  },
  "score": {
    "trendUp": 20,
    "rsiHealthy": 30
  },
  "decision": {
    "entry": "score >= 40"
  }
}

Step 2 — Serialize and submit

The strategy must be serialized into a JSON string and passed as thestrategySnapshotJson field of the request body.

Submit backtest
curl -X POST \
  "https://api.emidlabs.com/api/public/v1/backtest" \
  -H "Content-Type: application/json" \
  -H "x-api-key: em_YOUR_API_KEY" \
  -d '{
  "assetPair": "BTC-USDC",
  "initialDate": "2023-01-01",
  "finalDate": "2023-12-31",
  "strategySnapshotJson": "{"configuration":{"timeframe":"1H"},"inputs":{"emaFast":"ema(close, 9)","emaSlow":"ema(close, 21)","rsiValue":"rsi(close, 14)"},"conditions":{"trendUp":"emaFast > emaSlow","rsiHealthy":"rsiValue > 40 AND rsiValue < 65"},"score":{"trendUp":20,"rsiHealthy":30},"decision":{"entry":"score >= 40"}}"
}'
The API returns immediately with a backtest ID and status: "Running". Execution typically completes within 200–500ms for most date ranges.

Step 3 — Fetch the results

Use the returned id to fetch results via a GET request. Add includeTrades=true to receive individual trade details.

Fetch results
curl -X GET \
  "https://api.emidlabs.com/api/public/v1/backtest/YOUR_BACKTEST_ID?includeTrades=true" \
  -H "x-api-key: em_YOUR_API_KEY"

#Reading Results

When status is Completed, theresult object contains all performance metrics.

Key metrics

tradesTotal number of trades executed.
winRatePercentage of winning trades (0–1).
expectancyRAverage expected R per trade. Positive is profitable.
pnlRTotal profit/loss in R-units across all trades.
profitFactorGross profit divided by gross loss. >1 is profitable.
maxDrawdownPctLargest peak-to-trough drawdown as a percentage.
conditionsDistributionPctHow often each condition was true per candle.
scoreDistributionPctDistribution of total score values across all candles.

R-units explained

All profit/loss values are in R-units, not currency amounts. 1R = 1% of your position (the risk per trade under the fixed risk model). A result of +10R means the strategy would have returned 10× the risked amount per trade, in aggregate.

This makes results comparable across strategies and assets regardless of position size, and forces focus on the statistical edge rather than dollar amounts.