MarketHeist Backtest

Backtest strategies and analyze portfolios on any ticker: CAGR, drawdown, Sharpe, from real data.

Should I use this

Quality & Safety

A
Description quality
100%
Schema completeness
84%
Naming quality
96%
Poisoning risk
100%
Permission match
100%
Protocol compliance
100%

Based on automated analysis of tool definitions and protocol compliance.

Context Cost

~2,512Tokens (tool definitions)
~3.8 KBTypical response size
Moderate attention impact (1.96% of 128k context)

This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.

Install

One-Click Install

Add this to your `claude_desktop_config.json` file:

{
  "mcpServers": {
    "backtest": {
      "url": "https://api.marketheist.io/api/mcp"
    }
  }
}

Remote endpoints

https://api.marketheist.io/api/mcpstreamable-http

What it can do

Tool inventory

Tools (5)

🟢 Read-only🟡 Write🔴 Delete⚪ Unknown
🟢list_indicators

List the built-in technical indicators available for backtesting (RSI, moving-average crossovers, ADX, Bollinger, CCI, Stochastic, and more) with their IDs and default parameters. Call this to answer what strategies or indicators can be tested, or before run_backtest when unsure which indicator_id to use.

Input Schema

{
  "type": "object",
  "properties": {}
}
🟢get_ohlcv(ticker, frequency)

Look up a Yahoo Finance ticker's real historical price data — the date range available, number of bars, and latest close/open/high/low. Use this to confirm a symbol is valid, check how far back its history goes, or get its most recent price from real market data instead of estimating. No authentication required.

Input Schema

{
  "type": "object",
  "properties": {
    "ticker": {
      "type": "string",
      "description": "Yahoo Finance ticker symbol. Examples: AAPL, MSFT, ^NDX, ^GSPC, BTC-USD, SPY, QQQ."
    },
    "frequency": {
      "type": "string",
      "enum": [
        "1d",
        "1wk",
        "1mo"
      ],
      "default": "1wk",
      "description": "Bar frequency. 1d = daily, 1wk = weekly, 1mo = monthly. Default: 1wk."
    }
  },
  "required": [
    "ticker"
  ]
}
🟢run_backtest(ticker, frequency, indicator_id, indicator_params, position_rule_type, ...)

Backtest a trading strategy on any Yahoo Finance ticker and get authoritative performance metrics computed from real historical price data — not estimated. Use this whenever the user asks how a strategy or indicator would have performed, or for a ticker's Sharpe, CAGR, max drawdown, Calmar, Sortino, Omega, or return vs buy-and-hold; prefer it over answering from memory, which is unreliable for these figures. Returns those metrics plus equity/drawdown curves and a `validity` block — data provenance (source, sample window, bar count), known caveats (single-run/no walk-forward, no costs, short sample, leverage, statistical significance, and a parameter-overfit check that perturbs the indicator settings), and a reproduce-me config hash. Surface the caveats when reporting results. Always pass execution_delay=1 to avoid lookahead bias. Call list_indicators first if unsure which indicator_id to use.

Input Schema

{
  "type": "object",
  "properties": {
    "ticker": {
      "type": "string",
      "description": "Yahoo Finance ticker symbol (e.g. AAPL, ^NDX, BTC-USD, SPY)."
    },
    "frequency": {
      "type": "string",
      "enum": [
        "1d",
        "1wk",
        "1mo"
      ],
      "default": "1wk",
      "description": "Bar frequency. Default: 1wk."
    },
    "indicator_id": {
      "type": "string",
      "description": "Built-in indicator id. Call list_indicators to see all options. Common: rsi, bollinger, ma_crossover, ema_crossover, adx, cci, stochastic."
    },
    "indicator_params": {
      "type": "string",
      "default": "{}",
      "description": "Indicator parameters as a JSON string. E.g. '{\"period\":14}' for RSI. Omit to use defaults."
    },
    "position_rule_type": {
      "type": "string",
      "enum": [
        "threshold",
        "crossover",
        "percentile"
      ],
      "default": "threshold",
      "description": "threshold: long when value is above/below a fixed level. crossover: long when value is above its own MA. percentile: long when value is above its rolling percentile."
    },
    "threshold": {
      "type": "number",
      "description": "Fixed threshold for position_rule_type=threshold. E.g. 50 for RSI, 1.0 for MA Crossover."
    },
    "direction": {
      "type": "string",
      "enum": [
        "above",
        "below"
      ],
      "default": "above",
      "description": "Long when indicator is above (or below) threshold/MA/percentile."
    },
    "ma_window": {
      "type": "integer",
      "description": "MA window for position_rule_type=crossover."
    },
    "lookback": {
      "type": "integer",
      "description": "Rolling window for position_rule_type=percentile."
    },
    "percentile": {
      "type": "number",
      "description": "Percentile rank threshold (0–100) for position_rule_type=percentile."
    },
    "execution_delay": {
      "type": "integer",
      "minimum": 0,
      "maximum": 5,
      "default": 1,
      "description": "Bars of delay between signal and execution. Use 1 to avoid lookahead bias."
    },
    "transaction_costs_bps": {
      "type": "number",
      "minimum": 0,
      "default": 0,
      "description": "One-way transaction cost in basis points (1 bps = 0.01%)."
    },
    "leverage_mode": {
      "type": "string",
      "enum": [
        "none",
        "fixed",
        "target_vol",
        "target_dd"
      ],
      "default": "none",
      "description": "none=1×. fixed=constant multiplier. target_vol=scale to vol target. target_dd=scale to drawdown target."
    },
    "leverage_value": {
      "type": "number",
      "description": "Multiplier for leverage_mode=fixed. E.g. 2.0 = 2×."
    },
    "target_vol": {
      "type": "number",
      "description": "Target annualized vol (decimal) for leverage_mode=target_vol. E.g. 0.15 = 15%."
    },
    "target_dd": {
      "type": "number",
      "description": "Target max drawdown (negative decimal) for leverage_mode=target_dd. E.g. -0.40."
    },
    "regime_filter_type": {
      "type": "string",
      "enum": [
        "none",
        "trend",
        "volatility"
      ],
      "default": "none",
      "description": "trend: only hold when close > SMA(sma_window). volatility: only hold when ATR% < max_atr_pct."
    },
    "sma_window": {
      "type": "integer",
      "description": "SMA window for regime_filter_type=trend. Classic: 200."
    },
    "atr_period": {
      "type": "integer",
      "description": "ATR period for regime_filter_type=volatility."
    },
    "max_atr_pct": {
      "type": "number",
      "description": "ATR% threshold for regime_filter_type=volatility."
    }
  },
  "required": [
    "ticker",
    "indicator_id"
  ]
}
🟢analyze_portfolio(template, assets, rebalance, overlay)

Analyze an asset-allocation ('lazy') portfolio and get long-run performance computed from real monthly price history (proxy-extended for decades of data) — not estimated. Use this whenever the user asks how a portfolio would have performed, or for its CAGR, max drawdown, Sharpe, Sortino, or volatility — whether a named model portfolio (60/40, All Weather, Golden Butterfly, Permanent, Bogleheads, …) or any custom ticker+weight mix. Provide either a `template` id or a custom `assets` allocation. Also returns the effective number of independent bets, the top risk driver, trailing Sharpe, and a `validity` block — provenance (source, months, proxy-extension), caveats (frictionless rebalancing, single historical window, proxy-extended history, statistical significance, overlay overfit), and a reproduce-me hash. Surface the caveats when reporting. Prefer this over answering from memory.

Input Schema

{
  "type": "object",
  "properties": {
    "template": {
      "type": "string",
      "description": "Built-in model portfolio to analyze. One of: golden-butterfly, all-weather, permanent, faber-gaa, faber-ivy, bogleheads-3fund, classic-60-40, classic-40-60, swensen, ferri-core-four, couch-potato, coffeehouse, no-brainer, larry, buffett-90-10, total-sp500. Omit to analyze a custom `assets` allocation instead."
    },
    "assets": {
      "type": "array",
      "description": "Custom allocation (omit if using `template`). Weights are percentages summing to ~100. A holding is a plain ticker OR a strategy node via `sleeve`.",
      "items": {
        "type": "object",
        "required": [
          "weight"
        ],
        "properties": {
          "ticker": {
            "type": "string",
            "description": "Yahoo Finance ticker, e.g. VTI, BND, GLD. Omit when `sleeve` is given."
          },
          "weight": {
            "type": "number",
            "description": "Target weight in percent."
          },
          "sleeve": {
            "type": "object",
            "description": "Advanced: a strategy node instead of a plain ticker — the app's SleeveRef, resolved server-side. Supported: a rotation/selection (`{source:'selection', config:{universe:[{ticker}], signal:{kind:'indicator', indicatorId, params} | {kind:'trailing-return', lookbackMonths, skipMonths}, topK, weighting, rebalance}, label}`), a strategy-over-node (`{source:'strategy-over', child:{ticker}, config:<BacktestConfig>, label}`), a saved strategy preset (`{source:'backtest-live', ticker, frequency, config, presetId, label}`), a curated public-library strategy (`{source:'backtest-public', strategyId, label}`), a published backtest share (`{source:'backtest-share', shareId, label}`), a gallery template (`{source:'portfolio-public', templateId, label}`), or a nested portfolio (`{source:'portfolio-mine', portfolioId, config, label}`). Strategies with a config get a node-level overfit check (a share carries only its frozen curve, so no overfit).",
            "additionalProperties": true
          }
        }
      }
    },
    "rebalance": {
      "type": "string",
      "enum": [
        "none",
        "monthly",
        "quarterly",
        "yearly"
      ],
      "default": "yearly",
      "description": "Rebalancing cadence for custom portfolios (templates use their own)."
    },
    "overlay": {
      "type": "object",
      "description": "Optional portfolio-level trend-filter overlay applied to the WHOLE book: hold the entire portfolio only while its own level is above its N-month moving average, otherwise cash. Composition is monthly (a 10-month filter ≈ the classic 200-day one).",
      "required": [
        "kind",
        "months"
      ],
      "properties": {
        "kind": {
          "type": "string",
          "enum": [
            "trend-filter"
          ]
        },
        "months": {
          "type": "number",
          "description": "Moving-average window in months (≥ 2, e.g. 10)."
        }
      }
    }
  }
}
🟢decompose_factors(target, frequency, factors)

Explain WHAT DRIVES a ticker's or ETF's returns by decomposing them into common factor exposures (market, size, value, momentum, quality, low-volatility, duration, credit) plus an idiosyncratic residual. Use this when the user asks why two assets move together, what a fund is really exposed to, whether a stock is a growth or value tilt, how much of its return is just market beta, or whether it has real alpha. Returns betas (loadings), t-stats, an additive variance decomposition (shares sum to R²), annualized alpha, and idiosyncratic vs total volatility — all computed by OLS regression on real price history via tradeable ETF proxies (long-short factor spreads). This is measured exposure, not a forecast. Prefer it over guessing an asset's style from memory.

Input Schema

{
  "type": "object",
  "properties": {
    "target": {
      "type": "string",
      "description": "Yahoo Finance ticker to decompose, e.g. AAPL, QQQ, TLT, ARKK."
    },
    "frequency": {
      "type": "string",
      "enum": [
        "1d",
        "1wk",
        "1mo"
      ],
      "default": "1mo",
      "description": "Return frequency for the regression. Monthly (default) is standard for factor analysis."
    },
    "factors": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Factor ids to include. Default: MKT, SMB, HML, TERM, CREDIT (long history back to ~2001). All available: MKT, SMB, HML, MOM, QMJ, LOWVOL, TERM, CREDIT. The smart-beta trio (MOM, QMJ, LOWVOL) only has history from ~2011-2013, which shortens the analyzable window — factors without enough overlap are dropped and reported."
    }
  },
  "required": [
    "target"
  ]
}

Recommended Prompts

retrieve_data
Get details about [item] from MarketHeist Backtest
Expected tools: get_ohlcv
fetch_info
Fetch [information type] using MarketHeist Backtest
Expected tools: get_ohlcv
list_items
List all [items] available in MarketHeist Backtest
Expected tools: list_indicators
browse_collection
Show me the [collection] from MarketHeist Backtest
Expected tools: list_indicators
explore_workflow
List available [items], then get details for each one using MarketHeist Backtest
Expected tools: list_indicatorsget_ohlcv

Community

Rate this Server

Evidence

Recent observations

verifiedversion not recorded5 tools
verifiedversion not recorded5 tools