Skip to main content

pretium

determinism licence: MIT OR Apache-2.0 python 3.11+

A market simulator you can run a strategy against. Rust core, Python API.

Give it a seed and a set of companies and it runs a market forward: prices, a limit order book, fills, and an economy that advances itself daily. Your orders match against real depth, so trading moves the price the way it would anywhere else.

It exists because historical data can't answer two questions. What would have happened if I'd traded differently, and what actually caused this price move.

Install

pip install pretium

Wheels are prebuilt for Linux, macOS and Windows on CPython 3.11+, and the core package has no dependencies.

The engine is also published as a Rust crate, so you can use it without Python at all:

cargo add pretium

Both are built from the same source at the same version, and run the same market: https://crates.io/crates/pretium.

The API may still move before 1.0. What will not move is a published result: anything that changes the simulated trajectory arrives as a new model preset rather than an edit to an existing one, so a run you cited last month reproduces this month.

In thirty seconds

import pretium as pt

universe = pt.Universe.random(40, seed=111)

spec = pt.StrategySpec.momentum(lookback_days=1.0, top_k=5)
scores = pt.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's one market draw, which tells you as much about the seed as about the strategy. pt.rank runs many seeds and compares them with a paired sign test.

What makes it different

Determinism that's checked. The crate ships its own exp, log, sin and cos instead of calling the platform libm. Every release builds five targets -- linux-x86_64, linux-aarch64, macos-arm64, macos-x86_64 and windows-x86_64 -- runs one fixed simulation inside each, and compares digests. A disagreement fails the release.

The WebAssembly build is checked by hand rather than by that gate, because it needs a toolchain CI does not carry: on 2026-08-24 the native and wasm32-unknown-unknown builds hashed the same fixed simulation -- twelve instruments, five days, pt-v3 -- to 2b2f3141..., and tests/test_wasm_parity.py pins the Python half of that pair so the two cannot drift apart unnoticed.

Ground truth you can read. The simulator computed every price, so it can tell you why. One row per instrument per tick, with nine factor contributions that sum to the move and a residual around 1e-16. No historical dataset carries those labels. You can see that a stock fell, never that 60% of the fall was order-flow pressure.

Counterfactuals you can run. The same seed runs with and without your orders, so every fill is priced against the market where you never traded. That's the number TCA vendors approximate.

Results someone else can check. A StrategySpec is a declarative, hashable document rather than an arbitrary callable. A RunManifest carries the seed, universe, macro conditions, scenario, model and strategy together with the expected digest. reproduce() refuses on a mismatch and names the culprit, because a manifest that quietly reproduced a different market would be worse than no manifest.

Driving it from an agent

pip install "pretium[mcp]"
claude mcp add pretium -- pretium-mcp

Eleven read-only tools over the simulator, so a coding agent can ask whether a momentum strategy beats buy-and-hold here, and whether the difference is real. Strategies, universes and scenarios are composed as data. There's no path from a tool argument to code execution.

Every result carries computed caveats and full provenance. A model summarising a result has the tool output and nothing else, and will otherwise report return_pct: 88.7 as "the strategy made 88.7%". The MCP server has the tool list and the client configuration.

What it's bad at

Good results here don't predict real returns. The price process comes from a known model, so a strategy that fits that model's structure will look excellent and teach you nothing. A strategy that fails here is more informative, because it broke against a live order book under honest impact costs.

Realism is a stated envelope, not a score. pt.facts.measure() reports fourteen statistics against real-market bands. At 252 days the shipped pt-v12 preset holds all fourteen in band on thirty calibration seeds, all fourteen again at 504 days against bands re-derived at that window, and all fourteen again on a 60-name universe it never saw. On thirty seeds it never used it holds thirteen, the single miss being corr_persistence_acf1. Read that as fourteen in-band verdicts rather than fourteen independent validations: five of the fourteen were live calibration targets, the bands were used both to tune against and to grade against, and "held out" means unseen simulation seeds and another roster from the same generator rather than withheld market data. That is a market with the right volatility, the right tails, the right co-movement, industries that co-move more than strangers, correlation that stays elevated after a panic, volume that behaves, and volatility episodes it produces itself.

pt-v12 became the default on 2026-08-26, an era boundary: every trajectory that came from the default changed. Runs recorded before it are not comparable to runs after it unless they name their preset, and every earlier preset from pt-v1 onward stays selectable and reproduces bit for bit. Checked rather than asserted: pt-v1, pt-v2 and pt-v3 give identical market digests under 0.1.4 and 0.2.0. A fully specified run is still (package version, model, universe fingerprint, seed), since the preset pins the coefficients and the package version pins the implementation.

At 504 days pt-v12 holds all fourteen, which is the first two-year clean sheet this project has measured -- pt-v3 held seven there and pt-v10 held thirteen, missing volume-change autocorrelation. Read the headroom rather than the count: annualised volatility reads 33.89 against a band ending at 34.0, so that row is genuine but thin, and the certified horizon stays 252 days because that is where the certification is measured.

Beyond two years the model has now been measured rather than assumed. At 2520 days it holds ten of the fourteen against the (horizon-mismatched) two-year bands, and nothing runs away or drifts: measured year by year over ten years, annualised volatility reads 31.5, 35.6, 30.2, 33.5, 33.0, 33.1, 31.3, 32.4, 32.4, 31.6 percent -- flat, with the year-to-year variation a real market has.

Five gaps are measured and named rather than assumed. The certified horizon is 252 days; two and five-year panels are measured but not certified. Volatility memory decays exponentially where real markets decay hyperbolically. Scenario response has the right size, measured as a regression gain, but too much noise around it for one run to size a scenario from -- the driven-window noise ratio is 1.57x real. The endogenous MACRO economy cannot reach its own crisis regimes, so an inflation regime or a policy crisis has to be driven through a scenario; a volatility crisis does not: measured on pt-v10, the preset's own VIX crossed its crisis threshold on 10.2% of days against a real 12.5%, and that figure has not been re-measured on pt-v12. And certification was measured on a sector-balanced roster, which no real index is: re-measured on pt-v12, an S&P-like or technology-heavy roster holds all fourteen at one year, so the envelope transfers at the certified horizon, and the cost of concentration shows up in the second year instead. The realism envelope states each gap and what it forbids. pt.envelope.check() refuses to certify a question that falls outside one.

Single venue, no latency, no strategic counterparties. Orders arrive instantly, there's one book per name, and you trade against a market maker and aggregate flow rather than agents that adapt to you.

Worked examples

Eight notebooks and two scripts in examples/, numbered in reading order and executed as part of the test suite:

what it covers
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 gaps
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: sweep, evaluation, TCA and replay
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 actually transmit

The two scripts run from the command line rather than a notebook. The whole study takes about five seconds:

python examples/07-research-workflow.py

Documentation

Full docs: simoncoombes.github.io/pretium

Getting started and core concepts. Agents, evaluation and the RL environment. Scenarios and macro paths, strategy specs, model presets, checkpointing and forking, sharing a run, Arrow output and streaming sweeps, SEC EDGAR loading, transaction cost analysis, the MCP server, running in the browser, the realism envelope and metrics, and the conventions worth reading before you hit them.

Contributing

See CONTRIBUTING.md, and RELEASING.md for how a version reaches PyPI and crates.io. One rule shapes the rest: a change to the simulated trajectory is a breaking change, whatever its size. A market that runs differently from the same seed invalidates every published result that cited it.

Citing this

See CITATION.cff, or cite a specific result by its manifest. A citation identifies the software; it does not identify a run. A RunManifest does: it carries the package version and preset it was written by, the seed, the universe fingerprint, the macro conditions, the scenario and the strategy fingerprint.

Licence

MIT OR Apache-2.0, at your option. See LICENSE-MIT and LICENSE-APACHE.

Metadata

Release files for pretium 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pretium 0.3.0
File Size Uploaded
pretium-0.3.0.tar.gz 512.3 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for pretium 0.3.0
File
pretium-0.3.0-cp311-abi3-win_amd64.whl CPython 3.11 abi3 Windows x86-64 Details
pretium-0.3.0-cp311-abi3-manylinux_2_34_x86_64.whl CPython 3.11 abi3 Linux glibc 2.34+ x86-64 Details
pretium-0.3.0-cp311-abi3-manylinux_2_34_aarch64.whl CPython 3.11 abi3 Linux glibc 2.34+ ARM64 Details
pretium-0.3.0-cp311-abi3-macosx_11_0_arm64.whl CPython 3.11 abi3 macOS 11.0+ ARM64 Details
pretium-0.3.0-cp311-abi3-macosx_10_12_x86_64.whl CPython 3.11 abi3 macOS 10.12+ x86-64 Details

Total release size: 4.4 MB

Release files / pretium-0.3.0.tar.gz

Download URL pretium-0.3.0.tar.gz
Size 512.3 kB
Tags Source
SHA-256 checksum
How to use checksums
649233e98f10aa546f8a4bf88d23ad5398f4f237231769b99f19763cba2e8efd
BLAKE2b-256 checksum
How to use checksums
b809481eab37b50d750f1d08fc9b00e3690b18d36a1760a6bb95e0fe28115813
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 Aug 27, 2026.

Transparency log

Release files / pretium-0.3.0-cp311-abi3-win_amd64.whl

Download URL pretium-0.3.0-cp311-abi3-win_amd64.whl
Size 719.7 kB
Tags CPython 3.11 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
037adc5e03f0ddfb353dad6f9dce2387e9f3e9dafe043923cc1ff8aa69255bd8
BLAKE2b-256 checksum
How to use checksums
4b8ab1c19a1467af906541a5d1cf3a3c42f72ba6a38fafd61e1e2c2cbbded130
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 Aug 27, 2026.

Transparency log

Release files / pretium-0.3.0-cp311-abi3-manylinux_2_34_x86_64.whl

Download URL pretium-0.3.0-cp311-abi3-manylinux_2_34_x86_64.whl
Size 821.4 kB
Tags CPython 3.11 Linux glibc 2.34+ x86-64 abi3
SHA-256 checksum
How to use checksums
8084d62f4e99b36adf4c95aaa3334737d5652d3272e0f527e04bab29928da15f
BLAKE2b-256 checksum
How to use checksums
6084b5047202c73674e704f78cc82d5aa9108ed37ac0a7d58f8b424f0d6a60ae
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 Aug 27, 2026.

Transparency log

Release files / pretium-0.3.0-cp311-abi3-manylinux_2_34_aarch64.whl

Download URL pretium-0.3.0-cp311-abi3-manylinux_2_34_aarch64.whl
Size 804.9 kB
Tags CPython 3.11 Linux glibc 2.34+ ARM64 abi3
SHA-256 checksum
How to use checksums
f5092cb97ac2077eed2482aa6b4a1a3eaedbc776775778c721f5c381dcda1cee
BLAKE2b-256 checksum
How to use checksums
2bcf5353c15ddac4eef216973da303d98ee5f1f0b910bef0f627005cd5376d6b
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 Aug 27, 2026.

Transparency log

Release files / pretium-0.3.0-cp311-abi3-macosx_11_0_arm64.whl

Download URL pretium-0.3.0-cp311-abi3-macosx_11_0_arm64.whl
Size 771.1 kB
Tags CPython 3.11 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
abb2ca3717c5092e8fa639791da06a800494cb41308ac22b9e4aca49d9f6b67e
BLAKE2b-256 checksum
How to use checksums
b7d48f37b511af3b24e800d9d03738708978cb25e18da7762d4fa57a73c6c1c5
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 Aug 27, 2026.

Transparency log

Release files / pretium-0.3.0-cp311-abi3-macosx_10_12_x86_64.whl

Download URL pretium-0.3.0-cp311-abi3-macosx_10_12_x86_64.whl
Size 796.1 kB
Tags CPython 3.11 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
eea0b20c0416537664045be986d0ba6f072ee3af32dc85de487c0abfad351c6c
BLAKE2b-256 checksum
How to use checksums
54e16c9d812e6a12071d360733e7e5ad782e8960dc66b465a8ba7d329bd653e9
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 Aug 27, 2026.

Transparency log

Release history Release notifications | RSS feed

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.3

6 release files

0.4.2

6 release files

0.4.1

6 release files

0.4.0

6 release files

This release

0.3.0 This release

6 release files

0.2.0

6 release files

0.1.4

6 release files

0.1.3

6 release files

0.1.2

6 release files

0.1.1

6 release files

0.1.0

5 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page