1\section{Pseudocode}2\label{app:pseudocode}34The five algorithms below follow the control flow of the code line by line; names in typewriter font are the corresponding functions. $\Delta$ is the dividend interval, $T$ the number of ticks.56\begin{algorithm}[H]7\caption{Tick loop (\code{Simulation.run}, \code{experiments/runner.py})}8\label{alg:tick}9\footnotesize\begin{algorithmic}[1]10\State build streams from the master seed; draw fundamentals, population, accounts, latencies; register accounts11\State $\text{pending\_liq} \gets \emptyset$; record $P_0$12\For{$t = 0,\dots,T-1$}13 \State $\text{exchange.time} \gets t$14 \If{$t>0$ and $t \bmod \Delta = 0$}15 \State $D \gets \code{fund.step()}$ \Comment{pay $D_n$, reveal $x_n$, update public filter, draw latent $x_{n+1}$}16 \State pay $\operatorname{round}(D_k)$ cents per lot of every asset $k$; check conservation17 \EndIf18 \State \code{apply\_shocks}$(t)$ \Comment{after the dividend: a jump stays latent until news or the next dividend}19 \ForAll{news items drawn this tick} \State update the public filter with the item's value and stated noise \EndFor20 \ForAll{$(i,\text{act}) \in \text{pending\_liq}$} \State \code{exchange.submit}$(i,\text{act},t)$ \EndFor; $\text{pending\_liq}\gets\emptyset$21 \State $u \gets$ \code{activation} stream, one uniform per slot22 \State $A_c \gets \{i \text{ classical}: u_i < \text{activity}_i\}$; shuffle $A_c$ with the \code{shuffle} stream23 \State $A_\ell \gets \{i \text{ LLM}: (t-\text{offset}_i) \bmod \text{interval} = 0,\ t \ge \texttt{warmup}/2\}$, minus agents at their decision cap24 \State $\text{tw} \gets$ last 30 trades per asset25 \ForAll{$i \in A_c$}26 \State $o \gets$ \code{observe}$(i,t,\text{tw})$ \Comment{book depth 5, 60-tick mids, trades, dividend, $V^{\mathrm{pub}}$, $\hat x$, news, fresh private signal, account, open orders}27 \State $a \gets \text{policy}_i.\code{decide}(o,\text{rng}_i)$; \textbf{if} $a$ is not hold \textbf{then} \code{exchange.submit}$(i,a,t)$28 \EndFor29 \If{$A_\ell \neq \emptyset$}30 \State build observations for all $i\in A_\ell$; update each agent's equity-change history31 \State $(a_i, \text{rec}_i)_{i\in A_\ell} \gets$ \code{llm\_policy.decide\_batch} \Comment{Algorithm~\ref{alg:llm}, thread pool of width 8}32 \ForAll{$i \in A_\ell$} \State submit $a_i$ if not hold; update memory and cohort channel from $\text{rec}_i$ \EndFor33 \EndIf34 \State \code{exchange.process\_until}$(t+1)$ \Comment{arrivals with time $<t+1$ in (arrival, sequence) order: Algorithm~\ref{alg:order}}35 \State $\text{pending\_liq} \gets$ \code{exchange.margin\_check()} \Comment{Algorithm~\ref{alg:margin}}36 \State \code{exchange.end\_of\_tick}$(t)$ \Comment{call auction if enabled and $(t+1)\bmod k=0$; append midpoint; expire orders with $t-\text{submit}\ge$ TTL; log tick}37 \State record $P_{t+1}$ and the tick row (mid, quotes, depth, volume, LLM volume, $V_t$, $V^{\mathrm{pub}}_t$, $x$, halts, effective spread, total equity)38\EndFor39\State final conservation check; write manifest, frames and outcomes40\end{algorithmic}41\end{algorithm}4243\begin{algorithm}[H]44\caption{Order arrival (\code{Exchange.\_on\_order}, \code{exchange/engine.py})}45\label{alg:order}46\footnotesize\begin{algorithmic}[1]47\Require order $o$ (agent $i$, asset $k$, side, type, $q$, price $p$ or none, tag), account $c_i$, book $B_k$48\State remove $o$ from the agent's in-flight set49\State \textbf{reject} \code{frozen} if $c_i$ is frozen and tag $\ne$ liquidation; \code{halted} if $k$ is halted; \code{bad\_qty} unless $1\le q\le$ max order50\If{limit} \State \textbf{reject} \code{bad\_price} if $p\le0$; \code{price\_band} if $|p-\text{mid}_k| > 0.5\,\text{mid}_k$ \EndIf51\If{buy and limit}52 \State $\text{need} \gets p\,q + \max(\text{fee}_{\rm taker},\text{fee}_{\rm maker}) + q$; \textbf{reject} \code{insufficient\_cash} if need $>$ buying power53 \State reserve need cents on $c_i$ and on $o$ \Comment{buying power = free cash, or free cash $+(L-1)\,$equity if leveraged}54\ElsIf{buy and market}55 \State \textbf{reject} \code{no\_liquidity} if no ask; $q \gets$ largest $q'\le q$ whose notional plus taker fee on the total fits in buying power, walking the asks; \textbf{reject} \code{insufficient\_cash} if $q=0$56\Else \Comment{sell}57 \State $h \gets$ free (unreserved) holdings; \textbf{if} $q>h$ \textbf{then} \textbf{reject} \code{insufficient\_shares} if $h\le0$ else $q\gets h$ \Comment{no short selling}58 \State \textbf{reject} \code{no\_liquidity} if market and no bid; reserve $q$ lots59\EndIf60\If{position limit set and tag $\ne$ liquidation}61 \State \textbf{release and reject} \code{position\_limit} if $|\text{pos}+\text{side}\,(\text{same-side resting}+q)| >$ limit62\EndIf63\If{margin check on, $L_i>1$ and tag $\ne$ liquidation}64 \State gross$' \gets$ gross exposure with asset $k$ revalued at the post-trade position and price ($p$ or mid)65 \State \textbf{release and reject} \code{leverage\_cap} if equity $\le0$ or gross$' > L_i\,$equity66\EndIf67\State log \code{accept}68\If{call-auction mode}69 \State \textbf{if} market \textbf{then} convert to a limit at the band edge, tag \code{ioc}, reserve cash for buys; rest $o$ in $B_k$; \textbf{return}70\EndIf71\State fills $\gets B_k.\code{match}(o)$ \Comment{walk the opposite side while crossing; price--time priority; resting price}72\ForAll{fill $(r, p', q')$}73 \State fees: taker $=\operatorname{round}(p'q'\cdot 2/10^4)$ on $o$, maker $=0$ on $r$; move $p'q'$ cents and $q'$ lots; release the reservations consumed (all of it on the last fill); log \code{trade}; update last price and tick volume; check conservation74\EndFor75\If{$o$ has remaining quantity}76 \State \textbf{if} limit \textbf{then} rest $o$ in $B_k$ \textbf{else} release the reservation, cancel the remainder (\code{ioc}); count a rejection if nothing filled77\EndIf78\State \code{maybe\_halt}$(k)$: if a breaker is set and $|\text{last}/\text{mid}_{t-10}-1|>$ threshold, halt $k$ for 20 ticks and cancel all resting orders (releasing reservations)79\end{algorithmic}80\end{algorithm}8182\begin{algorithm}[H]83\caption{Margin check and liquidation (\code{Exchange.margin\_check}, \code{\_liquidate}; submitted by the runner at $t+1$)}84\label{alg:margin}85\footnotesize\begin{algorithmic}[1]86\State marks $\gets$ midpoint of every asset (fallback: last trade, reference)87\ForAll{accounts $c$ not frozen}88 \State $E \gets$ cash $+\sum_k Q_k\,\text{mark}_k$; $G \gets \sum_k |Q_k|\,\text{mark}_k$; \textbf{continue} if $G\le0$89 \If{$E\le0$}90 \State freeze $c$; log \code{bankrupt}; $f\gets1$ \Comment{full liquidation; no further orders accepted}91 \ElsIf{$L_c>1$ and $E/G < m$ ($m=0.25$)}92 \State log \code{margin\_call}; $f\gets$ liquidation fraction ($0.5$)93 \Else \State \textbf{continue}94 \EndIf95 \State act $\gets$ cancel every resting order of $c$; for each asset with $Q_k\ne0$ add a market order for $\max(1,\lfloor f|Q_k|\rfloor)$ lots on the side that reduces $|Q_k|$, tagged \code{liquidation}96 \State log \code{liquidate}; append $(c,\text{act})$ to the list returned to the runner97\EndFor98\State \Return list \Comment{the runner submits these at the start of tick $t+1$; liquidation orders bypass the frozen, position-limit and leverage checks}99\end{algorithmic}100\end{algorithm}101102\begin{algorithm}[H]103\caption{LLM decision pipeline (\code{LLMPolicy.decide\_one}, \code{\_call}, \code{to\_action}, \code{llm/policy.py})}104\label{alg:llm}105\footnotesize\begin{algorithmic}[1]106\Require observation $o$, provider $\pi$, model $M$, prompt id $\psi$107\State $S \gets$ \code{system\_prompt}$(\psi, o)$; $U \gets$ \code{user\_message}$(o, \text{adaptive})$ \Comment{Appendix~\ref{app:prompts}}108\If{$\pi=$ library}109 \State text $\gets$ recorded decision of a random one of the 5 nearest neighbours of \code{features}$(o)$, limit price rescaled to the midpoint; cached $\gets$ true110\Else111 \State key $\gets$ SHA-256$(\pi\,|\,M\,|\,\text{version}\,|\,S\,|\,U)$112 \If{cache enabled and key present} \State text $\gets$ cached response; cached $\gets$ true113 \ElsIf{frozen-only or halted for budget} \State error $\gets$ \code{frozen\_miss} / \code{budget\_halt}114 \ElsIf{budget cap reached} \State halt for budget; error $\gets$ \code{USD cap reached}115 \Else116 \State result $\gets$ provider$(\pi).\code{complete}(S,U,M,\text{effort}=\text{low},\text{max\_output}=1200,\text{cache\_key}=\code{ma-v1-}\psi)$117 \State \textbf{if} text non-empty and no error \textbf{then} store (key, $S$, $U$, text, usage) in the cache118 \EndIf119\EndIf120\State cost $\gets$ \code{budget.record}(tokens, latency, cached) \Comment{0 for cached hits; priced from the model table otherwise}121\State \textbf{if} error \textbf{then} dec $\gets$ none \textbf{else} (dec, err) $\gets$ \code{parse\_decision}(text) \Comment{lenient JSON, strict pydantic schema}122\State (action, valid, reason) $\gets$ \code{to\_action}(dec, $o$) if dec else (hold, false, err) \Comment{rules of Appendix~\ref{app:prompts}}123\State count invalid and failures124\State record $(t, i, \pi, M, \psi, \text{valid}, \text{reason}, \text{decision fields}, \text{tokens}, \text{latency}, \text{cost}, \text{cached}, \text{error})$125\Statex \hspace{\algorithmicindent} together with the prompt SHA, the request id, \code{features}$(o)$ and the relative limit price126\State \Return (action with meta \{valid, reason, rationale, confidence, llm\_action, provider, model\}, record)127\end{algorithmic}128\end{algorithm}129130\begin{algorithm}[H]131\caption{Matched-seed design runner (\code{run\_design}, \code{cell\_config}, \code{\_run\_one}, \code{experiments/design.py})}132\label{alg:design}133\footnotesize\begin{algorithmic}[1]134\Require design file with \code{base}, \code{seeds}, design-level \code{overrides}, \code{cells} (name, overrides, treatment) and optional \code{factors}135\State cells $\gets$ listed cells $\cup$ full factorial product of the factor levels (overrides merged, labels joined); keep only \code{--cells} if given136\State seeds $\gets$ explicit list or $\{\text{start},\dots,\text{start}+n-1\}$; truncate to \code{--max-seeds} if given137\ForAll{cell $c$, seed $s$}138 \State cfg $\gets$ base configuration; apply design overrides then cell overrides (dotted keys; sections merged, leaf dictionaries replaced); set name $\gets$ design/cell, seed $\gets s$, treatment $\gets$ design labels $\cup$ cell labels139 \State job $\gets$ (cfg as JSON, \code{results/runs/<design>/<cell>/seed<s>}, cache path)140\EndFor141\ForAll{jobs, sequentially if workers $\le1$ else in a process pool of the given width}142 \If{\code{outcomes.json} exists in the run directory} \State reuse it \Comment{an interrupted design resumes without new API calls}143 \Else144 \State build the LLM policy (shared SQLite cache) if \code{llm\_share}$>0$; run Algorithm~\ref{alg:tick}; save config, manifest and frames145 \State outcomes $\gets$ \code{run\_outcomes}(result); write \code{outcomes.json}146 \EndIf147\EndFor148\State write \code{outcomes.parquet} (one row per run) and \code{design.json} (expanded cells, seeds, run count, wall-clock)149\end{algorithmic}150\end{algorithm}151152\noindent Because every cell of a design is run on the same seed list and the only streams touched by $\varphi$ are the LLM assignment and the LLM agents' own generators, the control and each treatment of a given seed share the dividend path, the news, the endowments, latencies and activation draws of every non-replaced slot (common random numbers); the paired estimators of the analysis exploit this matching seed by seed.153