Tubby Labs Get started

Tubby Quant · open-source research workbench

Quant research that holds up to scrutiny.

Run BRAIN-style alphas on your own data, on your own machine. Screen fast in Alpha Lab, validate long/short on a pinned Qlib engine, and let a research loop propose and test ideas while every result keeps the evidence it came from.

Not yet known
Day 100

Alpha · FASTEXPR

-(close / ts_delay(close, 5) - 1)

Five-day reversal. Each weight is proportional to its signal; gross exposure is 100%.

Long0%

Short0%

Drag across the chart to move through time. Weights come only from prices to the left of the line; nothing to its right can reach them. The prices are synthetic.
daily bars checked on every import
27.9M
stocks in a universe rebuilt each month from what was known then
3,000
FASTEXPR operators, each documented and tested against a naive reference
73
automated tests in the offline suite, on synthetic fixtures only
2,200

What we build

Four tools with distinct jobs, from a first idea to a report you can reopen months later. Each one records what it used.

Alpha Lab, offline

A fast screen for WorldQuant-BRAIN-style FASTEXPR alphas on a fixed book: the same operators, neutralization, truncation and decay conventions, with every operator’s semantics written down. No account, no queue, no rate limit.

  • Batches with a leaderboard, in-batch correlations and a saved library
  • Sharpe, fitness, turnover, margin and drawdown in BRAIN’s conventions
  • Expressions parsed by an allow-listed grammar; nothing is ever evaluated as code
The Tubby console showing Alpha Lab: an expression editor, a simulation window, headline metrics and a cumulative PnL chart, all on synthetic toy data.
Real console, synthetic toy data. The screenshot shows the interface, not investment performance.

Data you can verify

Market data is converted once into immutable Qlib snapshots. Nothing in the source is ever modified, and nothing is filled in to look complete. Survivorship-free paths (Sharadar, HistoricalData) keep delisted names in the history.

  • Source files fingerprinted before and after every import
  • Every converted file read back and compared bit for bit
  • A top-3000 universe ranked on liquidity each month, effective from the next session

Long-only and long/short validation

Built on Qlib 0.9.7. Our pinned, reproducibly built derivative adds signed weights, stock borrow costs and restricted short proceeds, so an alpha’s direction and size carry straight into whole-share positions filled at the next open.

  • Top-k long-only, or long/short weights in proportion to the signal
  • Fills at the next open, with costs on both sides and borrow on shorts
  • The installed engine is checked byte for byte before each run

Research that keeps its evidence

A campaign reads sources, proposes hypotheses that must quote them exactly, tests each expression chronologically after costs, and refines, rejects or promotes it under explicit gates. The reserved holdout is scored once, by a person, and that access is recorded.

  • Immutable JSON records for every source, hypothesis, experiment, review and final
  • Anthropic, OpenAI-compatible or your own agent through a bounded HTTP contract
  • Promoted ideas hand off to Alpha Lab batches and Qlib validation

How a backtest runs

Six steps, always in this order. Each leaves a record, so any result can be traced back to the data it came from.

  1. Freeze the data

    Import once, verify every file, never touch the source.

  2. Fix the universe in time

    Rank at each month-end; members count from the next session.

  3. Write the alpha

    An allow-listed expression language. Anything the engine can’t evaluate is rejected up front.

  4. Build the portfolio

    Top-k long-only, or signed weights scaled to a gross exposure.

  5. Trade at the next open

    Signals from today’s close fill at tomorrow’s open, net of costs and borrow.

  6. Seal the record

    Metrics, positions and hashes are written once. A cancelled run is never marked complete.

The research loop

Two loops with different clocks. The inner one runs itself within budgets; the outer one is where people decide what the next campaign should ask.

  1. 1

    Read sources

    arXiv abstracts or a reviewed plan. A proposal must quote the text it builds on, exactly.

  2. 2

    Propose a mechanism

    A falsifiable price/volume expression, its family, horizon and required fields, from a model or your own agent.

  3. 3

    Evaluate in order

    Development then validation, delay 1, after costs, in the same Alpha Lab engine you screen with.

  4. 4

    Decide by the gates

    Sharpe, return, turnover and drawdown thresholds you set. Refine, reject, park or promote; failures are kept too.

  5. Score the holdout once

    A person finalizes promoted ideas on the reserved period. The access is recorded before the run; a repeat is labelled reused and never confirmed.

  6. 6

    Hand off

    Promoted or confirmed expressions become an Alpha Lab batch and a Qlib validation request, with their provenance attached.

Exact quotes, not vibes

Every cited source needs a verbatim excerpt from the retrieved text. An abstract is labelled as an abstract.

Budgets you can read

Model calls per day and per campaign, evaluations, ideas per family and refinement depth are explicit numbers in the campaign file.

Nothing is a trade

Promotion and confirmation mean deeper research. The loop places no orders and never reads the holdout on its own.

New in the lab · public release next

One harness, many research domains.

Nothing in the way we keep research honest is specific to equities. A domain decides what a candidate is and how it is scored; the harness keeps the count, the seals and the record. Quant is the first branch, machine learning the second, and the next one plugs into the same contract.

Everything tried is counted.

Every screen, validation, review and holdout access is a line in a ledger that carries the hash of the line before it. Edit or delete one and the chain breaks.

Sealed by construction.

The screen runs on data that physically ends where development ends; validation probes on data that ends where validation ends. Only an explicit final command loads the holdout.

Gates are identity.

Thresholds, data and code hash into the campaign’s ID. Changing a gate starts a new campaign; it cannot rescue an old candidate.

Agents propose, nothing more.

An agent can submit candidates over MCP. They face the same screen, count and review as everything the search generates.

Domain · autonomous alpha discovery

Search thousands of alphas. Keep the few that survive the count.

A typed search writes FASTEXPR expressions, screens them on data that stops where development ends, and spends a scarce validation budget only on fit, diverse candidates. A promotion has to beat the best result that luck alone would have produced from everything tried.

Six ways a candidate is born

  • Mechanism templates (reversal, momentum, volatility, volume, range, liquidity) with sampled windows
  • Random trees that pass a unit check: no price plus volume, no division by a return
  • Mutation and crossover of the fittest screened trees
  • Ensembles of mutually uncorrelated leaders, chosen on development data only
  • Seeds from the grounded research loop
  • Candidates your agent submits over MCP
  1. ScreenDevelopment only, signal oriented, scored by its weakest of three sub-periods.
  2. ShortlistFit, consistent and not a near-copy of anything already validated.
  3. ValidateOne counted trial, reserved before it runs, in the same Alpha Lab engine.
  4. ReviewResearch gates, the deflated Sharpe ratio, then doubled costs, both halves of validation and every window stretched and shrunk.
  5. HoldoutOnce per candidate, after the final trial count is known.

Why the count matters

How good does the best of N look by luck?

Validation length

Annualized Sharpe ratios of pure-noise daily returns, from the expected-maximum formula behind the deflated Sharpe ratio. Mathematics, not market data.
planted signals recovered from an artificial panel built to contain them
3 of 3
false promotions across five null panels, panels with nothing to find
0
candidates screened on those null panels, each one a line in a ledger
2,145
promotions on the planted panel that its reserved holdout then confirmed
8 of 8

The research benchmark: an artificial 300-name panel with three planted signals, its null twin with identical noise, and four more null panels with other noise. Known answers, no market data; rerun with tubby-lab benchmark alpha.

Domain · machine learning

The same discipline, applied to models.

Here a hypothesis is a training recipe and an experiment is a bounded training run. Recipes are searched the way alphas are: screened cheaply, validated on rows the screen never saw, and finalized once.

Models you can open and rerun

Ridge and logistic regression, histogram gradient-boosted trees, random forests and multilayer perceptrons, written in plain numpy. Every trained model is saved as JSON and reloads to identical predictions.

  • Tabular tasks from any numeric CSV, split by time or by a fixed seed
  • Cross-sectional return panels whose predictions Alpha Lab scores exactly like an alpha
  • A screen on one common subsample, so identical recipes look identical
  • Promotion only when a bootstrap p-value survives a Bonferroni correction across every recipe validated

friedman1

The error floor is known.

A regression with irreducible noise of exactly 1.0, so the gap between a confirmed model and the best possible model is measured, not guessed.

interaction

The best loss is known.

A classification task whose true probabilities are kept, so every holdout report sits beside the Bayes-optimal log loss.

null_regression

There is nothing to find.

Features carry no information about the target, so a promotion would be a false discovery. The search validated recipes and promoted none.

Built for agents, bounded by design.

Claude Code, Codex or any MCP client can check and simulate alphas, compare a batch, read the saved library and campaign reports, and queue candidates for a lab campaign through one small server. Everything stays inside the data root you launch it with.

  • Datasets are addressed by name; paths outside the data root are refused
  • No trading, no model calls, no downloads; the research holdout is never scored here
  • Research campaigns can call your agent back through a documented HTTP contract with the same limits

Running in four commands

Python 3.12 and Git. The package installs Alpha Lab, the research loop, the console and the data adapters on Windows, macOS and Linux; the verified long/short Qlib runtime uses the platform setup script.

  1. Try the demo first. Research → Try demo runs the real engine on synthetic prices with deterministic responses. No credentials, no downloads.
  2. Bring your own data. Yahoo, Stooq, Sharadar or HistoricalData imports become hashed snapshots with dated universes. Keep datasets and results outside the source folder.
  3. Screen, then validate. Batches in Alpha Lab; the candidates you keep go to the signed Qlib validator with their settings attached.
  4. Let a campaign run. A JSON file, a model or your agent, explicit budgets and gates. Finalize on the holdout only when you decide to.

Windows x64 has installation and synthetic signed-run evidence; macOS is experimental; Linux has no pinned signed runtime. Read the limitations before interpreting any statistic.

How we work

The rules we hold ourselves to, whichever idea we happen to be testing.

Reuse before we build.

We start from proven open-source software, change as little as we can, and write down every change we make.

Evidence over claims.

A result counts when its data, settings and tests are on record. A good-looking chart is not evidence.

Only what was known.

Universes, signals and fills follow the calendar. Look-ahead is a bug, not a detail.

Reproducible by default.

Pinned versions, fingerprinted inputs, and rebuilds that match byte for byte.

A backtest is not a trade.

Results are material for discussion, never a signal to buy or sell. Their limits are written down right beside them.

Open framework, private strategies.

The framework is free and open source under Apache 2.0. Specific strategies and portfolios stay private.

The framework is public.

tubby-quant is on GitHub under Apache 2.0: Alpha Lab, the research loop, the console, the data adapters and the MCP server, with about 2,200 offline tests on synthetic fixtures. Our long/short changes to Qlib live in a separate derivative under Qlib’s MIT license. Strategies, data and results are not part of either.

Where we are going

Each stage has to prove itself before the next one starts. Nothing here is a date or a promise of performance.

  1. Now

    The public research preview: offline Alpha Lab, verified US daily data with point-in-time universes, signed Qlib validation, a research loop with a sealed holdout, and the MCP server. In the lab: autonomous alpha discovery and a machine-learning domain on one harness, measured on planted-signal benchmarks.

  2. Next

    The lab domains in the public framework and the console, full-text sources, fundamentals and groups inside campaigns, automatic hand-off from a confirmed discovery into signed validation, and further domains on the same harness.

  3. Later

    Portfolio sleeves from confirmed ideas, a restartable paper account on historical sessions, and decision support for trades placed by people. Automation comes only after that has earned trust.