A high-performance options and stock backtesting engine exposed as a self-hosted MCP server. Backtest strategies, optimize parameters, and analyze price patterns through natural language.
Note
This project is under active development. Breaking changes to the API and configuration may occur between minor versions. Pin to a specific release tag for stability.
Describe a strategy in plain English and Claude generates a Rhai script that runs against historical data. Define entry logic, exit rules, position sizing, and stateful multi-phase strategies in a single script — or use the built-in wheel strategy script with parameter injection.
"Write a strategy that sells puts on SPY when VIX > 20 and RSI < 30, with a 50% stop loss"
"Build a custom mean-reversion strategy that buys QQQ on 3 consecutive down days and exits after a 2% gain or 5-day hold"
"Run the wheel script on SPY with 30-delta puts at 45 DTE and 25-delta calls at 30 DTE"
Run event-driven simulations across 32 built-in options strategies — singles, spreads, iron condors, butterflies, calendars, diagonals, and stock-leg combos. Signal-driven stock backtesting on OHLCV data. Full position management with stop-loss, take-profit, max-hold exits, and 5 dynamic sizing methods.
"Backtest an iron condor on SPY with $100k capital, 30-delta wings, and a 50% stop loss"
"Backtest buying SPY when RSI drops below 30 and selling when it crosses above 70"
"Run the wheel on SPY with 30-delta puts at 45 DTE and 30-delta calls at 30 DTE"
Grid-search across delta, DTE, slippage, and signal combinations with out-of-sample validation. Walk-forward analysis with rolling train/test windows. Permutation testing for statistical significance.
"Sweep DTE and delta for short puts on SPY — find the best risk-adjusted setup"
"Run walk-forward on this strategy with 4 windows to check if it holds up over time"
"Is this backtest result statistically significant or just luck?"
Discover seasonality, regime shifts, and price patterns. Gate entries using HMM regime detection. Cross-symbol correlation, rolling metrics, and distribution analysis.
"Show me SPY's average return by day of week — are any statistically significant?"
"Only enter covered calls when SPY is in a bullish HMM regime"
"Detect volatility regimes in SPY and show when they shift"
| Tool | Description |
|---|---|
| Backtesting | |
backtest |
Run a single backtest or grid/bayesian parameter sweep over a Rhai strategy |
scripting_guide |
Return the full Rhai scripting API reference |
| Statistics | |
aggregate_prices |
Time-based aggregation with significance testing |
distribution |
Distribution analysis with normality testing |
correlate |
Cross-symbol or cross-metric correlation matrices |
rolling_metric |
Rolling window calculations (Sharpe, volatility, returns, etc.) |
regime_detect |
Market regime detection (volatility clustering, trend state, HMM) |
generate_hypotheses |
Auto-scan for statistically significant patterns with FDR correction |
| Risk & Portfolio | |
drawdown_analysis |
Full drawdown distribution with episode tracking and Ulcer Index |
cointegration_test |
Engle-Granger cointegration test for pairs/stat-arb strategies |
monte_carlo |
Block-bootstrap Monte Carlo simulation with ruin probabilities |
factor_attribution |
Multi-factor regression decomposing returns into factor exposures |
portfolio_optimize |
Optimal portfolio weights via risk parity, min variance, or max Sharpe |
benchmark_analysis |
Benchmark-relative metrics: alpha, beta, Information Ratio, capture ratios |
git clone https://github.com/goldspanlabs/optopsy-mcp.git
cd optopsy-mcp
cargo build --releasePORT=8000 cargo run --releaseThis starts the MCP server over StreamableHTTP at /mcp.
Place your Parquet data files in ~/.optopsy/cache/ before your first session — see the Data section below.
To change the cache directory, set DATA_ROOT:
DATA_ROOT=/your/custom/cache/dir PORT=8000 cargo run --releaseSingles, verticals, straddles, strangles, butterflies, condors, iron condors/butterflies, calendars, diagonals, and stock-leg strategies (covered call, protective put) — with multi-expiration support for calendar and diagonal spreads.
Mid, spread (bid/ask worst-case), liquidity-based (volume-scaled), and per-leg fixed.
Fixed quantity, fixed fractional, risk per trade, Kelly criterion, and volatility targeting.
Write backtests as Rhai scripts with a callback-driven API. The engine provides a BarContext (ctx) object with access to OHLCV data, pre-computed indicators (SMA, EMA, RSI, ATR, MACD, Bollinger Bands, Stochastic, CCI, OBV), options chain lookup, portfolio state, and cross-symbol data. Scripts are fully sandboxed with no file or network access.
fn config() {
#{ symbol: params.SYMBOL, capital: params.CAPITAL,
data: #{ ohlcv: true, options: true, indicators: ["rsi:14", "sma:50"] } }
}
fn on_bar(ctx) {
if ctx.position_count >= 3 { return []; }
let spread = ctx.short_put(0.30, 45);
if spread == () { return []; }
[spread]
}
fn on_exit_check(ctx, pos) {
if pos.dte <= 7 { return close_position("dte_exit"); }
hold_position()
}
32 named helpers are available (bull_put_spread, iron_condor, short_strangle, etc.) along with action builders (hold_position(), close_position(), buy_stock()). See scripts/SCRIPTING_REFERENCE.md for the full API.
A built-in wheel strategy script is included and parameterized via constant injection.
RSI, MACD, Stochastic, Bollinger Bands, Keltner Channels, Supertrend, ATR, OBV, MFI, IV Rank, HMM regime filter, and more. Available as pre-computed O(1) lookups in Rhai scripts (ctx.rsi(14), ctx.sma(50)) and as a formula DSL for the built-in backtest tools (rsi(close, 14) < 30 and VIX > 20).
optopsy-mcp reads options chains and OHLCV prices from a local Parquet cache. Place your Parquet files directly into the cache directory — any file matching the expected schema will be picked up automatically.
The default cache directory is ~/.optopsy/cache/. To use a different location, set the DATA_ROOT environment variable.
~/.optopsy/cache/
├── options/ # required — options chain data
│ ├── SPY.parquet
│ └── ...
└── <category>/ # any subfolder name works for OHLCV data
├── SPY.parquet
└── ...
options/ is the fixed folder for options chain data. For OHLCV price data, you can organize files into any subfolder name you like (e.g. stocks/, etf/, futures/, indices/, or your own). The engine searches all non-options subdirectories when resolving a symbol's price data.
| Column | Type | Description |
|---|---|---|
datetime |
Datetime | Quote timestamp (intraday resolution supported) |
expiration |
Date/Datetime | Option expiration date |
strike |
Float64 | Strike price |
option_type |
String | "call" or "put" |
bid |
Float64 | Bid price |
ask |
Float64 | Ask price |
delta |
Float64 | Option delta |
Note: If your data has a
date(Date) column instead ofdatetime, it will be automatically cast to a Datetime at 15:59:00 on load.
| Column | Type | Description |
|---|---|---|
datetime |
Datetime | Bar timestamp (intraday resolution supported) |
open |
Float64 | Open price |
high |
Float64 | High price |
low |
Float64 | Low price |
close |
Float64 | Close price |
volume |
Int64/Float64 | Volume |
After cloning, configure git to use the project's shared hooks:
git config core.hooksPath .githooksThis enables a pre-push hook that runs cargo fmt --check, cargo clippy --all-targets, cargo build, and cargo test before every push, matching the CI checks.
cargo build --release # Build
cargo test # Run all tests
cargo clippy --all-targets # Lint
cargo fmt --check # Check formatting
cargo run --release # Run MCP server (stdio)
PORT=8000 cargo run --release # Run MCP + REST over HTTP- Polars — DataFrame engine for data processing
- rmcp — MCP server framework (v0.17)
- Tokio — Async runtime
- Axum — HTTP server and REST API (via
PORTenv var) - rusqlite — SQLite storage for backtest persistence
- rust_ti — Technical analysis indicators
- Rhai — Embedded scripting language for custom strategies
- garde — Input validation
- serde + schemars — JSON serialization and MCP schema generation