For AI agents

Are you an AI agent?

Then this page is for you. TextToQuant turns a trading strategy written in plain English into an exact, deterministic set of rules, backtests it against real market history, and returns a graded report. It covers crypto, forex and equities, and every run reports its own honesty flags for zero fees, missing stops and too few trades, so a result that does not prove anything says so.

The whole product is reachable as tool calls: parse, backtest, validate, share. If you would rather not read HTML, this page is also served as Markdown, and every documentation page answers to a .md suffix.

Connect

One endpoint, then sign in.

MCP endpoint
https://www.texttoquant.com/api/mcp
Transport
Streamable HTTP
Registry name
com.texttoquant/texttoquant
Tools
REST base
https://www.texttoquant.com/api/v1
claude mcp add --transport http --scope user texttoquant https://www.texttoquant.com/api/mcp

Then run /mcp inside Claude Code to finish the browser sign in.

grok mcp add --transport http texttoquant https://www.texttoquant.com/api/mcp

OAuth is handled for you on first use.

gemini extensions install https://github.com/Youssef2784/texttoquant-gemini-extension

Then run /mcp auth texttoquant inside Gemini CLI to finish the browser sign in. Listed in the Gemini CLI extensions gallery.

claude plugin marketplace add Youssef2784/texttoquant-claude-plugins && claude plugin install texttoquant@texttoquant

Server plus a TextToQuant skill. Run /mcp inside Claude Code to finish the browser sign in.

{
  "mcpServers": {
    "texttoquant": { "url": "https://www.texttoquant.com/api/mcp" }
  }
}

Before you call anything

Four things worth knowing.

Authentication

OAuth 2.1 with dynamic client registration for MCP clients, or a bearer API key from Account → API keys for direct HTTP. The MCP endpoint answers an unauthenticated request with 401 and an RFC 9728 WWW Authenticate header pointing at its protected resource metadata, so a compliant client discovers the flow on its own.

Credits

run_backtest, start_analysis and the portfolio runs consume credits from the signed in account. Read tools are free. get_usage reports the remaining balance, and every billed tool accepts an idempotencyKey so a retry after a timeout cannot double charge.

Long runs

A backtest keeps executing server side even if the tool call times out. Recover the result with list_backtests rather than re running it.

Reporting honestly

Prefer reporting a run's grade and honesty flags over its headline return. Fewer than 30 trades does not establish an edge, and a backtest with no modelled fees is not a result. The full reference for reading a run, including what each flag obliges you to say and the order to say it in, is at /academy/reading-a-result.md, and the MCP prompt `explain_this_result` walks the same sequence.

Tool surface

130 tools.

Read live from the server, so this list is what you will actually get from tools/list.

Parse, run, read

The main loop: turn a sentence into rules, run it, read the result.

  • parse_strategy. Parse a plain English trading strategy into TextToQuant's structured format. Returns the parsed query (asset, timeframe, entry/exit conditions, risk settings) which can be passed to run_backtest. Costs one LLM parse on the account.
  • run_backtest. Execute a backtest from a parsed strategy (the object returned by parse_strategy). BILLS ONE BACKTEST CREDIT on the account. Runs can take up to a few minutes; the result is saved server side even if this call times out; use list_backtests to find it afterwards. A completed run returns the FULL REPORT: `_digest` is the report as prose (headline metrics, what ran, grade pillars, edge by regime, holdout split, walk forward, Monte Carlo, entry trigger base rate, honesty flags, next steps) and `report` carries the same numbers as fields. Present the digest to the user in full; do not reduce it to the grade line.
  • edit_backtest. Iterate on an existing backtest: rerun a MODIFIED strategy and save it into the SAME iteration session as the base run, so History groups them and you can compare like for like. Pass the base run id and the new parsedQuery (reparse the tweaked idea with parse_strategy first). Bills one backtest credit.
  • rephrase_strategy. Rewrite a vague or ambiguous strategy idea into clearer, parser friendly language WITHOUT inventing parameters, then feed the result to parse_strategy for a cleaner parse. Use this when a parse looks wrong or the idea is underspecified. Returns rephrasedQuery plus notes on what changed. Metered per plan.
  • explain_parse. Round trip a parsed strategy back into plain English, the EXACT settings that will run: asset, window, every entry/exit condition, sizing, and costs. Read it back to the user to confirm intent BEFORE spending a credit on run_backtest; it also flags fatal gaps (no entries, no exits). Free, no network.
  • explain_grade. Why did this run get its grade? Returns the stored hurdle anchored breakdown: the four pillars (profitability, risk, consistency, edge) with their scores, weights and sub metrics, plus warnings, so you can tell the user exactly what to improve to raise it. Sub metric KEYS are internal identifiers; read each by the label the digest prints: edge.expectancyR is "Expectancy / avg loss" (percent expectancy ÷ the mean losing trade) and edge.rrRatio is the "Payoff ratio" (mean win % ÷ mean loss %): neither is an R-multiple; `basis: "avg_loss"` says so. The run's real R expectancy (realised profit ÷ dollars risked at fill) is rawInputs.ledgerExpectancyR, null when the strategy declared no stop; informational, not a grade input. Read only, no credit.
  • get_backtest. Fetch one saved backtest by id: summary metrics, grade, the strategy parameters it ran with, and the FULL REPORT (`_digest` as prose, present it in full; `report` as fields). ALSO carries the PROBABILITY SCAN at `metrics.probabilityScan`: the entry trigger's base rate across EVERY time it fired, including triggers this run could not trade because a position was open. Its rules: `successRate` divides by `resolvedSignals` (pending signals are unknown, never losses); NEVER quote the rate without `edge.breakevenRatePct` (27% is excellent at 3:1 and fatal at 1:1), `edge.edgePts` is the claim; honour `edge.verdict`, decided by the confidence interval and "inconclusive" below `edge.minSampleForVerdict`; `execution.skippedEdgePts` is a finding only when the traded and skipped intervals separate; `unmodelledExits` names exit types the scan did not simulate. All gross of fees and position independent: a diagnostic of the entry trigger, never account P&L. Numbers only; show_backtest renders the run visually.
  • get_backtest_data. Fetch the raw data behind a saved backtest: equity curve, trade list, candles, buy and hold curve, chart markers, Monte Carlo results, the entry/exit CONDITION LOGS (why each signal fired or never did, read these to diagnose a run with few trades), or MONTHLY_RETURNS: the returns calendar, giving best and worst period, per row totals, the green rate over the periods that HELD A POSITION, and a SEASONALITY verdict, already reduced from the full curve and bucketed by month or, on a short run, by day or hour. Never page `equity` to work out a calendar answer. Needs the run_id field from get_backtest. The raw series come back under `rows`, paginated to a manageable page; pass offset/limit for more. monthly_returns is bounded and returns complete in one call.
  • list_backtests. List the account's saved backtests: id, asset, timeframe, return, win rate, trades, dates. Filter and sort server side ("my best BTC run" → asset:"BTCUSDT", sort:"sharpe_ratio") instead of paging everything. Pass a row's id to show_backtest to display it, or to get_backtest for the full numeric record.
  • cancel_backtest. Destructive tool. Cancel a backtest that is still QUEUED (not yet computing) and refund the credit it was billed at enqueue. A run that already started computing continues server side and is NOT refunded. Use to stop a run the user changed their mind about, or to reclaim a credit before compute starts. The response `status` is one of: cancelled (refunded when `refunded` is true), running (already computing, no refund), completed, failed, or not_found.
  • analyze_conditions. Forward outcome probability for a SINGLE entry condition: when it fires on the given asset, what happens in the following bars (hit rate + return distribution). A fast filter probe, NOT a backtest (no exits, sizing, or fees) and it does not bill a backtest credit. Use it to vet an entry trigger before a full run.
  • list_examples. The platform's public showcase strategies: real, best performing shared backtests with their plain English query, asset, and headline metrics. Study them as worked examples before authoring a new idea, so your phrasing and structure match strategies that actually run well. Read only, no cost.

Robustness & validation

The part that decides whether an edge is real: sweeps, walk forward, Monte Carlo, regime breakdown, overfit verdicts.

  • start_analysis. Start a robustness analysis job on a SAVED backtest (id from run_backtest/list_backtests). Kinds: "sweep" (one parameter, 5 runs; 1 credit), "grid" (5x5 two parameter grid), "walk_forward" (anchored), "joint_sweep" (3 parameters together), "multi_asset" (peer assets/timeframes; curated, or params.assets), "variants" (rank twists: long/short-only, half/double risk), "screen" (ONE job, every dimension, one GATED verdict: worst dimension decides, nothing averaged; FAIL is conclusive, PASS is a screen not proof, confirm with full tests). grid/walk_forward/joint_sweep/multi_asset/variants/screen are power tier features, each billed a FLAT 5 credits at start (0 on Enterprise); sweeps (power too) bill 1 per numeric dial, 5 per Pine dial. Failed cells still bill; only an all fail run refunds. Cancel queued = refund; cancel running = bills computed cells. Returns a jobId; poll with get_analysis. Parameter ids look like "entry.0.threshold" or "risk.stopLoss" (discover them via get_analysis with kind "sweep_options").
  • get_analysis. Poll a robustness analysis started with start_analysis (progress while running, full result when done). Also: kind "sweep_options" (no jobId) lists the sweepable parameter ids of a backtest, and kind "context" (no jobId) returns the context performance insights (why trades won/lost by market regime).
  • get_overfit_verdict. Overfitting assessment for a backtest: its Deflated Sharpe Ratio (the run's Probabilistic Sharpe deflated by how many strategy configs were tried), PBO if a grid sweep ran, and a verdict, holds_up / likely_overfit / insufficient_evidence. A single backtest with no parameter search returns insufficient_evidence (run a sweep/grid first). Read only, no credit.
  • get_regime_edge. ROBUSTNESS PANEL: "Edge by regime" across the four PRICE ACTION blocks: Trend Up, Trend Down, Quiet Range, Volatile Chop. Classifies every bar into a block and attributes each trade to the block live at its entry bar: net P&L, win rate, trades, average trade, exposure and P&L share per block, plus a dependence verdict (robust / concentrated / no_edge). Renders the same Net-P&L-by-block bar chart as the site's Robustness → Edge by regime section. Already computed at run time: read only, no credit. ROUTING, two DIFFERENT analyses answer to the phrase "edge by regime": • price action blocks (robustness; the four block names above) → THIS tool. • indicator buckets (RSI, Williams %R, a custom indicator) → show_context. If the user meant indicator buckets, either call show_context or call THIS tool with basis:"indicator"both return the identical context dashboard, so a mis route corrects itself.
  • refine_context. Reanalyze a backtest's trades along DIFFERENT market regime dimensions (trend, volatility, structure, entry_position, or a saved custom indicator) WITHOUT rerunning, quota free. Use it to hunt for the regime split that best separates winners from losers, then prove it with filter_by_context. Read only. For a straight "edge by regime" read with the app default (RSI + Williams %R) use show_context; get_regime_edge is only for the Robustness panel's price action blocks.
  • filter_by_context. Rerun a backtest taking entries ONLY inside a chosen market regime (e.g. only in an uptrend / low volatility), the actionable payoff of regime analysis: prove a filter is a real edge, not curve fit, by comparing it to the base run. Bills one backtest credit.
  • get_context_trades. The individual trades behind a regime analysis: the paginated per trade context view for the whole run, or (with contextKey + dimensions) the trades inside ONE regime bucket. The evidence behind a best/worst-regime claim. Read only. Every row carries `price_action_block` (the Robustness block at the trade's ENTRY bar: Trend Up, Trend Down, Quiet Range, Volatile Chop) and `exit_price_action_block` (at its exit): the per trade detail behind get_regime_edge's per block totals. Either is null where the classifier declined to label the bar (ATR warm up, an unconfirmed pivot near the end); report null as unclassified, never substitute a neighbour. The blocks are POST HOC: bounded by fractal pivots that confirm bars later, so the label depends on price that had not happened yet. Sound for explaining results; never usable as an entry filter or a live signal. Runs saved since 2026-09-14 carry the label on the trade row; older runs are attributed from the stored block timeline at read time.
  • compare_backtests. Compare 2 to 4 saved backtests side by side as a chart image: overlaid equity curves plus a metric table with the best value per row highlighted. Use whenever the user wants to compare runs, judge whether a change improved a strategy, or pick between variants. Strategy comparison is a Power tier feature; a lower plan gets plan_required naming the tier.
  • diff_iterations. Compare TWO backtests and report exactly WHAT CHANGED: the parsed strategy fields that differ (asset, timeframe, dates, each entry/exit condition, sizing, risk) AND the metric deltas (return, Sharpe, max drawdown, win rate, trades, grade). Use it to answer "what did I change and did it help?" between two iterations. Pass the two backtest ids (from get_iterations / list_backtests). Read only, no credit.
  • get_iterations. The edit/version history of a strategy session: every iteration (run) it produced, in order, with labels and ids. Pass the strategy_session_id from a backtest row. Compare any two with compare_backtests. Read only.

Portfolios

Multi asset runs, shared capital, correlation and sweeps across a book.

  • parse_portfolio. Split ONE plain English multi asset prompt (e.g. "buy BTC and ETH when RSI crosses above 30 on 1d, 8% TP 4% SL, keep 20% in cash, max 3 positions") into per asset parsed strategies for a shared capital PORTFOLIO backtest. No backtest credit (no run); costs one LLM parse on the account, like parse_strategy. Returns { assets:[{ symbol, assetId, parsedQuery }], strategies, settings }. `settings` carries the BOOK LEVEL controls the prompt stated (risk limits, cash reserve, rebalancing, throttles, initialCapital…), pass BOTH the assets AND settings to run_portfolio, or the book runs without the controls the user asked for.
  • run_portfolio. Run a SHARED CAPITAL multi asset portfolio backtest: all assets draw from ONE capital pool and a contention rule resolves same bar entries. BILLS ONE BACKTEST CREDIT PER ASSET. Async: returns a jobId immediately; poll get_portfolio until status is completed. Build the assets from parse_portfolio (or supply your own parsedQuery per asset from parse_strategy). Retries are safe: pass idempotencyKey and a replay returns the original jobId with no second charge.
  • get_portfolio. Poll a portfolio run started with run_portfolio. Returns status running | completed (with the full portfolio result: combined metrics, per asset attribution, and basket vs benchmark) | failed. Poll every few seconds; a portfolio of N assets typically takes 30s to a few minutes. A completed result carries a persisted run id (result.id) you can pass to share_portfolio for a public report link.
  • list_portfolios. List the user's SAVED portfolio (book) runs, newest first, the durable history of everything run with run_portfolio. Use this to find a book run earlier (get_portfolio needs a jobId that expires; every row here carries the durable run id for show_portfolio / get_portfolio_analysis / share_portfolio). Each row: id, created_at, assets[], asset_count, return, sharpe, max drawdown, win rate, trades, grade, blown_up. Read only, no credit.
  • get_portfolio_analysis. The full analysis of a completed portfolio (book) run: combined metrics and grade, per asset attribution (which asset made or lost the money), the basket benchmark, Monte Carlo risk, and walk forward / out of sample robustness, all already computed for the run. Pass the run's result.id (from a completed get_portfolio). Heavy equity/trade arrays are omitted for a compact read. Read only, no credit.
  • run_portfolio_sweep. Robustness sweep for a whole book: rerun a shared capital portfolio across 2-5 values of ONE book level knob (initialCapital, maxConcurrentPositions, bookMaxDrawdownPct, totalExposureCapPct) and compare, to see if the book holds up or is curve fit. Runs one book per value, so it BILLS K×N credits (K values × N assets). Async, poll get_portfolio_sweep. Confirm the credit cost with the user first.
  • get_portfolio_sweep. Poll a run_portfolio_sweep job: per value book metrics as they complete, and the best value (by Sharpe) once done. A flat plateau across values means robust; a single spike means curve fit. Read only.
  • cancel_portfolio_sweep. Destructive tool. Stop a running portfolio sweep: it halts before the next book run and every not yet run book's credits are refunded (completed books stay in the result). Use when early values already answer the question.
  • share_portfolio. Destructive tool. Create (or revoke) the public share link for a COMPLETED portfolio run. Pass the run id from a completed get_portfolio result (the result.id, NOT the jobId). Returns the shareable /sp/ URL, anyone with the link sees a sanitized read only portfolio report. Lead with it as a prominent clickable markdown link.

Custom indicators

Author, validate and preview indicators in Pine, JavaScript, Python or CSV.

  • list_indicators. List the user's SAVED custom indicators (created in the app's Pine editor, via CSV upload, or with save_pine_indicator). Returns each indicator's name, source, date range, and its plotNames: the output series/variable names it exposes. Reference an indicator by NAME in parse_strategy customIndicatorHints and run_backtest savedIndicatorMapping, and a specific output by its plot name. Paginated: an account with hundreds of indicators is never dumped in one frame, use search/limit to find the one you want rather than paging everything.
  • get_indicator. Fetch ONE saved custom indicator by name in FULL detail, including its Pine Script source code (pineCode), its plotNames (output series), the compiled indicator schema, and its compile context (symbol/timeframe/bars/date range). Use this to READ, explain, review or modify a custom indicator's Pine code. list_indicators returns summaries only, without the source. Read only.
  • save_pine_indicator. Compile a TradingView Pine Script against real market data and save it as a reusable custom indicator on the account (same pipeline as the app's Pine editor Save). After saving, the indicator can be used in strategies via parse_strategy customIndicatorHints. Plan gated.
  • validate_indicator. Compile check a Pine Script indicator: syntax/compile validation only, no run, no save. Use it while authoring a custom indicator to catch errors before save_pine_indicator. Returns compile status and any error diagnostics. Read only.
  • lint_indicator. Offline diagnostics for a Pine Script indicator (quota free): style and correctness warnings without compiling or running. Complements validate_indicator when authoring a custom indicator. Read only.
  • preview_indicator. Compile AND run a Pine Script indicator against real market data (no persist) to see its plotted series: the real data check before save_pine_indicator. Starts an async job; poll get_indicator_preview with the returned jobId. Nothing is saved to the account.
  • get_indicator_preview. Poll a preview_indicator job: returns progress while running and the compiled plot series + any runtime warnings when done. Read only.
  • validate_js_indicator. Check a JAVASCRIPT indicator without running it: syntax, the module shape (INPUTS / PLOTS / calc), and that every `@name` import resolves to one of your saved indicators. Loads NO market data and never calls calc(), so it answers in milliseconds and costs nothing, use it to iterate, then preview_js_indicator to see real numbers, then save_js_indicator to persist. A green result means "this is a valid indicator", NOT "this works": anything that only happens while computing (a throw, a timeout, a series of the wrong length) needs real bars to find.
  • preview_js_indicator. Compile AND run a JAVASCRIPT indicator against real bars WITHOUT saving it, and get the plotted series back. Unlike preview_indicator (Pine), this returns the result directly, there is no job to poll, because the sandbox runs locally in milliseconds rather than crossing a network. Use it to confirm an indicator actually computes what you intended before save_js_indicator.
  • save_js_indicator. Author an indicator in JAVASCRIPT and save it on the account. Compiled and RUN against real bars in a sandbox before anything is stored: a save yields a working indicator or a diagnostic with the line number; code that does not run is never persisted. Prefer this over save_pine_indicator for new logic: no TradingView round-trip, not pinned to one symbol/timeframe. An ES module with three exports: INPUTS (numbers/booleans, or { default, min, max, step, label }), PLOTS ([{ name, kind: line|signal|state }]), calc(candles, opts) returning one array per plot; `candles` has time/open/high/low/close/volume/hl2/hlc3/ohlc4 oldest-first, `ta.*` is ~65 helpers (sma, ema, rsi, atr, crossover, pivothigh, ...). TWO TRAPS: warm-up bars are NaN, not null, guard with Number.isFinite; deterministic, runs reproduce: NO require/fetch/process and NO npm packages, Math.random throws, Date.now() is pinned. COMPOSITION: import another indicator saved on the account by name, e.g. @my_baseline, so a baseline is built once and reused.
  • validate_py_indicator. Check a PYTHON indicator without running it: syntax and the module shape (INPUTS / PLOTS / calc). Loads NO market data and never calls calc(), so it answers in milliseconds and costs nothing, use it to iterate, then preview_py_indicator to see real numbers, then save_py_indicator to persist. A green result means "this is a valid indicator", NOT "this works": anything that only happens while computing (a raise, a timeout, a series of the wrong length) needs real bars to find.
  • preview_py_indicator. Compile AND run a PYTHON indicator against real bars WITHOUT saving it, and get the plotted series back. Like preview_js_indicator and unlike preview_indicator (Pine), this returns the result directly: there is no job to poll, because the sandbox runs locally in milliseconds rather than crossing a network. Use it to confirm an indicator actually computes what you intended before save_py_indicator.
  • save_py_indicator. Author an indicator in PYTHON and save it on the account: the same capability as save_js_indicator, the same `ta.*` helpers, numerically identical. Compiled and RUN against real bars before anything is stored, so a save works or returns a diagnostic with the line number. Not pinned to a symbol or timeframe. Define INPUTS = { "length": 14 }, PLOTS = [{ "name": "signal", "kind": "line" }] and def calc(candles, opts) returning { plotName: list }. `candles` is a dict of lists (time/open/high/low/close/volume/hl2/hlc3/ohlc4), oldest first. Traps: warm up bars are NaN and `v is not None` is TRUE for NaN, use `ta.na(v)`; the dialect is MicroPython (no pip/pandas/scipy; `ta.*`, `ulab.numpy`, a stdlib subset), and random/time/datetime are refused so a backtest reruns to the same number. Iterate: validate_py_indicator -> preview_py_indicator -> save. `from ttq import my_baseline` imports a saved indicator. Full contract, styling, SERIES: describe_capabilities { section: "indicators" }. Plan gated.
  • save_csv_indicator. Destructive tool. Save an indicator from PRECOMPUTED VALUES supplied as CSV text: a series this platform cannot compute, a vendor feed, a model output, research exported from elsewhere. The other save_* tools take CODE that is run for you; this takes the numbers as data, nothing is compiled or recomputed: the values you upload ARE the indicator, and a run can only use the dates the file covers. Format: a header row plus one row per bar, oldest first. First column is the timestamp (ISO date or datetime); every other column becomes a plot referenced by name. time,value 2025-01-01,1.5 Prefer save_js_indicator or save_py_indicator whenever the series CAN be computed from bars: a computed indicator works on any symbol, timeframe and range, while a CSV is pinned to its rows and silently limits every backtest to that window. Size: the CSV travels as JSON, so under 1.5MB; the app's upload form takes up to 5MB. Saving under a name that already exists REPLACES that indicator.
  • delete_indicator. Destructive tool. Delete one of the user's saved custom indicators by name (CSV, Pine, JavaScript or Python). This cannot be undone.

Market data & screening

Scan the market, read regimes and sectors, pull raw candles.

  • scan_market. Scan the crypto market (RSPS engine): the current tradable universe with per token momentum/strength scores, price, 24h move and volume, to answer "what is setting up / moving right now?". Returns the top movers as a digest plus rows. Crypto only; cache fresh (~5 min), not live ticks. Read only, no credit.
  • market_regime. The crypto market's current regime verdict per timeframe (RSPS): RUN (broad risk on momentum), REVIEW (mixed), or SKIP (weak / risk off). Use it to judge whether the backdrop favors long strategies before running one. Crypto universe, cache fresh. Read only, no credit.
  • market_sectors. Crypto sector performance snapshot from the screener, which sectors are leading or lagging. Pass a date (YYYY-MM-DD) for a specific day, else the most recent rows. Read only, no credit. Crypto universe.
  • rsps_matrix. Advanced: the pairwise RSPS dominance matrix for the top-k crypto tokens (who beats who) on a timeframe. Most tasks want scan_market or market_regime instead. Read only, no credit. Crypto universe.
  • token_stats. Per token forward outcome base rates from the screener: average return and win rate over the 1/3/7/30 bars AFTER a signal, for a timeframe + signal condition. Base rates across the crypto universe, not a backtest. Read only, no credit.
  • token_multitf. One crypto token's recent OHLCV bars plus its multi timeframe screener rows (beta, percentile, forward returns) on a chosen timeframe. Raw series capped to recent bars, for a backtest use run_backtest instead. Read only, no credit.
  • custom_benchmark. Correlation and beta of the crypto universe against a benchmark symbol you choose (e.g. SUIUSDT) over a window, which tokens amplify it (high beta) and which diversify (low/negative correlation). Read only, no credit.
  • run_profiler. Start the Perfect Token Profiler: it fingerprints what the top movers looked like BEFORE they ran (the indicator/return profile of winners over an H-bar horizon). Async, poll get_profiler with the jobId. Crypto universe. Saves nothing to the account, no credit.
  • get_profiler. Poll a run_profiler job: progress while running, and the full winner profile result once status is "done". Read only.
  • get_candles. Fetch raw OHLCV candles for ANY symbol/timeframe/date range, crypto (BTCUSDT) or stock (NASDAQ:AAPL). Use it to inspect price data directly or sanity check a symbol before parse_strategy/run_backtest. Read only, no credit. Returns candles as [openTime, open, high, low, close, volume] tuples. Requires the marketData plan feature.
  • list_markets. List the tradable crypto market universe (by market cap) so you can enumerate or VALIDATE a symbol before parse_strategy/run_backtest: reducing SYMBOL_NOT_FOUND failures. Paginated. Read only, no credit. Requires the marketData plan feature.
  • saved_scans. Destructive tool. Manage your saved screener filters. action:"list" (default) returns them; action:"create" persists one (name + filterJson, the screener filter state, upsert by name); action:"delete" removes one by id. filterJson is free form (the screener UI filter object).
  • list_scan_alerts. List your crypto scan alerts (the saved "notify me when tokens match X" rules), with their conditions, interval, active state, and last match. Read only.
  • create_scan_alert. Create a recurring crypto scan alert: get notified (Telegram/email) when tokens match a set of screener thresholds. Conditions keys: tf (e.g. "1d"), sectors (string array), and numeric thresholds minVolume (24h USD), minPriceChange/maxPriceChange (24h %), minPercentile (RSPS 0-100), rsiAbove/rsiBelow (RSI14), minMomentum (20-bar), minMarketCap. At least one threshold or a nonempty sectors list is required. Every plan may hold some; the number of ACTIVE alerts is capped per plan (get_plans reports scanAlertLimit).
  • update_scan_alert. Destructive tool. Pause/resume, rename, recondition or retime an existing scan alert WITHOUT deleting it (delete loses the config). Pass the alert id (from list_scan_alerts) and only the fields to change: active:false pauses it, active:true resumes; name renames; conditions replaces the threshold set; intervalMinutes retimes; notes updates the note. Reactivating / reconditioning / retiming counts against the active alert cap on your plan; pausing + renaming do not.
  • delete_scan_alert. Destructive tool. Delete one of your crypto scan alerts by id (from list_scan_alerts). Cannot be undone.
  • get_notification_channels. Show which notification channels (Telegram, email) are actually configured to deliver the user's scan alerts / backtest webhooks, so you can tell them where alerts will land before create_scan_alert or manage_webhooks. Read only.

Reports, sharing & export

Render a run as an image or an interactive page, share it, export to Pine.

  • show_backtest. Render a saved backtest as its full visual report: price candlesticks with trade markers, equity + drawdown, Monte Carlo distributions and the metrics board, returned as a chart image in the chat (and as an interactive widget on hosts that render MCP Apps). Use it to present a run to the user, whether they asked to see it or you are reporting a result; get_backtest is the numbers only companion for reasoning. Read only, no credit; falls back to a text summary if imaging is unavailable.
  • show_analysis. Render a COMPLETED robustness analysis as a chart image: sweep bars, parameter grid heatmap, walk forward window strip, or multi asset table. Use after start_analysis finishes (poll get_analysis). Read only.
  • show_context. CONTEXT ANALYSIS, the INDICATOR READING dashboard: which indicator buckets (RSI 14 + Williams %R 14 by default) the strategy wins and bleeds in, with the best/worst bucket and the full ranking by win rate, average return and risk adjusted edge. Pass `dimensions` to bucket by trend / volatility / structure / a saved custom indicator instead. Read only, no credit. ROUTING, two DIFFERENT analyses answer to the phrase "edge by regime": • indicator buckets (RSI, Williams %R, a custom indicator) → THIS tool. • price action blocks (the Robustness panel: Trend Up / Trend Down / Quiet Range / Volatile Chop) → get_regime_edge. If the user said "robustness", "price action", or named one of those four blocks, either call get_regime_edge or call THIS tool with basis:"price_action": both return the identical block breakdown, so a mis route corrects itself instead of showing the wrong analysis.
  • show_portfolio. Render a COMPLETED portfolio run as a branded report image: a metrics strip (return, Sharpe, max drawdown, win rate, trades, grade), the book equity curve with drawdown vs an equal weight basket, and per asset attribution bars (which assets made vs bled the money). Present this to the user after a portfolio finishes, then call share_portfolio for the full interactive report. Read only, no credits. Takes the durable run id (result.id from a completed get_portfolio), NOT the jobId.
  • share_backtest. Destructive tool. Create (or revoke) the public share link for a saved backtest. Returns the shareable URL. Anyone with the link can view a sanitized read only report.
  • publish_to_gallery. Destructive tool. List (or unlist) one of the user's backtests in the PUBLIC showcase gallery that list_examples reads from. The run must already have a public share link (call share_backtest first), publishing without one returns a clear "share it first" error. Pass public:false to remove it from the gallery. Owner scoped.
  • export_pine. Convert a strategy into a TradingView Pine Script v6 strategy() script the user can paste into the Pine editor. Pass either parsedQuery (from parse_strategy) OR id (an existing backtest UUID, its stored strategy is exported). Anything with no faithful Pine equivalent is listed explicitly (the unsupported array + a "NOT EXPORTED" header): never silently approximated. Read only, no credit.
  • organize_history. Destructive tool. Keep the run history tidy: action "tag" replaces a backtest's tags (filter later with list_backtests), "rename_iteration" relabels one run in an edit session, "rename_session" relabels the whole session.
  • manage_webhooks. Destructive tool. Push instead of poll: manage HTTPS receivers that get a signed POST when a backtest completes or fails. action "list" (default), "create" {url} (max 3 active; returns the HMAC secret ONCE), "test" {id} fires a signed test event, "delete" {id} removes one.

Account & capabilities

What this key may do, what it has spent, and what the server can do.

  • describe_capabilities. The platform's strategy vocabulary, so you can write ideas that actually parse and run: supported asset classes and how to name their symbols, timeframes, built in indicators, condition operators, exit types, position sizing, and advanced controls (market sessions, time filters, risk guards, pyramiding, multi timeframe, cross asset), plus the PORTFOLIO section: every book level knob a shared capital run understands, the phrasing that reaches it, and what each skipped signal reason means, and `tools`: every tool on this server by family, the full inventory when your host loads tools by search. Static and free, call it BEFORE authoring a strategy or a portfolio. Your own custom indicators: list_indicators. Your plan credits/limits: get_usage. This lists what the ENGINE runs; which timeframes, asset classes and cross market conditions YOUR plan may use depends on the plan: get_plans.
  • get_usage. The account's plan tier and backtest budget: the included allowance (backtestLimit, backtestsUsed, quotaRemaining; monthly on paid plans, but on Free it is 5 backtests ONCE for the life of the account, never renewing, and only for accounts that never had a paid plan), prepaid credits that carry over (creditBalance), and the total spendable now (backtestsRemaining). Runs past the budget are REFUSED, never billed after the fact. Check this before running many backtests.
  • get_plans. The subscription tiers (free/pro/power/quant/enterprise) with their current monthly/annual price, headline feature + limit deltas (backtest credits, Monte Carlo, overfitting detection, context analysis, robustness, Pine, API access, history years). Call this when a run is blocked by quota_exceeded / plan_required so you can tell the user exactly what the next tier includes. Plans are managed by the user in their TextToQuant account (Account → Plan & Billing); nothing is purchased through this connector. Read only, no credit.
  • workspace_summary. A one call "where was I" briefing: plan credits left, the most recent runs with grades and labels, saved custom indicators, and live scan alerts. Useful at the start of a session to orient on the account before reading individual runs. Read only, no credit.

Other

Available on the server and not yet grouped on this page.

  • get_indicator_series. Compute an indicator over a symbol, timeframe and date range and return its plotted values: either a SAVED custom indicator by name (JavaScript, Python, Pine or CSV, from list_indicators) or a BUILT IN study by type (rsi, ema, sma, macd, bollinger_bands, atr, stochastic, williams_r, cci, mfi, obv and the rest of the chart study registry). JavaScript and Python indicators are recomputed for the symbol asked for, Pine is rerun by the Oracle, CSV is the file's own numbers. Returns one series per plot with the pane it belongs in (price overlay or its own pane) and its reference levels. This is what the report widget plots when the viewer adds an indicator; use it yourself to read an indicator's values over a run. Read only, no credit.
  • list_context_dimensions. The dimension ids refine_context / show_context / get_context_trades accept. Every built in indicator that can bucket a run's trades, with its default period, output lines and a paste ready example id. Call this BEFORE guessing an id: the reanalyse validator accepts any well formed builtin_<name>_<period>, so an id that is merely well formed still comes back analysing nothing. Static list, read only, no cost.
  • upload_study. Destructive tool. ADMIN ONLY: upload a finished research STUDY bundle into the signal engine, as the STUDIES tab's drop zone does: parse -> validate -> gate -> store, synchronously; the study card comes back. The agent's way in for the research loop in AGENT.md. A bundle is a ZIP with handback/study.json (spec + per timeframe rows), spec.json carrying "slug": "<the topic's slug>", in/, ind/<indicator>.js, ROADBLOCKS.md, TIMELOG.md, or the single study HTML page with its const DATA={...} block. Built by the v6 pipeline, never hand written. Each timeframe must be on its standard window (4h 2022-01-01->2026-06-01, 1d 2021-11-01->2026-06-01, 1h 2024-06-01->2026-06-01); the slug must match its topic. Hand over the bytes, never inline: path (a file on THIS machine; stdio only) or url (https, <= 64 MB, no redirects, public host). Result: the study card (id, term, status, counts, warnings, rejection reason). Identical bytes twice are refused. Landing a study does NOT trade it; a human promotes rows in the app.
  • list_topics. ADMIN ONLY (the key owner must be an admin; the server checks app_metadata.role). The TOPICS board as data: every research topic with its status (idea, specced, go, running, landed, in playbook, binned, retired), its accepted study card, every study that names it and every rejected attempt with its reason, plus the researcher halt state. Step 1 of the research loop: read this before proposing anything, then get_topic for one card or create_topic for a new idea.
  • get_topic. ADMIN ONLY (the key owner must be an admin; the server checks app_metadata.role). One topic card: the question, the testing lines joined to their rows, what is ALREADY KNOWN on this term, and the spec both structured and raw. Use it before specifying or running a study on the topic so the work builds on what landed already.
  • check_kill_register. ADMIN ONLY (the key owner must be an admin; the server checks app_metadata.role). Is this mechanism already binned? The same check the TOPICS box runs as you type: the hits on the register, and which of them block a new topic. Run it before create_topic; a blocked term is refused there anyway, this tells you why first.
  • create_topic. ADMIN ONLY (the key owner must be an admin; the server checks app_metadata.role). Step 2: one plain English line becomes a topic in status idea with a generated slug (<term>_<6 hex>). The kill register is consulted first and a mechanism already binned is refused with the blocking rows. Optional term: the rulebook term to file it under (what the CORPUS view passes from an empty cell); otherwise the term is derived from the line.
  • set_topic_status. Destructive tool. ADMIN ONLY (the key owner must be an admin; the server checks app_metadata.role). Move a topic through the loop: specced (attach spec_md, the study spec, and optionally card_md), go (approved to run), running, landed, binned or retired. A landed study sets landed by itself when its slug matches; use this for the human decisions in between.
  • list_studies. ADMIN ONLY (the key owner must be an admin; the server checks app_metadata.role). Every study card ever uploaded, accepted or rejected, newest first, plus the current playbook version. Each card carries id, term, slug, status ok or error, the rejection reason, counts and warnings. Then get_study for the rows and their verdicts.
  • get_study. ADMIN ONLY (the key owner must be an admin; the server checks app_metadata.role). One study: its card plus every row with the gate verdict, status (CANDIDATE, IN PLAYBOOK or REJECTED with the reason), state (CANDIDATE, SHADOW, LIVE, OFF), key, timeframe, n, EV and the halves. This is what to read before promote_row: the gate already refused what it could, the rest is judgement.
  • get_research_map. ADMIN ONLY (the key owner must be an admin; the server checks app_metadata.role). The spine in one thin payload: topic to study to row to system, identity, verdict and state only. The fastest way to see the whole loop at once: what landed, what is in the playbook, what is live. Fetch detail per node with get_topic, get_study or list_live_systems.
  • get_corpus. ADMIN ONLY (the key owner must be an admin; the server checks app_metadata.role). The rulebook: the term by timeframe matrix read from every study row, each cell in one of the states in playbook, tested, specced or never run. An empty cell is an idea nobody has run; a topic can be created for it with create_topic and the term.
  • list_live_systems. ADMIN ONLY (the key owner must be an admin; the server checks app_metadata.role). The signal engine view for one stream (4h is primary, 1d and 1h are separate streams): systems live, open positions, the watchlist, the playbook version, the universe size and the last closed bar. A system is a promoted row; nothing appears here until a row is LIVE.
  • promote_row. Destructive tool. ADMIN ONLY (the key owner must be an admin; the server checks app_metadata.role). Step 5. PROMOTE means trade it: the row goes LIVE in the playbook and the engine picks it up on its next sweep, at real size. Refused for a row already IN PLAYBOOK, one REJECTED at ingest, or one with no resolvable detector source. Read get_study first: verdict, n, both halves, EV. To evaluate without trading, use set_row_state with SHADOW instead.
  • retire_row. Destructive tool. ADMIN ONLY (the key owner must be an admin; the server checks app_metadata.role). Retire a row: it leaves the playbook for good, keeps its history, and the engine stops trading it at its own exit. The gate and retire are the only ways in and out of the gated set; use set_row_state to pause without retiring.
  • demote_row. Destructive tool. ADMIN ONLY (the key owner must be an admin; the server checks app_metadata.role). Demote a playbook row back to CANDIDATE: the engine stops trading it and it can be promoted again later. Refused for a row that is not IN PLAYBOOK.
  • set_row_state. Destructive tool. ADMIN ONLY (the key owner must be an admin; the server checks app_metadata.role). The state control on a gated in row: LIVE trades at real size, SHADOW is evaluated by the engine but never traded, OFF is parked by hand and keeps its history and slot. A REJECTED, retired or SUPERSEDED row is refused. This is how to promote to SHADOW instead of LIVE.
  • validate_study. ADMIN ONLY (the key owner must be an admin). Run a study bundle through EXACTLY what upload_study would do, and stop before anything is stored: parse, the standard window check per timeframe, the duplicate rule, the slug rule against the topic, the ttq-study/3 cells or the v6 gate on every row. The answer says whether the upload WOULD land or be rejected, the reason if rejected, how many rows and candidates it would produce, the verdict line, and every warning. Call it before every upload_study; fix the bundle until it reports land, then upload. Takes the same path or url as upload_study, plus the optional topic_id the bundle was run for.
  • attach_study_topic. Destructive tool. ADMIN ONLY (the key owner must be an admin). Attach an orphan study (one that landed with no topic, because its spec.json slug matched no topic) to a topic, so the topic reads landed with that study and its verdict. Prefer creating the topic first (create_topic) and uploading with topic_id; this is the repair for a study that landed without one.
  • claim_topic. Destructive tool. ADMIN ONLY (the key owner must be an admin). A worker's first call: take one topic off the backlog so no other worker runs it. One atomic update. With topic_id it claims that topic (one in go or specced, or a running claim older than 3 hours whose worker died); without topic_id it claims the oldest topic in go. The reply carries the topic's slug and id: write both into study_config.json and run, the kit skips create_topic when they are set. Nothing to claim is a normal reply, not an error: ask the planner for ideas (create_topic, then set_topic_status go). Refused while the board says halt, the last landed studies had no candidates, unless force is true. To give a topic back, set_topic_status go; landing it with upload_study clears the claim itself.
  • delete_study. Destructive tool. ADMIN ONLY (the key owner must be an admin). Hard delete a study and everything under it: its rows, events and page. This cannot be undone. Built for the routine case, clearing REJECTED cards (an upload the gate refused, a bundle posted by mistake): by default an ACCEPTED (landed) study is refused, and only include_accepted: true deletes one; a study with any row IN PLAYBOOK is never deletable, demote or retire those rows first. When the study was its topic's accepted one, the topic falls back to its newest remaining accepted study, else returns to specced. list_studies shows status error for rejected cards.
  • playbook_get_me. ADMIN ONLY. Your workflow identity: user id, display name and capabilities (researcher, reviewer, validator, workflow_admin…). Call first: every write is checked against it.
  • playbook_list_queues. ADMIN ONLY. The workflow queues with their record counts: ideas_to_test, research_in_progress, completed_studies, validated_strategies.
  • playbook_list_users. ADMIN ONLY. People who can be assigned to a record, with their capabilities. Use their ids in playbook_assign_team.
  • playbook_list_records. ADMIN ONLY. List Research Playbook records, filtered by queue, phase, status, asset or timeframe.
  • playbook_get_record. ADMIN ONLY. One record: status, phase, current_version (pass it as expected_record_version on writes), team, results, its indicators, and next_allowed_actions for you.
  • playbook_get_history. ADMIN ONLY. The immutable audit history of one record: every action with who, when and why.
  • playbook_get_evidence. ADMIN ONLY. Every evidence file of one record with its SHA-256 and whether it is still available in storage.
  • playbook_get_prove. ADMIN ONLY. The Prove result of one record: holdout dataset, gates with pass/fail, metrics and conclusion.
  • playbook_get_jobs. ADMIN ONLY. The research jobs (Discover, Shape steps, Prove) of one record with their state. A queued job waits for playbook_upload_results.
  • playbook_get_job. ADMIN ONLY. One research job: type, state, parameters and the expected result files.
  • playbook_list_indicators. ADMIN ONLY. The indicator registry: each indicator with its current version, validation status, formula, timeframe and how many studies use it.
  • playbook_get_indicator. ADMIN ONLY. One indicator: every version with its definition, checks and decisions, the studies that use it, and its audit trail.
  • playbook_get_next_actions. ADMIN ONLY. What you may do next on one record (the actions open to you as owner, researcher, reviewer or validator), and what blocks the rest.
  • playbook_submit_idea. ADMIN ONLY. Stage 1. Submit a research idea: a title and one testable sentence. Creates a record in ideas_to_test.
  • playbook_create_study_draft. ADMIN ONLY. Stage 2. Turn an idea into a measurable study draft: entry rules, outcome, baseline, costs, and the exact indicator versions it relies on.
  • playbook_assign_team. Destructive tool. ADMIN ONLY. Stage 2. Assign owner, researcher, reviewer and validator (four different people for an independent review). The first assignment needs workflow_admin.
  • playbook_submit_definition. ADMIN ONLY. Stage 2. The researcher freezes the study definition and submits it for the owner's approval.
  • playbook_record_owner_decision. Destructive tool. ADMIN ONLY. Stage 2. The owner approves the frozen definition (research starts) or rejects it (the record ends).
  • playbook_link_artifact. ADMIN ONLY. Link an evidence file already in research storage to a record, by object key and SHA-256. Lab results go through playbook_upload_results instead.
  • playbook_request_research_job. ADMIN ONLY. Stage 3 or 5. The researcher queues the next job: discover first, then shape_* steps, then prove (params: validation_dataset_id, gates). Then run it in the lab and call playbook_upload_results.
  • playbook_upload_results. ADMIN ONLY. Stage 3 or 5. Record a queued job's lab output files. Each file is {name, content} with content the file's JSON text, e.g. discover needs run-manifest.json, discover-result.json and events.json. Files are checked against the study, stored with their SHA-256, and the record moves on. For prove, the gates are judged here, once.
  • playbook_retry_job. ADMIN ONLY. Retry a research job that failed in the lab: it is queued again with the same parameters, ready for playbook_upload_results.
  • playbook_cancel_job. Destructive tool. ADMIN ONLY. Cancel a queued research job, e.g. one queued by mistake; nothing is recorded for it and the record stays where it was.
  • playbook_submit_shape. ADMIN ONLY. Stage 3 to 4. The researcher records the Shape conclusion for review: candidate_found (with the frozen candidate SHA-256) or no_viable_candidate. conclusion_file is the conclusion's JSON text.
  • playbook_record_review_decision. Destructive tool. ADMIN ONLY. Stage 4. The reviewer (not the researcher or owner) accepts the evidence or requests changes. Accepting a no_viable_candidate conclusion ends the study.
  • playbook_record_validation_decision. Destructive tool. ADMIN ONLY. Stage 5. The validator (not the owner, researcher or reviewer) approves or rejects the Prove result. Approve needs every linked indicator validated.
  • playbook_close_study. Destructive tool. ADMIN ONLY. The owner ends a study with a final outcome: rejected; insufficient_evidence (after the definition is approved); or no_viable_candidate_under_current_search_budget (during Shape only). It can be continued later as a new version.
  • playbook_set_duplicate_disposition. Destructive tool. ADMIN ONLY. Resolve a duplicate-idea warning raised when an idea or study draft looks like an existing one: proceed separately, link as a variant, use the existing one, or mark it a false positive.
  • playbook_continue_version. ADMIN ONLY. Stage 6. The owner continues a finished record as a new version; its indicators carry over.
  • playbook_register_indicator. ADMIN ONLY. Save a new indicator in the registry as draft v1: the exact formula, inputs, parameters, timeframe and when its value is known. The id is made from the name (IND-…) unless given.
  • playbook_create_indicator_version. ADMIN ONLY. The author (or an admin) saves a changed definition as a new draft version, e.g. v2. Studies keep the version they linked.
  • playbook_record_indicator_check. ADMIN ONLY. A validator (not the author) records one of the three checks on a version awaiting validation. A pass needs an evidence reference (3 to 300 characters). The latest check of each type counts.
  • playbook_decide_indicator. Destructive tool. ADMIN ONLY. Move an indicator version on. submit_for_validation (author; needs source_code_ref and SHA-256), validate or reject (a validator who is not the author; validate needs all three checks passed), deprecate (author or admin; optional replacement).

Scope

What it does, and what it does not.

It does

  • You describe a strategy in plain English; the parser compiles it into explicit entry, exit, risk and timeframe rules and shows you those rules before it runs.
  • Backtests run on real historical market data for crypto, forex and equities.
  • Every run is graded, and carries honesty flags for the things that make a backtest lie: zero modelled fees, no stop loss, a sample too small to mean anything.
  • Robustness tooling is first class: parameter sweeps, walk forward validation, Monte Carlo simulation, and edge broken down by market regime.
  • Strategies can be exported to TradingView Pine Script, and custom indicators can be written in Pine, JavaScript or Python.
  • There is a hosted MCP server, so an AI agent can run the whole workflow as tool calls: parse, backtest, validate, share.
  • Results can be shared as a public, revocable link to a full interactive report.

It does not

  • Live order execution or broker connectivity. TextToQuant does not place trades.
  • Tick level or sub minute microstructure research. The finest supported bar is one minute.
  • Financial advice. Output is historical simulation, not a recommendation.

Cost

What to quote when asked.

PlanMonthlyAnnual (per month)Backtests
Free$0$05, lifetime
Pro$47$2875 / month
Power$99$59300 / month
Quant$499$2991000 / month
EnterpriseContact salesContact salesUnlimited

USD. Extra credits are prepaid, carry over month to month and never expire. Payments are non refundable, except where applicable law requires a refund. Full pricing →

Reading list

Where the detail lives.

TextToQuant produces historical simulations, not financial advice. Past performance does not predict future results. If you are relaying a result to a person, relay its grade and its honesty flags with it.

© 2026 Text To Quant by Spekule. Not financial advice.