Evaluate
Four calls turn a market into a result: score one, rank twelve, price the execution, replay it later.
tf.evaluate
Score agents on one identical market.scores = tf.evaluate(
agents: dict[str, Agent | StrategySpec],
*, seed: int, universe: Universe,
days: int, scenario: Scenario | None = None,
model: str | None = None)
agents
A dict of name to agent, or name to StrategySpec. A spec carries its own fingerprint into the result.
one engine each
Every agent gets its own Engine built from the same seed and roster, so nobody eats another agent's depth.
returns
A dict of name to Scorecard.
tf.reference_agents(seed=3)
The five shipped baselines as a ready dict: hold, random, momentum, mean_reversion and oracle.
tf.capture_ratio(scores)
Each agent's P&L as a fraction of the Oracle's.
One market is one sample. Use rank before you call a winner.
tf.rank
Repeat that across twelve seeds, and separate with a sign test.ranking = tf.rank(
factory: Callable[[], dict],
*, seeds: Iterable[int], universe: Universe,
days: int, workers: int = 1)
ranking.report()
ranking.separation("mean_reversion", "momentum")
factory
A callable returning a fresh agent dict per seed, because an agent that carries state across markets is not being measured on either.
report()
Pooled captures, their per-seed ranges, and how many seeds each agent topped.
separation(a, b)
A paired sign test: wins, losses, ties and a p-value.
workers
Processes. Seeds are independent, so this scales linearly.
On the published twelve-market grid, mean-reversion pools at +0.783 and momentum at +0.259, and mean-reversion wins 9 to 3 at p = 0.15. One seed picks the pooled leader eight times in twelve.
tf.tca.analyse
Price the execution against the world where you never traded.ex = tf.tca.analyse(
algo, *, seed: int,
universe: Universe, days: int)
ex.shortfall_bps()
ex.by_step()
ex.partial_fills()
algo
Any object with an act method.
shortfall_bps()
What the footprint cost, against the same seed run with no orders.
by_step()
Where it was paid, per decision.
partial_fills()
What you asked for against what you got.
Round-trip shortfall measured over eight simulation seeds runs -17.72 to +2.03 bps. The range crosses zero, so one run tells you nothing.
tf.RunManifest
Write the run down so someone else can replay it.manifest = tf.RunManifest.of(
engine, spec, seed=7)
manifest.to_json(path)
pt.RunManifest.from_json(text)
pt.reproduce(manifest)
carries
Package version, preset, seed, universe fingerprint, macro conditions, scenario and strategy fingerprint, with the expected digest.
reproduce()
Raises on a mismatch and names the component that disagreed.
era_fingerprint()
The digest of a small fixed probe, recomputed before every replay, so two builds that agree on the probe agree on the arithmetic.
A manifest that quietly reproduced a different market would be worse than no manifest, so it refuses rather than warning.
What a Scorecard carries
return_pct
What it made, as a percentage.
pnl
What it made, in currency.
impact_bps
What its own footprint cost, in basis points.
trades
How many fills it took.
strategy_fingerprint
A sha256 over the spec. This is the one to cite.
universe_fingerprint
A sha256 over the roster, order included.
model
The preset the run used, so a result names its own coefficients.
strategy_fingerprint is empty for a hand-built agent, because that result is reproducible only by citing code at a commit. A StrategySpec gives you one, which is why the spec grammar exists.