Skip to content

EmidLabs Backtest

by emidlabs · remote · no sign-in to list tools · v0.1.0 · published by GitHub user emidlabs

Run crypto trading strategy backtests through EmidLabs's Backtesting API.

Changes · 3

9 tools: 3 change things and 6 only read.

Scanned Oct 21, 2026

No check matched anything in the tool definitions. No finding is not a safety guarantee. How the checks work.

claude mcp add --transport http backtest https://mcp.backtest.emidlabs.com/mcp

Tools

Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.

9 tools

Changes things 3Claude Code: ask
  • submit_backtestSubmits a strategy for backtesting against historical OHLCV data.No findings

    Why it is in this group

    • The name "submit_backtest" says "submit": a word for a change.
    Description, as the server wrote it
    Submits a strategy for backtesting against historical OHLCV data. Returns immediately with an id and status — call get_backtest_result to fetch the outcome once it finishes. Testing the same strategy against many assets? Use submit_backtest_batch instead — one call per asset here adds up fast. Optionally accepts confirmationSources to only count a candidate Entry/Exit as a real trade once corroborated by a submit_confirmation_source result (multi-timeframe or cross-asset confirmation) — see the confirmationSources argument and submit_confirmation_source's own description.

    Annotations the server declares

    • title: Submit Backtest
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
    • readOnlyHint: false
  • submit_backtest_batchSubmits ONE strategy against MANY asset pairs in a single call — the same backtest you'd get from calling submit_backtest once per asset, without needing dozens of round trips.No findings

    Why it is in this group

    • The name "submit_backtest_batch" says "submit": a word for a change.
    Description, as the server wrote it
    Submits ONE strategy against MANY asset pairs in a single call — the same backtest you'd get from calling submit_backtest once per asset, without needing dozens of round trips. Returns immediately with a batchId (pass it to get_backtest_batch_results to fetch every asset's outcome, paginated) plus the per-asset id/status assigned right away. Best-effort: one bad asset pair (unknown, or its date range outside coverage) shows up with an error in that item only — every other asset in the batch is unaffected. Optionally accepts confirmationSources, applied identically to every asset in the batch — see submit_backtest's own confirmationSources argument for the full semantics.

    Annotations the server declares

    • title: Submit Backtest Batch
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
    • readOnlyHint: false
  • submit_confirmation_sourceRuns a strategy against historical data purely to produce a signal timeline used to confirm OTHER backtests — not a backtest itself.No findings

    Why it is in this group

    • The name "submit_confirmation_source" says "submit": a word for a change.
    Description, as the server wrote it
    Runs a strategy against historical data purely to produce a signal timeline used to confirm OTHER backtests — not a backtest itself. Walks the same candles and evaluates the same DSL as submit_backtest, but never simulates a position: no trade, no PnL, no WinRate/drawdown, none of that applies here, because this strategy is never meant to be traded on its own. Returns immediately with an id and status — call get_confirmation_source to check completion, then pass that id as a confirmationSources sourceId in submit_backtest (e.g. only count an XRP entry once a BTC-neutral confirmation source agrees). Costs the same capacity as a regular backtest of the same size — the compute is identical, it just skips trade simulation.

    Annotations the server declares

    • title: Submit Confirmation Source
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: false
    • readOnlyHint: false
Only reads 6Claude Code: allow
  • get_backtest_batch_resultsFetches every asset's outcome from a submit_backtest_batch call, paginated.No findings

    Why it is in this group

    • The name "get_backtest_batch_results" says "get": a word for reading.
    Description, as the server wrote it
    Fetches every asset's outcome from a submit_backtest_batch call, paginated. By default (waitForCompletion: true) polls internally until every item in the batch is done — a cheap check, not one that pages through everything — so one call returns the finished page. Each item has the same aggregate metrics and recency fields (recentTradeCount/recentAvgPnlR/recentOutcomes) get_backtest_result returns for a single backtest, plus assetPair/status/error, so the single-result and batch-result shapes never drift apart. totalCount/completedCount/failedCount/pendingCount come back on every page, not just the last, so you can tell the batch is done from a single pageSize=1 call.

    Annotations the server declares

    • title: Get Backtest Batch Results
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • readOnlyHint: true
  • get_backtest_resultFetches a submitted backtest by id.No findings

    Why it is in this group

    • The name "get_backtest_result" says "get": a word for reading.
    Description, as the server wrote it
    Fetches a submitted backtest by id. By default (waitForCompletion: true) polls internally until it finishes, so one call returns one final answer — no need to poll from the caller's side. Only aggregate metrics are returned here, no trade-by-trade detail — call get_backtest_trades for that (paginated, sortable). Fetching many results from the same submit_backtest_batch call? Use get_backtest_batch_results instead.

    Annotations the server declares

    • title: Get Backtest Result
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • readOnlyHint: true
  • get_backtest_tradesFetches the closed-trade list for a completed backtest, paginated and sortable — the trade-by-trade detail get_backtest_result deliberately omits.No findings

    Why it is in this group

    • The name "get_backtest_trades" says "get": a word for reading.
    Description, as the server wrote it
    Fetches the closed-trade list for a completed backtest, paginated and sortable — the trade-by-trade detail get_backtest_result deliberately omits. Only closed trades ever appear; a position still open when the backtest's date range ends isn't represented here or anywhere else. Example: sortBy="exitTime", sortDirection="desc", pageSize=5 for the most recently closed trades.

    Annotations the server declares

    • title: Get Backtest Trades
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • readOnlyHint: true
  • get_confirmation_sourceFetches a submitted confirmation source by id.No findings

    Why it is in this group

    • The name "get_confirmation_source" says "get": a word for reading.
    Description, as the server wrote it
    Fetches a submitted confirmation source by id. By default (waitForCompletion: true) polls internally until it finishes, so one call returns one final answer. No trade-outcome fields here at all (no PnlR/WinRate/...) — a confirmation source never opens a position. Once Completed, its id can be used as a confirmationSources sourceId in submit_backtest; its raw signal timeline is available separately via get_confirmation_source_signals.

    Annotations the server declares

    • title: Get Confirmation Source
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • readOnlyHint: true
  • get_confirmation_source_signalsFetches a completed confirmation source's raw signal timeline, paginated — the actual data a backtest's confirmationSources requirement is checked against.No findings

    Why it is in this group

    • The name "get_confirmation_source_signals" says "get": a word for reading.
    Description, as the server wrote it
    Fetches a completed confirmation source's raw signal timeline, paginated — the actual data a backtest's confirmationSources requirement is checked against. Can easily run into the thousands for a frequent condition over a long range (every candle-condition match is a row, not just closed trades), which is why this is paginated from the start. Debugging/inspection only — you do NOT need this tool to make confirmationSources work, and should not fetch these rows to reconstruct the gating yourself. To actually gate a backtest by this source, pass its id directly as sourceId in submit_backtest's own confirmationSources array; the backend applies the backward-only state check against this exact timeline automatically, including the higher-timeframe-to-lower-timeframe alignment. Reimplementing that alignment by hand from this raw data is unnecessary and easy to get wrong (e.g. failing to correctly persist a higher-timeframe state across every lower-timeframe candle until the next higher-timeframe close). Use this tool only to sanity-check a source's signal density or diagnose an unexpectedly low ConfirmedSignalsCount after the fact.

    Annotations the server declares

    • title: Get Confirmation Source Signals
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • readOnlyHint: true
  • list_available_assetsLists every asset pair with real historical data, each with its supported timeframes and the date range actually available.No findings

    Why it is in this group

    • The name "list_available_assets" says "list": a word for reading.
    Description, as the server wrote it
    Lists every asset pair with real historical data, each with its supported timeframes and the date range actually available. Optional to call — submit_backtest already returns a clear error (with the real available range) when an asset or date range doesn't have data, so this is for up-front exploration or for recovering from an "unknown asset" error, not a required step before every submit_backtest.

    Annotations the server declares

    • title: List Available Assets
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: false
    • readOnlyHint: true

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Install

Pinned to version 0.1.0. Values in angle brackets are yours to fill in.

claude mcp add --transport http backtest https://mcp.backtest.emidlabs.com/mcp

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__backtest__list_available_assets",
      "mcp__backtest__get_backtest_batch_results",
      "mcp__backtest__get_backtest_trades",
      "mcp__backtest__get_backtest_result",
      "mcp__backtest__get_confirmation_source",
      "mcp__backtest__get_confirmation_source_signals"
    ],
    "ask": [
      "mcp__backtest__submit_confirmation_source",
      "mcp__backtest__submit_backtest_batch",
      "mcp__backtest__submit_backtest"
    ],
    "deny": []
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as backtest. Review it before you use it.