Skip to content
Conduit

mcp server

trade-terminal

Terminal-native, MCP-native trading-strategy backtester an AI agent can drive — with built-in overfitting guards (walk-forward, deflated Sharpe, costs).

ceruleane/trade-terminalcommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

Before you start

  • uv (`curl -LsSf https://astral.sh/uv/install.sh | sh`)
~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "trade-terminal": {
      "command": "uvx",
      "args": [
        "trade-terminal"
      ]
    }
  }
}

same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12

Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs

README

synced Oct 23, 2026

Trade Terminal

A terminal-native platform for market data → strategy → backtest, built so an AI agent can drive the whole loop over MCP — and so the tool won't let the agent fool itself: look-ahead detection, walk-forward robustness, transaction costs, and a deflated-Sharpe overfitting check are built in. And built so the codebase is the product: legible, plug-and-play, fork-friendly.

An AI agent drives the optimize loop over MCP — and flags its own winner as overfit:

https://github.com/user-attachments/assets/0536490f-880e-4842-9963-34b99bbbb08d

Scope so far: equities, numbers (OHLCV) via yfinance; a cache-first two-store data model; multi-asset backtesting (cross-sectional & long/short, see examples/pairs_reversion.py) with look-ahead guardrails and full provenance; an MCP server + a self-describing tool surface so any coding agent can drive the whole loop; a sandbox that confines agent-written code; and an optimization engine with the honesty guards that make results trustworthy at scale — walk-forward robustness, transaction costs, and a deflated-Sharpe multiple-testing guard. Strategies can also read point-in-time signals — non-price data (sentiment, narrative, filings) an agent produces offline, served <= now so there's no look-ahead — so the platform expresses semantic strategies, not just price ones (see examples/narrative_signal.py). Paper/live trading and derivatives are planned for later; their plug-in seams already exist, so they drop in without core edits. See the roadmap.

Install

This project uses uv. From the repo root:

uv sync                 # create the venv + lockfile, install everything
uv run tt --help        # run the CLI

(No uv? pip install -e . works too — you just won't get the lockfile.)

Quickstart (offline — no network, no API key)

DEMO below is synthetic data from the built-in sample source — deterministic, not real prices — so this runs anywhere in seconds:

uv sync
export TT_HOME=./demo-store        # a throwaway data dir for the demo (delete when done)

# 1. Pull synthetic DEMO bars into the read-only store (cached for next time)
uv run tt fetch DEMO --from 2020-01-01 --to 2023-12-31 --source sample

# 2. Open an analysis workspace over a development window
uv run tt analyze DEMO --from 2020-01-01 --to 2021-12-31 --name demo --source sample

# 3. Backtest a strategy out-of-sample (warns on look-ahead)
uv run tt backtest examples/sma_cross.py --workspace demo --from 2022-01-01 --to 2023-12-31

# 4. Inspect what ran, and map a run back to its exact code
uv run tt runs

For real equity data, drop --source sample (the default is yfinance): uv run tt fetch AAPL --from 2020-01-01 --to 2022-12-31.

# Pull AAPL daily bars into the read-only store (cached for next time)
uv run tt fetch AAPL --from 2020-01-01 --to 2022-12-31

# Open an analysis workspace over a development window
uv run tt analyze AAPL --from 2020-01-01 --to 2021-12-31 --name aapl-demo

# Backtest a strategy out-of-sample (warns on look-ahead)
uv run tt backtest examples/sma_cross.py --workspace aapl-demo --from 2022-01-01 --to 2022-12-31

# 4. Inspect what ran, and map a run back to its exact code
uv run tt runs

How it's built

Two folder-based stores and a plug-in registry:

  • Read-only store — the canonical, append-only cache of everything ever downloaded. Never mutated, only added to. A request that partially overlaps what's already stored fetches only the missing date gaps (range-merge).
  • Analysis workspace — a disposable, per-analysis working copy of the data a strategy needs. The store is durable; the workspace is throwaway.
  • Plug-in registry — seven extension kinds (data sources, data categories, config dimensions, execution backends, sandboxes, optimization objectives, and cost models) are all registered through one entry point. Built-ins and your own drop-ins are treated identically. Run tt kinds to see what's installed.

See docs/architecture.md for the component/seam map. The short version: every component depends only on trade_terminal/core/contracts.py (the "narrow waist"), so you can replace any one piece by satisfying its interface — without reading the others.

Extending it

Drop a .py file under trade_terminal/plugins/ (or any discovered path) that defines register(registry). That's the whole extension mechanism; built-ins use the exact same path. Example — a new data source:

def register(registry):
    registry.register("source", "my_source", MySource())

Drive it with an agent (MCP)

Install the optional extra and launch the server:

uv sync --extra mcp
uv run tt mcp          # stdio MCP server

Point any MCP-capable agent (Claude Code, etc.) at it and it can fetch data, open workspaces, write and submit its own strategy code, backtest it, and read run provenance — through the same core the CLI uses. See docs/mcp-server.md.

By default that agent-submitted code runs in a confined sandbox (restricted) that cannot write to the source tree or anything outside a scratch dir — an agent uses the functionality, it does not get to edit the code. See docs/security.md.

Data frequency

The default interval is daily (1d), but --interval also accepts intraday bars — 1h, 30m, 15m, 5m, 1m — and backtests run on them unchanged (the engine is interval-agnostic). Two limits worth knowing:

  • History is provider-bound. yfinance serves only recent intraday data (roughly 1m ≈ 7 days, ≤30m ≈ 60 days, 1h ≈ 2 years). Long-history high-frequency research needs a dedicated source plug-in (e.g. Polygon, databento) — which drops in without core changes.
  • Coverage is tracked per calendar day. A day's intraday bars are fetched and cached together, so re-fetching the current day won't pick up newer bars until it closes. Fine for historical backtests; relevant only for intraday paper/live.

Tick / quote / order-book data is a different shape and would arrive as its own data category. Production-grade high-frequency support (performance + a high-freq source) is planned alongside the vectorized backtest engine.

Optimize a batch (the agent loop)

Evaluate many strategy candidates at once, ranked by an objective — each run in a sandbox:

tt optimize ./candidates --workspace demo --from 2023-01-01 --to 2023-12-31 --objective sharpe
tt optimize ./candidates -w demo --from 2023-01-01 --to 2023-12-31 --windows 3   # walk-forward robustness
tt leaderboard            # list experiments; pass an id to view one

--windows N splits the window into N consecutive periods and ranks by the mean score while surfacing each candidate's worst window and consistency — so a one-window-lucky strategy is visibly fragile, not mistaken for a robust one.

Add --commission-bps / --slippage-bps to either backtest or optimize to model transaction costs (frictionless by default — a leaderboard run that omits them says so). This matters at scale: without costs the ranking quietly rewards high-churn strategies that only "win" because trading was assumed free. With costs on, the metrics report total_costs.

The leaderboard also reports a deflated Sharpe — the probability the #1 result's edge is real after the number of strategies you tried. Test enough arbitrary rules and the best one looks great by luck alone; this flags it. Together with look-ahead, walk-forward, and costs, it's a layered defense against fooling yourself — no single oracle.

Via MCP, an agent calls optimize(...) with a batch of inline candidate codes, reads the ranked leaderboard, and proposes the next batch. See docs/experiment-engine.md.

Data location

The read-only store, workspaces, and run records live under $TT_HOME (default: ~/.trade-terminal). Point TT_HOME somewhere else to sandbox them.

Disclaimer

Trade Terminal is a research and educational tool, provided "as is" without warranty of any kind (see LICENSE). It is not financial advice, not a recommendation to buy or sell any security, and not a solicitation. It currently backtests only — it does not place real orders. Backtested or simulated results are hypothetical, do not represent actual trading, and are no guarantee of future performance. The default yfinance source is unofficial and intended for personal research, not production use. You are solely responsible for any decisions made with this software. Markets carry risk of loss.

↑↓ navigate openesc close