Skip to main content
Glama

Server Details

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

If you are the author of this connector, you can claim ownership with GitHub, an HTTP challenge, or a DNS record. Claimed connector authors can inspect health checks, view analytics, and manage their listing.
Status
Healthy
Last Tested
Transport
Streamable HTTP
URL

Available Tools

9 tools
get_backtest_batch_resultsGet Backtest Batch ResultsA
Read-onlyIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo1-based page number. Default 1.
batchIdNoThe batchId returned by submit_backtest_batch.
pageSizeNoItems per page, 1-100. Default 20.
pollTimeoutMsNoDefaults to 300000 (5 minutes) — a batch's slowest item determines the total wait, so this is higher than get_backtest_result's default.
backtestApiKeyNoYour EmidLabs backtest API key. Not needed if this connector was added with a static 'x-api-key' header.
backtestBaseUrlNoDefaults to the public production API.
waitForCompletionNoIf true (default), polls internally until every item in the batch is done or pollTimeoutMs elapses.

Output Schema

ParametersJSON Schema
NameRequiredDescription
pageNo
itemsNo
batchIdNo
pageSizeNo
totalCountNoTotal items in this batch, across every page — not just this one.
totalPagesNo
failedCountNoHow many items finished unsuccessfully (Failed, Cancelled, or Expired).
pendingCountNoHow many items are still Queued or Running. The whole batch is done once this reaches 0 — true on every page, not just the last.
completedCountNoHow many items finished successfully.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond readOnly/idempotent/non-destructive annotations, it discloses internal polling (waitForCompletion), that a call returns only the finished page, and that counts appear on every page. It also explains the response shape stays consistent with get_backtest_result, which is valuable behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, with purpose first, then behavior and edge-case tips; no filler. Despite length, every sentence adds non-redundant operational knowledge.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a paginated polling tool with 7 optional params and an output schema, the description covers the data shape, pagination counts, polling timeout semantics, and relation to sibling tools. Output schema handles return values, so nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3; the description adds meaningful semantics around waitForCompletion ('polls internally until every item... done', 'cheap check') and the pageSize=1 trick. It doesn't need to restate parameter properties because the schema already documents them.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Fetches every asset's outcome from a submit_backtest_batch call') and adds pagination. It is clearly distinguished from get_backtest_result (single-result) and submit_backtest_batch (submission).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the originating call (submit_backtest_batch) and contrasts with the single-backtest tool get_backtest_result, giving an agent enough context to choose between them. It gives concrete usage advice (waitForCompletion behavior, pageSize=1 completion check), though it doesn't explicitly state exclusion conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_backtest_resultGet Backtest ResultA
Read-onlyIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoThe id returned by submit_backtest.
pollTimeoutMsNoDefaults to 120000 (2 minutes).
backtestApiKeyNoYour EmidLabs backtest API key. Not needed if this connector was added with a static 'x-api-key' header.
backtestBaseUrlNoDefaults to the public production API.
waitForCompletionNoIf true (default), polls internally until the backtest finishes or pollTimeoutMs elapses.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNo
resultNo
statusNo
runtimeMsNoHow long the analyser actually took to run this backtest, in milliseconds — pure compute time, not counting queue/messaging latency. Null until Status is "Completed".
errorMessageNo
recentAvgPnlRNoAverage pnlR of the most recent RecentTradeCount closed trades. This is the recency signal for a rolling ranking — weighted alongside expectancyR, not a replacement for it.
unitsConsumedNoThe actual execution-unit cost of this backtest, matching what's debited from the account's plan balance (CandlesProcessed normalized by the account's candles-per-unit rate). Null until Status is "Completed".
recentOutcomesNo"Win"/"Loss" per recent trade, chronological — oldest first, so the LAST element is the most recent trade. Lets a caller see whether recent trades were genuinely a streak (e.g. all "Loss") versus alternating, which RecentAvgPnlR alone can't distinguish.
candlesProcessedNoNumber of candles the analyser processed for this backtest. Null until Status is "Completed". This is raw volume, not the plan's billing unit — see UnitsConsumed for that.
recentTradeCountNoNumber of trades the recency fields below are based on (up to 5, fewer if the backtest has fewer trades). Null until Status is "Completed".

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses important behavior beyond annotations: internal polling with waitForCompletion, the single-final-answer contract, and the limitation to aggregate metrics only. These details meaningfully shape an agent's expectations about latency and output scope, complementing the readOnlyHint and idempotentHint annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no filler. The core purpose is front-loaded, followed by the most important behavioral nuance, then targeted sibling routing. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity, a complete input schema, an output schema, and strong annotations, the description covers all essential context: what it does, how polling behaves, what is omitted from results, and which sibling tools handle those omissions. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the description adds limited new parameter-level meaning. It does reinforce the id and waitForCompletion semantics, but most parameter explanation is already supplied by the schema, so no significant compensation is needed or provided.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action ('Fetches a submitted backtest by id') on a clear resource. It also explicitly distinguishes itself from get_backtest_trades and get_backtest_batch_results by naming what the tool does not return and which sibling covers that need.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit guidance on when to use this tool versus alternatives: use get_backtest_trades for trade-by-trade detail and get_backtest_batch_results when fetching many results from a batch. It also clarifies that the caller does not need to poll because the tool polls internally by default.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_backtest_tradesGet Backtest TradesA
Read-onlyIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoThe id returned by submit_backtest.
pageNo1-based page number. Default 1.
sortByNoOne of: number, pnlR, pnlPct, entryTime, exitTime. Defaults to number (closing order).
pageSizeNoTrades per page, 1-100. Default 20.
sortDirectionNo"asc" or "desc". Defaults to asc.
backtestApiKeyNoYour EmidLabs backtest API key. Not needed if this connector was added with a static 'x-api-key' header.
backtestBaseUrlNoDefaults to the public production API.

Output Schema

ParametersJSON Schema
NameRequiredDescription
pageNo
itemsNoThe trades on this page, in the requested sort order.
pageSizeNo
totalCountNoTotal closed trades across the whole backtest, not just this page.
totalPagesNo

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so the bar is lower. The description adds valuable info: only closed trades ever appear, open positions are not represented anywhere. It does not mention pagination performance or error handling, but the open-position caveat is meaningful beyond annotations, so a 3 is fair.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences: first defines the tool and its key differentiator, second adds the critical behavioral caveat, third is a concrete example. Every sentence adds value with no filler. Front-loaded and efficiently structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has a rich output schema and 100% schema parameter coverage, so the description need not elaborate return format. It covers the essential nuance about closed trades. Slightly less than a 5 because it could mention what happens if the backtest ID is invalid or the backtest isn't completed, but the essentials are covered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all parameters. The description adds an example usage that shows the meaning of sortBy/sortDirection/pageSize, but does not explain each parameter beyond the schema. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clear verb+resource ('Fetches the closed-trade list for a completed backtest'), plus specifics: paginated, sortable, and deliberately omits trade-by-trade detail that get_backtest_result provides. This sharply distinguishes it from the sibling tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use: for trade-by-trade detail and when get_backtest_result omits it. Also provides a concrete example. It does not explicitly list alternatives like get_backtest_batch_results, but naming the primary alternative is sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_confirmation_sourceGet Confirmation SourceA
Read-onlyIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoThe id returned by submit_confirmation_source.
pollTimeoutMsNoDefaults to 120000 (2 minutes).
backtestApiKeyNoYour EmidLabs backtest API key. Not needed if this connector was added with a static 'x-api-key' header.
backtestBaseUrlNoDefaults to the public production API.
waitForCompletionNoIf true (default), polls internally until the confirmation source finishes or pollTimeoutMs elapses.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNo
statusNo
assetPairNo
runtimeMsNoHow long the analyser actually took to compute this confirmation source's signal timeline, in milliseconds. Null until Status is "Completed".
timeframeNo
errorMessageNo
unitsConsumedNoThe actual execution-unit cost, same pool/rate as a regular backtest — computing a confirmation source's signal timeline costs the same per candle as simulating trades, it just skips the trade simulation itself.
candlesProcessedNoNumber of candles the analyser processed. Null until Status is "Completed". This is raw volume, not the plan's billing unit — see UnitsConsumed for that.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnly/idempotent annotations, the description discloses the internal polling behavior, that one call returns one final answer, and that the tool never opens a position. This adds meaningful behavioral context beyond what annotations alone provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no filler; the first sentence front-loads the core action, and subsequent sentences pack high-value semantics about polling, outcome scope, and sibling routing. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema and fully documented parameters, the description supplies the missing conceptual context: polling semantics, lifecycle (Completed → sourceId), and the distinction from trade-outcome and signal-timeline tools. No critical behavior is left unexplained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds extra meaning for the id parameter by explaining that a Completed id can be used as a confirmationSources sourceId in submit_backtest, and it reinforces the waitForCompletion default polling semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource ('Fetches a submitted confirmation source by id') and sharply distinguishes itself from get_confirmation_source_signals by noting the raw signal timeline is available separately. It also states that no trade-outcome fields appear, preventing confusion with backtest result siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It names the sibling get_confirmation_source_signals as the destination for raw signal timelines, and gives an explicit when-not through 'No trade-outcome fields here at all — a confirmation source never opens a position.' The lifecycle note that a Completed id can become a confirmationSources sourceId in submit_backtest gives actionable downstream context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_confirmation_source_signalsGet Confirmation Source SignalsA
Read-onlyIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoThe id returned by submit_confirmation_source.
pageNo1-based page number. Default 1.
pageSizeNoSignals per page, 1-100. Default 20.
backtestApiKeyNoYour EmidLabs backtest API key. Not needed if this connector was added with a static 'x-api-key' header.
backtestBaseUrlNoDefaults to the public production API.

Output Schema

ParametersJSON Schema
NameRequiredDescription
pageNo
itemsNoThe signals on this page, in candle order.
pageSizeNo
totalCountNoTotal signals across the whole confirmation source, not just this page — can easily be in the thousands for a frequent condition over a long range.
totalPagesNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool readOnly and idempotent, and the description adds substantial non-obvious behavior: every candle-condition match is a row rather than only closed trades, timelines can reach thousands of rows, pagination is mandatory from the start, and the backend automatically applies backward-only state checks and higher-timeframe alignment. This is far beyond what annotations convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and then provides highly relevant warnings. It is somewhat long and contains minor repetition around not reimplementing the alignment logic, but the details are valuable enough that the length is mostly justified.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity, the output schema presence, and the clear sibling context, this description is complete: it explains what the tool returns and why it is paginated, when to use it, when not to use it, and how to accomplish gating correctly instead. Nothing essential is missing for an agent to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds context about pagination and data scale but does not add parameter-specific semantics beyond what the schema already documents for id, page, pageSize, backtestApiKey, and backtestBaseUrl.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a precise verb and resource: 'Fetches a completed confirmation source's raw signal timeline, paginated.' It also clarifies the data's role ('the actual data a backtest's confirmationSources requirement is checked against'), which distinguishes it clearly from sibling tools like get_confirmation_source or submit_confirmation_source.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage guidance is explicit: 'Debugging/inspection only,' 'you do NOT need this tool to make confirmationSources work,' and direct alternatives are provided ('pass its id directly as sourceId in submit_backtest's own confirmationSources array'). It even names the precise diagnostic cases: sanity-check signal density or diagnose low ConfirmedSignalsCount.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_available_assetsList Available AssetsA
Read-onlyIdempotent
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
backtestApiKeyNoYour EmidLabs backtest API key. Not needed if this connector was added with a static 'x-api-key' header.
backtestBaseUrlNoDefaults to the public production API. Override only for self-hosted/staging use.

Output Schema

ParametersJSON Schema
NameRequiredDescription
assetsNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, which covers safety. The description adds useful context by noting the tool is optional and that submit_backtest errors provide the real range, and clarifies it lists only assets with real historical data. This goes beyond the annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured sentence that leads with the core function and then explains usage context and optionality. Every clause adds value; there is no redundancy or wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema, and the description explains purpose, scope, and usage trade-offs with a sibling. It is complete for a read-only list tool. Minor gaps like pagination or result size limits are not mentioned, but these are not essential given the output schema and annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, with both parameters (backtestApiKey and backtestBaseUrl) already described in the schema. The description does not add parameter-specific semantics beyond what the schema provides, so the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists asset pairs with real historical data, including supported timeframes and date ranges. It uses a specific verb ('Lists') and resource ('every asset pair with real historical data'), effectively distinguishing it from the sibling tools submit_backtest and get_backtest_result.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says the tool is optional and explains the alternative: submit_backtest already returns a clear error with the available range. It gives concrete scenarios for use (up-front exploration, recovering from an 'unknown asset' error) and states it is not required before every submit_backtest.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

submit_backtestSubmit BacktestAInspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
assetPairNoe.g. "BTC-USDC".
finalDateNoISO date string, e.g. "2025-06-01".
initialDateNoISO date string, e.g. "2025-01-01".
backtestApiKeyNoYour EmidLabs backtest API key (created in the Console). Not needed if this connector was added with a static 'x-api-key' header.
backtestBaseUrlNoDefaults to the public production API. Override only for self-hosted/staging use.
confirmationSourcesNoOptional. Each entry names a submit_confirmation_source result (same account only, must already be Completed) that every candidate Entry/Exit must be corroborated by before it's simulated as a trade — an unconfirmed candidate is dropped before trade simulation, never appears in get_backtest_trades or affects PnlR/WinRate/etc. See ConfirmedSignalsCount/UnconfirmedSignalsCount on get_backtest_result. A sourceId that doesn't exist, isn't Completed, or belongs to another account fails this submission immediately (unlike live, this is synchronous/batch — letting it through would produce a confusing zero-trade result with no explanation).
strategySnapshotJsonNoThe Strategy DSL object — every field below documents its own exact shape, this is just the execution model that ties them together. Entry fills at the close of the candle where decision.entry turns true (no lookahead). A position closes on the first of these to happen, checked in this order: stop-loss hit, take-profit hit, decision.exit turning true (a same-candle stop/take-profit always wins over exit). Multiple positions can be open at once by default — cap with configuration.maxOpenPositions. Results are measured in R-units (risk multiples); expectancyR (average R per trade) is the metric to optimize, not raw win rate or trade count.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNo
statusNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations are all false and convey no safety profile, so the description carries the burden. It discloses asynchronous behavior ('Returns immediately with an id and status'), points to the polling pattern, and details confirmation-source validation semantics (unconfirmed candidates dropped, invalid sourceId fails submission immediately). This is meaningful behavioral context beyond the annotations, though it stops short of discussing rate limits or duplicate-submission effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a few focused sentences, each earning its place: core purpose, async result flow, batch alternative, and confirmationSources usage. It is front-loaded with the main action and remains scannable despite the somewhat long confirmation-sources sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is complex with 7 parameters and a large strategy DSL schema, but the schema and output schema carry the detailed documentation. The description adds the orchestration context an agent needs: poll get_backtest_result, use the batch variant for many assets, and use confirmation sources for cross-validation. A minor gap is not flagging that strategySnapshotJson is effectively required despite being nullable in the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents every parameter in extensive detail. The tool description adds only the cross-tool pointer to submit_confirmation_source and a 'multi-timeframe or cross-asset confirmation' gloss; it doesn't add syntax or format details beyond what the schema provides. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Submits a strategy for backtesting against historical OHLCV data,' naming the action and resource precisely. It explicitly distinguishes itself from submit_backtest_batch and get_backtest_result, so an agent can tell them apart without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says to use submit_backtest_batch instead when testing the same strategy against many assets, and directs the caller to get_backtest_result to fetch the outcome. It also explains the confirmationSources prerequisite via submit_confirmation_source, giving clear when-to-use and alternative guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

submit_backtest_batchSubmit Backtest BatchAInspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
finalDateNoISO date string, e.g. "2025-06-01".
assetPairsNoe.g. ["BTC-USDC", "ETH-USDC", "SOL-USDC"]. Every asset gets the exact same strategySnapshotJson and date range.
initialDateNoISO date string, e.g. "2025-01-01".
backtestApiKeyNoYour EmidLabs backtest API key (created in the Console). Not needed if this connector was added with a static 'x-api-key' header.
backtestBaseUrlNoDefaults to the public production API. Override only for self-hosted/staging use.
confirmationSourcesNoOptional. A JSON-encoded STRING (not a native array/object — pass it exactly like a quoted string value), containing the same shape as submit_backtest's own confirmationSources: [{"sourceId":"<a submit_confirmation_source id>","signalType":"entry","validityWindow":{"count":1}}]. Applied identically to every asset pair in this batch (one shared gate, not one per asset). Passed as a raw JSON string rather than a native array because this tool already has one array parameter (assetPairs) — a second one crashes the MCP SDK's own parameter marshaller. A sourceId that doesn't exist, isn't Completed, or belongs to another account fails that item only (same best-effort semantics as an unknown asset pair), not the whole batch.
strategySnapshotJsonNoSame Strategy DSL object submit_backtest takes — see that tool's description for the full shape.

Output Schema

ParametersJSON Schema
NameRequiredDescription
itemsNo
batchIdNoPass this to get_backtest_batch_results to fetch every item's status/result, paginated.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are minimal (readOnlyHint=false, destructiveHint=false, idempotentHint=false), so the description carries the behavioral burden. It discloses immediate return behavior, per-asset id/status assignment, and best-effort error isolation for bad asset pairs. This adds meaningful context beyond the annotations, though it does not discuss broader failure modes like authentication errors or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences cover purpose, benefit, return behavior, error semantics, and cross-references, with no filler. The primary action and distinguishing batch behavior are front-loaded before the secondary details about best-effort handling and confirmationSources.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given an output schema exists and the input schema has 100% parameter coverage, the description is complete for invoking the tool correctly. It covers return values, the follow-up results tool, best-effort per-item errors, and the shared strategy/date-range semantics, while deferring the heavy DSL shape to submit_backtest appropriately.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The main description adds a useful pointer that strategySnapshotJson and confirmationSources share semantics with submit_backtest, but it does not add parameter meaning beyond what the input schema already thoroughly documents.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Submits ONE strategy against MANY asset pairs in a single call.' It clearly distinguishes itself from the sibling submit_backtest by emphasizing the batching benefit and the single-call semantics, so an agent can tell the two apart without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly frames the tool as the batched alternative to calling submit_backtest once per asset, and tells the agent to pass the returned batchId to get_backtest_batch_results. It gives clear context for when batch submission is appropriate, though it does not explicitly spell out when not to use it, such as when per-asset confirmationSources are needed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

submit_confirmation_sourceSubmit Confirmation SourceAInspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
assetPairNoe.g. "BTC-USDC".
finalDateNoISO date string, e.g. "2025-06-01".
initialDateNoISO date string, e.g. "2025-01-01".
backtestApiKeyNoYour EmidLabs backtest API key (created in the Console). Not needed if this connector was added with a static 'x-api-key' header.
backtestBaseUrlNoDefaults to the public production API. Override only for self-hosted/staging use.
strategySnapshotJsonNoThe Strategy DSL object — identical shape to submit_backtest's own. riskManagement is accepted but never used (no position is ever opened), so it's fine to omit.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNo
statusNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses behavior well beyond the annotations: no trade, no PnL, no WinRate/drawdown, immediate return of id and status, and identical compute cost to a regular backtest despite skipping trade simulation. This gives the agent a clear mental model of side effects and cost. No contradiction with the annotations exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence adds non-obvious value: the confirmation-only purpose, the no-trade-simulation caveat, the async workflow with get_confirmation_source, and the cost equivalence. It is front-loaded with the most important distinction and avoids filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with complex schema and an output schema, the description covers the full lifecycle: what it does, what it does not do, how to retrieve results, how to wire results into a subsequent backtest, and cost implications. An agent has enough context to invoke it correctly and understand the follow-up steps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already covers 100% of parameters with rich descriptions, including the strategy DSL structure, so the description does not need to enumerate parameters. The tool description adds useful cross-context that the DSL matches submit_backtest's, but parameter-level meaning is otherwise left to the schema, which is sufficient.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific, concrete statement: it 'runs a strategy against historical data purely to produce a signal timeline used to confirm OTHER backtests — not a backtest itself.' It clearly distinguishes this from submit_backtest by stating it never simulates a position, so an agent can understand exactly what this tool produces and how it differs from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage guidance is explicit and actionable: call get_confirmation_source to check completion, then pass the returned id as a confirmationSources sourceId in submit_backtest. It also names the alternative submit_backtest and clarifies this tool is not for standalone trading, giving the agent both the workflow and the when-not-to-use signal.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 3 tool updates
    • Changedsubmit_backtest1 field changed
      • addedInput schema / properties / strategySnapshotJson / properties / configuration / properties / timezone
        Added value: +{
        +  "description": "IANA timezone id (e.g. \"America/Sao_Paulo\") used to localize the DSL's hour()/minute()/dayOfWeek()/isWeekend() functions, for time-of-day or weekday gating conditions. Omit/null defaults to \"America/Sao_Paulo\".",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedsubmit_backtest_batch1 field changed
      • addedInput schema / properties / strategySnapshotJson / properties / configuration / properties / timezone
        Added value: +{
        +  "description": "IANA timezone id (e.g. \"America/Sao_Paulo\") used to localize the DSL's hour()/minute()/dayOfWeek()/isWeekend() functions, for time-of-day or weekday gating conditions. Omit/null defaults to \"America/Sao_Paulo\".",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedsubmit_confirmation_source1 field changed
      • addedInput schema / properties / strategySnapshotJson / properties / configuration / properties / timezone
        Added value: +{
        +  "description": "IANA timezone id (e.g. \"America/Sao_Paulo\") used to localize the DSL's hour()/minute()/dayOfWeek()/isWeekend() functions, for time-of-day or weekday gating conditions. Omit/null defaults to \"America/Sao_Paulo\".",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
  2. 1 tool update
    • Changedsubmit_backtest_batch3 fields changed
      • changedInput schema / properties / confirmationSources / description
        Previous value: -"Optional. Same shape as submit_backtest's own confirmationSources — applied identically to every asset pair in this batch (one shared confirmationSources gate, not one per asset). A sourceId that doesn't exist, isn't Completed, or belongs to another account fails that item only (same best-effort semantics as an unknown asset pair), not the whole batch."New value: +"Optional. A JSON-encoded STRING (not a native array/object — pass it exactly like a quoted string value), containing the same shape as submit_backtest's own confirmationSources: [{\"sourceId\":\"<a submit_confirmation_source id>\",\"signalType\":\"entry\",\"validityWindow\":{\"count\":1}}]. Applied identically to every asset pair in this batch (one shared gate, not one per asset). Passed as a raw JSON string rather than a native array because this tool already has one array parameter (assetPairs) — a second one crashes the MCP SDK's own parameter marshaller. A sourceId that doesn't exist, isn't Completed, or belongs to another account fails that item only (same best-effort semantics as an unknown asset pair), not the whole batch."
      • removedInput schema / properties / confirmationSources / items
        Removed value: -{
        -  "description": "One confirmation requirement: this backtest's own candidate Entry/Exit only counts as a trade once sourceId's own signal timeline is corroborated within validityWindow.",
        -  "properties": {
        -    "signalType": {
        -      "description": "\"entry\" or \"exit\" — which of the source's signal types counts as confirming. Defaults to \"entry\" when omitted.",
        -      "type": [
        -        "string",
        -        "null"
        -      ]
        -    },
        -    "sourceId": {
        -      "description": "The id returned by submit_confirmation_source (same account only) whose signal timeline this backtest's candidates must be corroborated by.",
        -      "type": [
        -        "string",
        -        "null"
        -      ]
        -    },
        -    "validityWindow": {
        -      "description": "An OBJECT, not a bare number — e.g. { \"count\": 5 }. Defaults to { \"count\": 1 } when omitted.",
        -      "properties": {
        -        "count": {
        -          "description": "Number of candles of the source's own timeframe. Defaults to 1 when omitted.",
        -          "type": "integer"
        -        }
        -      },
        -      "type": [
        -        "object",
        -        "null"
        -      ]
        -    }
        -  },
        -  "required": [
        -    "sourceId"
        -  ],
        -  "type": [
        -    "object",
        -    "null"
        -  ]
        -}
      • changedInput schema / properties / confirmationSources / type
        Previous value: -[
        -  "array",
        -  "null"
        -]New value: +[
        +  "string",
        +  "null"
        +]
  3. 2 tool updates
    • Changedsubmit_backtest1 field changed
      • changedInput schema / properties / confirmationSources / items / properties / validityWindow / description
        Previous value: -"How recent the source's own signal must be, expressed in candles of the SOURCE's own timeframe — not a fixed duration, so it scales automatically with whichever strategy is confirming."New value: +"An OBJECT, not a bare number — e.g. { \"count\": 5 }. Defaults to { \"count\": 1 } when omitted."
    • Changedsubmit_backtest_batch1 field changed
      • changedInput schema / properties / confirmationSources / items / properties / validityWindow / description
        Previous value: -"How recent the source's own signal must be, expressed in candles of the SOURCE's own timeframe — not a fixed duration, so it scales automatically with whichever strategy is confirming."New value: +"An OBJECT, not a bare number — e.g. { \"count\": 5 }. Defaults to { \"count\": 1 } when omitted."
  4. 1 tool update
    • Changedsubmit_backtest_batch1 field changed
      • addedInput schema / properties / confirmationSources
        Added value: +{
        +  "default": null,
        +  "description": "Optional. Same shape as submit_backtest's own confirmationSources — applied identically to every asset pair in this batch (one shared confirmationSources gate, not one per asset). A sourceId that doesn't exist, isn't Completed, or belongs to another account fails that item only (same best-effort semantics as an unknown asset pair), not the whole batch.",
        +  "items": {
        +    "description": "One confirmation requirement: this backtest's own candidate Entry/Exit only counts as a trade once sourceId's own signal timeline is corroborated within validityWindow.",
        +    "properties": {
        +      "signalType": {
        +        "description": "\"entry\" or \"exit\" — which of the source's signal types counts as confirming. Defaults to \"entry\" when omitted.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "sourceId": {
        +        "description": "The id returned by submit_confirmation_source (same account only) whose signal timeline this backtest's candidates must be corroborated by.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "validityWindow": {
        +        "description": "How recent the source's own signal must be, expressed in candles of the SOURCE's own timeframe — not a fixed duration, so it scales automatically with whichever strategy is confirming.",
        +        "properties": {
        +          "count": {
        +            "description": "Number of candles of the source's own timeframe. Defaults to 1 when omitted.",
        +            "type": "integer"
        +          }
        +        },
        +        "type": [
        +          "object",
        +          "null"
        +        ]
        +      }
        +    },
        +    "required": [
        +      "sourceId"
        +    ],
        +    "type": [
        +      "object",
        +      "null"
        +    ]
        +  },
        +  "type": [
        +    "array",
        +    "null"
        +  ]
        +}
  5. 6 tool updates
    • Changedget_backtest_batch_results2 fields changed
      • addedOutput schema / properties / items / items / properties / result / properties / confirmedSignalsCount
        Added value: +{
        +  "description": "Only meaningful when the request declared confirmationSources — how many candidates cleared confirmation and became one of the Trades above.",
        +  "type": "integer"
        +}
      • addedOutput schema / properties / items / items / properties / result / properties / unconfirmedSignalsCount
        Added value: +{
        +  "description": "Only meaningful when the request declared confirmationSources — how many candidates were dropped before trade simulation because they weren't corroborated. ConfirmedSignalsCount + UnconfirmedSignalsCount is the total candidate count, same as what a backtest without confirmationSources would have produced.",
        +  "type": "integer"
        +}
    • Changedget_backtest_result2 fields changed
      • addedOutput schema / properties / result / properties / confirmedSignalsCount
        Added value: +{
        +  "description": "Only meaningful when the request declared confirmationSources — how many candidates cleared confirmation and became one of the Trades above.",
        +  "type": "integer"
        +}
      • addedOutput schema / properties / result / properties / unconfirmedSignalsCount
        Added value: +{
        +  "description": "Only meaningful when the request declared confirmationSources — how many candidates were dropped before trade simulation because they weren't corroborated. ConfirmedSignalsCount + UnconfirmedSignalsCount is the total candidate count, same as what a backtest without confirmationSources would have produced.",
        +  "type": "integer"
        +}
    • Addedget_confirmation_source
    • Addedget_confirmation_source_signals
    • Changedsubmit_backtest1 field changed
      • addedInput schema / properties / confirmationSources
        Added value: +{
        +  "default": null,
        +  "description": "Optional. Each entry names a submit_confirmation_source result (same account only, must already be Completed) that every candidate Entry/Exit must be corroborated by before it's simulated as a trade — an unconfirmed candidate is dropped before trade simulation, never appears in get_backtest_trades or affects PnlR/WinRate/etc. See ConfirmedSignalsCount/UnconfirmedSignalsCount on get_backtest_result. A sourceId that doesn't exist, isn't Completed, or belongs to another account fails this submission immediately (unlike live, this is synchronous/batch — letting it through would produce a confusing zero-trade result with no explanation).",
        +  "items": {
        +    "description": "One confirmation requirement: this backtest's own candidate Entry/Exit only counts as a trade once sourceId's own signal timeline is corroborated within validityWindow.",
        +    "properties": {
        +      "signalType": {
        +        "description": "\"entry\" or \"exit\" — which of the source's signal types counts as confirming. Defaults to \"entry\" when omitted.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "sourceId": {
        +        "description": "The id returned by submit_confirmation_source (same account only) whose signal timeline this backtest's candidates must be corroborated by.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      },
        +      "validityWindow": {
        +        "description": "How recent the source's own signal must be, expressed in candles of the SOURCE's own timeframe — not a fixed duration, so it scales automatically with whichever strategy is confirming.",
        +        "properties": {
        +          "count": {
        +            "description": "Number of candles of the source's own timeframe. Defaults to 1 when omitted.",
        +            "type": "integer"
        +          }
        +        },
        +        "type": [
        +          "object",
        +          "null"
        +        ]
        +      }
        +    },
        +    "required": [
        +      "sourceId"
        +    ],
        +    "type": [
        +      "object",
        +      "null"
        +    ]
        +  },
        +  "type": [
        +    "array",
        +    "null"
        +  ]
        +}
    • Addedsubmit_confirmation_source
  6. 2 tool updates
    • Changedget_backtest_batch_results3 fields changed
      • addedOutput schema / properties / items / items / properties / candlesProcessed
        Added value: +{
        +  "description": "Number of candles the analyser processed for this item. Null until Status is \"Completed\". This is raw volume, not the plan's billing unit — see UnitsConsumed for that.",
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / items / items / properties / unitsConsumed / description
        Previous value: -"Number of candles the analyser processed for this item. Null until Status is \"Completed\"."New value: +"The actual execution-unit cost of this item, matching what's debited from the account's plan balance (CandlesProcessed normalized by the account's candles-per-unit rate). Null until Status is \"Completed\"."
      • changedOutput schema / properties / items / items / properties / unitsConsumed / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +[
        +  "number",
        +  "null"
        +]
    • Changedget_backtest_result3 fields changed
      • addedOutput schema / properties / candlesProcessed
        Added value: +{
        +  "description": "Number of candles the analyser processed for this backtest. Null until Status is \"Completed\". This is raw volume, not the plan's billing unit — see UnitsConsumed for that.",
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / unitsConsumed / description
        Previous value: -"Number of candles the analyser processed for this backtest. Null until Status is \"Completed\"."New value: +"The actual execution-unit cost of this backtest, matching what's debited from the account's plan balance (CandlesProcessed normalized by the account's candles-per-unit rate). Null until Status is \"Completed\"."
      • changedOutput schema / properties / unitsConsumed / type
        Previous value: -[
        -  "integer",
        -  "null"
        -]New value: +[
        +  "number",
        +  "null"
        +]
  7. 2 tool updates
    • Changedsubmit_backtest1 field changed
      • changedInput schema / properties / strategySnapshotJson / properties / inputs / description
        Previous value: -"Named computed values, one JSON-string expression each, evaluated once per candle. Raw fields: close, open, high, low, volume. Built-in functions (case-sensitive, lowercase — no others exist, e.g. avg()/SMA() uppercase/close[N] bracket indexing are NOT supported): ema(series,period), sma(series,period), rsi(series,period), atr(period), adx(period), adxPlusDi(period), adxMinusDi(period), crossUp(a,b), crossDown(a,b), highest(series,n), lowest(series,n), change(series), volumeSma(period), volumeSpike(multiplier), body(), range(), upperWick(), lowerWick(), abs(x), min(a,b), max(a,b). Candlestick patterns (all no-arg, boolean, read only closed-candle OHLC, same in backtest and live): single-candle hammer(), shootingStar(), doji(), bullishMarubozu(), bearishMarubozu(), spinningTop(), dragonflyDoji(), gravestoneDoji(), longLeggedDoji(); two-candle bullishEngulfing(), bearishEngulfing(), piercingLine(), darkCloudCover(), bullishHarami(), bearishHarami(), haramiCross(), tweezerTop(), tweezerBottom(); three-plus-candle morningStar(), eveningStar(), threeWhiteSoldiers(), threeBlackCrows(), threeInsideUp(), threeInsideDown(), threeOutsideUp(), threeOutsideDown(), risingThreeMethods(), fallingThreeMethods(). Caveat: hammer()/shootingStar() are shape-only, no prior-trend check (same shape is Hammer in a downtrend but Hanging Man in an uptrend, and vice versa for shootingStar/Inverted Hammer) — pair with a trend/momentum condition rather than using the shape alone. An input may only reference inputs defined above it (no forward/circular references). Example: {\"emaFast\":\"ema(close, 9)\",\"emaSlow\":\"ema(close, 21)\"}"New value: +"Named computed values, one JSON-string expression each, evaluated once per candle. Raw fields: close, open, high, low, volume. Built-in functions (case-sensitive, lowercase — no others exist, e.g. avg()/SMA() uppercase/close[N] bracket indexing are NOT supported): ema(series,period), sma(series,period), rsi(series,period), atr(period), adx(period), adxPlusDi(period), adxMinusDi(period), crossUp(a,b), crossDown(a,b), highest(series,n), lowest(series,n), change(series), shift(series,n) [look-back only, NaN before enough history], any(boolSeries,n), all(boolSeries,n), count(boolSeries,n) [over the n candles before the current one], swingHigh(series,confirmBars), swingLow(series,confirmBars) [confirmed N-bar swing point, true confirmBars candles AFTER the actual peak/trough — never at the peak itself, so it can't repaint between backtest and live], body(), range(), upperWick(), lowerWick(), isBullish(), isBearish(), abs(x), min(a,b), max(a,b). There is no volumeSma()/volumeSpike() — volume is a plain series like close/open/high/low, so use sma(volume,period) and volume > sma(volume,period) * multiplier instead. Candlestick patterns (all no-arg, boolean, read only closed-candle OHLC, same in backtest and live): single-candle hammer(), shootingStar(), doji(), bullishMarubozu(), bearishMarubozu(), spinningTop(), dragonflyDoji(), gravestoneDoji(), longLeggedDoji(); two-candle bullishEngulfing(), bearishEngulfing(), piercingLine(), darkCloudCover(), bullishHarami(), bearishHarami(), haramiCross(), tweezerTop(), tweezerBottom(); three-plus-candle morningStar(), eveningStar(), threeWhiteSoldiers(), threeBlackCrows(), threeInsideUp(), threeInsideDown(), threeOutsideUp(), threeOutsideDown(), risingThreeMethods(), fallingThreeMethods(). Caveat: hammer()/shootingStar() are shape-only, no prior-trend check (same shape is Hammer in a downtrend but Hanging Man in an uptrend, and vice versa for shootingStar/Inverted Hammer) — pair with a trend/momentum condition rather than using the shape alone. An input may only reference inputs defined above it (no forward/circular references). Example: {\"emaFast\":\"ema(close, 9)\",\"emaSlow\":\"ema(close, 21)\"}"
    • Changedsubmit_backtest_batch1 field changed
      • changedInput schema / properties / strategySnapshotJson / properties / inputs / description
        Previous value: -"Named computed values, one JSON-string expression each, evaluated once per candle. Raw fields: close, open, high, low, volume. Built-in functions (case-sensitive, lowercase — no others exist, e.g. avg()/SMA() uppercase/close[N] bracket indexing are NOT supported): ema(series,period), sma(series,period), rsi(series,period), atr(period), adx(period), adxPlusDi(period), adxMinusDi(period), crossUp(a,b), crossDown(a,b), highest(series,n), lowest(series,n), change(series), volumeSma(period), volumeSpike(multiplier), body(), range(), upperWick(), lowerWick(), abs(x), min(a,b), max(a,b). Candlestick patterns (all no-arg, boolean, read only closed-candle OHLC, same in backtest and live): single-candle hammer(), shootingStar(), doji(), bullishMarubozu(), bearishMarubozu(), spinningTop(), dragonflyDoji(), gravestoneDoji(), longLeggedDoji(); two-candle bullishEngulfing(), bearishEngulfing(), piercingLine(), darkCloudCover(), bullishHarami(), bearishHarami(), haramiCross(), tweezerTop(), tweezerBottom(); three-plus-candle morningStar(), eveningStar(), threeWhiteSoldiers(), threeBlackCrows(), threeInsideUp(), threeInsideDown(), threeOutsideUp(), threeOutsideDown(), risingThreeMethods(), fallingThreeMethods(). Caveat: hammer()/shootingStar() are shape-only, no prior-trend check (same shape is Hammer in a downtrend but Hanging Man in an uptrend, and vice versa for shootingStar/Inverted Hammer) — pair with a trend/momentum condition rather than using the shape alone. An input may only reference inputs defined above it (no forward/circular references). Example: {\"emaFast\":\"ema(close, 9)\",\"emaSlow\":\"ema(close, 21)\"}"New value: +"Named computed values, one JSON-string expression each, evaluated once per candle. Raw fields: close, open, high, low, volume. Built-in functions (case-sensitive, lowercase — no others exist, e.g. avg()/SMA() uppercase/close[N] bracket indexing are NOT supported): ema(series,period), sma(series,period), rsi(series,period), atr(period), adx(period), adxPlusDi(period), adxMinusDi(period), crossUp(a,b), crossDown(a,b), highest(series,n), lowest(series,n), change(series), shift(series,n) [look-back only, NaN before enough history], any(boolSeries,n), all(boolSeries,n), count(boolSeries,n) [over the n candles before the current one], swingHigh(series,confirmBars), swingLow(series,confirmBars) [confirmed N-bar swing point, true confirmBars candles AFTER the actual peak/trough — never at the peak itself, so it can't repaint between backtest and live], body(), range(), upperWick(), lowerWick(), isBullish(), isBearish(), abs(x), min(a,b), max(a,b). There is no volumeSma()/volumeSpike() — volume is a plain series like close/open/high/low, so use sma(volume,period) and volume > sma(volume,period) * multiplier instead. Candlestick patterns (all no-arg, boolean, read only closed-candle OHLC, same in backtest and live): single-candle hammer(), shootingStar(), doji(), bullishMarubozu(), bearishMarubozu(), spinningTop(), dragonflyDoji(), gravestoneDoji(), longLeggedDoji(); two-candle bullishEngulfing(), bearishEngulfing(), piercingLine(), darkCloudCover(), bullishHarami(), bearishHarami(), haramiCross(), tweezerTop(), tweezerBottom(); three-plus-candle morningStar(), eveningStar(), threeWhiteSoldiers(), threeBlackCrows(), threeInsideUp(), threeInsideDown(), threeOutsideUp(), threeOutsideDown(), risingThreeMethods(), fallingThreeMethods(). Caveat: hammer()/shootingStar() are shape-only, no prior-trend check (same shape is Hammer in a downtrend but Hanging Man in an uptrend, and vice versa for shootingStar/Inverted Hammer) — pair with a trend/momentum condition rather than using the shape alone. An input may only reference inputs defined above it (no forward/circular references). Example: {\"emaFast\":\"ema(close, 9)\",\"emaSlow\":\"ema(close, 21)\"}"
  8. 2 tool updates
    • Changedsubmit_backtest1 field changed
      • changedInput schema / properties / strategySnapshotJson / properties / inputs / description
        Previous value: -"Named computed values, one JSON-string expression each, evaluated once per candle. Raw fields: close, open, high, low, volume. Built-in functions (case-sensitive, lowercase — no others exist, e.g. avg()/SMA() uppercase/close[N] bracket indexing are NOT supported): ema(series,period), sma(series,period), rsi(series,period), atr(period), adx(period), adxPlusDi(period), adxMinusDi(period), crossUp(a,b), crossDown(a,b), highest(series,n), lowest(series,n), change(series), volumeSma(period), volumeSpike(multiplier), body(), range(), upperWick(), lowerWick(), abs(x), min(a,b), max(a,b). An input may only reference inputs defined above it (no forward/circular references). Example: {\"emaFast\":\"ema(close, 9)\",\"emaSlow\":\"ema(close, 21)\"}"New value: +"Named computed values, one JSON-string expression each, evaluated once per candle. Raw fields: close, open, high, low, volume. Built-in functions (case-sensitive, lowercase — no others exist, e.g. avg()/SMA() uppercase/close[N] bracket indexing are NOT supported): ema(series,period), sma(series,period), rsi(series,period), atr(period), adx(period), adxPlusDi(period), adxMinusDi(period), crossUp(a,b), crossDown(a,b), highest(series,n), lowest(series,n), change(series), volumeSma(period), volumeSpike(multiplier), body(), range(), upperWick(), lowerWick(), abs(x), min(a,b), max(a,b). Candlestick patterns (all no-arg, boolean, read only closed-candle OHLC, same in backtest and live): single-candle hammer(), shootingStar(), doji(), bullishMarubozu(), bearishMarubozu(), spinningTop(), dragonflyDoji(), gravestoneDoji(), longLeggedDoji(); two-candle bullishEngulfing(), bearishEngulfing(), piercingLine(), darkCloudCover(), bullishHarami(), bearishHarami(), haramiCross(), tweezerTop(), tweezerBottom(); three-plus-candle morningStar(), eveningStar(), threeWhiteSoldiers(), threeBlackCrows(), threeInsideUp(), threeInsideDown(), threeOutsideUp(), threeOutsideDown(), risingThreeMethods(), fallingThreeMethods(). Caveat: hammer()/shootingStar() are shape-only, no prior-trend check (same shape is Hammer in a downtrend but Hanging Man in an uptrend, and vice versa for shootingStar/Inverted Hammer) — pair with a trend/momentum condition rather than using the shape alone. An input may only reference inputs defined above it (no forward/circular references). Example: {\"emaFast\":\"ema(close, 9)\",\"emaSlow\":\"ema(close, 21)\"}"
    • Changedsubmit_backtest_batch1 field changed
      • changedInput schema / properties / strategySnapshotJson / properties / inputs / description
        Previous value: -"Named computed values, one JSON-string expression each, evaluated once per candle. Raw fields: close, open, high, low, volume. Built-in functions (case-sensitive, lowercase — no others exist, e.g. avg()/SMA() uppercase/close[N] bracket indexing are NOT supported): ema(series,period), sma(series,period), rsi(series,period), atr(period), adx(period), adxPlusDi(period), adxMinusDi(period), crossUp(a,b), crossDown(a,b), highest(series,n), lowest(series,n), change(series), volumeSma(period), volumeSpike(multiplier), body(), range(), upperWick(), lowerWick(), abs(x), min(a,b), max(a,b). An input may only reference inputs defined above it (no forward/circular references). Example: {\"emaFast\":\"ema(close, 9)\",\"emaSlow\":\"ema(close, 21)\"}"New value: +"Named computed values, one JSON-string expression each, evaluated once per candle. Raw fields: close, open, high, low, volume. Built-in functions (case-sensitive, lowercase — no others exist, e.g. avg()/SMA() uppercase/close[N] bracket indexing are NOT supported): ema(series,period), sma(series,period), rsi(series,period), atr(period), adx(period), adxPlusDi(period), adxMinusDi(period), crossUp(a,b), crossDown(a,b), highest(series,n), lowest(series,n), change(series), volumeSma(period), volumeSpike(multiplier), body(), range(), upperWick(), lowerWick(), abs(x), min(a,b), max(a,b). Candlestick patterns (all no-arg, boolean, read only closed-candle OHLC, same in backtest and live): single-candle hammer(), shootingStar(), doji(), bullishMarubozu(), bearishMarubozu(), spinningTop(), dragonflyDoji(), gravestoneDoji(), longLeggedDoji(); two-candle bullishEngulfing(), bearishEngulfing(), piercingLine(), darkCloudCover(), bullishHarami(), bearishHarami(), haramiCross(), tweezerTop(), tweezerBottom(); three-plus-candle morningStar(), eveningStar(), threeWhiteSoldiers(), threeBlackCrows(), threeInsideUp(), threeInsideDown(), threeOutsideUp(), threeOutsideDown(), risingThreeMethods(), fallingThreeMethods(). Caveat: hammer()/shootingStar() are shape-only, no prior-trend check (same shape is Hammer in a downtrend but Hanging Man in an uptrend, and vice versa for shootingStar/Inverted Hammer) — pair with a trend/momentum condition rather than using the shape alone. An input may only reference inputs defined above it (no forward/circular references). Example: {\"emaFast\":\"ema(close, 9)\",\"emaSlow\":\"ema(close, 21)\"}"
  9. 3 tool updates
    • Changedget_backtest_batch_results6 fields changed
      • changedOutput schema / properties / items / items / properties / result / properties / bothHit / description
        Previous value: -"Trades where both stop-loss and take-profit were hit on the same candle (resolved as stop-loss)."New value: +"Trades where both stop-loss and take-profit were hit on the same candle (resolved as stop-loss). A high BothHit relative to Trades means many trades' outcome was decided by the engine's stop-wins-ties precedence rule rather than real intracandle price path data — treat results with more skepticism the higher this ratio is."
      • changedOutput schema / properties / items / items / properties / result / properties / conditionsDistributionPct / description
        Previous value: -"For each condition name (see strategySnapshotJson.conditions): fraction of candles where it was true."New value: +"For each possible count of simultaneously-true conditions (0, 1, 2...N): fraction of all candles where exactly that many were true at once. A strategy-tuning diagnostic (how selective is the entry setup), not a performance metric."
      • addedOutput schema / properties / items / items / properties / result / properties / currentDrawdownR
        Added value: +{
        +  "description": "How far below its own peak the equity curve sits at the end of the backtest window, in R-units. 0 if the backtest ends at a new high. Includes any still-open position's unrealized PnL (see UnrealizedPnlRAtEnd) — a slump caused by an open, underwater position at window end shows up here.",
        +  "type": "number"
        +}
      • addedOutput schema / properties / items / items / properties / result / properties / maxDrawdownR
        Added value: +{
        +  "description": "Worst peak-to-trough dip across closed trades, in R-units. 0 if equity never fell below its running high-water mark. Historical/all-time — see CurrentDrawdownR for where the equity curve sits right now.",
        +  "type": "number"
        +}
      • addedOutput schema / properties / items / items / properties / result / properties / openPositionsAtEnd
        Added value: +{
        +  "description": "Number of positions still open (never hit stop/take/exit-signal) when the backtest's date range ended. 0 in the common case. Check this before trusting CurrentDrawdownR/UnrealizedPnlRAtEnd at face value.",
        +  "type": "integer"
        +}
      • addedOutput schema / properties / items / items / properties / result / properties / unrealizedPnlRAtEnd
        Added value: +{
        +  "description": "Sum of unrealized PnL, in R-units, across all positions still open at window end — marked to market against the last available candle's close. 0 when OpenPositionsAtEnd is 0. Does NOT include exit fee (the position hasn't closed, so none has been paid) — a slight overestimate of true current drawdown when a position is open. This value feeds ONLY CurrentDrawdownR/MaxDrawdownR — it is never included in PnlR/ExpectancyR/Trades/Wins/Losses or any other metric describing closed, realized trades.",
        +  "type": "number"
        +}
    • Changedget_backtest_result6 fields changed
      • changedOutput schema / properties / result / properties / bothHit / description
        Previous value: -"Trades where both stop-loss and take-profit were hit on the same candle (resolved as stop-loss)."New value: +"Trades where both stop-loss and take-profit were hit on the same candle (resolved as stop-loss). A high BothHit relative to Trades means many trades' outcome was decided by the engine's stop-wins-ties precedence rule rather than real intracandle price path data — treat results with more skepticism the higher this ratio is."
      • changedOutput schema / properties / result / properties / conditionsDistributionPct / description
        Previous value: -"For each condition name (see strategySnapshotJson.conditions): fraction of candles where it was true."New value: +"For each possible count of simultaneously-true conditions (0, 1, 2...N): fraction of all candles where exactly that many were true at once. A strategy-tuning diagnostic (how selective is the entry setup), not a performance metric."
      • addedOutput schema / properties / result / properties / currentDrawdownR
        Added value: +{
        +  "description": "How far below its own peak the equity curve sits at the end of the backtest window, in R-units. 0 if the backtest ends at a new high. Includes any still-open position's unrealized PnL (see UnrealizedPnlRAtEnd) — a slump caused by an open, underwater position at window end shows up here.",
        +  "type": "number"
        +}
      • addedOutput schema / properties / result / properties / maxDrawdownR
        Added value: +{
        +  "description": "Worst peak-to-trough dip across closed trades, in R-units. 0 if equity never fell below its running high-water mark. Historical/all-time — see CurrentDrawdownR for where the equity curve sits right now.",
        +  "type": "number"
        +}
      • addedOutput schema / properties / result / properties / openPositionsAtEnd
        Added value: +{
        +  "description": "Number of positions still open (never hit stop/take/exit-signal) when the backtest's date range ended. 0 in the common case. Check this before trusting CurrentDrawdownR/UnrealizedPnlRAtEnd at face value.",
        +  "type": "integer"
        +}
      • addedOutput schema / properties / result / properties / unrealizedPnlRAtEnd
        Added value: +{
        +  "description": "Sum of unrealized PnL, in R-units, across all positions still open at window end — marked to market against the last available candle's close. 0 when OpenPositionsAtEnd is 0. Does NOT include exit fee (the position hasn't closed, so none has been paid) — a slight overestimate of true current drawdown when a position is open. This value feeds ONLY CurrentDrawdownR/MaxDrawdownR — it is never included in PnlR/ExpectancyR/Trades/Wins/Losses or any other metric describing closed, realized trades.",
        +  "type": "number"
        +}
    • Changedget_backtest_trades10 fields changed
      • addedOutput schema / properties / items / items / properties / conditionsAtEntry / description
        Added value: +"Every named condition from strategySnapshotJson.conditions at entry time — true AND false, not just the ones that were true."
      • addedOutput schema / properties / items / items / properties / entryExecutionCandleOpenTime / description
        Added value: +"Candle open time this trade's entry actually filled on. Currently always equal to EntrySignalCandleOpenTime — see that field's note."
      • addedOutput schema / properties / items / items / properties / entryPrice / description
        Added value: +"Fill price at entry — always the entry candle's close."
      • addedOutput schema / properties / items / items / properties / entrySignalCandleOpenTime / description
        Added value: +"Candle open time this trade's entry signal fired on. Currently always equal to EntryExecutionCandleOpenTime — reserved for a future delayed-fill model (e.g. signal on candle close, execution on next candle open), not yet implemented. Don't rely on these differing today."
      • addedOutput schema / properties / items / items / properties / exitExecutionCandleOpenTime / description
        Added value: +"Candle open time this trade's exit actually filled on. Currently always equal to ExitSignalCandleOpenTime — see that field's note."
      • addedOutput schema / properties / items / items / properties / exitPrice / description
        Added value: +"Fill price at exit — StopPrice, TakePrice, or the exit candle's close, depending on ExitReason."
      • addedOutput schema / properties / items / items / properties / exitSignalCandleOpenTime / description
        Added value: +"Candle open time this trade's exit signal fired on. Currently always equal to ExitExecutionCandleOpenTime — same reserved-for-future-use note as the entry pair."
      • addedOutput schema / properties / items / items / properties / holdingCandles
        Added value: +{
        +  "description": "Timeframe-agnostic candle count the position was held for (exit candle index minus entry candle index). Minimum possible value is 1, not 0 — a position opened on candle i can earliest close on candle i+1. Derive real elapsed time from EntryExecutionCandleOpenTime/ExitExecutionCandleOpenTime if needed.",
        +  "type": "integer"
        +}
      • addedOutput schema / properties / items / items / properties / scoreBreakdownAtEntry / description
        Added value: +"Weight contributed by each condition toward TotalScoreAtEntry — 0 for conditions that were false."
      • addedOutput schema / properties / items / items / properties / totalScoreAtEntry / description
        Added value: +"Total score at entry — the value compared against the threshold in decision.entry."
  10. 5 tool updates
    • Changedget_backtest_batch_results1 field changed
      • addedOutput schema / properties / items / items / properties / result / properties / totalFeeR
        Added value: +{
        +  "description": "Total R subtracted across all trades by configuration.entryFeePct/exitFeePct (0 if neither was set on the request). expectancyR/pnlR above are already net of this — TotalFeeR is just how much fees cost, for diagnostics. Caveat: a trade's fee-in-R cost scales inversely with that trade's own stop distance, so once fees are applied, expectancyR is only a fair comparison WITHIN one archetype's own stop convention — use pnlPct-based metrics (see get_backtest_trades) for comparisons across strategies/timeframes with different typical stop widths.",
        +  "type": "number"
        +}
    • Changedget_backtest_result1 field changed
      • addedOutput schema / properties / result / properties / totalFeeR
        Added value: +{
        +  "description": "Total R subtracted across all trades by configuration.entryFeePct/exitFeePct (0 if neither was set on the request). expectancyR/pnlR above are already net of this — TotalFeeR is just how much fees cost, for diagnostics. Caveat: a trade's fee-in-R cost scales inversely with that trade's own stop distance, so once fees are applied, expectancyR is only a fair comparison WITHIN one archetype's own stop convention — use pnlPct-based metrics (see get_backtest_trades) for comparisons across strategies/timeframes with different typical stop widths.",
        +  "type": "number"
        +}
    • Changedget_backtest_trades4 fields changed
      • addedOutput schema / properties / items / items / properties / feeR
        Added value: +{
        +  "description": "R-units subtracted from this trade's PnlR by configuration.entryFeePct/exitFeePct (0 if neither was set). PnlR is already net of this — PnlR + FeeR recovers the pre-fee raw R. Not directly comparable across trades with different RiskDistance: this scales inversely with each trade's own stop distance.",
        +  "type": "number"
        +}
      • addedOutput schema / properties / items / items / properties / riskDistance
        Added value: +{
        +  "description": "Price distance between EntryPrice and StopPrice — the denominator PnlR/FeeR are expressed in units of.",
        +  "type": "number"
        +}
      • addedOutput schema / properties / items / items / properties / stopPrice
        Added value: +{
        +  "description": "The stop-loss price this trade was risk-managed against.",
        +  "type": "number"
        +}
      • addedOutput schema / properties / items / items / properties / takePrice
        Added value: +{
        +  "description": "The take-profit price this trade was risk-managed against.",
        +  "type": "number"
        +}
    • Changedsubmit_backtest2 fields changed
      • addedInput schema / properties / strategySnapshotJson / properties / configuration / properties / entryFeePct
        Added value: +{
        +  "description": "Simulated exchange fee on entry, as a percent (e.g. 0.1 = 0.1%). Omit/null = 0 (no fee, backward compatible). Subtracted from every trade's pnlR/pnlPct so results are net-of-fee by construction. 0-5 range. See the pnlR/expectancyR field descriptions on get_backtest_result for the R-vs-% caveat once a fee is set.",
        +  "type": [
        +    "number",
        +    "null"
        +  ]
        +}
      • addedInput schema / properties / strategySnapshotJson / properties / configuration / properties / exitFeePct
        Added value: +{
        +  "description": "Simulated exchange fee on exit, as a percent (e.g. 0.1 = 0.1%). Same semantics as EntryFeePct — real exchanges can charge different maker/taker rates per leg, so this is independent, not assumed equal.",
        +  "type": [
        +    "number",
        +    "null"
        +  ]
        +}
    • Changedsubmit_backtest_batch2 fields changed
      • addedInput schema / properties / strategySnapshotJson / properties / configuration / properties / entryFeePct
        Added value: +{
        +  "description": "Simulated exchange fee on entry, as a percent (e.g. 0.1 = 0.1%). Omit/null = 0 (no fee, backward compatible). Subtracted from every trade's pnlR/pnlPct so results are net-of-fee by construction. 0-5 range. See the pnlR/expectancyR field descriptions on get_backtest_result for the R-vs-% caveat once a fee is set.",
        +  "type": [
        +    "number",
        +    "null"
        +  ]
        +}
      • addedInput schema / properties / strategySnapshotJson / properties / configuration / properties / exitFeePct
        Added value: +{
        +  "description": "Simulated exchange fee on exit, as a percent (e.g. 0.1 = 0.1%). Same semantics as EntryFeePct — real exchanges can charge different maker/taker rates per leg, so this is independent, not assumed equal.",
        +  "type": [
        +    "number",
        +    "null"
        +  ]
        +}
  11. 2 tool updates
    • Changedget_backtest_batch_results2 fields changed
      • changedOutput schema / properties / items / items / properties / result / properties / profitFactor / description
        Previous value: -"grossProfitR / abs(grossLossR). Greater than 1 means profitable."New value: +"grossProfitR / abs(grossLossR). Greater than 1 means profitable. Null when there are no losing trades — the ratio is undefined (division by zero), not infinite."
      • changedOutput schema / properties / items / items / properties / result / properties / profitFactor / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
    • Changedget_backtest_result2 fields changed
      • changedOutput schema / properties / result / properties / profitFactor / description
        Previous value: -"grossProfitR / abs(grossLossR). Greater than 1 means profitable."New value: +"grossProfitR / abs(grossLossR). Greater than 1 means profitable. Null when there are no losing trades — the ratio is undefined (division by zero), not infinite."
      • changedOutput schema / properties / result / properties / profitFactor / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
  12. 2 tool updates
    • Changedget_backtest_batch_results2 fields changed
      • addedOutput schema / properties / items / items / properties / runtimeMs
        Added value: +{
        +  "description": "How long the analyser actually took to run this item, in milliseconds — pure compute time. Null until Status is \"Completed\".",
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / items / items / properties / unitsConsumed
        Added value: +{
        +  "description": "Number of candles the analyser processed for this item. Null until Status is \"Completed\".",
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
    • Changedget_backtest_result2 fields changed
      • addedOutput schema / properties / runtimeMs
        Added value: +{
        +  "description": "How long the analyser actually took to run this backtest, in milliseconds — pure compute time, not counting queue/messaging latency. Null until Status is \"Completed\".",
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / unitsConsumed
        Added value: +{
        +  "description": "Number of candles the analyser processed for this backtest. Null until Status is \"Completed\".",
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
  13. 3 tool updates
    • Addedget_backtest_batch_results
    • Changedget_backtest_result3 fields changed
      • addedOutput schema / properties / recentAvgPnlR
        Added value: +{
        +  "description": "Average pnlR of the most recent RecentTradeCount closed trades. This is the recency signal for a rolling ranking — weighted alongside expectancyR, not a replacement for it.",
        +  "type": [
        +    "number",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / recentOutcomes
        Added value: +{
        +  "description": "\"Win\"/\"Loss\" per recent trade, chronological — oldest first, so the LAST element is the most recent trade. Lets a caller see whether recent trades were genuinely a streak (e.g. all \"Loss\") versus alternating, which RecentAvgPnlR alone can't distinguish.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "array",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / recentTradeCount
        Added value: +{
        +  "description": "Number of trades the recency fields below are based on (up to 5, fewer if the backtest has fewer trades). Null until Status is \"Completed\".",
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
    • Addedsubmit_backtest_batch
  14. 1 tool update
    • Addedget_backtest_trades
  15. 2 tool updates
    • Changedget_backtest_result3 fields changed
      • addedInput schema / properties / id / default
        Added value: +null
      • changedInput schema / properties / id / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • removedInput schema / required
        Removed value: -[
        -  "id"
        -]
    • Changedsubmit_backtest18 fields changed
      • addedInput schema / properties / assetPair / default
        Added value: +null
      • changedInput schema / properties / assetPair / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • addedInput schema / properties / finalDate / default
        Added value: +null
      • changedInput schema / properties / finalDate / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • addedInput schema / properties / initialDate / default
        Added value: +null
      • changedInput schema / properties / initialDate / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • addedInput schema / properties / strategySnapshotJson / default
        Added value: +null
      • changedInput schema / properties / strategySnapshotJson / properties / conditions / additionalProperties / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / strategySnapshotJson / properties / conditions / type
        Previous value: -"object"New value: +[
        +  "object",
        +  "null"
        +]
      • changedInput schema / properties / strategySnapshotJson / properties / configuration / properties / timeframe / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / strategySnapshotJson / properties / configuration / type
        Previous value: -"object"New value: +[
        +  "object",
        +  "null"
        +]
      • changedInput schema / properties / strategySnapshotJson / properties / decision / properties / entry / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / strategySnapshotJson / properties / decision / type
        Previous value: -"object"New value: +[
        +  "object",
        +  "null"
        +]
      • changedInput schema / properties / strategySnapshotJson / properties / inputs / additionalProperties / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedInput schema / properties / strategySnapshotJson / properties / inputs / type
        Previous value: -"object"New value: +[
        +  "object",
        +  "null"
        +]
      • changedInput schema / properties / strategySnapshotJson / properties / score / type
        Previous value: -"object"New value: +[
        +  "object",
        +  "null"
        +]
      • changedInput schema / properties / strategySnapshotJson / type
        Previous value: -"object"New value: +[
        +  "object",
        +  "null"
        +]
      • removedInput schema / required
        Removed value: -[
        -  "assetPair",
        -  "initialDate",
        -  "finalDate",
        -  "strategySnapshotJson"
        -]
  16. 1 tool update
    • Changedsubmit_backtest1 field changed
      • changedInput schema / properties / strategySnapshotJson / properties / configuration / properties / timeframe / description
        Previous value: -"One of \"15M\", \"30M\", \"1H\", \"2H\", \"4H\", \"1D\"."New value: +"One of \"5M\", \"15M\", \"30M\", \"1H\", \"2H\", \"4H\", \"1D\"."

Frequently Asked Questions

Discussions

No comments yet. Be the first to start the discussion!

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    exposes a remote MCP endpoint so agents can: run strategy backtests by symbol/timeframe/date range, pass strategy inputs programmatically, receive structured backtest results (trades, win rate, profit, drawdown), keep long-running runs observable via progress notifications, support Binance Futures tickers only, enforce a maximum of 1440 candles per backtest, apply a rate limit of 3 backtests per
    5
    -
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to backtest trading strategies described in plain English, providing access to market data, technical indicators, and comprehensive performance reports.
    13
    1
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides tools to research crypto trading strategies via backtesting, walk-forward validation, and paper trading, with a deflated-Sharpe overfitting check. Enables natural-language-driven analysis and interpretation of strategy performance.
    3
    Apache 2.0
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables backtesting of limit-order strategies on Polymarket's BTC 5-minute markets using historical data, with tools to browse markets, get price series, and run simulations.
    MIT
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

TDQS

A4.5/5.0
Disambiguation5/5

Each tool maps to a distinct resource and action: submitting/fetching backtests, fetching batch results, fetching trades, submitting/fetching confirmation sources, fetching signals, and listing available assets. The singular vs. batch result tools are explicitly cross-referenced and serve different call patterns, so an agent shouldn't confuse them.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern: submit_*, get_*, and list_*. Resource names are clear and predictable, such as backtest, backtest_batch, backtest_trades, confirmation_source, and confirmation_source_signals. The list_/get_ verb variation is conventional and not confusing.

Tool Count5/5

Nine tools is well-scoped for this domain, covering single and batch backtests, result and trade retrieval, asset discovery, and the confirmation-source workflow. Each tool has a distinct role, and none feel like filler or duplication.

Completeness5/5

The tool set covers the full backtesting lifecycle: submit single/batch, fetch aggregate results, fetch trade detail, list available assets, and submit/fetch confirmation sources plus their signals. The confirmation-source workflow integrates cleanly with submit_backtest, and there are no dead ends or obvious missing operations.

Resources