Docs / Start

Quickstart

Connect a client, authenticate, and take one idea through the full gauntlet.

1. Get a key#

Sign up at quantbase.live/start. The free tier is 200 trials a month, a 10-asset universe and one holdout evaluation, and takes no card.

You will pass through a $0 checkout. Free and paid signup deliberately share one path — the same customer record, webhook and key mint — rather than having a second, less-tested flow beside the one that handles money.

Your key is shown once. Only its SHA-256 is stored, so a database dump of this server is not a set of working credentials. The same property means a lost key cannot be recovered, only replaced.

One tenant per mailbox#

Signing up again with the same address returns the same tenant, with the same handle and the same trial count. Address spellings that reach one mailbox are treated as one identity: you+quant@gmail.com, y.o.u@gmail.com and you@googlemail.com are the same person here.

This is not an anti-fraud afterthought, it is the product. A fresh tenant is a fresh N, and if N could be reset on demand then every deflated Sharpe, PBO and minimum-backtest-length this server computes would be a number you could choose. It also means signing up again is the supported way to replace a key you lost, and it costs you nothing.

2. Connect a client#

The endpoint is https://mcp.quantbase.live/mcp, streamable HTTP, TLS. Authentication is a bearer token.

Claude Code#

claude mcp add --transport http quant-research \
  https://mcp.quantbase.live/mcp \
  --header "Authorization: Bearer $QUANT_KEY"

Claude Desktop / any mcpServers config#

{
  "mcpServers": {
    "quant-research": {
      "type": "http",
      "url": "https://mcp.quantbase.live/mcp",
      "headers": { "Authorization": "Bearer YOUR_KEY" }
    }
  }
}

Cursor — .cursor/mcp.json#

{
  "mcpServers": {
    "quant-research": {
      "url": "https://mcp.quantbase.live/mcp",
      "headers": { "Authorization": "Bearer YOUR_KEY" }
    }
  }
}

Raw HTTP#

curl -sS https://mcp.quantbase.live/mcp \
  -H "Authorization: Bearer $QUANT_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Transport is stateless HTTP, so a redeploy will not kill your connection. The corollary is that a connected client cannot be told about new tools — reconnect to refresh the tool list.

3. Orient#

server_status()

Call this first in any new session. It reports what the server holds, what changed recently, and which research lines are already closed. It is cheaper than rediscovering that by trial and error.

4. Check whether the idea can survive its own costs#

cost_model_refresh()
cost_breakeven(trades_per_day=20)

Do this before ingesting data. At the Coinbase entry tier — 60 bps taker per side, non-promotional, so a 120 bps round trip — twenty trades a day is an 8,760% annual cost drag (120 × 20 × 365 / 100). Most intraday ideas die here, and they die in one tool call rather than a week.

5. Ingest, then check what you got#

Coinbase spot is built in, and 22 liquid USD pairs are pre-registered:

data_ingest_universe(universe="coinbase-liquid-22", timeframe="1h")
job_status(job_id=...)
data_quality_report(...)

Any other venue#

Point data_ingest at an OHLCV CSV over https and label it with the venue it came from:

data_ingest(
  symbol="BTCUSDT", timeframe="1d",
  start="2024-01-01", end="2026-01-01",
  source="url", venue="binance",
  url="https://example.com/Binance_BTCUSDT_d.csv",
)

venue is a label on the data, not an API this server calls. Common column spellings are normalised, so an exchange export, a vendor file or your own bucket all work as-is.

This server is reached over MCP, which means the client calling it is already an integration layer — your agent can fetch from wherever it has access and hand over the location. That is why there is no list of supported exchanges to wait on.

Two limits worth knowing: the URL must be public https — the server refuses private, loopback and cloud-metadata addresses, and re-checks on every redirect — and the download is capped at 64 MB.

The built-in cost model is Coinbase's published ladder. It does not describe Binance, and the server will not pretend it does: a cost model always names the venue it came from. See Costs.

Heavy work is asynchronous. A submit returns a job_id; poll job_status.

6. Register a split — once#

split_register(train=..., test=..., holdout=...)

Ranges are immutable. The holdout is unreadable until you freeze a strategy. A split also freezes the data-gap policy in force when it was registered, so a later policy change cannot retroactively alter what your backtest saw.

It also records a digest of the bars inside its own range, re-checked before every run. Appending newer bars is fine; revising history the split already covers is refused. That matters most when the data came from a URL you chose rather than from the built-in venue.

7. Register a strategy and test it across a universe#

strategy_register(family="my-idea", spec={...})
feature_validate(...)
backtest_cross_section(universe="coinbase-liquid-22", ...)

Prefer backtest_cross_section over backtest_submit. One specification across many assets counts as one trial — the spec is the hypothesis and the assets are the sample. Testing the same idea on ten assets one at a time costs you ten trials and tells you less.

8. Find out whether the result means anything#

stats_deflated_sharpe(...)      # against the ledger's N, not yours
stats_pbo(...)                  # did selection help, or hurt?
stats_bootstrap_ci(...)         # does the interval straddle zero?
stats_min_backtest_length(...)  # do you even have enough history?

9. Gate, freeze, and spend the holdout#

gate_check(...)
strategy_freeze(...)
holdout_evaluate(...)

One holdout attempt per strategy, ever. gate_check will tell you whether you are ready before you spend it.

Next#

Read this page as Markdown: /docs/quickstart.md