tradefloor
A market simulator you can run a strategy against, with a Rust core and a Python API.
Give it a seed and a list of companies. It runs a market forward: prices, a limit order book, fills, and an economy that moves each day. Your orders match against real depth, so your trades move the price.
Real market data cannot tell you what happens if you trade differently, or what caused a move. This can, because it computed every price.
Documentation
The full documentation lives at https://tradefloor.dev: install, core concepts, the realism envelope, presets, the API surface, and the notebooks, whose source is maintained in a separate repository.
Install
pip install tradefloor
Formerly pretium. Versions through 0.4.3 were published under that name and remain installable forever; results recorded against them replay under those exact versions. The rename changed no behaviour: 0.5.0 reproduces the same known-answer digest on every platform.
Wheels for Linux, macOS and Windows on CPython 3.11+. No dependencies. The same
engine is a Rust crate: cargo add tradefloor.
The API can still change before 1.0. A published result cannot: new coefficients ship as a new preset, so a run you cited last month replays this month.
The demo
python examples/rate-shock/counterfactual.py
Run an agent in a controlled market, checkpoint the world and fork it, then raise rates by 200bps in one branch and compare what the same agent does next.
One changed variable, in the same world and with the same agent. The run takes two seconds and needs no keys and no network. It prints the nine checks that prove the two branches started identical, the step at which the agent's behaviour changed, and the side-by-side. The walkthrough is Your first counterfactual experiment.
First run
import tradefloor as tf
universe = tf.Universe.random(40, seed=111)
spec = tf.StrategySpec.momentum(lookback_days=1.0, top_k=5)
scores = tf.evaluate({"mine": spec}, seed=7, universe=universe, days=10)
scores["mine"].return_pct # what it made
scores["mine"].impact_bps # what its own footprint cost
scores["mine"].strategy_fingerprint # sha256, cite this
That is one market draw. It tells you as much about the seed as about the
strategy. tf.rank runs many seeds and compares them with a paired sign test.
Contents
engine.truth() |
why each price moved: nine factors that sum to the move, to 1e-16 |
engine.prints() |
how each print was arrived at: the shock that arrived and the depth that absorbed it |
| counterfactual TCA | the same seed with your orders and without them |
tf.rank |
many seeds, paired sign tests |
RunManifest |
version, preset, seed, universe, macro, scenario. reproduce() stops on a mismatch |
World / compare |
fork a running experiment, change one variable, and measure where the two came apart |
| MCP server | twelve read-only tools for a coding agent, scenarios included |
| more | a Gymnasium environment, Arrow output, checkpoints, SEC EDGAR data, a browser build |
No historical dataset carries the labels truth() gives you. Real data shows
you that a stock fell. It never shows you that 60% of the fall was order flow.
To drive it from an agent:
pip install "tradefloor[mcp]"
claude mcp add tradefloor -- tradefloor-mcp
Strategies, universes and scenarios are data, so a tool argument cannot reach code. Each result carries its own caveats. See the MCP page.
Controlled scenarios
scenario = tf.Scenario.load("liquidity_crisis") # ships with the package
control, stress = tf.branch(engine, 2)
for day in range(80):
scenario.apply(stress, day)
... # run both branches
A scenario is an explicit collection of market interventions and assumptions, for controlled experiments rather than for forecasting. It names targets from a registry of fields the engine actually reads, and it keeps what it asserts happened apart from what it assumes happened next:
tradefloor scenario show scenarios/oil_price_spike.yml
Exogenous shocks
day 50+ commodity.oil x1.4
Assumed transmission
day 55..74 ramp macro.inflation +1.50pp
day 55+ macro.corporate_yield +0.50pp
tradefloor does not claim what a war, an election, an oil shock or a recession will do to markets. It lets you state those assumptions and measure how an agent behaves under them.
Six scenarios ship inside the package, so Scenario.load works on a plain
pip install -- each one recording what it was measured to be worth. Their
source is here.
tradefloor scenario list names them, and tradefloor scenario targets
lists every target and what it actually reaches.
Realism
tf.facts.measure() scores fourteen shape statistics against real-market
bands, and four more on a protocol that varies the roster with the seed. The
default preset, pt-v18, holds all fourteen at one year and at two years, on
the certification roster and on a held-out one, at thirty seeds each -- and it
is the first default to hold the other four as well: the index level returns
+5.8 per cent a year inside a band of 2.9 to 11.9, where pt-v16 lost 13.6
and was reported red for three releases.
One row reads further from real than before: the crisis lever is 6.53x
against real markets' 6.16x, where pt-v16 read 6.23x.
Five of the fourteen were calibration targets, and the bands both tuned the model and graded it. So this is a stated envelope, not a test against market data that was held back.
Five limits are measured and written down:
| limit | what it means |
|---|---|
| horizon | one year is certified. Two and five years are measured, not certified |
| volatility memory | it decays too fast |
| scenario size | the response has the right sign, but one run cannot size it |
| macro crises | an inflation crisis or a policy crisis needs a scenario to drive it |
| roster | certification used a sector-balanced roster, which no real index is |
tf.envelope.check() refuses a question that falls outside a limit, and
the realism envelope says
what each one forbids.
Good results here do not predict real returns. The prices come from a known model, so a strategy shaped like that model looks excellent and teaches you nothing. A strategy that fails here tells you more. There is one venue, no latency, and no counterparty that adapts to you.
Seed determinism
Each release builds five targets, runs one fixed simulation in each, and
compares digests. A disagreement stops the release. The crate ships its own
exp, log, sin and cos, so the platform libm cannot change a result.
pt-v18 became the default at 0.7.0, taking it from pt-v16. Naming your
preset explicitly makes a run replay exactly, and every preset from pt-v1 on
is still selectable.
eng = tf.Engine(seed=42, universe=u, model="pt-v10")
Examples
Twelve numbered examples/ in reading order, run by the test suite:
00-a-year-in-one-market |
Start here: one company, one year, two crises, one chart |
01-first-simulation |
Universe, engine, order book, determinism |
02-evaluating-a-strategy |
Specs, baselines, ranking across seeds |
03-why-did-the-price-move |
The nine factors that sum to every move |
04-how-realistic-is-this |
The realism panel and the limits |
05-training-an-agent |
The Gymnasium environment, and what size costs |
06-execution-and-impact |
TCA and the counterfactual run |
07-research-workflow.py |
A whole study in one file. It runs in about five seconds |
08-claude-agent.py |
An LLM agent trading the market through the harness |
09-a-pandemic-shaped-market |
A real 2020-21 macro path, and which fields transmit |
10-forking-a-market |
Fork a market, raise the rate in one branch, and compare the futures |
11-scenario-fork.py |
A scenario file applied to one branch of a fork, and what it cost |
Beside them, one directory per self-contained study. Each asks one question, and they come in no particular order.
rate-shock/ |
The canonical demo: checkpoint, fork, +200bps in one branch, compare |
finrobot/ |
The same experiment with a real FinRobot agent |
Agent frameworks
The framework decides; Tradefloor runs the market it decides in. Each adapter
under tradefloor.integrations carries one framework's output through the
same loop of observation, decision, execution and evaluation, so two
frameworks can be measured on one market through one harness.
| Framework | Tradefloor support |
|---|---|
| Plain Python | Generic callable |
| OpenAI Agents SDK | Adapter |
| PydanticAI | Adapter |
| LangGraph | Adapter |
| FinRobot | Existing integration |
pip install "tradefloor[openai-agents]" # or [pydantic-ai], or [langgraph]
A plain Python function needs no extra. FinRobot keeps the finrobot extra
it has always had, and its section below covers the rate-shock experiment
that integration was built for.
Each example runs offline in seconds, with a deterministic function standing
where a model would sit, so reading one costs no API key and no provider
account. The market replays from a seed; a live model call does not, so an
adapter records each exchange keyed by a digest of the exact input it sent
and replays that recording later with the framework uninstalled. The four
sit together in
examples/integrations/,
which sets out what each framework contributes and what Tradefloor keeps.
FinRobot integration
Evaluate a FinRobot financial AI agent inside a controlled Tradefloor market. Run shared history, checkpoint the world, fork it, raise rates by 200bps in one branch, and compare how the same agent responds. The canonical rate-shock experiment, with the agent swapped and nothing else moved.
pip install "tradefloor[finrobot]"
python examples/integrations/finrobot/rate_shock.py # replays a real recorded run
python examples/integrations/finrobot/rate_shock.py --live # calls FinRobot
The default run replays a genuine recorded FinRobot run and needs no API key, no network and no FinRobot install.
FinRobot is a project of the AI4Finance Foundation, licensed Apache-2.0. The notebooks above are a Tradefloor integration for FinRobot, maintained in this repository without endorsement from AI4Finance, and they form no part of FinRobot's own interface.
More
Full docs: tradefloor.dev.
To contribute, see CONTRIBUTING.md and RELEASING.md. One rule shapes the rest: a change to the simulated trajectory is a breaking change, whatever its size.
To cite the software, see CITATION.cff. To cite a result, use its
RunManifest.
Licence
MIT OR Apache-2.0, at your option, which is the Rust-ecosystem norm. See LICENSE-MIT and LICENSE-APACHE.
GitHub's sidebar reads Apache-2.0 because its detection picks one file and
stops. So does the sidebar of rust-lang/rust, serde and pyo3, which
carry the same two files. The grant that applies is the dual one, stated in
pyproject.toml, rust/Cargo.toml and this section.
Metadata
Release files for tradefloor 0.7.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tradefloor-0.7.1.tar.gz | 1.2 MB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| tradefloor-0.7.1-cp311-abi3-win_amd64.whl | CPython 3.11 | abi3 | Windows x86-64 | Details |
| tradefloor-0.7.1-cp311-abi3-manylinux_2_34_x86_64.whl | CPython 3.11 | abi3 | Linux glibc 2.34+ x86-64 | Details |
| tradefloor-0.7.1-cp311-abi3-manylinux_2_34_aarch64.whl | CPython 3.11 | abi3 | Linux glibc 2.34+ ARM64 | Details |
| tradefloor-0.7.1-cp311-abi3-macosx_11_0_arm64.whl | CPython 3.11 | abi3 | macOS 11.0+ ARM64 | Details |
| tradefloor-0.7.1-cp311-abi3-macosx_10_12_x86_64.whl | CPython 3.11 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 8.2 MB
Release files / tradefloor-0.7.1.tar.gz
| Download URL | tradefloor-0.7.1.tar.gz |
|---|---|
| Size | 1.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
77ec042857298573526963b3de54df59797342eeeef87e11fee998bdec80f00a
|
|
BLAKE2b-256 checksum How to use checksums |
f410d537263ca5975301acf018c91149c5a82bb5d3ee9cd021da129982b4618e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.
Transparency logRelease files / tradefloor-0.7.1-cp311-abi3-win_amd64.whl
| Download URL | tradefloor-0.7.1-cp311-abi3-win_amd64.whl |
|---|---|
| Size | 1.4 MB |
| Tags | CPython 3.11 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
4ffde43931ba73404f57dbcd9c936d27dd96bed9401f686c911c2ac700365c79
|
|
BLAKE2b-256 checksum How to use checksums |
3777bdf2ce6dd4b4e99b21aed04933a06ac8a469d1a3175f29441c5d3d87e933
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.
Transparency logRelease files / tradefloor-0.7.1-cp311-abi3-manylinux_2_34_x86_64.whl
| Download URL | tradefloor-0.7.1-cp311-abi3-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.11 Linux glibc 2.34+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
08c48710734c8880b9e80bd340e4f95a5af2bff865d20008f2572e6748415b5a
|
|
BLAKE2b-256 checksum How to use checksums |
6541e4c8c94c69a7d842e52786fa6819c305c82476f37f0a38c151ad7752deb7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.
Transparency logRelease files / tradefloor-0.7.1-cp311-abi3-manylinux_2_34_aarch64.whl
| Download URL | tradefloor-0.7.1-cp311-abi3-manylinux_2_34_aarch64.whl |
|---|---|
| Size | 1.4 MB |
| Tags | CPython 3.11 Linux glibc 2.34+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
c60ea6ed5ac26e57a88046d66443b57257ee7c52ee51349e9d2c474b7b5286c5
|
|
BLAKE2b-256 checksum How to use checksums |
675ec508d46022070ec896f4cb5bae1059eb47e2df392e806fb85b0ddd459f61
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.
Transparency logRelease files / tradefloor-0.7.1-cp311-abi3-macosx_11_0_arm64.whl
| Download URL | tradefloor-0.7.1-cp311-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.4 MB |
| Tags | CPython 3.11 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
f7089a6f2fe4ff818cd423067536955514649b863695f278b42b669eee7ba1d1
|
|
BLAKE2b-256 checksum How to use checksums |
21740254cc638fc77c4a6dfd4315d8fc277b216c24bdc977a02ca1a74a7028e8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.
Transparency logRelease files / tradefloor-0.7.1-cp311-abi3-macosx_10_12_x86_64.whl
| Download URL | tradefloor-0.7.1-cp311-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 1.4 MB |
| Tags | CPython 3.11 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
83a4aa5127f8db3ce8509a272d9ddd3bc870107189eca49a9edcd7f68d045c75
|
|
BLAKE2b-256 checksum How to use checksums |
42048a9ec0778ac847a5b96e09697fac98d4faaaf331068e4f21802c857df797
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 8, 2026.
Transparency log