Agents
An agent is any object with an act method. The harness gives it an observation and takes back target weights.
Three kinds of agent use this page
An LLM agent trades inside the market from here. A model that studies the market from outside uses the MCP server instead, and writes no code at all.
class Mine:
def act(self, obs):
# target weights, one per name
return {"AAA": 0.2, "AAB": -0.1}
scores = tf.evaluate(
{"mine": Mine()}, seed=7,
universe=u, days=10)
scores["mine"].return_pct
scores["mine"].impact_bps
Three rules of the harness
The observation is narrow on purpose
Everything in it is information available to a trader inside the simulated market. Nothing in it is something only the simulator knows.
The agent sees
The agent never sees
The Oracle is the exception. It reads the true mispricing and declares itself, which is why it is a reference and not a competitor.
Compare agents
Ten agents in one evaluate call get ten private engines, built from the same seed and roster. Each agent pays its own impact and sees nobody else's orders. That is what makes the comparison clean. It is also why there is no arena. To make agents take each other's depth, drive one engine yourself and combine their flow into each tick.
Run the pair across twelve seeded markets. Then read the pooled number and the paired number against each other. Here is the measurement the docs publish.
ranking = tf.rank(
lambda: tf.reference_agents(seed=3),
seeds=range(12), universe=u,
days=10, workers=4)
ranking.separation("mean_reversion",
"momentum")
{'wins': 9, 'losses': 3,
'ties': 0, 'p_value': 0.1460}
Twelve markets, one square each
The squares show the tally, not the seed order. Which seed fell which way is in the agents docs.
Pooled, mean-reversion leads by three times. Paired, 9 to 3 at p = 0.15 is not a separation. Both numbers are true and they answer different questions: how much it won by, and how often. Report the pair.
The shipped baselines
Five reference agents ship. Each one is also a StrategySpec, so you can cite it as data.
Read this before you conclude
Momentum can work here for a reason real markets do not supply
Returns trend, because the mispricing process has a herding term with a dial on it. pt-v14 turns that dial well down. momentum_theta sits at 0.0186 and return autocorrelation at lag one reads +0.0114, against a real band of -0.08 to 0.06. pt-v1 ships the same knob at 0.25 and measures +0.249. The dial exists either way, and real markets have no equivalent.
No counterparty adapts to you
You trade against a market maker and aggregate flow. Orders arrive instantly and there is one book per name. Nothing in the market learns your pattern and front-runs it.