LEARN/COUNTERFACTUALS

Counterfactuals

Run the same agent from the same state, change one controlled input, and inspect where the two runs first diverge.

import tradefloor as tf

u = tf.Universe.random(24, seed=7)
world = tf.World(seed=7, universe=u, agent=Mine())
world.run(50)

control, stress = world.fork("control", "stress")
stress.apply(tf.Scenario.load("liquidity_crisis"))

started = tf.agree(control, stress)
control.run(80)
stress.run(80)

result = tf.compare(control, stress,
                    agreement=started)
print(result.render())

The three steps

Fork Both arms carry the same engine state, agent, portfolio and generator position, bit for bit.
Change one input A scenario document drives the stressed arm. Its intervention days are relative to the fork.
Compare compare() finds the first step at which the macro, the decision, the orders, the prices and the portfolios came apart.

The result is controlled attribution inside the simulated market. It says what this model does under the stated change, and a statement about a real market needs evidence from a real market.

The pieces

WorldThe run loop of market, agent, portfolio and macro path, advanced a day at a time by run(days). Constructed from seed, universe and agent; pins hold macro fields from day zero; max_leverage defaults to 2x, matching evaluate.
World.fork(*labels)Returns one World per label, each identical to this one at the fork. The fork step is recorded so a comparison quotes the window after it.
World.apply(scenario)Drives this arm from a Scenario document. The resolved scenario is reconstructible from the world afterwards.
World.intervene(**fields)Changes one macro field in this arm on the current day, recorded beside the day-zero pins.
World.checkpoint(label)A serialisable Checkpoint of the experiment state. It outlives the process and carries a fingerprint.
agree(a, b)Verifies two arms are identical: engine state, books, portfolio, agent state, generator position. Returns an Agreement with identical, differences and render().
compare(control, treatment)Returns a Comparison: per-series divergence steps and the summary of both arms. Pass agreement= so the published document states that the arms started identical. Arms with different steps_per_day are refused.
Agreement, Comparison, DivergenceThe result types. Each carries as_dict() for a machine and render() for a person.
World.manifest()A RunManifest for the run, so the counterfactual is citable and replayable like any other run.

Three kinds of fork

Three mechanisms copy a running experiment, at three scopes.

Engine.fork

An in-process copy of the engine: every column, the order book, the day's endogenous news and the generator position. tf.branch calls it. The copy can be checkpointed, forked again and written to a manifest.

Checkpoint

A serialised save of a run that replays the order log. It outlives the process, carries a fingerprint, and RunManifest.of(..., derived_from=checkpoint) records the lineage. The mechanics are on checkpoints and forking, and the reference is the counterfactual API.

World.fork

An experiment-level fork: the engine plus the agent, the portfolio and the trace. The unit this page's comparison operates on.

External agents

The agent is a parameter throughout, so the same experiment runs with an external agent swapped in. tradefloor.integrations.finrobot runs a FinRobot agent behind an observation allowlist that keeps fair value, the attribution and the macro path ahead on the tradefloor side. Install with pip install "tradefloor[finrobot]"; the shipped studies are examples/rate-shock/ and examples/finrobot/.

All pages