A structured research system for building and validating systematic investment strategies. Design, test, and deploy hypotheses — without bias or overfit.
Pin a virtual today and the platform replays history forward, bar by bar. The question isn't whether your strategy survives a backtest — it's whether your methodology survives when reality unfolds.
Only what existed on the pinned date is visible — universe, constituents, filings, prices. Acting twenty years ago, not fooling yourself with today's survivors.
Build with what was knowable. Replay forward bar by bar — pure methodology, no hindsight in the design.
AI assistants agree with you. Quantin's Skeptic doesn't — it probes for curve-fit. The Tutor explains why a step exists. The Librarian reads your saved work. The Mathematician derives the model. Same thread, same data, swap posture per question.
You My backtest got Sharpe 1.62 and 23.47% return on 9 trades. OOS was set to 40%. Ready to deploy?
You set OOS to 40% — good instinct. But you haven't revealed it yet. Your headline numbers — the 1.62 Sharpe, the 23.47% return — are in-sample only. Hypothesis generation. Not validation.
Until you show the OOS Sharpe and the walk-forward decay ratio, you have nothing except evidence that you can fit a curve.
All the hallmarks of curve-fit:
Before you trade this or show it to anyone:
If those three hold up, I'll eat my words. Until then: this is a backtest artifact, not a strategy.
You What's walk-forward and why does the platform keep nagging me about it?
A regular backtest fits parameters on the same window it scores on. That's an in-sample result — the strategy has seen every bar before it traded. Of course it looks good.
Walk-forward slides a rolling window. Fit on the first opt_bars, then trade the next test_bars blind — the strategy has never seen them. Step forward. Repeat. Stitch all those blind segments into one out-of-sample equity curve.
Then check the decay ratio — OOS Sharpe divided by IS Sharpe. Close to 1.0 means the edge survived first contact with the unknown. Far below 1.0 means you fit noise.
Want me to run one now on your last backtest? I can pick sensible defaults for opt / test bars based on your timeframe.
You Read my project library. Anything worth picking back up?
I read 18 saved backtests, 4 active projects, 11 trading configs. Three patterns surfaced:
Promising tier across four tickers (KO, PG, CL, KMB). You walked away after the first build — OOS Sharpe never decayed below 0.85. Worth running per-regime to see if it survives 2022.
Half-life under 15 days, beta stable across two epochs. Sitting in “Untitled Project” from April; never got a forward stress test.
Two configs disagree on direction (long vs short on identical filter output). One of them is wrong — the other is a strong candidate.
Weak tier in five rebuilds across three years. You've optimised this six times; each rebuild looks worse out-of-sample. The data is telling you something.
Want me to open the first one and queue a per-regime optimisation, or shall we start with the contradiction?
You Derive the OU process so I understand what the Stochastic Builder is actually fitting.
Start with the continuous-time SDE. The process is pulled back toward its long-run mean \(\mu\) at speed \(\theta\), perturbed by Brownian noise of size \(\sigma\):
Three parameters, three meanings. \(\theta\) is the speed of reversion — large \(\theta\) snaps back fast. \(\mu\) is the level it reverts to. \(\sigma\) is the noise scale — the width of the band around \(\mu\) the process explores.
From \(\theta\) you get the most actionable quantity, the half-life — the expected time for a deviation from the mean to shrink by half:
And the trading signal — the z-score at each bar — is just the standardised deviation from the fitted mean:
The Stochastic Builder fits \((\theta, \mu, \sigma)\) by maximum likelihood on the discretised AR(1) form. Want me to walk through the AR(1) derivation, or show how the half-life maps to the platform's signal-window control?
Connect QuanterLab's MCP server to Claude, Codex, or any MCP-compatible client. Your assistant, our research substrate — same point-in-time data, same tools, same boundaries.
The same canonical loop, applied to different primitives — indicator rules, stochastic processes, factor portfolios, paper execution. Drag, swipe, or use the arrows.
Six diagnostics before you build a rule. Hurst, HMM regimes, volatility squeeze, Monte Carlo, return distribution. If Hurst > 0.5 you're not mean-reverting — the platform tells you so.
A library of momentum, mean-reversion, crossover and breakout indicators in one builder with up to twenty layers per rule. Four optimisation modes — Static, Per-Regime, Dynamic Mean, Regression — plus walk-forward as the final judge.
Indicator rules react to symptoms. Stochastic methods describe the underlying process: Ornstein-Uhlenbeck, Kalman, cointegrated pairs, realised volatility surface.
Rank an index by composite factor scores; build a portfolio with MVO / HRP / IVOL; backtest with point-in-time fundamentals; autopsy each rebalance to see which factor carried the run.
Four paper-trade engines (Basic, Universal, OU, Kalman) — each with its own capital pool, morning brief, and per-trade signal alerts. Plus the Portfolio Visualiser tracks up to three portfolios side-by-side, real-time.
Every backtest, walk-forward, and grid search exports as standalone Python — yfinance + numpy + scipy, no platform deps. Run it on your laptop, scale it on your GPU, drop the JSON output back into the platform viewer.
1 #!/usr/bin/env python3 2 """ 3 QuanterLab — Grid Search Parameter Optimizer 4 Generated by QuanterLab on 2026-05-13 19:18 5 6 Runs a 50x50 parameter sweep over: 7 X-axis: level_covariance (0.0001 to 1) 8 Y-axis: trend_covariance (1e-05 to 0.1) 9 10 Outputs: PNG heatmap + CSV results + interactive HTML 3D 11 Ticker: NFLX · Method: kalman_trend 12 """ 13 import yfinance as yf 14 import numpy as np 15 from scipy import stats 16 from statsmodels.regression.linear_model import OLS 17 18 # 50×50 grid — same axes the platform ran 19 LEVEL_COV_GRID = np.logspace(-4, 0, 50) 20 TREND_COV_GRID = np.logspace(-5, -1, 50) 21 22 results = np.zeros((50, 50, 5)) # sharpe, sortino, mdd, … 23 for i, lc in enumerate(LEVEL_COV_GRID): 24 for j, tc in enumerate(TREND_COV_GRID): 25 results[i, j] = backtest(price, lc, tc) 26 27 # 2,500 backtests → CSV + PNG heatmap + 3D HTML viewer 28 np.savetxt("grid.csv", results.reshape(-1, 5), delimiter=",") 29 plot_surface(results, save="grid.html") 30 # Drop grid.html back into QuanterLab's 3D viewer to compare 31 # cloud vs. local. Or scale to 200×200 on your own GPU.
Articles that explain why, not just how. Method deep-dives, conceptual explanations, terminology breakdowns — each grounded in real academic sources you can chase down.
Free to start. Closed beta — invitation-based.