Skip to main content
Glama

luxalgo-mcp-server

Simulate from a real trade series

propfirms_simulate_trades
Read-only

Simulate a challenge by resampling the trader's OWN R-multiple trade series with a stationary block bootstrap instead of a win-rate model. WHY THIS BEATS WIN-RATE MATH: challenge rules are breached by streaks, not by averages - a daily-loss limit dies to a cluster of losses inside one day, and a trailing drawdown dies to a losing streak right after an equity peak. Real trade series are streaky (autocorrelation, volatility clustering, edge that comes and goes), and the stationary bootstrap resamples contiguous blocks of the actual series (geometric length, mean blockMeanLength, default 5 trades), so the trader's real streak structure survives into every simulated day. A parametric model with identical summary statistics shuffles trades independently and therefore understates breach risk for streaky traders. Use propfirms_simulate when only summary stats are available; use this whenever the actual trades are. Provide the series as rSeries (array of R-multiples: each trade's P&L divided by the amount risked on it), rSeriesText (pasted JSON/CSV/whitespace text, optional 'R' suffix per value), or one of the timestamped-log inputs below; exactly one of the four, at least 10 trades, 100+ strongly recommended. Returns the same full SimResult as propfirms_simulate (structuredContent, histograms off by default) plus a text summary that also reports the sample's win rate and mean R. TIMESTAMPED LOGS: tradeLogText accepts a pasted CSV/TSV trade log with a header row (open time and R required; close time and direction optional; loose header names are matched; timestamps without an offset are read as UTC). The R-series and, unless tradesPerDay is passed, the trades-per-day rate are derived from the log, and parse warnings are surfaced in the text output. NEWS WINDOWS: with a timestamped input, newsFilter runs the simulation TWICE on the same seed and options, once on the full history and once without the trades opened inside configurable windows around scheduled releases (a built-in recurring-template calendar of high- and medium-impact events across USD, EUR, GBP, JPY, AUD, CAD, CHF, NZD, plus optional custom event times). The returned SimResult is the news-avoided scenario; structuredContent.newsComparison carries both scenarios' pass probability, funded probability and EV, the excluded-trade count, and a calendar caveat that must be relayed verbatim. PORTFOLIO MODE: tradeLogTexts (2 to 5 logs) merges several timestamped histories into one chronological series and simulates the combined account, so cross-strategy loss clustering survives. Overlap across the histories is ALWAYS analyzed and attached as structuredContent.portfolioOverlap; the text summary carries the audit-risk verdict, and a 'high' verdict is an explicit warning that a prop firm may audit or refuse payouts for correlated accounts. SIMULATED RULES (engine v1): consistency rules (steps[].consistency) and funded payout gating (funded.payoutRules) are actually SIMULATED, not merely flagged - a distinguishing feature of this engine. Consistency uses a rational stop rule (the trader stops a day once more profit cannot help and keeps trading until the best-day share complies - flag 'consistency-stop-rule'); payouts follow a maximum-withdrawal model (withdraw everything the rules allow above buffer/caps, never below the loss floor; balances and floors carry across payouts - flag 'funded-withdrawal-model'); a funded consistency gate is checked per payout window (flag 'funded-consistency-window-approximated'). The pre-1.0 flag id 'funded-payout-resets-account' no longer exists. UNITS: every *Pct rule field and every percent-mode risk value is in PERCENT UNITS (5 = 5%, 0.5 = 0.5%). The one exception is winRate, which is a FRACTION in [0, 1] (0.55 = 55% winners). Probabilities in results are fractions in [0, 1]. DETERMINISM: identical inputs including seed reproduce byte-identical results on any platform. Include the seed and path count when reporting numbers so users can reproduce them exactly; re-run with a few different seeds to gauge Monte Carlo spread. ASSUMPTIONS: every result carries assumptions.flags - dataset-declared rules the engine does NOT simulate (e.g. scaling plans or soft daily lockouts, which make real odds worse than simulated) plus engine simplifications - and assumptions.disclaimer. These are material: always surface the flags and the disclaimer to the user alongside the numbers, never just the headline probability. Results are distributions under stated assumptions, not promises. Composes with any broker-statistics tool: if another MCP server exposes round-trip statistics (winRate, avgWin, avgLoss) or a raw R-multiple series from the user's real trades, feed them here to answer "given my actual trading, what are my odds on this challenge and what risk should I use?". Convert currency statistics to R-multiples by dividing by the average amount risked per trade: winRate stays a fraction, avgWinR = avgWin / avgRisk, avgLossR = |avgLoss| / avgRisk.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
seedNoRNG seed (integer or string). Default 42. Same inputs + seed reproduce byte-identical results - include the seed when reporting so users can reproduce the numbers.
specNoInline challenge ruleset, for challenges not in the directory or for what-if rule edits. Mutually exclusive with firmId/challengeId. Identify the challenge EITHER by directory reference (firmId + challengeId, discovered via propfirms_list_simulatable; firmId accepts the directory id or the firm's name) OR by a full inline `spec` object - the exact shape propfirms_challenge_rules returns, so you can fetch a directory entry, change one rule, and re-simulate to model rule variations. Provide exactly one of the two forms; providing both or neither is an error. Directory references need network access; inline specs are fully offline.
pathsNoMonte Carlo paths (independent simulated trader journeys). Default 10,000 (well under a second); capped at 100,000 per tool call. Confidence intervals shrink roughly with the square root of paths.
firmIdNoDirectory firm id or firm name (e.g. 'ftmo' or 'FTMO'); discover with propfirms_list_simulatable. Must be paired with challengeId. Mutually exclusive with `spec`.
contextYesExplain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as "a user", "the customer", or "an account". Example: "Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution."
rSeriesNoThe trader's real trades as R-multiples in chronological order: each trade's P&L divided by the amount risked on it (+1.8 = won 1.8x risk, -1 = lost exactly the risk, -1.4 = stop slipped 40%). At least 10 trades; 100+ strongly recommended - short series make the simulation overconfident in the sample. Mutually exclusive with rSeriesText, tradeLogText, and tradeLogTexts.
riskModeNoHow riskValue is interpreted. 'percent-of-balance' (default): risk compounds with the current balance. 'percent-of-initial': constant currency risk derived from the initial account size - how most prop traders size, since loss limits are fixed in currency. 'fixed-amount': explicit currency risked per 1R.
riskValueYesRisk per trade - the value of 1R. PERCENT UNITS for percent modes (0.5 = 0.5% risked per trade; a typical prop range is 0.25-2), or a currency amount for 'fixed-amount'. NOT a fraction.
attemptCapNoMaximum challenge attempts per path before that path gives up. Default 25. Journey statistics (expected attempts/cost, P(funded)) are censored at this cap.
importRiskNoRisk per trade for imports that carry P&L but no risk data (e.g. TradingView, MT5 deals, broker JSON, ThinkOrSwim): cash risked per trade ("25") or a percent of entry value ("1%"). Applies to tradeLogText/tradeLogTexts only, is labeled rSource inferred, and is never applied silently: without it such files are refused with needs-risk.
newsFilterNoWhat-if comparison: what are my odds if I do not OPEN trades around scheduled news? Requires a timestamped input (tradeLogText or tradeLogTexts). The simulation runs TWICE with the same seed and options, once on the full history and once with every trade opened inside [event - preMinutes, event + postMinutes] removed; trades opened earlier but held through an event are only counted, not removed. The returned SimResult is the news-AVOIDED scenario; structuredContent.newsComparison carries both scenarios' headline numbers, the excluded-trade count, and a calendar caveat that MUST be relayed to the user (the calendar is a recurring-template approximation of scheduled releases, not a historical feed).
challengeIdNoDirectory challenge id; discover with propfirms_list_simulatable. Must be paired with firmId. Mutually exclusive with `spec`.
rSeriesTextNoThe same series as pasted text: a JSON array, CSV, or whitespace/newline separated numbers, with an optional 'R' suffix per value (e.g. "1.8R, -1R, 0.4, 2.1"). Parsed with the library's parseRSeries; unparseable tokens are reported back. Mutually exclusive with rSeries, tradeLogText, and tradeLogTexts.
tradeLogTextNoThe trader's trades as one pasted TIMESTAMPED log instead of a bare series. Accepted formats, auto-detected: the generic CSV template (header: open time,close time,symbol,direction,quantity,entry price,exit price,stop loss,pnl,fees,r), plain timestamped CSV/TSV logs (open time + R columns), real platform exports: TradingView strategy-tester list of trades (both generations), MT4/MT5 account statements (CSV or pasted HTML), MT5 deals tables, and ThinkOrSwim account statements, plus broker trade-history JSON in the @luxalgo/broker-sdk shape (a bare fills array, {"trades": [...]}, or one snapshot account; fills replay FIFO into round trips with price-based P&L, disclosed). Timestamps WITHOUT an explicit offset are read as UTC. Files that carry P&L but no risk information need importRisk to become R-multiples; ambiguous rule readings are refused with diagnostics rather than guessed, and skipped rows are reported as warnings. Timestamps unlock two things a bare series cannot do: tradesPerDay is derived from the log when not given, and newsFilter can compare odds with and without trading around news. Mutually exclusive with rSeries, rSeriesText, and tradeLogTexts.
tradesPerDayNoAverage trades per simulated trading day. REQUIRED with rSeries/rSeriesText, which carry no timestamps. Optional with tradeLogText/tradeLogTexts: when omitted it is derived from the log's own timestamps (trades divided by distinct UTC trading days) and the output says so. More trades per day means more ways to hit the daily loss limit within a single day.
tradeLogTextsNoPORTFOLIO MODE: 2 to 5 timestamped trade logs (same format as tradeLogText), one per strategy or account. They are merged into one chronological series and the combined account is simulated, which preserves cross-strategy loss clustering (exactly what daily and max loss limits punish). Overlap across the histories is ALWAYS analyzed and attached as structuredContent.portfolioOverlap with an audit-risk verdict; see the attached structuredContent.portfolioOverlap analysis for the methodology. Mutually exclusive with rSeries, rSeriesText, and tradeLogText.
simulateFundedNoWhether to simulate the funded stage (payouts, blowup risk) after passing. Default true - EV is only meaningful with it on; set false to study the evaluation alone.
blockMeanLengthNoMean block length of the stationary bootstrap (geometrically distributed blocks). Default 5 trades. 1 = i.i.d. resampling (destroys streaks - only for comparison); raise toward 10 if the trader's edge comes and goes in long regimes.
fundedHorizonDaysNoFunded-stage horizon in trading days for the payout/EV simulation. Default 90 (about 4 calendar months). EV scales with this choice - state it when reporting EV.
includeHistogramsNoInclude histogram arrays (attempts, cost, net, drawdown) in the result. Default FALSE for this tool to keep responses compact; summary quantiles (p05...p95) are always included.
tradesPerDayModelNo'fixed' (default): the same count every day. 'poisson': daily count drawn Poisson(tradesPerDay); days can then have zero trades, which do not count as trading days.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed22 schema fields changed
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • changedInput schema / properties / context / description
      Previous value: -"Explain why you are calling this tool and how it fits into the user's overall goal. This parameter is used for analytics and user intent tracking. YOU MUST provide 15-25 words (count carefully). NEVER use first person ('I', 'we', 'you') - maintain third-person perspective. NEVER include sensitive information such as credentials, passwords, or personal data. Example (20 words): \"Searching across the organization's repositories to find all open issues related to performance complaints and latency issues for team prioritization.\""New value: +"Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
    • removedInput schema / properties / newsFilter / additionalProperties
      Removed value: -false
    • changedInput schema / properties / seed / anyOf
      Previous value: -[
      -  {
      -    "type": "integer"
      -  },
      -  {
      -    "type": "string"
      -  }
      -]New value: +[
      +  {
      +    "maximum": 9007199254740991,
      +    "minimum": -9007199254740991,
      +    "type": "integer"
      +  },
      +  {
      +    "type": "string"
      +  }
      +]
    • changedInput schema / properties / spec / additionalProperties
      Previous value: -trueNew value: +{}
    • addedInput schema / properties / spec / properties / constraints / propertyNames
      Added value: +{
      +  "type": "string"
      +}
    • changedInput schema / properties / spec / properties / dailyLoss / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": true,
      -    "description": "Daily loss rule: the daily floor is anchor minus limit, reset at each trading-day boundary. Exactly one of pct/amount must be set.",
      -    "properties": {
      -      "amount": {
      -        "description": "Daily loss limit as a fixed currency amount (alternative to pct).",
      -        "exclusiveMinimum": 0,
      -        "type": "number"
      -      },
      -      "basis": {
      -        "description": "Anchor today's loss is measured from: prior day's closing balance or closing equity (they differ only with overnight positions). Default 'prior-day-balance'.",
      -        "enum": [
      -          "prior-day-balance",
      -          "prior-day-equity"
      -        ],
      -        "type": "string"
      -      },
      -      "evaluation": {
      -        "description": "'intraday': fails the moment equity touches the daily floor. 'end-of-day': only the close is checked. Default 'intraday'.",
      -        "enum": [
      -          "intraday",
      -          "end-of-day"
      -        ],
      -        "type": "string"
      -      },
      -      "includesOpenPnl": {
      -        "description": "Whether floating (unrealized) P&L counts toward the daily loss, i.e. breach can happen intra-position. Default true.",
      -        "type": "boolean"
      -      },
      -      "limitBasis": {
      -        "description": "What a percentage limit is a percent OF. 'initial-balance': a fixed currency allowance (always e.g. 5% of the starting account). 'anchor': recomputed daily from the day's anchor. Default 'initial-balance'.",
      -        "enum": [
      -          "initial-balance",
      -          "anchor"
      -        ],
      -        "type": "string"
      -      },
      -      "pct": {
      -        "description": "Daily loss limit in PERCENT UNITS (5 = 5%); what it is a percent OF is set by limitBasis. Exactly one of pct/amount.",
      -        "exclusiveMinimum": 0,
      -        "maximum": 100,
      -        "type": "number"
      -      }
      -    },
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": {},
      +    "description": "Daily loss rule: the daily floor is anchor minus limit, reset at each trading-day boundary. Exactly one of pct/amount must be set.",
      +    "properties": {
      +      "amount": {
      +        "description": "Daily loss limit as a fixed currency amount (alternative to pct).",
      +        "exclusiveMinimum": 0,
      +        "type": "number"
      +      },
      +      "basis": {
      +        "description": "Anchor today's loss is measured from: prior day's closing balance or closing equity (they differ only with overnight positions). Default 'prior-day-balance'.",
      +        "enum": [
      +          "prior-day-balance",
      +          "prior-day-equity"
      +        ],
      +        "type": "string"
      +      },
      +      "evaluation": {
      +        "description": "'intraday': fails the moment equity touches the daily floor. 'end-of-day': only the close is checked. Default 'intraday'.",
      +        "enum": [
      +          "intraday",
      +          "end-of-day"
      +        ],
      +        "type": "string"
      +      },
      +      "includesOpenPnl": {
      +        "description": "Whether floating (unrealized) P&L counts toward the daily loss, i.e. breach can happen intra-position. Default true.",
      +        "type": "boolean"
      +      },
      +      "limitBasis": {
      +        "description": "What a percentage limit is a percent OF. 'initial-balance': a fixed currency allowance (always e.g. 5% of the starting account). 'anchor': recomputed daily from the day's anchor. Default 'initial-balance'.",
      +        "enum": [
      +          "initial-balance",
      +          "anchor"
      +        ],
      +        "type": "string"
      +      },
      +      "pct": {
      +        "description": "Daily loss limit in PERCENT UNITS (5 = 5%); what it is a percent OF is set by limitBasis. Exactly one of pct/amount.",
      +        "exclusiveMinimum": 0,
      +        "maximum": 100,
      +        "type": "number"
      +      }
      +    },
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / properties / spec / properties / fees / additionalProperties
      Previous value: -trueNew value: +{}
    • changedInput schema / properties / spec / properties / funded / additionalProperties
      Previous value: -trueNew value: +{}
    • changedInput schema / properties / spec / properties / funded / properties / dailyLoss / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": true,
      -    "description": "Daily loss rule: the daily floor is anchor minus limit, reset at each trading-day boundary. Exactly one of pct/amount must be set.",
      -    "properties": {
      -      "amount": {
      -        "description": "Daily loss limit as a fixed currency amount (alternative to pct).",
      -        "exclusiveMinimum": 0,
      -        "type": "number"
      -      },
      -      "basis": {
      -        "description": "Anchor today's loss is measured from: prior day's closing balance or closing equity (they differ only with overnight positions). Default 'prior-day-balance'.",
      -        "enum": [
      -          "prior-day-balance",
      -          "prior-day-equity"
      -        ],
      -        "type": "string"
      -      },
      -      "evaluation": {
      -        "description": "'intraday': fails the moment equity touches the daily floor. 'end-of-day': only the close is checked. Default 'intraday'.",
      -        "enum": [
      -          "intraday",
      -          "end-of-day"
      -        ],
      -        "type": "string"
      -      },
      -      "includesOpenPnl": {
      -        "description": "Whether floating (unrealized) P&L counts toward the daily loss, i.e. breach can happen intra-position. Default true.",
      -        "type": "boolean"
      -      },
      -      "limitBasis": {
      -        "description": "What a percentage limit is a percent OF. 'initial-balance': a fixed currency allowance (always e.g. 5% of the starting account). 'anchor': recomputed daily from the day's anchor. Default 'initial-balance'.",
      -        "enum": [
      -          "initial-balance",
      -          "anchor"
      -        ],
      -        "type": "string"
      -      },
      -      "pct": {
      -        "description": "Daily loss limit in PERCENT UNITS (5 = 5%); what it is a percent OF is set by limitBasis. Exactly one of pct/amount.",
      -        "exclusiveMinimum": 0,
      -        "maximum": 100,
      -        "type": "number"
      -      }
      -    },
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": {},
      +    "description": "Daily loss rule: the daily floor is anchor minus limit, reset at each trading-day boundary. Exactly one of pct/amount must be set.",
      +    "properties": {
      +      "amount": {
      +        "description": "Daily loss limit as a fixed currency amount (alternative to pct).",
      +        "exclusiveMinimum": 0,
      +        "type": "number"
      +      },
      +      "basis": {
      +        "description": "Anchor today's loss is measured from: prior day's closing balance or closing equity (they differ only with overnight positions). Default 'prior-day-balance'.",
      +        "enum": [
      +          "prior-day-balance",
      +          "prior-day-equity"
      +        ],
      +        "type": "string"
      +      },
      +      "evaluation": {
      +        "description": "'intraday': fails the moment equity touches the daily floor. 'end-of-day': only the close is checked. Default 'intraday'.",
      +        "enum": [
      +          "intraday",
      +          "end-of-day"
      +        ],
      +        "type": "string"
      +      },
      +      "includesOpenPnl": {
      +        "description": "Whether floating (unrealized) P&L counts toward the daily loss, i.e. breach can happen intra-position. Default true.",
      +        "type": "boolean"
      +      },
      +      "limitBasis": {
      +        "description": "What a percentage limit is a percent OF. 'initial-balance': a fixed currency allowance (always e.g. 5% of the starting account). 'anchor': recomputed daily from the day's anchor. Default 'initial-balance'.",
      +        "enum": [
      +          "initial-balance",
      +          "anchor"
      +        ],
      +        "type": "string"
      +      },
      +      "pct": {
      +        "description": "Daily loss limit in PERCENT UNITS (5 = 5%); what it is a percent OF is set by limitBasis. Exactly one of pct/amount.",
      +        "exclusiveMinimum": 0,
      +        "maximum": 100,
      +        "type": "number"
      +      }
      +    },
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • addedInput schema / properties / spec / properties / funded / properties / firstPayoutMinDays / maximum
      Added value: +9007199254740991
    • changedInput schema / properties / spec / properties / funded / properties / maxLoss / additionalProperties
      Previous value: -trueNew value: +{}
    • changedInput schema / properties / spec / properties / funded / properties / payoutRules / additionalProperties
      Previous value: -trueNew value: +{}
    • addedInput schema / properties / spec / properties / funded / properties / payoutRules / properties / minWinningDays / maximum
      Added value: +9007199254740991
    • changedInput schema / properties / spec / properties / maxLoss / additionalProperties
      Previous value: -trueNew value: +{}
    • changedInput schema / properties / spec / properties / sources / items / additionalProperties
      Previous value: -trueNew value: +{}
    • changedInput schema / properties / spec / properties / steps / items / additionalProperties
      Previous value: -trueNew value: +{}
    • changedInput schema / properties / spec / properties / steps / items / properties / consistency / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": true,
      -    "properties": {
      -      "maxBestDayProfitPct": {
      -        "description": "Maximum share of the step's total profit the best single day may contribute, in PERCENT UNITS (40 = the best day may be at most 40% of total profit).",
      -        "exclusiveMinimum": 0,
      -        "maximum": 100,
      -        "type": "number"
      -      }
      -    },
      -    "required": [
      -      "maxBestDayProfitPct"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": {},
      +    "properties": {
      +      "maxBestDayProfitPct": {
      +        "description": "Maximum share of the step's total profit the best single day may contribute, in PERCENT UNITS (40 = the best day may be at most 40% of total profit).",
      +        "exclusiveMinimum": 0,
      +        "maximum": 100,
      +        "type": "number"
      +      }
      +    },
      +    "required": [
      +      "maxBestDayProfitPct"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / properties / spec / properties / steps / items / properties / dailyLoss / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": true,
      -    "description": "Daily loss rule: the daily floor is anchor minus limit, reset at each trading-day boundary. Exactly one of pct/amount must be set.",
      -    "properties": {
      -      "amount": {
      -        "description": "Daily loss limit as a fixed currency amount (alternative to pct).",
      -        "exclusiveMinimum": 0,
      -        "type": "number"
      -      },
      -      "basis": {
      -        "description": "Anchor today's loss is measured from: prior day's closing balance or closing equity (they differ only with overnight positions). Default 'prior-day-balance'.",
      -        "enum": [
      -          "prior-day-balance",
      -          "prior-day-equity"
      -        ],
      -        "type": "string"
      -      },
      -      "evaluation": {
      -        "description": "'intraday': fails the moment equity touches the daily floor. 'end-of-day': only the close is checked. Default 'intraday'.",
      -        "enum": [
      -          "intraday",
      -          "end-of-day"
      -        ],
      -        "type": "string"
      -      },
      -      "includesOpenPnl": {
      -        "description": "Whether floating (unrealized) P&L counts toward the daily loss, i.e. breach can happen intra-position. Default true.",
      -        "type": "boolean"
      -      },
      -      "limitBasis": {
      -        "description": "What a percentage limit is a percent OF. 'initial-balance': a fixed currency allowance (always e.g. 5% of the starting account). 'anchor': recomputed daily from the day's anchor. Default 'initial-balance'.",
      -        "enum": [
      -          "initial-balance",
      -          "anchor"
      -        ],
      -        "type": "string"
      -      },
      -      "pct": {
      -        "description": "Daily loss limit in PERCENT UNITS (5 = 5%); what it is a percent OF is set by limitBasis. Exactly one of pct/amount.",
      -        "exclusiveMinimum": 0,
      -        "maximum": 100,
      -        "type": "number"
      -      }
      -    },
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": {},
      +    "description": "Daily loss rule: the daily floor is anchor minus limit, reset at each trading-day boundary. Exactly one of pct/amount must be set.",
      +    "properties": {
      +      "amount": {
      +        "description": "Daily loss limit as a fixed currency amount (alternative to pct).",
      +        "exclusiveMinimum": 0,
      +        "type": "number"
      +      },
      +      "basis": {
      +        "description": "Anchor today's loss is measured from: prior day's closing balance or closing equity (they differ only with overnight positions). Default 'prior-day-balance'.",
      +        "enum": [
      +          "prior-day-balance",
      +          "prior-day-equity"
      +        ],
      +        "type": "string"
      +      },
      +      "evaluation": {
      +        "description": "'intraday': fails the moment equity touches the daily floor. 'end-of-day': only the close is checked. Default 'intraday'.",
      +        "enum": [
      +          "intraday",
      +          "end-of-day"
      +        ],
      +        "type": "string"
      +      },
      +      "includesOpenPnl": {
      +        "description": "Whether floating (unrealized) P&L counts toward the daily loss, i.e. breach can happen intra-position. Default true.",
      +        "type": "boolean"
      +      },
      +      "limitBasis": {
      +        "description": "What a percentage limit is a percent OF. 'initial-balance': a fixed currency allowance (always e.g. 5% of the starting account). 'anchor': recomputed daily from the day's anchor. Default 'initial-balance'.",
      +        "enum": [
      +          "initial-balance",
      +          "anchor"
      +        ],
      +        "type": "string"
      +      },
      +      "pct": {
      +        "description": "Daily loss limit in PERCENT UNITS (5 = 5%); what it is a percent OF is set by limitBasis. Exactly one of pct/amount.",
      +        "exclusiveMinimum": 0,
      +        "maximum": 100,
      +        "type": "number"
      +      }
      +    },
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / properties / spec / properties / steps / items / properties / maxDays / anyOf
      Previous value: -[
      -  {
      -    "exclusiveMinimum": 0,
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "exclusiveMinimum": 0,
      +    "maximum": 9007199254740991,
      +    "type": "integer"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / properties / spec / properties / steps / items / properties / maxLoss / additionalProperties
      Previous value: -trueNew value: +{}
    • addedInput schema / properties / spec / properties / steps / items / properties / minTradingDays / maximum
      Added value: +9007199254740991
  2. Changed5 schema fields changed
    • removedInput schema / additionalProperties
      Removed value: -false
    • addedInput schema / properties / context
      Added value: +{
      +  "description": "Explain why you are calling this tool and how it fits into the user's overall goal. This parameter is used for analytics and user intent tracking. YOU MUST provide 15-25 words (count carefully). NEVER use first person ('I', 'we', 'you') - maintain third-person perspective. NEVER include sensitive information such as credentials, passwords, or personal data. Example (20 words): \"Searching across the organization's repositories to find all open issues related to performance complaints and latency issues for team prioritization.\"",
      +  "type": "string"
      +}
    • changedInput schema / properties / importRisk / description
      Previous value: -"Risk per trade for imports that carry P&L but no risk data (e.g. TradingView, MT5 deals, ThinkOrSwim): cash risked per trade (\"25\") or a percent of entry value (\"1%\"). Applies to tradeLogText/tradeLogTexts only, is labeled rSource inferred, and is never applied silently: without it such files are refused with needs-risk."New value: +"Risk per trade for imports that carry P&L but no risk data (e.g. TradingView, MT5 deals, broker JSON, ThinkOrSwim): cash risked per trade (\"25\") or a percent of entry value (\"1%\"). Applies to tradeLogText/tradeLogTexts only, is labeled rSource inferred, and is never applied silently: without it such files are refused with needs-risk."
    • changedInput schema / properties / tradeLogText / description
      Previous value: -"The trader's trades as one pasted TIMESTAMPED log instead of a bare series. Accepted formats, auto-detected: the generic CSV template (header: open time,close time,symbol,direction,quantity,entry price,exit price,stop loss,pnl,fees,r), plain timestamped CSV/TSV logs (open time + R columns), and real platform exports: TradingView strategy-tester list of trades (both generations), MT4/MT5 account statements (CSV or pasted HTML), MT5 deals tables, and ThinkOrSwim account statements. Timestamps WITHOUT an explicit offset are read as UTC. Files that carry P&L but no risk information need importRisk to become R-multiples; ambiguous rule readings are refused with diagnostics rather than guessed, and skipped rows are reported as warnings. Timestamps unlock two things a bare series cannot do: tradesPerDay is derived from the log when not given, and newsFilter can compare odds with and without trading around news. Mutually exclusive with rSeries, rSeriesText, and tradeLogTexts."New value: +"The trader's trades as one pasted TIMESTAMPED log instead of a bare series. Accepted formats, auto-detected: the generic CSV template (header: open time,close time,symbol,direction,quantity,entry price,exit price,stop loss,pnl,fees,r), plain timestamped CSV/TSV logs (open time + R columns), real platform exports: TradingView strategy-tester list of trades (both generations), MT4/MT5 account statements (CSV or pasted HTML), MT5 deals tables, and ThinkOrSwim account statements, plus broker trade-history JSON in the @luxalgo/broker-sdk shape (a bare fills array, {\"trades\": [...]}, or one snapshot account; fills replay FIFO into round trips with price-based P&L, disclosed). Timestamps WITHOUT an explicit offset are read as UTC. Files that carry P&L but no risk information need importRisk to become R-multiples; ambiguous rule readings are refused with diagnostics rather than guessed, and skipped rows are reported as warnings. Timestamps unlock two things a bare series cannot do: tradesPerDay is derived from the log when not given, and newsFilter can compare odds with and without trading around news. Mutually exclusive with rSeries, rSeriesText, and tradeLogTexts."
    • changedInput schema / required
      Previous value: -[
      -  "riskValue"
      -]New value: +[
      +  "riskValue",
      +  "context"
      +]
  3. Changed17 schema fields changed
    • changedInput schema / properties / blockMeanLength / description
      Previous value: -"Mean block length of the stationary bootstrap (geometrically distributed blocks). Default 5 trades. 1 = i.i.d. resampling (destroys streaks — only for comparison); raise toward 10 if the trader's edge comes and goes in long regimes."New value: +"Mean block length of the stationary bootstrap (geometrically distributed blocks). Default 5 trades. 1 = i.i.d. resampling (destroys streaks - only for comparison); raise toward 10 if the trader's edge comes and goes in long regimes."
    • changedInput schema / properties / fundedHorizonDays / description
      Previous value: -"Funded-stage horizon in trading days for the payout/EV simulation. Default 90 (about 4 calendar months). EV scales with this choice — state it when reporting EV."New value: +"Funded-stage horizon in trading days for the payout/EV simulation. Default 90 (about 4 calendar months). EV scales with this choice - state it when reporting EV."
    • addedInput schema / properties / importRisk
      Added value: +{
      +  "description": "Risk per trade for imports that carry P&L but no risk data (e.g. TradingView, MT5 deals, ThinkOrSwim): cash risked per trade (\"25\") or a percent of entry value (\"1%\"). Applies to tradeLogText/tradeLogTexts only, is labeled rSource inferred, and is never applied silently: without it such files are refused with needs-risk.",
      +  "type": "string"
      +}
    • changedInput schema / properties / rSeries / description
      Previous value: -"The trader's real trades as R-multiples in chronological order: each trade's P&L divided by the amount risked on it (+1.8 = won 1.8x risk, -1 = lost exactly the risk, -1.4 = stop slipped 40%). At least 10 trades; 100+ strongly recommended — short series make the simulation overconfident in the sample. Mutually exclusive with rSeriesText, tradeLogText, and tradeLogTexts."New value: +"The trader's real trades as R-multiples in chronological order: each trade's P&L divided by the amount risked on it (+1.8 = won 1.8x risk, -1 = lost exactly the risk, -1.4 = stop slipped 40%). At least 10 trades; 100+ strongly recommended - short series make the simulation overconfident in the sample. Mutually exclusive with rSeriesText, tradeLogText, and tradeLogTexts."
    • changedInput schema / properties / riskMode / description
      Previous value: -"How riskValue is interpreted. 'percent-of-balance' (default): risk compounds with the current balance. 'percent-of-initial': constant currency risk derived from the initial account size — how most prop traders size, since loss limits are fixed in currency. 'fixed-amount': explicit currency risked per 1R."New value: +"How riskValue is interpreted. 'percent-of-balance' (default): risk compounds with the current balance. 'percent-of-initial': constant currency risk derived from the initial account size - how most prop traders size, since loss limits are fixed in currency. 'fixed-amount': explicit currency risked per 1R."
    • changedInput schema / properties / riskValue / description
      Previous value: -"Risk per trade — the value of 1R. PERCENT UNITS for percent modes (0.5 = 0.5% risked per trade; a typical prop range is 0.25-2), or a currency amount for 'fixed-amount'. NOT a fraction."New value: +"Risk per trade - the value of 1R. PERCENT UNITS for percent modes (0.5 = 0.5% risked per trade; a typical prop range is 0.25-2), or a currency amount for 'fixed-amount'. NOT a fraction."
    • changedInput schema / properties / seed / description
      Previous value: -"RNG seed (integer or string). Default 42. Same inputs + seed reproduce byte-identical results — include the seed when reporting so users can reproduce the numbers."New value: +"RNG seed (integer or string). Default 42. Same inputs + seed reproduce byte-identical results - include the seed when reporting so users can reproduce the numbers."
    • changedInput schema / properties / simulateFunded / description
      Previous value: -"Whether to simulate the funded stage (payouts, blowup risk) after passing. Default true — EV is only meaningful with it on; set false to study the evaluation alone."New value: +"Whether to simulate the funded stage (payouts, blowup risk) after passing. Default true - EV is only meaningful with it on; set false to study the evaluation alone."
    • changedInput schema / properties / spec / description
      Previous value: -"Inline challenge ruleset, for challenges not in the directory or for what-if rule edits. Mutually exclusive with firmId/challengeId. Identify the challenge EITHER by directory reference (firmId + challengeId, discovered via propfirms_list_simulatable; firmId accepts the directory id or the firm's name) OR by a full inline `spec` object — the exact shape propfirms_challenge_rules returns, so you can fetch a directory entry, change one rule, and re-simulate to model rule variations. Provide exactly one of the two forms; providing both or neither is an error. Directory references need network access; inline specs are fully offline."New value: +"Inline challenge ruleset, for challenges not in the directory or for what-if rule edits. Mutually exclusive with firmId/challengeId. Identify the challenge EITHER by directory reference (firmId + challengeId, discovered via propfirms_list_simulatable; firmId accepts the directory id or the firm's name) OR by a full inline `spec` object - the exact shape propfirms_challenge_rules returns, so you can fetch a directory entry, change one rule, and re-simulate to model rule variations. Provide exactly one of the two forms; providing both or neither is an error. Directory references need network access; inline specs are fully offline."
    • changedInput schema / properties / spec / properties / fees / description
      Previous value: -"Fees — everything that goes into expected total cost."New value: +"Fees - everything that goes into expected total cost."
    • changedInput schema / properties / spec / properties / flagsNotSimulated / description
      Previous value: -"Honesty channel: ids of rules this entry has that the engine does not simulate (e.g. 'scaling-plan', 'soft-daily-lockout'). Surfaced in every result's assumption flags. Consistency rules and payout gating do NOT belong here — the engine simulates them."New value: +"Honesty channel: ids of rules this entry has that the engine does not simulate (e.g. 'scaling-plan', 'soft-daily-lockout'). Surfaced in every result's assumption flags. Consistency rules and payout gating do NOT belong here - the engine simulates them."
    • changedInput schema / properties / spec / properties / funded / properties / maxLoss / properties / mode / description
      Previous value: -"How the max-loss floor behaves — the single most consequential rule difference between firms. 'static-initial': floor fixed at initial balance minus the limit; never moves (classic CFD two-step). 'trailing-realized-eod': floor ratchets up with end-of-day balance highs; intraday highs do not move it. 'trailing-intraday-unrealized': floor trails the peak unrealized equity intraday and never stops trailing (futures-style; the most-miscalculated rule in the industry: it cuts pass probability dramatically). 'trailing-locks-at-initial': trails intraday peak equity until the floor reaches the initial balance, then freezes (common futures variant). Locking is also composable: locksAtInitial adds the same lock to an EOD trail, and lockOffsetAmount shifts the lock level to initial balance + that amount (e.g. 100 models 'stops trailing $100 above the start')."New value: +"How the max-loss floor behaves - the single most consequential rule difference between firms. 'static-initial': floor fixed at initial balance minus the limit; never moves (classic CFD two-step). 'trailing-realized-eod': floor ratchets up with end-of-day balance highs; intraday highs do not move it. 'trailing-intraday-unrealized': floor trails the peak unrealized equity intraday and never stops trailing (futures-style; the most-miscalculated rule in the industry: it cuts pass probability dramatically). 'trailing-locks-at-initial': trails intraday peak equity until the floor reaches the initial balance, then freezes (common futures variant). Locking is also composable: locksAtInitial adds the same lock to an EOD trail, and lockOffsetAmount shifts the lock level to initial balance + that amount (e.g. 100 models 'stops trailing $100 above the start')."
    • changedInput schema / properties / spec / properties / funded / properties / payoutRules / description
      Previous value: -"Payout gating — SIMULATED (engine v1), not just flagged: a payout happens only when these conditions are met, and on each eligible payout day the trader withdraws the maximum the rules allow (profit above the buffer, under the caps, never below the loss floor); balances and loss floors carry across payouts (see flag 'funded-withdrawal-model'). Omit for ungated payouts."New value: +"Payout gating - SIMULATED (engine v1), not just flagged: a payout happens only when these conditions are met, and on each eligible payout day the trader withdraws the maximum the rules allow (profit above the buffer, under the caps, never below the loss floor); balances and loss floors carry across payouts (see flag 'funded-withdrawal-model'). Omit for ungated payouts."
    • changedInput schema / properties / spec / properties / maxLoss / properties / mode / description
      Previous value: -"How the max-loss floor behaves — the single most consequential rule difference between firms. 'static-initial': floor fixed at initial balance minus the limit; never moves (classic CFD two-step). 'trailing-realized-eod': floor ratchets up with end-of-day balance highs; intraday highs do not move it. 'trailing-intraday-unrealized': floor trails the peak unrealized equity intraday and never stops trailing (futures-style; the most-miscalculated rule in the industry: it cuts pass probability dramatically). 'trailing-locks-at-initial': trails intraday peak equity until the floor reaches the initial balance, then freezes (common futures variant). Locking is also composable: locksAtInitial adds the same lock to an EOD trail, and lockOffsetAmount shifts the lock level to initial balance + that amount (e.g. 100 models 'stops trailing $100 above the start')."New value: +"How the max-loss floor behaves - the single most consequential rule difference between firms. 'static-initial': floor fixed at initial balance minus the limit; never moves (classic CFD two-step). 'trailing-realized-eod': floor ratchets up with end-of-day balance highs; intraday highs do not move it. 'trailing-intraday-unrealized': floor trails the peak unrealized equity intraday and never stops trailing (futures-style; the most-miscalculated rule in the industry: it cuts pass probability dramatically). 'trailing-locks-at-initial': trails intraday peak equity until the floor reaches the initial balance, then freezes (common futures variant). Locking is also composable: locksAtInitial adds the same lock to an EOD trail, and lockOffsetAmount shifts the lock level to initial balance + that amount (e.g. 100 models 'stops trailing $100 above the start')."
    • changedInput schema / properties / spec / properties / steps / items / properties / consistency / description
      Previous value: -"Consistency rule — SIMULATED (engine v1), not just flagged: one outsized day effectively raises the target (total profit must reach best day / pct), and the simulated trader keeps trading — rationally stopping days early when that helps — until the best-day share complies (see flag 'consistency-stop-rule'). null or omitted = no consistency rule."New value: +"Consistency rule - SIMULATED (engine v1), not just flagged: one outsized day effectively raises the target (total profit must reach best day / pct), and the simulated trader keeps trading - rationally stopping days early when that helps - until the best-day share complies (see flag 'consistency-stop-rule'). null or omitted = no consistency rule."
    • changedInput schema / properties / spec / properties / steps / items / properties / maxLoss / properties / mode / description
      Previous value: -"How the max-loss floor behaves — the single most consequential rule difference between firms. 'static-initial': floor fixed at initial balance minus the limit; never moves (classic CFD two-step). 'trailing-realized-eod': floor ratchets up with end-of-day balance highs; intraday highs do not move it. 'trailing-intraday-unrealized': floor trails the peak unrealized equity intraday and never stops trailing (futures-style; the most-miscalculated rule in the industry: it cuts pass probability dramatically). 'trailing-locks-at-initial': trails intraday peak equity until the floor reaches the initial balance, then freezes (common futures variant). Locking is also composable: locksAtInitial adds the same lock to an EOD trail, and lockOffsetAmount shifts the lock level to initial balance + that amount (e.g. 100 models 'stops trailing $100 above the start')."New value: +"How the max-loss floor behaves - the single most consequential rule difference between firms. 'static-initial': floor fixed at initial balance minus the limit; never moves (classic CFD two-step). 'trailing-realized-eod': floor ratchets up with end-of-day balance highs; intraday highs do not move it. 'trailing-intraday-unrealized': floor trails the peak unrealized equity intraday and never stops trailing (futures-style; the most-miscalculated rule in the industry: it cuts pass probability dramatically). 'trailing-locks-at-initial': trails intraday peak equity until the floor reaches the initial balance, then freezes (common futures variant). Locking is also composable: locksAtInitial adds the same lock to an EOD trail, and lockOffsetAmount shifts the lock level to initial balance + that amount (e.g. 100 models 'stops trailing $100 above the start')."
    • changedInput schema / properties / tradeLogText / description
      Previous value: -"The trader's trades as one pasted TIMESTAMPED log instead of a bare series. Format: CSV/TSV/semicolon text with a header row. Required columns: an open time (openedAt/entry/time/date; ISO 8601, 'YYYY-MM-DD HH:mm', MT4/MT5 'YYYY.MM.DD HH:mm', or epoch seconds/ms; timestamps WITHOUT an explicit offset are read as UTC) and an R-multiple result (r/rMultiple/result, optional 'R' suffix). Optional columns: close time (closedAt/exit) and direction (direction/side; long/buy or short/sell). Unparseable rows are skipped and reported as warnings in the text output. Timestamps unlock two things a bare series cannot do: tradesPerDay is derived from the log when not given, and newsFilter can compare odds with and without trading around news. Mutually exclusive with rSeries, rSeriesText, and tradeLogTexts."New value: +"The trader's trades as one pasted TIMESTAMPED log instead of a bare series. Accepted formats, auto-detected: the generic CSV template (header: open time,close time,symbol,direction,quantity,entry price,exit price,stop loss,pnl,fees,r), plain timestamped CSV/TSV logs (open time + R columns), and real platform exports: TradingView strategy-tester list of trades (both generations), MT4/MT5 account statements (CSV or pasted HTML), MT5 deals tables, and ThinkOrSwim account statements. Timestamps WITHOUT an explicit offset are read as UTC. Files that carry P&L but no risk information need importRisk to become R-multiples; ambiguous rule readings are refused with diagnostics rather than guessed, and skipped rows are reported as warnings. Timestamps unlock two things a bare series cannot do: tradesPerDay is derived from the log when not given, and newsFilter can compare odds with and without trading around news. Mutually exclusive with rSeries, rSeriesText, and tradeLogTexts."
  4. Added

TDQS

A5/5.0
Behavior5/5

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

Beyond the readOnlyHint/openWorldHint annotations, the description discloses material behavior: consistency rules and payout gating are truly simulated, newsFilter runs the simulation twice on the same seed, portfolio mode merges logs and attaches overlap analysis, results carry assumptions.flags/disclaimer that must be surfaced, and identical inputs plus seed reproduce byte-identical results. No contradiction with annotations exists; the description substantially extends 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 long but tightly organized into labeled sections (TIMESTAMPED LOGS, NEWS WINDOWS, PORTFOLIO MODE, SIMULATED RULES, UNITS, DETERMINISM, ASSUMPTIONS), each carrying load-bearing information. The core mechanism and sibling differentiation are front-loaded in the first sentences, and the promotional 'WHY THIS BEATS WIN-RATE MATH' section earns its place by explaining when bootstrap resampling matters.

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 21-parameter tool with nested objects and no output schema, the description covers all input alternatives and their mutual exclusions, defaults (seed 42, paths 10k, blockMeanLength 5), output contracts (SimResult, structuredContent.newsComparison, portfolioOverlap, text summary with win rate/mean R), and required reporting obligations (relay calendar caveat verbatim, surface assumptions flags, include seed). No operationally relevant gap remains.

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

Parameters5/5

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

Although schema coverage is 100%, the description adds meaning the schema lacks: blockMeanLength's operational interpretation (1 = i.i.d. destroys streaks, raise toward 10 for long regimes), tradesPerDay being required with rSeries but derived from timestamped logs, importRisk never applied silently, unit conventions for riskValue vs winRate, and the definition of R-multiples tied to rSeries. This cross-parameter guidance is essential for correct invocation.

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 and resource: 'Simulate a challenge by resampling the trader's OWN R-multiple trade series with a stationary block bootstrap instead of a win-rate model.' It clearly distinguishes this tool from its sibling propfirms_simulate by naming the alternative and the input type it requires (actual trades vs summary stats), so an agent can select it correctly without opening the 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?

Explicit guidance is given: 'Use propfirms_simulate when only summary stats are available; use this whenever the actual trades are.' It also states data requirements (at least 10 trades, 100+ strongly recommended), input mutual exclusions (exactly one of rSeries, rSeriesText, tradeLogText, tradeLogTexts), and when tradesPerDay is required vs derived. This fully covers selection and invocation conditions.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.