SPB Git

spb/wp27_uqo

Public

fix: leaf dict overrides replace instead of merge (provider_mix was half mock in live cells)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Oct 27, 2026) parent 7377aa2 Browse files

53 changed files +972 −2

53 changed files
Unified Split
modified configs/baseline.yaml +1 −1
@@ -34,7 +34,7 @@ population:
34 decision_interval: 20 34 decision_interval: 20
35 stagger: true 35 stagger: true
36 stagger_slots: 4 36 stagger_slots: 4
37− informed_share: 0.3 37+ informed_share: null # inherit the replaced slot's information (matched pairs hold information fixed)
38 precision: 2.0 38 precision: 2.0
39 max_order_qty: 50 39 max_order_qty: 50
40 reasoning_effort: low 40 reasoning_effort: low
added docs/research_log.md +24 −0
@@ -0,0 +1,24 @@
1+# Research log — WP 27 (chronological, 2026-10-27)
2+
3+All times local. Code revision in each run manifest (`git_revision`). Entries record every change made
4+between the pre-analysis plan and the confirmatory runs, so that nothing is revised silently.
5+
6+| # | When | Phase | Change | Why | Consequence for pre-registration |
7+|---|---|---|---|---|---|
8+| 1 | 18:30 | 2 | Engine written: integer-cent accounting, price–time LOB, latency heap, fees, halts, margin, event log, replay | — | — |
9+| 2 | 18:50 | 2 | Market-maker rule replaced (A–S formula in ticks² produced negative reservation prices → MM dumped inventory) by a bounded inventory-skew rule targeting the endowment | engine smoke run: price fell 30 % below value | baseline only |
10+| 3 | 19:05 | 2 | Reservation accounting: limit bids reserve notional + worst-case fee + 1 c/lot; market buys priced lot-by-lot on the total fee; releases equal cash charged | property test found reserved cash 6 c above cash | — |
11+| 4 | 19:20 | 3 | Calibration sweep (36 cells × 10 seeds): baseline = fundamentalist aggressiveness 20, trend + leveraged 10 %, noise market-order rate 0.6, MM size 20 | stylized facts: ACF₁ ≈ 0, kurtosis > 10, Σ ACF|r| ≈ 2.7, spread ≈ 24 bp, tracking error ≈ 1 % | baseline frozen |
12+| 5 | 19:40 | 2 | Periodic call auction added (robustness) with market orders as IOC and a ±2 % collar | first version let band-edge market orders set the clearing price | robustness arm only |
13+| 6 | 20:10 | 4 | OpenAI adapter verified live (gpt-5.4-nano); `max_output_tokens` raised 400 → 1200 because reasoning tokens count against it | smoke test truncated JSON | — |
14+| 7 | 20:30 | 5 | LLM decisions batched into 4 stagger slots; parallel run workers | one decision per tick made API runs 10× slower | none (same decision count) |
15+| 8 | 20:45 | 1→2 | **Fundamental timing restructured**: the upcoming dividend's deviation is latent during the period; PV = μ/r + x/(1+r−ρ); public filter updated by news; private signals are about the latent deviation | methodologist audit + classical runs: dividends revealed x exactly, so V^pub ≡ V, news and private signals were redundant (H1 unidentified) | this *is* the pre-registered economy; no confirmatory run had been analysed |
16+| 9 | 21:05 | 1→2 | Shocks applied after the dividend step (a t = 300 jump was paid out at once); shock size 40 c → 10 c (+2.2 % of V) | public value jumped at the shock; 40 c was +9 % with the corrected PV | thresholds unchanged |
17+| 10 | 21:10 | 1→2 | LLM slots inherit the replaced slot's information set (`llm.informed_share: null`); within-tick shuffle moved to its own RNG stream | methodologist audit: treatment bundled information; activations diverged across arms | matched-pair CRN now exact for every non-replaced agent |
18+| 11 | 21:12 | — | First git commit; pilot and confirmatory designs launched on the frozen revision | manifests now carry `git_revision` | **freeze** |
19+| 12 | — | 5 | Pilot (3 seeds × {5, 25, 50 %}, gpt-5.4-nano) runs concurrently with the confirmatory design on the same revision; pilot seeds (1–3) are never pooled with confirmatory seeds (201–207) | time budget | the pilot's role is reduced to cost/validity/variance reporting; the seed count (7) was fixed by the USD cap, not by the pilot variance |
20+
21+Known deviations from `docs/identification.md` / `docs/protocol.md` (written before items 8–12):
22+- Noisy dividends (`jump_prob = 1`) were proposed to make V^pub ≠ V; item 8 achieves this through the timing of information instead (no jumps in the baseline).
23+- The `mini-only at 25 %` cell needed for the model-mix decomposition was not run (≈ 8.5 USD): the two-model arm is compared with the single-model diverse-prompt arm only, and this limitation is stated in the paper.
24+- Anthropic cells: the key provided on 2026-10-27 is rejected (HTTP 401). The adapter is implemented and dry-run tested with the mock provider; Claude cells are not part of the reported results.
added paper/appendices/hyperparameters.tex +1 −0
@@ -0,0 +1 @@
1+% hyperparameters — to be written
added paper/appendices/prompts.tex +1 −0
@@ -0,0 +1 @@
1+% prompts — to be written
added paper/appendices/pseudocode.tex +1 −0
@@ -0,0 +1 @@
1+% pseudocode — to be written
added paper/appendices/reproducibility.tex +1 −0
@@ -0,0 +1 @@
1+% reproducibility — to be written
added paper/main.tex +95 −0
@@ -0,0 +1,95 @@
1+% ============================================================================
2+% UQO Working Paper No. 27 — The Invisible Hand of Machines
3+% ============================================================================
4+\documentclass[12pt,letterpaper]{article}
5+\usepackage[utf8]{inputenc}
6+\usepackage[T1]{fontenc}
7+\usepackage[english]{babel}
8+\usepackage[letterpaper,top=1in,bottom=1in,left=1in,right=1in]{geometry}
9+\usepackage{mathptmx}
10+\usepackage{microtype}
11+\usepackage{setspace}
12+\onehalfspacing
13+\usepackage{amsmath,amssymb,amsthm}
14+\usepackage{booktabs,tabularx,multirow,threeparttable,array,longtable}
15+\usepackage{siunitx}
16+\sisetup{input-symbols = {()}, table-format = -1.3, parse-numbers = false}
17+\usepackage{graphicx,subcaption,float,rotating}
18+\usepackage[dvipsnames]{xcolor}
19+\usepackage[authoryear,round,semicolon]{natbib}
20+\bibliographystyle{aer}
21+\usepackage[font=small,labelfont=bf,labelsep=period,justification=justified,singlelinecheck=false]{caption}
22+\usepackage{fancyhdr}
23+\pagestyle{fancy}\fancyhf{}\renewcommand{\headrulewidth}{0pt}\fancyfoot[C]{\thepage}
24+\usepackage{titlesec}
25+\titleformat{\section}{\large\bfseries}{\thesection.}{0.5em}{}
26+\titleformat{\subsection}{\normalsize\bfseries}{\thesubsection.}{0.5em}{}
27+\titleformat{\subsubsection}{\normalsize\itshape}{\thesubsubsection.}{0.5em}{}
28+\usepackage[toc,page]{appendix}
29+\usepackage{enumitem}
30+\setlist{nosep,leftmargin=*}
31+\usepackage{listings}
32+\lstset{basicstyle=\ttfamily\footnotesize,breaklines=true,columns=fullflexible,frame=single,framerule=0.3pt,xleftmargin=0.5em}
33+\usepackage{algorithm,algpseudocode}
34+\usepackage{hyperref}
35+\hypersetup{colorlinks=true,linkcolor=NavyBlue,citecolor=NavyBlue,urlcolor=NavyBlue,breaklinks=true,
36+ pdftitle={The Invisible Hand of Machines: Price Discovery in Markets Populated by LLM Agents},
37+ pdfauthor={Simon-Pierre Boucher}}
38+
39+\theoremstyle{plain}
40+\newtheorem{proposition}{Proposition}
41+\newtheorem{lemma}{Lemma}
42+\newtheorem{corollary}{Corollary}
43+\theoremstyle{definition}
44+\newtheorem{assumption}{Assumption}
45+\newtheorem{definition}{Definition}
46+\theoremstyle{remark}
47+\newtheorem{remark}{Remark}
48+\newtheorem{hypothesis}{Hypothesis}
49+
50+\newcommand{\E}{\mathbb{E}}
51+\newcommand{\Var}{\operatorname{Var}}
52+\newcommand{\Cov}{\operatorname{Cov}}
53+\newcommand{\Corr}{\operatorname{Corr}}
54+\newcommand{\code}[1]{\texttt{#1}}
55+
56+% ============================================================================
57+% METADATA
58+% ============================================================================
59+\newcommand{\WPnumber}{27}
60+\newcommand{\WPtitle}{The Invisible Hand of Machines}
61+\newcommand{\WPsubtitle}{Price Discovery in Markets Populated by LLM Agents}
62+\newcommand{\WPdate}{October 2026}
63+\newcommand{\WPversion}{1.0}
64+\newcommand{\WPabstract}{\input{sections/abstract}}
65+\newcommand{\WPkeywords}{price discovery, large language models, agent-based markets, limit order book, herding, liquidity spirals, randomized simulation experiments}
66+\newcommand{\WPjel}{G14, G12, D53, C63, C15, D83}
67+\newcommand{\WPauthor}{Simon-Pierre Boucher}
68+\newcommand{\WPaffiliation}{Département des sciences administratives\\Université du Québec en Outaouais}
69+\newcommand{\WPemail}{simon-pierre.boucher@uqo.ca}
70+\newcommand{\WPaddress}{Gatineau -- Pavillon Alexandre-Taché\\283, boulevard Alexandre-Taché\\Gatineau, Québec, Canada J9A 1L8}
71+
72+\begin{document}
73+\input{sections/titlepage}
74+\input{sections/introduction}
75+\input{sections/literature}
76+\input{sections/model}
77+\input{sections/theory}
78+\input{sections/identification}
79+\input{sections/implementation}
80+\input{sections/results}
81+\input{sections/mechanisms}
82+\input{sections/robustness}
83+\input{sections/limitations}
84+\input{sections/conclusion}
85+\newpage
86+\bibliography{references}
87+\newpage
88+\begin{appendices}
89+\input{appendices/proofs}
90+\input{appendices/prompts}
91+\input{appendices/pseudocode}
92+\input{appendices/hyperparameters}
93+\input{appendices/reproducibility}
94+\end{appendices}
95+\end{document}
added paper/sections/abstract.tex +1 −0
@@ -0,0 +1 @@
1+% abstract — to be written
added paper/sections/conclusion.tex +1 −0
@@ -0,0 +1 @@
1+% conclusion — to be written
added paper/sections/identification.tex +1 −0
@@ -0,0 +1 @@
1+% identification — to be written
added paper/sections/implementation.tex +1 −0
@@ -0,0 +1 @@
1+% implementation — to be written
added paper/sections/introduction.tex +1 −0
@@ -0,0 +1 @@
1+% introduction — to be written
added paper/sections/limitations.tex +1 −0
@@ -0,0 +1 @@
1+% limitations — to be written
added paper/sections/literature.tex +298 −0
@@ -0,0 +1,298 @@
1+% paper/sections/literature.tex — UQO WP 27, "The Invisible Hand of Machines"
2+% Section: Related literature. Every citation key is in paper/references.bib and every claim is
3+% backed by the corresponding row of docs/literature_ledger.md.
4+\section{Related literature}
5+\label{sec:literature}
6+
7+The paper sits at the intersection of six literatures: agent-based and heterogeneous-agent models of
8+financial markets; the microstructure of double auctions and the measurement of price discovery;
9+information aggregation with correlated signals, herding and feedback trading; liquidity spirals,
10+fire sales and the measurement of contagion; algorithmic trading, flash crashes, algorithmic
11+monoculture and algorithmic collusion; and, closest to our question, the rapidly growing work that
12+places large language model (LLM) agents in economic experiments and market simulations. We review
13+each in turn and close with a statement of what the present paper adds and where it overlaps with
14+existing work.
15+
16+\subsection{Agent-based and heterogeneous-agent models of financial markets}
17+\label{sec:literature:abm}
18+
19+Our baseline population of rule-based traders descends from agent-based computational finance, which
20+showed that interacting heterogeneous rules reproduce the fat tails, volatility clustering and bubbles
21+of real markets \citep{lebaron2006}. In the Santa Fe artificial stock market the speed of belief
22+updating governs whether prices track fundamentals or display excess volatility and technical-trading
23+regimes \citep{lebaron1999}; in adaptive belief systems, discrete-choice switching between predictors
24+produces increasingly complex price dynamics as the intensity of choice rises \citep{brock1997}, and
25+the share of trend followers determines whether the fundamental price is stable \citep{brock1998}.
26+Interacting noise traders who switch between optimistic, pessimistic and fundamentalist states generate
27+scaling laws and clustered volatility endogenously \citep{lux1999,lux2000}; herd behaviour among
28+speculators yields bubbles and crashes in a mean-field model of contagious optimism \citep{lux1995}; and
29+recruitment-type opinion dynamics generate persistent herding states without any informational reason
30+\citep{kirman1993}. These mechanisms matter for us because they describe what a \emph{classical}
31+population does on its own, before any LLM is introduced, and because trend following and herding are
32+precisely the channels through which a correlated LLM order flow can be amplified.
33+
34+Closer to our exchange design, \citet{chiarella2002} simulate a double auction populated by
35+fundamentalist, chartist and noise traders and reproduce order-book regularities, and
36+\citet{chiarella2009} show that heterogeneous rules in a limit-order book generate fat tails,
37+volatility clustering and order-flow autocorrelation, with the chartist share driving excess
38+volatility. Leverage in an agent-based model produces fat tails and clustered volatility through
39+synchronized margin-driven selling \citep{thurner2012}, which is the closest antecedent of our leverage
40+treatment. Multi-agent reinforcement-learning markets reproduce the same stylized facts
41+\citep{lussange2021} and are a precursor of LLM-populated markets. The surveys of \citet{hommes2006}
42+and \citet{hommes2021} summarize the laboratory and agent-based evidence that expectation heterogeneity
43+drives aggregate instability; we follow their lead in treating an LLM policy as one more expectation
44+type. \citet{farmer2009} argue that agent-based models are the appropriate tool for out-of-equilibrium
45+dynamics and for policy counterfactuals that cannot be solved analytically; \citet{axtell2025}
46+identify validation, calibration and scale as the open frontiers, which our matched-seed design and
47+power analysis address directly. For calibration and validation we use the moment set of structural
48+stochastic volatility models \citep{franke2012} and the catalogue of stylized facts: heavy tails
49+\citep{mandelbrot1963,cont2001}, conditional heteroskedasticity \citep{engle1982,bollerslev1986}, the
50+long memory of absolute returns \citep{ding1993}, and the long memory of order-flow signs coexisting
51+with nearly efficient prices \citep{lillo2004}.
52+
53+\subsection{Double auctions, zero intelligence and the measurement of price discovery}
54+\label{sec:literature:lob}
55+
56+The continuous double auction is the institution we study, and its experimental pedigree is long:
57+\citet{smith1962} showed that double auctions with induced values converge to competitive equilibrium
58+with few traders, and \citet{smith1988} showed that experimental asset markets with known dividend
59+streams nevertheless produce bubbles and crashes; our dividend-paying asset and bubble metrics follow
60+that design. The zero-intelligence tradition established that market structure, not trader
61+rationality, drives allocative efficiency \citep{gode1993}, a point reviewed by \citet{ladley2012}. A
62+zero-intelligence model of the continuous double auction predicts spread and price impact from
63+order-flow rates alone \citep{farmer2005}, and the statistical theory of \citet{smith2003} ties
64+spread, depth and price diffusion to the same parameters. These results fix the benchmark against
65+which any effect of ``intelligence'' must be measured: a change in the composition of a population can
66+move liquidity merely by changing order-flow rates, which is why we report realized order and volume
67+shares alongside the assigned treatment. On the empirical side we rely on the order-book facts of
68+\citet{bouchaud2002}, the Markovian book model of \citet{cont2010}, the linear relation between
69+order-flow imbalance and short-horizon price changes \citep{cont2014}, the survey of
70+\citet{gould2013}, and the treatment of impact and the slow digestion of order flow in
71+\citet{bouchaud2018}. Our event-driven exchange, with per-agent latency and a price--time matching
72+engine, follows the design of ABIDES \citep{byrd2020}, and our realism checklist is that of
73+\citet{vyetrenko2020}.
74+
75+The outcome variables are standard measures of price discovery and market quality. The price-impact
76+coefficient $\lambda=\Cov(v,Y)/\Var(Y)$ of \citet{kyle1985} and the adverse-selection spread of
77+\citet{glosten1985} tie liquidity to the information content of order flow. \citet{hasbrouck1991}
78+measures that content by the permanent price impact in a VAR of quote revisions and trades;
79+\citet{hasbrouck1993} decomposes the transaction price into an efficient random-walk component and a
80+pricing error whose standard deviation is a market-quality metric; \citet{hasbrouck1995} attributes
81+price discovery across venues through information shares, which we adapt to LLM versus rule-based
82+order flow. Variance ratios reject the random walk under autocorrelation \citep{lo1988}, the effective
83+spread can be inferred from serial covariance \citep{roll1984}, and illiquidity can be measured as
84+absolute return per unit of volume \citep{amihud2002}. \citet{bai2016} define informativeness by how
85+well prices forecast future fundamentals, and \citet{bond2012} argue that informativeness is the
86+welfare-relevant object because real decisions feed on prices. \citet{hendershott2014} separate
87+transitory price pressure from permanent information effects, which justifies our separation of the
88+pricing error from the efficient-price variance. Because the simulator observes the latent value, we
89+can compute these statistics against the truth rather than against a proxy, which is the main
90+advantage of a simulated economy for this question \citep{fama1970}.
91+
92+\subsection{Information aggregation with correlated signals, herding and feedback}
93+\label{sec:literature:info}
94+
95+The theoretical core of the paper is the aggregation of \emph{correlated} private signals.
96+\citet{hellwig1980} shows that competitive prices aggregate dispersed private signals imperfectly
97+because of noise supply, and \citet{grossman1980} that prices cannot be fully informationally
98+efficient when information is costly. With strategic informed traders, \citet{foster1996} show that
99+the correlation structure of signals, not only their precision, governs trading intensity and price
100+informativeness, and \citet{back2000} that more correlated information leads to faster revelation.
101+\citet{goldstein2015} show that information diversity across traders is complementary, so that a loss
102+of diversity reduces informativeness about some components of value; \citet{dugast2018} show that
103+abundant cheap data can lower informativeness by crowding out costly deep information, a close parallel
104+to shared-model crowding; and \citet{kondor2012} warn that public information can raise disagreement
105+through higher-order beliefs, so that shared inputs do not trivially homogenize behaviour.
106+\citet{pasquariello2007} ties information heterogeneity among strategic speculators to contagion and
107+shows that homogeneity reduces it. Our stylized model (Section~\ref{sec:theory}) borrows the
108+correlated-error structure of these papers and reinterprets the common component as the signature of a
109+shared foundation model or prompt family.
110+
111+Herding supplies the behavioural counterpart. Sequential decision-makers who follow their predecessors
112+destroy information aggregation \citep{banerjee1992}, informational cascades become more likely as
113+signals become more correlated \citep{bikhchandani1992}, reputational concerns make managers mimic one
114+another \citep{scharfstein1990}, and short-horizon speculators herd on the same information source
115+even when it is unrelated to fundamentals \citep{froot1992}. The buy-side imbalance statistic of
116+\citet{lakonishok1992} is the standard empirical measure of institutional herding, and we compute it
117+for LLM cohorts. Feedback trading closes the loop: the share of trend followers determines the
118+stability of the fundamental price in heterogeneous-belief models \citep{brock1998}, and
119+contagious optimism among speculators produces bubbles and crashes \citep{lux1995}. Our feedback
120+extension (Proposition~\ref{prop:feedback}) is a mechanical version of this amplification.
121+
122+\subsection{Liquidity spirals, fire sales, leverage and contagion measurement}
123+\label{sec:literature:spirals}
124+
125+The leverage treatment and the H3 and H6 hypotheses draw on the literature on funding constraints.
126+\citet{brunnermeier2009} show that market liquidity and funding liquidity reinforce each other through
127+margins, producing liquidity spirals; our margin-call mechanism follows this logic. Liquidation values
128+fall when potential buyers are themselves constrained \citep{shleifer1992}, constrained arbitrageurs can
129+amplify rather than correct mispricing \citep{shleifer1997}, forced sales push prices below
130+fundamentals and propagate losses \citep{shleifer2011}, and financially constrained arbitrageurs may
131+under-provide liquidity \citep{gromb2002}. Endogenous margins amplify booms and crashes in the leverage
132+cycle, with leverage caps as a policy lever \citep{geanakoplos2010}, and procyclical intermediary
133+leverage amplifies price moves \citep{adrian2010}. In the agent-based setting, \citet{thurner2012}
134+obtain fat tails and clustered volatility from synchronized margin-driven selling. Across assets,
135+losses of convergence traders propagate through reduced risk-bearing capacity \citep{kyle2001},
136+distressed selling induces endogenous correlation \citep{cont2013}, fire-sale spillovers scale with
137+common exposures and leverage \citep{greenwood2015}, cross-market rebalancing transmits shocks between
138+assets with unrelated fundamentals \citep{kodres2002}, and dense networks are robust to small shocks
139+but fragile to large ones \citep{acemoglu2015}. For measurement we use the spillover index of
140+\citet{diebold2009}, its generalized directional form \citep{diebold2012} and its network
141+interpretation \citep{diebold2014}, and we heed the warning of \citet{forbes2002} that correlation-based
142+contagion tests must adjust for heteroskedasticity.
143+
144+\subsection{Algorithmic trading, flash crashes, monoculture and algorithmic collusion}
145+\label{sec:literature:algo}
146+
147+The evidence on algorithmic and high-frequency trading is, on average, favourable to liquidity and
148+price discovery: algorithmic trading improves liquidity \citep{hendershott2011}, high-frequency traders
149+trade in the direction of permanent price changes and against transitory pricing errors
150+\citep{brogaard2014}, and algorithmic strategies in foreign exchange improve price efficiency even
151+though they are more correlated with each other than human trades \citep{chaboud2014}. That last
152+finding is the one we take most seriously: correlation among algorithms is a documented fact, and its
153+consequences depend on what the algorithms are correlated \emph{on}. High-frequency market makers
154+behave as new market makers with tight inventory control \citep{menkveld2013}, a feature we build into
155+the market-maker policy; \citet{menkveld2016} reviews the speed, adverse-selection and liquidity
156+consequences, and \citet{foucault2016} show how fast traders reacting to common news signals affect
157+informativeness and liquidity. The darker evidence concerns stress. During the Flash Crash,
158+high-frequency traders did not trigger the crash but their synchronized inventory management amplified
159+it \citep{kirilenko2017}; order-flow toxicity rose before the crash and liquidity provision withdrew
160+when flow became toxic \citep{easley2011}; the August 2007 quant unwind revealed that common strategies
161+produce simultaneous deleveraging \citep{khandani2011}; and ultrafast extreme events proliferate in a
162+machine ecology operating beyond human response time \citep{johnson2013}. \citet{budish2015} show that
163+continuous-time trading creates a latency arms race with correlated sniping and propose frequent batch
164+auctions, which motivates our latency-matching treatment and call-auction robustness arm.
165+
166+The algorithmic-monoculture literature gives the homogenization mechanism a name. \citet{kleinberg2021}
167+show that when many decision-makers rely on the same algorithm, outcomes can be worse even if that
168+algorithm is individually more accurate; \citet{bommasani2021} identify homogenization as a
169+structural risk of foundation models, and \citet{bommasani2022} document outcome homogenization
170+across deployers of shared models. On the output side, generative AI raises individual creativity but
171+reduces collective diversity \citep{doshi2024}, standard LLM outputs show diminished diversity of
172+thought relative to human samples \citep{park2024brm}, and LLM assistance homogenizes human ideation
173+\citep{anderson2024}; conversely, ensembles of twelve LLMs match human crowd forecasting accuracy
174+\citep{schoenegger2024}, which illustrates the diversity benefit our H4 tests in a market. The
175+algorithmic-collusion literature shows that learning algorithms can coordinate without being told to:
176+Q-learning pricing algorithms learn tacit collusion \citep{calvano2020,klein2021}, algorithmic pricing
177+raised margins in German retail gasoline \citep{assad2024}, asymmetric adoption softens competition
178+\citep{brown2023}, LLM pricing agents reach supracompetitive prices with a sensitivity to prompt
179+wording \citep{fish2024}, and LLM sellers in continuous double auctions collude more when they can
180+communicate \citep{agrawal2025}. In securities markets, \citet{colliard2026} show that Q-learning market
181+makers learn adverse-selection pricing but quote markups that shrink with the number of algorithms,
182+and \citet{dou2025} show that reinforcement-learning informed speculators in a Kyle-type market sustain
183+supracompetitive profits through price-trigger strategies or homogenized learning biases, lowering
184+price informativeness and liquidity. \citet{dou2025} is the nearest theoretical neighbour of our
185+mechanism; the difference is that their channel is strategic, whereas ours is a shared-error structure
186+in signals, and that they have no language models.
187+
188+The policy literature has already drawn the systemic conclusion. \citet{gensler2020} argue that deep
189+learning increases uniformity and interconnectedness because models built on the same data generate
190+correlated predictions; \citet{danielsson2022} show that AI in risk management can create endogenous
191+systemic risk through common models and procyclical responses; the \citet{fsb2024} warns that common AI
192+models and data sources could raise correlations in trading, lending and pricing;
193+\citet{danielsson2025} model AI as amplifying existing vulnerabilities and making crises faster;
194+\citet{aldasoro2025} list monoculture and correlation among the financial-stability concerns of an
195+intelligent financial system; and \citet{meng2026} propose a unified model in which the AI adoption
196+share and signal correlation raise systemic coupling convexly, with 13F evidence of tail-loss
197+amplification. None of these provides a controlled experiment; the present paper is an attempt to
198+supply one.
199+
200+\subsection{LLM agents in economics and markets}
201+\label{sec:literature:llm}
202+
203+\paragraph{LLMs as simulated subjects.}
204+\citet{horton2023} proposed using LLMs as simulated economic agents to replicate classic behavioural
205+experiments at low cost; \citet{aher2023} showed that LLMs can simulate multiple humans and replicate
206+human-subject studies with fidelity that varies by model and task; and \citet{argyle2023} showed that
207+conditioning on demographic backstories produces ``silicon samples'' matching sub-population response
208+distributions. GPT choices in budgetary tasks score higher on rationality than humans and are largely
209+stable across demographic prompts \citep{chen2023pnas}; chatbot choices in behavioural games fall within
210+the human distribution and are more cooperative than the median human \citep{mei2024}; in repeated
211+games LLMs cooperate well but coordinate poorly \citep{akata2025}; and expectations elicited from an
212+LLM reading newspaper articles track professional forecasters and are extrapolative
213+\citep{bybee2023}. \citet{manning2024} automate hypothesis generation and testing with LLM subjects, and
214+\citet{immorlica2024} propose a framework in which generative agents are economic agents with new
215+primitives such as prompts and context. Generative agents with memory, reflection and planning produce
216+believable emergent social behaviour \citep{park2023}, social-network simulations reproduce
217+information propagation \citep{gao2023s3}, and EconAgent produces realistic macroeconomic dynamics
218+\citep{li2024econagent}. \citet{anthis2025} conclude that LLM social simulations are a promising
219+method provided that validity concerns---homogeneity, sycophancy, drift---are addressed; homogeneity is
220+the concern this paper turns into a treatment.
221+
222+\paragraph{Single-agent trading and backtests.}
223+ChatGPT-derived sentiment on headlines predicts next-day returns \citep{lopezlira2023chatgpt}.
224+FinMem \citep{yu2023finmem}, TradingGPT \citep{li2023tradinggpt} and FinAgent \citep{zhang2024finagent}
225+evaluate one LLM agent, or a small team with layered memory and distinct characters, by backtesting on
226+historical prices. In these designs the market does not react to the agent, so nothing can be learned
227+about equilibrium prices, and \citet{lopezlira2025memorization} show that such backtests are
228+contaminated by memorization of the historical period. Both points motivate a synthetic economy with
229+an endogenous price and no history to memorize.
230+
231+\paragraph{LLM-populated market simulators.}
232+A second generation places many LLM agents on a matching engine. ASFM couples LLM traders to a real
233+order-matching system and finds reactions to rate and inflation shocks consistent with economic priors
234+\citep{gao2024asfm}; StockAgent adds bulletin-board communication and reports that GPT- and
235+Gemini-driven agents differ systematically in trading behaviour \citep{zhang2024stockagent};
236+TwinMarket scales to a social-media-connected population, reproduces bubbles and crashes, and reports
237+that agents of one model family are more homogeneous \citep{yang2025twinmarket}; FCLAgent combines
238+LLM-decided direction with rule-based sizing and reproduces path-dependent patterns absent from
239+conventional agent-based models \citep{hashimoto2025}; StockSim provides an open order-level simulator
240+with latency, slippage and price--time matching \citep{papadakis2025}; and \citet{li2026switch} find
241+that LLM agents' trading-style switching in a year-long simulation is only partially consistent with
242+behavioural-finance theory. \citet{lopezlira2025trade} is the closest in spirit: LLM agents in a
243+persistent order-book simulation adhere to assigned strategies, generate price discovery and bubbles,
244+and are analysed with partial-dependence-style perturbations. These papers establish that LLM markets
245+\emph{can} produce the patterns we study. They are descriptive in the sense that the population
246+composition is fixed, the information set of LLM agents is not held equal to that of the agents they
247+replace, and the fundamental value, the efficient price and the transaction price are not separated.
248+
249+\paragraph{Experimental-finance replications.}
250+A third strand replicates laboratory markets with LLM subjects. In Smith--Suchanek--Williams-type
251+markets, LLM agents price near fundamentals and form only muted bubbles, with lower variance in their
252+strategy text than humans \citep{henning2025}. In a simulated call auction, LLM agents exhibit
253+disposition effects and extrapolative beliefs, and prompt interventions causally change bubble size
254+\citep{ouyang2026}. Across fifteen models, \citet{saxena2026} find behaviour ranging from fundamental
255+pricing to human-like bubbles, with mixed populations unstable and advanced models adapting to exploit
256+weaker ones. Replications of \citet{smith1962} find slower or absent convergence with model-family
257+differences \citep{struski2026}, and the trading institution alone moves the efficiency of identical
258+LLM agents from 56\,\% to 89\,\% \citep{chupilkin2026}. These studies answer the question of
259+behavioural fidelity---whether LLMs behave like humans---and their answers conflict. Our results do not
260+require fidelity: they require only that errors be correlated within a model.
261+
262+\paragraph{Correlated behaviour from shared inputs.}
263+The single paper that measures correlated trading from shared inputs is \citet{song2026}: overlap in
264+retrieved documents among retrieval-augmented trading agents raises mean pairwise action correlation
265+from 0.04 to 0.41 and increases position volatility without raising profits. That design is a backtest
266+without market feedback, so it cannot speak to informativeness or liquidity. \citet{cho2025} document
267+peer conformity in LLM multi-agent systems, with the confidence gap and format of peer information
268+controlling its strength. In LLM re-creations of herding experiments, \citet{hansen2025} find that AI
269+agents rely more on private signals than humans but can be prompted to herd when maximizing profit.
270+Finally, LLM service behaviour drifts over months \citep{chen2024hdsr}, which is why we cache every
271+response and replay from a frozen decision library.
272+
273+\subsection{What this paper adds}
274+\label{sec:literature:adds}
275+
276+We should be candid about overlap. The hypothesis that shared models correlate trading is not ours: it
277+is stated by \citet{gensler2020}, the \citet{fsb2024} and \citet{danielsson2025}, modelled as
278+homogenized learning biases by \citet{dou2025}, and measured in a backtest by \citet{song2026}.
279+Model-family homogeneity inside LLM markets has been observed by \citet{yang2025twinmarket},
280+\citet{zhang2024stockagent} and \citet{saxena2026}. LLM-populated order-book simulators exist and are
281+open source \citep{lopezlira2025trade,papadakis2025,gao2024asfm}. Our simulator is therefore not the
282+contribution; the design is. First, we treat the LLM penetration share as a randomized treatment
283+assigned to trader slots by an independent seed stream, so that matched pairs across the share share
284+every other stream---fundamentals, news, endowments, latencies, policy assignment, activation,
285+tie-breaks---and differences in outcomes are causal effects on the same market history
286+(Section~\ref{sec:identification}). Second, we separate three prices: the latent value known to the
287+simulator only, the public value implied by announced dividends and news, and the transaction price, so
288+that an information-efficiency loss can be distinguished from transitory pressure
289+\citep{hasbrouck1993,hendershott2014}. Third, we derive the shared-error mechanism in a Kyle--Hellwig
290+setting with a model-specific common error and an effective number of models, and then test it by
291+intervention---prompt diversity at equal share, a two-model mix, inherited information sets, memory,
292+communication cohorts---so that the effective number of models is manipulated rather than observed.
293+Fourth, we report the realized dose (the share of orders and volume actually originated by LLM agents)
294+alongside the assigned share, and we run fairness designs with equal decision opportunities, equal
295+dollar budgets and matched latency, because naive comparisons confound ``being an LLM'' with being slow
296+and infrequent. Fifth, the leverage interaction and the safeguard counterfactuals connect the LLM
297+literature to \citet{brunnermeier2009}, \citet{thurner2012} and \citet{kirilenko2017}, with thresholds,
298+estimators and seed counts fixed before the first confirmatory call.
added paper/sections/mechanisms.tex +1 −0
@@ -0,0 +1 @@
1+% mechanisms — to be written
added paper/sections/model.tex +1 −0
@@ -0,0 +1 @@
1+% model — to be written
added paper/sections/results.tex +1 −0
@@ -0,0 +1 @@
1+% results — to be written
added paper/sections/robustness.tex +1 −0
@@ -0,0 +1 @@
1+% robustness — to be written
modified results/figures/fig_baseline_paths.pdf +0 −0

Binary file not shown.

modified results/figures/fig_baseline_paths.png +0 −0

Binary file not shown.

modified results/figures/fig_classical_lambda_bp_100.pdf +0 −0

Binary file not shown.

modified results/figures/fig_classical_lambda_bp_100.png +0 −0

Binary file not shown.

modified results/figures/fig_classical_mad_pct.pdf +0 −0

Binary file not shown.

modified results/figures/fig_classical_mad_pct.png +0 −0

Binary file not shown.

modified results/figures/fig_classical_max_dd.pdf +0 −0

Binary file not shown.

modified results/figures/fig_classical_max_dd.png +0 −0

Binary file not shown.

modified results/figures/fig_classical_n_bubbles.pdf +0 −0

Binary file not shown.

modified results/figures/fig_classical_n_bubbles.png +0 −0

Binary file not shown.

modified results/figures/fig_classical_spread_bp.pdf +0 −0

Binary file not shown.

modified results/figures/fig_classical_spread_bp.png +0 −0

Binary file not shown.

modified results/figures/fig_classical_time_to_absorb.pdf +0 −0

Binary file not shown.

modified results/figures/fig_classical_time_to_absorb.png +0 −0

Binary file not shown.

modified results/figures/fig_contagion_excess.pdf +0 −0

Binary file not shown.

modified results/figures/fig_contagion_excess.png +0 −0

Binary file not shown.

modified results/figures/fig_contagion_spillover.pdf +0 −0

Binary file not shown.

modified results/figures/fig_contagion_spillover.png +0 −0

Binary file not shown.

modified results/figures/fig_wealth_depth.pdf +0 −0

Binary file not shown.

modified results/figures/fig_wealth_depth.png +0 −0

Binary file not shown.

added results/tables/tab_classical_cells.tex +22 −0
@@ -0,0 +1,22 @@
1+\begin{tabular}{lrrrrrrrr}
2+\toprule
3+Cell & Mean $|P/V-1|$ (\%) & Time to absorb (ticks) & Quoted spread (bp) & Price impact (bp/100 lots) & Bubble episodes & Max drawdown & Crashes & Vol. clustering $\sum_{1}^{10}\mathrm{ACF}|r|$ \\
4+\midrule
5+Control & 0.63 & 25.27 & 20.69 & 10.76 & 0.00 & 0.03 & 0.00 & 2.02 \\
6+Placebo shock & 0.52$^{***}$ & -- & 19.03$^{*}$ & 9.35$^{*}$ & 0.00 & 0.03 & 0.00 & 1.73$^{*}$ \\
7+Trend followers 16\% & 1.49$^{***}$ & 34.47 & 34.63$^{***}$ & 14.04$^{**}$ & 0.13$^{**}$ & 0.06$^{***}$ & 0.00 & 2.27 \\
8+Leveraged 19\% & 2.74$^{***}$ & 52.80$^{***}$ & 36.26$^{***}$ & 15.13$^{***}$ & 0.90$^{***}$ & 0.08$^{***}$ & 0.13$^{**}$ & 2.42$^{*}$ \\
9+Leveraged 19\% + funding shock & 2.96$^{***}$ & 60.43$^{***}$ & 38.00$^{***}$ & 16.49$^{***}$ & 1.37$^{***}$ & 0.09$^{***}$ & 0.30$^{***}$ & 2.39$^{*}$ \\
10+Market makers withdraw & 0.64 & 33.17$^{**}$ & 19.38 & 8.72$^{***}$ & 0.00 & 0.03 & 0.00 & 1.63$^{***}$ \\
11+Signal precision 0.5 & 0.60 & 24.97 & 20.27 & 9.52 & 0.00 & 0.03$^{*}$ & 0.00 & 2.03 \\
12+Signal precision 8 & 0.58 & 26.20 & 17.67$^{***}$ & 8.58$^{**}$ & 0.00 & 0.03$^{**}$ & 0.00 & 1.83 \\
13+Misleading news 50\% & 0.71$^{***}$ & 23.17 & 23.52$^{**}$ & 12.00 & 0.00 & 0.04$^{***}$ & 0.00 & 2.04 \\
14+Circuit breaker 5\% & 0.64$^{*}$ & 25.13 & 20.60 & 10.56 & 0.00 & 0.03 & 0.00 & 1.96 \\
15+Position limit 300 & 1.89$^{***}$ & 53.30$^{***}$ & 38.48$^{***}$ & 12.30 & 0.63$^{***}$ & 0.03 & 0.00 & 0.77$^{***}$ \\
16+Call auction (5 ticks) & 1.36$^{***}$ & 25.10 & -- & -2.83$^{***}$ & 0.13 & 0.06$^{***}$ & 0.00 & 0.24$^{***}$ \\
17+Mock LLM 25\% & 0.66 & 28.23 & 16.26$^{***}$ & 11.04 & 0.00 & 0.03 & 0.00 & 1.97 \\
18+Mock LLM 50\% & 0.68 & 28.30$^{*}$ & 13.57$^{***}$ & 12.36$^{*}$ & 0.00 & 0.03 & 0.00 & 2.40$^{**}$ \\
19+\midrule
20+Seeds per cell & 30 & & & & & & & \\
21+\bottomrule
22+\end{tabular}
\ No newline at end of file
added results/tables/tab_classical_effects.csv +66 −0
@@ -0,0 +1,66 @@
1+outcome,level,n,control_mean,treat_mean,diff,se,ci_lo,ci_hi,t,p,p_wilcoxon,cohen_d,pct_change,cell,p_holm
2+mad_pct,placebo_shock,30,0.6282540919469869,0.5228496884134598,-0.105404403533527,0.0260831529140309,-0.158750441033583,-0.052058366033470985,-4.041091346622702,0.0003577844519032219,0.00012333691120147705,-0.7377989624947274,-16.777352489161533,placebo_shock,0.0010733533557096657
3+time_to_absorb,placebo_shock,0,,,,,,,,,,,,placebo_shock,
4+spread_bp,placebo_shock,30,20.68987407852468,19.02562407892965,-1.664249999595028,0.9104903111467902,-3.526411772827072,0.19791177363701595,-1.8278612954143953,0.07787609209897943,0.09194962680339813,-0.3337202878296929,-8.043789891029146,placebo_shock,0.15575218419795886
5+n_bubbles,placebo_shock,30,0.0,0.0,0.0,0.0,0.0,0.0,,,1.0,,,placebo_shock,
6+max_dd,placebo_shock,30,0.03313559734901605,0.03124532261713216,-0.0018902747318838898,0.0019984533683765375,-0.005977570799307531,0.002197021335539752,-0.9458688212572467,0.35203053516393307,0.5676916025573617,-0.17269122994780536,-5.704664720462692,placebo_shock,0.35203053516393307
7+mad_pct,trend_heavy,30,0.6282540919469868,1.4894389768807208,0.8611848849337337,0.1246024914283476,0.606344175980891,1.1160255938865764,6.911457989818415,1.3536543920906025e-07,5.587935447692871e-09,1.2618538154242858,137.07588951229656,trend_heavy,5.41461756836241e-07
8+time_to_absorb,trend_heavy,30,25.266666666666666,34.46666666666667,9.2,5.806140229775379,-2.6748901043157947,21.07489010431579,1.584529418152878,0.12391908710163213,0.5270892568655381,0.28929416845095574,36.41160949868073,trend_heavy,0.12391908710163213
9+spread_bp,trend_heavy,30,20.68987407852468,34.62717383838306,13.937299759858377,2.3683605689552474,9.09345852097283,18.781140998743922,5.884787959464519,2.185900359452944e-06,6.917864084243774e-06,1.0744103705111714,67.36290277534737,trend_heavy,6.557701078358832e-06
10+n_bubbles,trend_heavy,30,0.0,0.13333333333333333,0.13333333333333333,0.06312427686319992,0.004229691154525234,0.2624369755121414,2.112235418114766,0.04339741781077554,0.045500263896358396,0.38563966175427117,,trend_heavy,0.08679483562155108
11+max_dd,trend_heavy,30,0.03313559734901605,0.06073696070483838,0.027601363355822337,0.0035535803541489716,0.02033347547981643,0.03486925123182825,7.767198319744326,1.4490308139866929e-08,6.910413503646851e-07,1.4180899094467303,83.29822174351703,trend_heavy,7.245154069933464e-08
12+mad_pct,leverage_heavy,30,0.6282540919469867,2.7377706861587074,2.109516594211721,0.33054271789106565,1.4334808295898054,2.7855523588336366,6.381978727805274,5.61666122443336e-07,3.725290298461914e-09,1.1651845702456904,335.77442968564475,leverage_heavy,2.246664489773344e-06
13+time_to_absorb,leverage_heavy,30,25.266666666666666,52.8,27.533333333333335,7.952550857058357,11.268540589909744,43.79812607675693,3.4622014782710733,0.001683414812682758,0.006827030024128609,0.6321086160922663,108.97097625329816,leverage_heavy,0.001683414812682758
14+spread_bp,leverage_heavy,30,20.68987407852468,36.25765496390989,15.567780885385222,3.372307612659998,8.67063739358322,22.464924377187224,4.616358492013639,7.358646567477612e-05,0.00013739429414272308,0.842827893202134,75.24347816859843,leverage_heavy,0.00022075939702432835
15+n_bubbles,leverage_heavy,30,0.0,0.9,0.9,0.22154110176243813,0.4468975717247238,1.3531024282752764,4.062451585011451,0.00033757404082763944,0.0004730724812796508,0.741698790627796,,leverage_heavy,0.0006751480816552789
16+max_dd,leverage_heavy,30,0.03313559734901605,0.07811242732953337,0.04497682998051735,0.005317411213479523,0.0341015029473002,0.0558521570137345,8.458407329209757,2.5464721711326925e-09,2.60770320892334e-08,1.5442868315917366,135.73568481889137,leverage_heavy,1.2732360855663462e-08
17+mad_pct,leverage_heavy_funding_shock,30,0.6282540919469867,2.958604840512614,2.3303507485656274,0.3309132677965215,1.6535571242931841,3.007144372838071,7.042179856017618,9.569332641420283e-08,1.862645149230957e-09,1.285720253716444,370.9248818967131,leverage_heavy_funding_shock,3.827733056568113e-07
18+time_to_absorb,leverage_heavy_funding_shock,30,25.266666666666666,60.43333333333333,35.166666666666664,7.943924640712425,18.91951651661322,51.41381681672011,4.426863075517904,0.00012425575522840936,0.000614000783560083,0.8082309218159505,139.1820580474934,leverage_heavy_funding_shock,0.00012425575522840936
19+spread_bp,leverage_heavy_funding_shock,30,20.68987407852468,38.00473078793235,17.31485670940766,3.345013937297895,10.47353505149898,24.156178367316343,5.176318255760278,1.553831088819794e-05,7.910653948783875e-05,0.9450620911685667,83.68758864211667,leverage_heavy_funding_shock,3.107662177639588e-05
20+n_bubbles,leverage_heavy_funding_shock,30,0.0,1.3666666666666667,1.3666666666666667,0.24203796288790566,0.8716434504469067,1.8616898828864268,5.6464971459853475,4.2177639491799116e-06,4.338803172973628e-05,1.0309046192482385,,leverage_heavy_funding_shock,1.2653291847539736e-05
21+max_dd,leverage_heavy_funding_shock,30,0.03313559734901605,0.094022027434633,0.06088643008561697,0.006712607068457487,0.047157607133218205,0.07461525303801574,9.070459430244629,5.752487239564372e-10,9.313225746154785e-09,1.6560317456268137,183.749305752066,leverage_heavy_funding_shock,2.876243619782186e-09
22+mad_pct,liquidity_shock,30,0.6282540919469867,0.6375685616065419,0.009314469659554982,0.027251007041271744,-0.04642009771922102,0.06504903703833098,0.3418027688095411,0.7349639130942708,0.8871948085725307,0.06240436223156962,1.4825959399148578,liquidity_shock,0.7349639130942708
23+time_to_absorb,liquidity_shock,30,25.266666666666666,33.166666666666664,7.9,3.8561340893364338,0.013320256450725765,15.786679743549275,2.0486839453654575,0.04963907844851497,0.015751121568152216,0.3740368033584474,31.266490765171504,liquidity_shock,0.19855631379405989
24+spread_bp,liquidity_shock,30,20.68987407852468,19.38476399998455,-1.3051100785401253,0.9903887839086477,-3.3306825766258523,0.720462419545602,-1.3177755036657475,0.19789462166450567,0.23665234446525574,-0.24059178969515385,-6.3079653050898985,liquidity_shock,0.39578924332901133
25+n_bubbles,liquidity_shock,30,0.0,0.0,0.0,0.0,0.0,0.0,,,1.0,,,liquidity_shock,
26+max_dd,liquidity_shock,30,0.03313559734901605,0.03023922492546186,-0.0028963724235541942,0.0018099280248392202,-0.006598090870082065,0.0008053460229736757,-1.6002693940337684,0.12037802875949395,0.09749059620220792,-0.29216788173247266,-8.740969396286442,liquidity_shock,0.36113408627848187
27+mad_pct,info_low,30,0.6282540919469867,0.6026463991451105,-0.025607692801876355,0.02365127473041428,-0.07397998095474381,0.022764595350991106,-1.0827193499615573,0.28785378862941297,0.370740607380867,-0.1976766038070917,-4.076008915838018,info_low,0.8635613658882388
28+time_to_absorb,info_low,30,25.266666666666666,24.966666666666665,-0.3,2.7780543923574554,-5.981759190706424,5.381759190706425,-0.1079892462960094,0.914747917936226,0.34541581215055495,-0.019716048721435186,-1.187335092348285,info_low,1.0
29+spread_bp,info_low,30,20.68987407852468,20.27325361817352,-0.4166204603511574,0.9304469506093098,-2.3195981441693014,1.4863572234669868,-0.4477637979019981,0.6576507775114152,0.761065473780036,-0.08175011084836957,-2.0136442530773735,info_low,1.0
30+n_bubbles,info_low,30,0.0,0.0,0.0,0.0,0.0,0.0,,,1.0,,,info_low,
31+max_dd,info_low,30,0.03313559734901605,0.030426155138508,-0.0027094422105080505,0.0015618758372030646,-0.005903836970086592,0.00048495254907049033,-1.7347359796281854,0.09340609319392706,0.19807579927146435,-0.3167180091193932,-8.176832250735044,info_low,0.37362437277570826
32+mad_pct,info_high,30,0.6282540919469867,0.583635110753795,-0.04461898119319179,0.030384585406036172,-0.10676243592952972,0.017524473543146145,-1.4684742476139836,0.1527397481733936,0.06056523136794567,-0.2681054901778685,-7.102059782040676,info_high,0.3054794963467872
33+time_to_absorb,info_high,30,25.266666666666666,26.2,0.9333333333333333,3.646737900920172,-6.525083118717398,8.391749785384064,0.25593649960361226,0.7998066240890291,0.8192500254019224,0.046727398040603475,3.6939313984168867,info_high,0.7998066240890291
34+spread_bp,info_high,30,20.68987407852468,17.674358574644632,-3.01551550388005,0.8436325288226298,-4.740937758895465,-1.2900932488646346,-3.574441952930017,0.0012527919846749588,0.0008718203753232956,-0.6526008293708632,-14.574837393573327,info_high,0.005011167938699835
35+n_bubbles,info_high,30,0.0,0.0,0.0,0.0,0.0,0.0,,,1.0,,,info_high,
36+max_dd,info_high,30,0.03313559734901605,0.02785980850434493,-0.005275788844671122,0.002186873838565948,-0.009748448042910727,-0.0008031296464315165,-2.412479746948157,0.02239567174887383,0.005382779985666275,-0.44045652564262017,-15.92181601285599,info_high,0.06718701524662149
37+mad_pct,misleading_news,30,0.6282540919469868,0.707292854995019,0.07903876304803209,0.01962027022094286,0.038910804805506176,0.119166721290558,4.028423775920547,0.0003703271034647764,0.0009753641365557986,0.7354861910872733,12.5807000799768,misleading_news,0.0014813084138591056
38+time_to_absorb,misleading_news,30,25.266666666666666,23.166666666666668,-2.1,1.8403835182518,-5.864006924421055,1.6640069244210554,-1.1410665109600702,0.263177805181749,0.281084103394311,-0.2083292892221821,-8.311345646437996,misleading_news,0.263177805181749
39+spread_bp,misleading_news,30,20.68987407852468,23.51591601826055,2.8260419397358745,1.0597430147248355,0.6586241129775665,4.993459766494182,2.6667238193305405,0.012395591106970309,0.03692078702122783,0.48687493016122274,13.659058189576903,misleading_news,0.024791182213940617
40+n_bubbles,misleading_news,30,0.0,0.0,0.0,0.0,0.0,0.0,,,1.0,,,misleading_news,
41+max_dd,misleading_news,30,0.03313559734901605,0.038069095171641455,0.004933497822625399,0.0016643866992440016,0.001529444809360157,0.00833755083589064,2.964153597758438,0.006012508226009909,0.014990431977029232,0.541177929800797,14.888815103168488,misleading_news,0.01803752467802973
42+mad_pct,breaker_5,30,0.6282540919469869,0.6436703744684232,0.015416282521436609,0.008871426884037416,-0.0027278227098096845,0.0335603877526829,1.7377455422842427,0.09286600685468777,0.10880943004054569,0.31726747757104234,2.453829225952333,breaker_5,0.37146402741875106
43+time_to_absorb,breaker_5,30,25.266666666666666,25.133333333333333,-0.13333333333333333,0.1333333333333333,-0.4060306189510271,0.13936395228436047,-1.0000000000000002,0.3255819880161932,0.31731050786291415,-0.1825741858350554,-0.5277044854881267,breaker_5,0.6511639760323864
44+spread_bp,breaker_5,30,20.68987407852468,20.599037031113088,-0.09083704741159479,0.059877925033521344,-0.2133011545995525,0.03162705977636293,-1.5170373282097143,0.14008374994513234,0.10880943004054569,-0.27697185507927624,-0.43904108389852536,breaker_5,0.420251249835397
45+n_bubbles,breaker_5,30,0.0,0.0,0.0,0.0,0.0,0.0,,,1.0,,,breaker_5,
46+max_dd,breaker_5,30,0.03313559734901605,0.0331720767406367,3.64793916206511e-05,0.0003926976674050563,-0.0007666775181525398,0.000839636301393842,0.09289434251470523,0.9266262966626592,1.0,0.01696010895330508,0.1100912448820976,breaker_5,0.9266262966626592
47+mad_pct,poslimit_300,30,0.6282540919469869,1.8911586792602286,1.2629045873132414,0.19593886537029576,0.8621646118120634,1.6636445628144194,6.445401145538619,4.729705740517956e-07,9.313225746154785e-09,1.1767638665270463,201.01812363839045,poslimit_300,1.8918822962071823e-06
48+time_to_absorb,poslimit_300,30,25.266666666666666,53.3,28.033333333333335,8.112780230299235,11.440834726217158,44.625831940449515,3.455453314097644,0.0017134343335242206,0.00545559119110836,0.630876575512421,110.94986807387863,poslimit_300,0.005140303000572662
49+spread_bp,poslimit_300,30,20.68987407852468,38.48234651034019,17.792472431815515,1.9105986967985755,13.884859342902955,21.700085520728077,9.312511550242768,3.2378780191024443e-10,4.6566128730773926e-08,1.7002242143651225,85.99604020927048,poslimit_300,1.6189390095512222e-09
50+n_bubbles,poslimit_300,30,0.0,0.6333333333333333,0.6333333333333333,0.1946605258045745,0.23520785580467946,1.031458810861987,3.2535272917589646,0.0028932275163866,0.004508698364904228,0.5940100963850257,,poslimit_300,0.0057864550327732
51+max_dd,poslimit_300,30,0.03313559734901605,0.034456638636437525,0.0013210412874214686,0.002740865520307808,-0.004284658119811537,0.006926740694654474,0.4819796074026687,0.6334381365601258,0.4771064817905426,0.08799703441064186,3.9867737210438325,poslimit_300,0.6334381365601258
52+mad_pct,auction_5,30,0.6282540919469867,1.35564882733449,0.7273947353875033,0.11832214381516283,0.4853987795360435,0.9693906912389632,6.147579074664201,1.0633232074358769e-06,1.862645149230957e-09,1.1223892444134396,115.78034185710999,auction_5,3.1899696223076306e-06
53+time_to_absorb,auction_5,30,25.266666666666666,25.1,-0.16666666666666666,3.980724630312361,-8.308162677749255,7.974829344415922,-0.04186842400439756,0.9668905278378153,0.2664233269499078,-0.007644093424799773,-0.6596306068601583,auction_5,0.9668905278378153
54+spread_bp,auction_5,0,,,,,,,,,,,,auction_5,
55+n_bubbles,auction_5,30,0.0,0.13333333333333333,0.13333333333333333,0.07926868804398468,-0.028789337147194394,0.29545600381386106,1.6820428926406503,0.10329970911247394,0.10247043485974941,0.3070976116635082,,auction_5,0.20659941822494787
56+max_dd,auction_5,30,0.03313559734901605,0.05628606196832761,0.02315046461931156,0.0032313309119088966,0.016541650854735784,0.029759278383887335,7.164374448309136,6.931526079709137e-08,5.587935447692871e-09,1.3080298319175145,69.86584359855824,auction_5,2.7726104318836547e-07
57+mad_pct,mock_llm_25_indep,30,0.6282540919469867,0.6573609826050393,0.02910689065805242,0.04227381377767932,-0.05735276636605522,0.11556654768216007,0.6885324047441619,0.4965892162378058,0.5978077705949545,0.12570824321721819,4.632980673130024,mock_llm_25_indep,0.9931784324756116
58+time_to_absorb,mock_llm_25_indep,30,25.266666666666666,28.233333333333334,2.966666666666667,2.9774954117853922,-3.1229952088309387,9.056328542164273,0.9963631362534218,0.3273152497245478,0.8483154780154493,0.1819101883975308,11.741424802110819,mock_llm_25_indep,0.9819457491736434
59+spread_bp,mock_llm_25_indep,30,20.68987407852468,16.25631641329572,-4.43355766522896,0.9814521456395995,-6.440852685825813,-2.426262644632108,-4.5173447171381635,9.678202704795945e-05,0.00013739429414272308,-0.8247505338677887,-21.428635323744324,mock_llm_25_indep,0.0003871281081918378
60+n_bubbles,mock_llm_25_indep,30,0.0,0.0,0.0,0.0,0.0,0.0,,,1.0,,,mock_llm_25_indep,
61+max_dd,mock_llm_25_indep,30,0.03313559734901605,0.032746308923070254,-0.0003892884259457959,0.0021208214839804843,-0.0047268553906545515,0.00394827853876296,-0.18355548964694385,0.8556395780450193,0.7000329215079546,-0.03351249407784571,-1.174834489462903,mock_llm_25_indep,0.9931784324756116
62+mad_pct,mock_llm_50_indep,30,0.6282540919469867,0.6798607327887491,0.05160664084176236,0.031913313378619,-0.01366341365885941,0.11687669534238414,1.6170881484320372,0.11668682433457427,0.06989291124045849,0.29523855212349637,8.214294423746791,mock_llm_50_indep,0.28389459081403096
63+time_to_absorb,mock_llm_50_indep,30,25.266666666666666,28.3,3.033333333333333,1.7554403667530416,-0.5569453397462927,6.623612006412959,1.7279614795140847,0.09463153027134365,0.11816765662651728,0.3154811602766217,12.00527704485488,mock_llm_50_indep,0.28389459081403096
64+spread_bp,mock_llm_50_indep,30,20.68987407852468,13.5671243158387,-7.1227497626859755,0.8152976245444828,-8.790220631564733,-5.455278893807219,-8.736379879268686,1.2878226187043162e-09,1.862645149230957e-09,-1.5950374436032397,-34.42625960724973,mock_llm_50_indep,5.151290474817265e-09
65+n_bubbles,mock_llm_50_indep,30,0.0,0.0,0.0,0.0,0.0,0.0,,,1.0,,,mock_llm_50_indep,
66+max_dd,mock_llm_50_indep,30,0.03313559734901605,0.03175647106215273,-0.0013791262868633192,0.002565621448445398,-0.00662641132371529,0.003868158749988652,-0.5375408315591457,0.5949953367044932,1.0,-0.09814107967500967,-4.162068582428232,mock_llm_50_indep,0.5949953367044932
added results/tables/tab_classical_effects.tex +84 −0
@@ -0,0 +1,84 @@
1+\begin{tabular}{llrrrrr}
2+\toprule
3+Cell & Outcome & Control & Effect & 95\% CI & $d$ & $p$ (Holm) \\
4+\midrule
5+Placebo shock & Mean $|P/V-1|$ (\%) & 0.63 & -0.11$^{***}$ & [-0.16, -0.05] & -0.74 & 0.001 \\
6+ & Time to absorb (ticks) & -- & -- & [--, --] & -- & -- \\
7+ & Quoted spread (bp) & 20.69 & -1.66 & [-3.53, 0.20] & -0.33 & 0.156 \\
8+ & Bubble episodes & 0.00 & 0.00 & [0.00, 0.00] & -- & -- \\
9+ & Max drawdown & 0.03 & -0.00 & [-0.01, 0.00] & -0.17 & 0.352 \\
10+\addlinespace
11+Trend followers 16\% & Mean $|P/V-1|$ (\%) & 0.63 & 0.86$^{***}$ & [0.61, 1.12] & 1.26 & 0.000 \\
12+ & Time to absorb (ticks) & 25.27 & 9.20 & [-2.67, 21.07] & 0.29 & 0.124 \\
13+ & Quoted spread (bp) & 20.69 & 13.94$^{***}$ & [9.09, 18.78] & 1.07 & 0.000 \\
14+ & Bubble episodes & 0.00 & 0.13$^{*}$ & [0.00, 0.26] & 0.39 & 0.087 \\
15+ & Max drawdown & 0.03 & 0.03$^{***}$ & [0.02, 0.03] & 1.42 & 0.000 \\
16+\addlinespace
17+Leveraged 19\% & Mean $|P/V-1|$ (\%) & 0.63 & 2.11$^{***}$ & [1.43, 2.79] & 1.17 & 0.000 \\
18+ & Time to absorb (ticks) & 25.27 & 27.53$^{***}$ & [11.27, 43.80] & 0.63 & 0.002 \\
19+ & Quoted spread (bp) & 20.69 & 15.57$^{***}$ & [8.67, 22.46] & 0.84 & 0.000 \\
20+ & Bubble episodes & 0.00 & 0.90$^{***}$ & [0.45, 1.35] & 0.74 & 0.001 \\
21+ & Max drawdown & 0.03 & 0.04$^{***}$ & [0.03, 0.06] & 1.54 & 0.000 \\
22+\addlinespace
23+Leveraged 19\% + funding shock & Mean $|P/V-1|$ (\%) & 0.63 & 2.33$^{***}$ & [1.65, 3.01] & 1.29 & 0.000 \\
24+ & Time to absorb (ticks) & 25.27 & 35.17$^{***}$ & [18.92, 51.41] & 0.81 & 0.000 \\
25+ & Quoted spread (bp) & 20.69 & 17.31$^{***}$ & [10.47, 24.16] & 0.95 & 0.000 \\
26+ & Bubble episodes & 0.00 & 1.37$^{***}$ & [0.87, 1.86] & 1.03 & 0.000 \\
27+ & Max drawdown & 0.03 & 0.06$^{***}$ & [0.05, 0.07] & 1.66 & 0.000 \\
28+\addlinespace
29+Market makers withdraw & Mean $|P/V-1|$ (\%) & 0.63 & 0.01 & [-0.05, 0.07] & 0.06 & 0.735 \\
30+ & Time to absorb (ticks) & 25.27 & 7.90 & [0.01, 15.79] & 0.37 & 0.199 \\
31+ & Quoted spread (bp) & 20.69 & -1.31 & [-3.33, 0.72] & -0.24 & 0.396 \\
32+ & Bubble episodes & 0.00 & 0.00 & [0.00, 0.00] & -- & -- \\
33+ & Max drawdown & 0.03 & -0.00 & [-0.01, 0.00] & -0.29 & 0.361 \\
34+\addlinespace
35+Signal precision 0.5 & Mean $|P/V-1|$ (\%) & 0.63 & -0.03 & [-0.07, 0.02] & -0.20 & 0.864 \\
36+ & Time to absorb (ticks) & 25.27 & -0.30 & [-5.98, 5.38] & -0.02 & 1.000 \\
37+ & Quoted spread (bp) & 20.69 & -0.42 & [-2.32, 1.49] & -0.08 & 1.000 \\
38+ & Bubble episodes & 0.00 & 0.00 & [0.00, 0.00] & -- & -- \\
39+ & Max drawdown & 0.03 & -0.00 & [-0.01, 0.00] & -0.32 & 0.374 \\
40+\addlinespace
41+Signal precision 8 & Mean $|P/V-1|$ (\%) & 0.63 & -0.04 & [-0.11, 0.02] & -0.27 & 0.305 \\
42+ & Time to absorb (ticks) & 25.27 & 0.93 & [-6.53, 8.39] & 0.05 & 0.800 \\
43+ & Quoted spread (bp) & 20.69 & -3.02$^{***}$ & [-4.74, -1.29] & -0.65 & 0.005 \\
44+ & Bubble episodes & 0.00 & 0.00 & [0.00, 0.00] & -- & -- \\
45+ & Max drawdown & 0.03 & -0.01$^{*}$ & [-0.01, -0.00] & -0.44 & 0.067 \\
46+\addlinespace
47+Misleading news 50\% & Mean $|P/V-1|$ (\%) & 0.63 & 0.08$^{***}$ & [0.04, 0.12] & 0.74 & 0.001 \\
48+ & Time to absorb (ticks) & 25.27 & -2.10 & [-5.86, 1.66] & -0.21 & 0.263 \\
49+ & Quoted spread (bp) & 20.69 & 2.83$^{**}$ & [0.66, 4.99] & 0.49 & 0.025 \\
50+ & Bubble episodes & 0.00 & 0.00 & [0.00, 0.00] & -- & -- \\
51+ & Max drawdown & 0.03 & 0.00$^{**}$ & [0.00, 0.01] & 0.54 & 0.018 \\
52+\addlinespace
53+Circuit breaker 5\% & Mean $|P/V-1|$ (\%) & 0.63 & 0.02 & [-0.00, 0.03] & 0.32 & 0.371 \\
54+ & Time to absorb (ticks) & 25.27 & -0.13 & [-0.41, 0.14] & -0.18 & 0.651 \\
55+ & Quoted spread (bp) & 20.69 & -0.09 & [-0.21, 0.03] & -0.28 & 0.420 \\
56+ & Bubble episodes & 0.00 & 0.00 & [0.00, 0.00] & -- & -- \\
57+ & Max drawdown & 0.03 & 0.00 & [-0.00, 0.00] & 0.02 & 0.927 \\
58+\addlinespace
59+Position limit 300 & Mean $|P/V-1|$ (\%) & 0.63 & 1.26$^{***}$ & [0.86, 1.66] & 1.18 & 0.000 \\
60+ & Time to absorb (ticks) & 25.27 & 28.03$^{***}$ & [11.44, 44.63] & 0.63 & 0.005 \\
61+ & Quoted spread (bp) & 20.69 & 17.79$^{***}$ & [13.88, 21.70] & 1.70 & 0.000 \\
62+ & Bubble episodes & 0.00 & 0.63$^{***}$ & [0.24, 1.03] & 0.59 & 0.006 \\
63+ & Max drawdown & 0.03 & 0.00 & [-0.00, 0.01] & 0.09 & 0.633 \\
64+\addlinespace
65+Call auction (5 ticks) & Mean $|P/V-1|$ (\%) & 0.63 & 0.73$^{***}$ & [0.49, 0.97] & 1.12 & 0.000 \\
66+ & Time to absorb (ticks) & 25.27 & -0.17 & [-8.31, 7.97] & -0.01 & 0.967 \\
67+ & Quoted spread (bp) & -- & -- & [--, --] & -- & -- \\
68+ & Bubble episodes & 0.00 & 0.13 & [-0.03, 0.30] & 0.31 & 0.207 \\
69+ & Max drawdown & 0.03 & 0.02$^{***}$ & [0.02, 0.03] & 1.31 & 0.000 \\
70+\addlinespace
71+Mock LLM 25\% & Mean $|P/V-1|$ (\%) & 0.63 & 0.03 & [-0.06, 0.12] & 0.13 & 0.993 \\
72+ & Time to absorb (ticks) & 25.27 & 2.97 & [-3.12, 9.06] & 0.18 & 0.982 \\
73+ & Quoted spread (bp) & 20.69 & -4.43$^{***}$ & [-6.44, -2.43] & -0.82 & 0.000 \\
74+ & Bubble episodes & 0.00 & 0.00 & [0.00, 0.00] & -- & -- \\
75+ & Max drawdown & 0.03 & -0.00 & [-0.00, 0.00] & -0.03 & 0.993 \\
76+\addlinespace
77+Mock LLM 50\% & Mean $|P/V-1|$ (\%) & 0.63 & 0.05 & [-0.01, 0.12] & 0.30 & 0.284 \\
78+ & Time to absorb (ticks) & 25.27 & 3.03 & [-0.56, 6.62] & 0.32 & 0.284 \\
79+ & Quoted spread (bp) & 20.69 & -7.12$^{***}$ & [-8.79, -5.46] & -1.60 & 0.000 \\
80+ & Bubble episodes & 0.00 & 0.00 & [0.00, 0.00] & -- & -- \\
81+ & Max drawdown & 0.03 & -0.00 & [-0.01, 0.00] & -0.10 & 0.595 \\
82+\addlinespace
83+\bottomrule
84+\end{tabular}
\ No newline at end of file
added results/tables/tab_contagion.tex +10 −0
@@ -0,0 +1,10 @@
1+\begin{tabular}{lrrrrrr}
2+\toprule
3+Cell & Return correlation & Fundamental correlation & Excess comovement & DY spillover (\%) & Mean $|P/V-1|$ (\%) & Max drawdown \\
4+\midrule
5+Two assets & -0.01 & 0.38 & -0.39 & 1.21 & 0.76 & 0.04 \\
6+Two assets + leveraged 19\% + funding shock & 0.02$^{*}$ & 0.34 & -0.32 & 1.25 & 11.82$^{***}$ & 0.12$^{***}$ \\
7+\midrule
8+Seeds per cell & 30 & & & & & \\
9+\bottomrule
10+\end{tabular}
\ No newline at end of file
added results/tables/tab_scale.tex +9 −0
@@ -0,0 +1,9 @@
1+\begin{tabular}{rrrrrrrr}
2+\toprule
3+Traders & Seeds & Wall-clock (s) & Orders & Trades & Mean $|P/V-1|$ (\%) & ACF$_1$ & Spread (bp) \\
4+\midrule
5+100 & 3 & 0.6 & 13,689 & 10,521 & 0.82 & 0.11 & 25.5 \\
6+1,000 & 3 & 2.7 & 14,939 & 11,840 & 0.99 & 0.15 & 14.2 \\
7+10,000 & 1 & 23.7 & 15,378 & 11,885 & 1.23 & 0.10 & 10.9 \\
8+\bottomrule
9+\end{tabular}
\ No newline at end of file
added results/tables/tab_stylized_facts.tex +22 −0
@@ -0,0 +1,22 @@
1+\begin{tabular}{lrrrr}
2+\toprule
3+Statistic & Mean & SD & Min & Max \\
4+\midrule
5+ACF$_1$ of returns & -0.007 & 0.146 & -0.292 & 0.312 \\
6+Variance ratio (5) & 1.18 & 0.29 & 0.69 & 1.79 \\
7+Excess kurtosis & 20.4 & 15.3 & 1.8 & 66.0 \\
8+Vol. clustering $\sum_{1}^{10}\mathrm{ACF}|r|$ & 2.02 & 0.59 & 0.68 & 3.71 \\
9+Tick volatility (bp) & 17.0 & 7.7 & 6.0 & 38.6 \\
10+Quoted spread (bp) & 20.7 & 5.0 & 13.0 & 38.6 \\
11+Effective spread (bp) & 30.4 & 10.3 & 17.4 & 69.2 \\
12+Depth, 5 levels (lots) & 139 & 5 & 133 & 150 \\
13+Price impact (bp/100 lots) & 10.8 & 3.9 & 5.4 & 22.3 \\
14+Mean $|P/V-1|$ (\%) & 0.63 & 0.15 & 0.41 & 0.98 \\
15+Bubble episodes & 0.00 & 0.00 & 0.00 & 0.00 \\
16+Max drawdown & 0.033 & 0.012 & 0.010 & 0.060 \\
17+MM P\&L (\%) & 4.9 & 1.2 & 1.9 & 7.1 \\
18+Wealth Gini (final) & 0.285 & 0.023 & 0.243 & 0.338 \\
19+\midrule
20+Runs (seeds) & 30 & & & \\
21+\bottomrule
22+\end{tabular}
\ No newline at end of file
added results/tables/tab_threshold_sensitivity.tex +14 −0
@@ -0,0 +1,14 @@
1+\begin{tabular}{lllrrrrrrrrr}
2+\toprule
3+Design & Cell & Outcome & b3/c7 & b3/c10 & b3/c15 & b5/c7 & b5/c10 & b5/c15 & b8/c7 & b8/c10 & b8/c15 \\
4+\midrule
5+classical confirmatory & leverage heavy & n bubbles & +2.33 & +2.33 & +2.33 & +0.90 & +0.90 & +0.90 & +0.30 & +0.30 & +0.30 \\
6+classical confirmatory & leverage heavy & n crashes & +0.93 & +0.13 & +0.00 & +0.93 & +0.13 & +0.00 & +0.93 & +0.13 & +0.00 \\
7+classical confirmatory & leverage heavy funding shock & n bubbles & +2.27 & +2.27 & +2.27 & +1.37 & +1.37 & +1.37 & +0.47 & +0.47 & +0.47 \\
8+classical confirmatory & leverage heavy funding shock & n crashes & +1.23 & +0.30 & +0.00 & +1.23 & +0.30 & +0.00 & +1.23 & +0.30 & +0.00 \\
9+classical confirmatory & mock llm 50 indep & n bubbles & +0.00 & +0.00 & +0.00 & +0.00 & +0.00 & +0.00 & +0.00 & +0.00 & +0.00 \\
10+classical confirmatory & mock llm 50 indep & n crashes & +0.00 & +0.00 & +0.00 & +0.00 & +0.00 & +0.00 & +0.00 & +0.00 & +0.00 \\
11+classical confirmatory & trend heavy & n bubbles & +1.10 & +1.10 & +1.10 & +0.13 & +0.13 & +0.13 & +0.00 & +0.00 & +0.00 \\
12+classical confirmatory & trend heavy & n crashes & +0.07 & +0.00 & +0.00 & +0.07 & +0.00 & +0.00 & +0.07 & +0.00 & +0.00 \\
13+\bottomrule
14+\end{tabular}
\ No newline at end of file
added results/tables/threshold_sensitivity.csv +109 −0
@@ -0,0 +1,109 @@
1+design,bubble_thr,crash_thr,cell,outcome,control,effect,p,n
2+classical_confirmatory,0.03,0.07,leverage_heavy,n_bubbles,0.06666666666666667,2.3333333333333335,7.712408930919837e-07,30
3+classical_confirmatory,0.03,0.07,leverage_heavy,bubble_amp,0.00285286025986331,0.05610639628186829,1.92806912918991e-09,30
4+classical_confirmatory,0.03,0.07,leverage_heavy,n_crashes,0.0,0.9333333333333333,0.004069703036845098,30
5+classical_confirmatory,0.03,0.07,leverage_heavy_funding_shock,n_bubbles,0.06666666666666667,2.2666666666666666,9.309666772654047e-08,30
6+classical_confirmatory,0.03,0.07,leverage_heavy_funding_shock,bubble_amp,0.00285286025986331,0.07032997069381303,1.225662004179797e-09,30
7+classical_confirmatory,0.03,0.07,leverage_heavy_funding_shock,n_crashes,0.0,1.2333333333333334,0.00027633309040706456,30
8+classical_confirmatory,0.03,0.07,trend_heavy,n_bubbles,0.06666666666666667,1.1,9.439794156231982e-06,30
9+classical_confirmatory,0.03,0.07,trend_heavy,bubble_amp,0.00285286025986331,0.027465752199760496,2.7211457127751164e-07,30
10+classical_confirmatory,0.03,0.07,trend_heavy,n_crashes,0.0,0.06666666666666667,0.1607882084258767,30
11+classical_confirmatory,0.03,0.07,mock_llm_50_indep,n_bubbles,0.06666666666666667,0.0,,30
12+classical_confirmatory,0.03,0.07,mock_llm_50_indep,bubble_amp,0.00285286025986331,1.2987245178545475e-06,0.9961006414963004,30
13+classical_confirmatory,0.03,0.07,mock_llm_50_indep,n_crashes,0.0,0.0,,30
14+classical_confirmatory,0.03,0.1,leverage_heavy,n_bubbles,0.06666666666666667,2.3333333333333335,7.712408930919837e-07,30
15+classical_confirmatory,0.03,0.1,leverage_heavy,bubble_amp,0.00285286025986331,0.05610639628186829,1.92806912918991e-09,30
16+classical_confirmatory,0.03,0.1,leverage_heavy,n_crashes,0.0,0.13333333333333333,0.04339741781077554,30
17+classical_confirmatory,0.03,0.1,leverage_heavy_funding_shock,n_bubbles,0.06666666666666667,2.2666666666666666,9.309666772654047e-08,30
18+classical_confirmatory,0.03,0.1,leverage_heavy_funding_shock,bubble_amp,0.00285286025986331,0.07032997069381303,1.225662004179797e-09,30
19+classical_confirmatory,0.03,0.1,leverage_heavy_funding_shock,n_crashes,0.0,0.3,0.009981299812861963,30
20+classical_confirmatory,0.03,0.1,trend_heavy,n_bubbles,0.06666666666666667,1.1,9.439794156231982e-06,30
21+classical_confirmatory,0.03,0.1,trend_heavy,bubble_amp,0.00285286025986331,0.027465752199760496,2.7211457127751164e-07,30
22+classical_confirmatory,0.03,0.1,trend_heavy,n_crashes,0.0,0.0,,30
23+classical_confirmatory,0.03,0.1,mock_llm_50_indep,n_bubbles,0.06666666666666667,0.0,,30
24+classical_confirmatory,0.03,0.1,mock_llm_50_indep,bubble_amp,0.00285286025986331,1.2987245178545475e-06,0.9961006414963004,30
25+classical_confirmatory,0.03,0.1,mock_llm_50_indep,n_crashes,0.0,0.0,,30
26+classical_confirmatory,0.03,0.15,leverage_heavy,n_bubbles,0.06666666666666667,2.3333333333333335,7.712408930919837e-07,30
27+classical_confirmatory,0.03,0.15,leverage_heavy,bubble_amp,0.00285286025986331,0.05610639628186829,1.92806912918991e-09,30
28+classical_confirmatory,0.03,0.15,leverage_heavy,n_crashes,0.0,0.0,,30
29+classical_confirmatory,0.03,0.15,leverage_heavy_funding_shock,n_bubbles,0.06666666666666667,2.2666666666666666,9.309666772654047e-08,30
30+classical_confirmatory,0.03,0.15,leverage_heavy_funding_shock,bubble_amp,0.00285286025986331,0.07032997069381303,1.225662004179797e-09,30
31+classical_confirmatory,0.03,0.15,leverage_heavy_funding_shock,n_crashes,0.0,0.0,,30
32+classical_confirmatory,0.03,0.15,trend_heavy,n_bubbles,0.06666666666666667,1.1,9.439794156231982e-06,30
33+classical_confirmatory,0.03,0.15,trend_heavy,bubble_amp,0.00285286025986331,0.027465752199760496,2.7211457127751164e-07,30
34+classical_confirmatory,0.03,0.15,trend_heavy,n_crashes,0.0,0.0,,30
35+classical_confirmatory,0.03,0.15,mock_llm_50_indep,n_bubbles,0.06666666666666667,0.0,,30
36+classical_confirmatory,0.03,0.15,mock_llm_50_indep,bubble_amp,0.00285286025986331,1.2987245178545475e-06,0.9961006414963004,30
37+classical_confirmatory,0.03,0.15,mock_llm_50_indep,n_crashes,0.0,0.0,,30
38+classical_confirmatory,0.05,0.07,leverage_heavy,n_bubbles,0.0,0.9,0.00033757404082763944,30
39+classical_confirmatory,0.05,0.07,leverage_heavy,bubble_amp,0.0,0.04273920530809517,4.378937522799665e-05,30
40+classical_confirmatory,0.05,0.07,leverage_heavy,n_crashes,0.0,0.9333333333333333,0.004069703036845098,30
41+classical_confirmatory,0.05,0.07,leverage_heavy_funding_shock,n_bubbles,0.0,1.3666666666666667,4.2177639491799116e-06,30
42+classical_confirmatory,0.05,0.07,leverage_heavy_funding_shock,bubble_amp,0.0,0.06542884594559688,2.562375048895747e-07,30
43+classical_confirmatory,0.05,0.07,leverage_heavy_funding_shock,n_crashes,0.0,1.2333333333333334,0.00027633309040706456,30
44+classical_confirmatory,0.05,0.07,trend_heavy,n_bubbles,0.0,0.13333333333333333,0.04339741781077554,30
45+classical_confirmatory,0.05,0.07,trend_heavy,bubble_amp,0.0,0.007614737144890871,0.04373909157771441,30
46+classical_confirmatory,0.05,0.07,trend_heavy,n_crashes,0.0,0.06666666666666667,0.1607882084258767,30
47+classical_confirmatory,0.05,0.07,mock_llm_50_indep,n_bubbles,0.0,0.0,,30
48+classical_confirmatory,0.05,0.07,mock_llm_50_indep,bubble_amp,0.0,0.0,,30
49+classical_confirmatory,0.05,0.07,mock_llm_50_indep,n_crashes,0.0,0.0,,30
50+classical_confirmatory,0.05,0.1,leverage_heavy,n_bubbles,0.0,0.9,0.00033757404082763944,30
51+classical_confirmatory,0.05,0.1,leverage_heavy,bubble_amp,0.0,0.04273920530809517,4.378937522799665e-05,30
52+classical_confirmatory,0.05,0.1,leverage_heavy,n_crashes,0.0,0.13333333333333333,0.04339741781077554,30
53+classical_confirmatory,0.05,0.1,leverage_heavy_funding_shock,n_bubbles,0.0,1.3666666666666667,4.2177639491799116e-06,30
54+classical_confirmatory,0.05,0.1,leverage_heavy_funding_shock,bubble_amp,0.0,0.06542884594559688,2.562375048895747e-07,30
55+classical_confirmatory,0.05,0.1,leverage_heavy_funding_shock,n_crashes,0.0,0.3,0.009981299812861963,30
56+classical_confirmatory,0.05,0.1,trend_heavy,n_bubbles,0.0,0.13333333333333333,0.04339741781077554,30
57+classical_confirmatory,0.05,0.1,trend_heavy,bubble_amp,0.0,0.007614737144890871,0.04373909157771441,30
58+classical_confirmatory,0.05,0.1,trend_heavy,n_crashes,0.0,0.0,,30
59+classical_confirmatory,0.05,0.1,mock_llm_50_indep,n_bubbles,0.0,0.0,,30
60+classical_confirmatory,0.05,0.1,mock_llm_50_indep,bubble_amp,0.0,0.0,,30
61+classical_confirmatory,0.05,0.1,mock_llm_50_indep,n_crashes,0.0,0.0,,30
62+classical_confirmatory,0.05,0.15,leverage_heavy,n_bubbles,0.0,0.9,0.00033757404082763944,30
63+classical_confirmatory,0.05,0.15,leverage_heavy,bubble_amp,0.0,0.04273920530809517,4.378937522799665e-05,30
64+classical_confirmatory,0.05,0.15,leverage_heavy,n_crashes,0.0,0.0,,30
65+classical_confirmatory,0.05,0.15,leverage_heavy_funding_shock,n_bubbles,0.0,1.3666666666666667,4.2177639491799116e-06,30
66+classical_confirmatory,0.05,0.15,leverage_heavy_funding_shock,bubble_amp,0.0,0.06542884594559688,2.562375048895747e-07,30
67+classical_confirmatory,0.05,0.15,leverage_heavy_funding_shock,n_crashes,0.0,0.0,,30
68+classical_confirmatory,0.05,0.15,trend_heavy,n_bubbles,0.0,0.13333333333333333,0.04339741781077554,30
69+classical_confirmatory,0.05,0.15,trend_heavy,bubble_amp,0.0,0.007614737144890871,0.04373909157771441,30
70+classical_confirmatory,0.05,0.15,trend_heavy,n_crashes,0.0,0.0,,30
71+classical_confirmatory,0.05,0.15,mock_llm_50_indep,n_bubbles,0.0,0.0,,30
72+classical_confirmatory,0.05,0.15,mock_llm_50_indep,bubble_amp,0.0,0.0,,30
73+classical_confirmatory,0.05,0.15,mock_llm_50_indep,n_crashes,0.0,0.0,,30
74+classical_confirmatory,0.08,0.07,leverage_heavy,n_bubbles,0.0,0.3,0.05918466045448987,30
75+classical_confirmatory,0.08,0.07,leverage_heavy,bubble_amp,0.0,0.019283614900718903,0.029827175281888312,30
76+classical_confirmatory,0.08,0.07,leverage_heavy,n_crashes,0.0,0.9333333333333333,0.004069703036845098,30
77+classical_confirmatory,0.08,0.07,leverage_heavy_funding_shock,n_bubbles,0.0,0.4666666666666667,0.004069703036845098,30
78+classical_confirmatory,0.08,0.07,leverage_heavy_funding_shock,bubble_amp,0.0,0.03740679784531051,0.0023922175643250406,30
79+classical_confirmatory,0.08,0.07,leverage_heavy_funding_shock,n_crashes,0.0,1.2333333333333334,0.00027633309040706456,30
80+classical_confirmatory,0.08,0.07,trend_heavy,n_bubbles,0.0,0.0,,30
81+classical_confirmatory,0.08,0.07,trend_heavy,bubble_amp,0.0,0.0,,30
82+classical_confirmatory,0.08,0.07,trend_heavy,n_crashes,0.0,0.06666666666666667,0.1607882084258767,30
83+classical_confirmatory,0.08,0.07,mock_llm_50_indep,n_bubbles,0.0,0.0,,30
84+classical_confirmatory,0.08,0.07,mock_llm_50_indep,bubble_amp,0.0,0.0,,30
85+classical_confirmatory,0.08,0.07,mock_llm_50_indep,n_crashes,0.0,0.0,,30
86+classical_confirmatory,0.08,0.1,leverage_heavy,n_bubbles,0.0,0.3,0.05918466045448987,30
87+classical_confirmatory,0.08,0.1,leverage_heavy,bubble_amp,0.0,0.019283614900718903,0.029827175281888312,30
88+classical_confirmatory,0.08,0.1,leverage_heavy,n_crashes,0.0,0.13333333333333333,0.04339741781077554,30
89+classical_confirmatory,0.08,0.1,leverage_heavy_funding_shock,n_bubbles,0.0,0.4666666666666667,0.004069703036845098,30
90+classical_confirmatory,0.08,0.1,leverage_heavy_funding_shock,bubble_amp,0.0,0.03740679784531051,0.0023922175643250406,30
91+classical_confirmatory,0.08,0.1,leverage_heavy_funding_shock,n_crashes,0.0,0.3,0.009981299812861963,30
92+classical_confirmatory,0.08,0.1,trend_heavy,n_bubbles,0.0,0.0,,30
93+classical_confirmatory,0.08,0.1,trend_heavy,bubble_amp,0.0,0.0,,30
94+classical_confirmatory,0.08,0.1,trend_heavy,n_crashes,0.0,0.0,,30
95+classical_confirmatory,0.08,0.1,mock_llm_50_indep,n_bubbles,0.0,0.0,,30
96+classical_confirmatory,0.08,0.1,mock_llm_50_indep,bubble_amp,0.0,0.0,,30
97+classical_confirmatory,0.08,0.1,mock_llm_50_indep,n_crashes,0.0,0.0,,30
98+classical_confirmatory,0.08,0.15,leverage_heavy,n_bubbles,0.0,0.3,0.05918466045448987,30
99+classical_confirmatory,0.08,0.15,leverage_heavy,bubble_amp,0.0,0.019283614900718903,0.029827175281888312,30
100+classical_confirmatory,0.08,0.15,leverage_heavy,n_crashes,0.0,0.0,,30
101+classical_confirmatory,0.08,0.15,leverage_heavy_funding_shock,n_bubbles,0.0,0.4666666666666667,0.004069703036845098,30
102+classical_confirmatory,0.08,0.15,leverage_heavy_funding_shock,bubble_amp,0.0,0.03740679784531051,0.0023922175643250406,30
103+classical_confirmatory,0.08,0.15,leverage_heavy_funding_shock,n_crashes,0.0,0.0,,30
104+classical_confirmatory,0.08,0.15,trend_heavy,n_bubbles,0.0,0.0,,30
105+classical_confirmatory,0.08,0.15,trend_heavy,bubble_amp,0.0,0.0,,30
106+classical_confirmatory,0.08,0.15,trend_heavy,n_crashes,0.0,0.0,,30
107+classical_confirmatory,0.08,0.15,mock_llm_50_indep,n_bubbles,0.0,0.0,,30
108+classical_confirmatory,0.08,0.15,mock_llm_50_indep,bubble_amp,0.0,0.0,,30
109+classical_confirmatory,0.08,0.15,mock_llm_50_indep,n_crashes,0.0,0.0,,30
added scripts/45_recompute_outcomes.py +11 −0
@@ -0,0 +1,11 @@
1+"""Recompute outcomes.parquet for one or more designs from saved run artefacts (no simulation, no API)."""
2+import sys
3+from pathlib import Path
4+ROOT = Path(__file__).resolve().parents[1]
5+sys.path.insert(0, str(ROOT / "src"))
6+from market_agents.analysis.reload import recompute_design # noqa: E402
7+for d in sys.argv[1:] or ["classical_confirmatory", "exploratory_mock", "pilot_openai", "confirmatory_openai"]:
8+ p = ROOT / "results/runs" / d
9+ if p.exists():
10+ df = recompute_design(p)
11+ print(f"{d}: {len(df)} runs recomputed")
added scripts/46_threshold_sensitivity.py +39 −0
@@ -0,0 +1,39 @@
1+"""Pre-registered sensitivity grid for the bubble/crash definitions: bubble 3/5/8 % (>= 10 ticks), crash 7/10/15 % (20-tick window).
2+Writes results/tables/threshold_sensitivity.csv and a LaTeX fragment with the control-vs-treatment paired effects per threshold."""
3+import sys
4+from pathlib import Path
5+import pandas as pd
6+ROOT = Path(__file__).resolve().parents[1]
7+sys.path.insert(0, str(ROOT / "src"))
8+from market_agents.analysis.reload import recompute_design # noqa: E402
9+from market_agents.analysis.estimators import paired_effects # noqa: E402
10+
11+rows = []
12+for design, control, cells in (("classical_confirmatory", "control", ["leverage_heavy", "leverage_heavy_funding_shock", "trend_heavy", "mock_llm_50_indep"]),
13+ ("confirmatory_openai", "dose_000", ["dose_025", "dose_050", "dose_100", "leverage_025"])):
14+ p = ROOT / "results/runs" / design
15+ if not p.exists():
16+ continue
17+ for b in (0.03, 0.05, 0.08):
18+ for c in (0.07, 0.10, 0.15):
19+ df = recompute_design(p, write=False, bubble_thr=b, crash_thr=c)
20+ df["cell"] = df.name.str.split("/").str[-1]
21+ for cell in cells:
22+ if cell not in set(df.cell):
23+ continue
24+ for oc in ("n_bubbles", "bubble_amp", "n_crashes"):
25+ e = paired_effects(df, oc, "cell", cell, control)
26+ rows.append({"design": design, "bubble_thr": b, "crash_thr": c, "cell": cell, "outcome": oc, "control": e.get("control_mean"),
27+ "effect": e.get("diff"), "p": e.get("p"), "n": e.get("n")})
28+t = pd.DataFrame(rows)
29+out = ROOT / "results/tables"
30+out.mkdir(parents=True, exist_ok=True)
31+t.to_csv(out / "threshold_sensitivity.csv", index=False)
32+if len(t):
33+ piv = t[t.outcome.isin(["n_bubbles", "n_crashes"])].pivot_table(index=["design", "cell", "outcome"], columns=["bubble_thr", "crash_thr"], values="effect")
34+ lines = ["\\begin{tabular}{lll" + "r" * piv.shape[1] + "}", "\\toprule", "Design & Cell & Outcome & " + " & ".join(f"b{int(b*100)}/c{int(c*100)}" for b, c in piv.columns) + " \\\\", "\\midrule"]
35+ for (d, cell, oc), r in piv.iterrows():
36+ lines.append(f"{d.replace('_', ' ')} & {cell.replace('_', ' ')} & {oc.replace('_', ' ')} & " + " & ".join(f"{v:+.2f}" for v in r.values) + " \\\\")
37+ lines += ["\\bottomrule", "\\end{tabular}"]
38+ (out / "tab_threshold_sensitivity.tex").write_text("\n".join(lines))
39+print(t.groupby(["design", "cell", "outcome"])["effect"].agg(["min", "max"]).round(2).to_string() if len(t) else "nothing")
added scripts/60_frozen_library.py +59 −0
@@ -0,0 +1,59 @@
1+"""Phase 6 (scaling arm) — build the frozen decision library from recorded live LLM decisions and replay it
2+at N = 1,000 traders with zero API calls. The library policy is a k-NN replay of recorded decisions (non-adaptive);
3+runs are labelled provider = 'library' and reported separately from online runs."""
4+from __future__ import annotations
5+
6+import sys
7+from pathlib import Path
8+
9+import numpy as np
10+import pandas as pd
11+
12+ROOT = Path(__file__).resolve().parents[1]
13+sys.path.insert(0, str(ROOT / "src"))
14+from market_agents.experiments.config import RunConfig # noqa: E402
15+from market_agents.experiments.runner import run_config # noqa: E402
16+from market_agents.llm.library import DecisionLibrary, FEATURES # noqa: E402
17+from market_agents.metrics.outcomes import run_outcomes # noqa: E402
18+
19+SRC = ROOT / "results/runs/confirmatory_openai"
20+LIB = ROOT / "results/library/gpt-5.4-nano_single.npz"
21+OUT = ROOT / "results/runs/library_scale"
22+
23+
24+def build() -> DecisionLibrary:
25+ run_dirs = [p.parent for p in SRC.glob("dose_*/seed*/llm_decisions.parquet")]
26+ if not run_dirs:
27+ raise SystemExit("no confirmatory runs with LLM decisions yet")
28+ lib = DecisionLibrary.from_runs(run_dirs)
29+ LIB.parent.mkdir(parents=True, exist_ok=True)
30+ lib.save(LIB)
31+ print(f"library: {len(lib)} recorded decisions from {len(run_dirs)} runs; features {FEATURES}")
32+ return lib
33+
34+
35+def replay(seeds=(301, 302, 303, 304, 305), n_traders=1000, shares=(0.0, 0.25)):
36+ rows = []
37+ for n in (100, n_traders):
38+ act = {k: v * 100.0 / n for k, v in RunConfig().population.activity.items()}
39+ for share in shares:
40+ for s in seeds:
41+ cfg = RunConfig.from_yaml(ROOT / "configs/baseline.yaml", **{
42+ "name": f"library_scale/n{n}_share{int(share * 100)}", "seed": s, "population.n_traders": n, "population.activity": act,
43+ "population.llm_share": share, "population.llm.provider_mix": {"library": 1.0}, "population.llm.models": {"library": "knn-replay"},
44+ "population.llm.frozen_library": str(LIB), "population.llm.usd_cap": 0.0, "population.llm.cache": False,
45+ "treatment": {"arm": "library", "share": share, "n": n}})
46+ res = run_config(cfg, out_dir=OUT / f"n{n}_share{int(share * 100)}" / f"seed{s:04d}")
47+ oc = run_outcomes(res)
48+ oc["run_dir"] = str(OUT / f"n{n}_share{int(share * 100)}" / f"seed{s:04d}")
49+ rows.append(oc)
50+ print(f" n={n} share={share} seed={s}: mad={oc['mad_pct']:.2f} spread={oc['spread_bp']:.1f} bubbles={oc['n_bubbles']} llm_vol={oc['llm_share_volume']:.3f} wall={oc['wall_s']:.1f}s", flush=True)
51+ df = pd.DataFrame(rows)
52+ OUT.mkdir(parents=True, exist_ok=True)
53+ df.to_parquet(OUT / "outcomes.parquet", index=False)
54+ print(df.groupby("name")[["mad_pct", "spread_bp", "n_bubbles", "max_dd", "llm_share_volume"]].mean().round(3))
55+
56+
57+if __name__ == "__main__":
58+ build()
59+ replay()
added src/market_agents/analysis/reload.py +50 −0
@@ -0,0 +1,50 @@
1+"""Rebuild run-level outcomes from saved run artefacts (no re-simulation): used after metric changes and for
2+threshold-sensitivity grids. Every recomputed number is still traceable to the saved parquet files."""
3+from __future__ import annotations
4+
5+import json
6+from dataclasses import dataclass
7+from pathlib import Path
8+
9+import pandas as pd
10+
11+from ..experiments.config import RunConfig
12+from ..metrics.outcomes import run_outcomes
13+
14+
15+@dataclass
16+class SavedRun:
17+ config: RunConfig
18+ ticks: pd.DataFrame
19+ trades: pd.DataFrame
20+ agents: pd.DataFrame
21+ llm: pd.DataFrame
22+ manifest: dict
23+ run_dir: Path
24+
25+
26+def load_run(run_dir: str | Path) -> SavedRun:
27+ rd = Path(run_dir)
28+ cfg = RunConfig.from_yaml(rd / "config.yaml")
29+ with open(rd / "manifest.json") as f:
30+ man = json.load(f)
31+ llm_p = rd / "llm_decisions.parquet"
32+ return SavedRun(cfg, pd.read_parquet(rd / "ticks.parquet"), pd.read_parquet(rd / "trades.parquet"), pd.read_parquet(rd / "agents.parquet"),
33+ pd.read_parquet(llm_p) if llm_p.exists() else pd.DataFrame(columns=["t", "agent_id", "provider", "model", "valid"]), man, rd)
34+
35+
36+def recompute_design(design_dir: str | Path, write: bool = True, **thresholds) -> pd.DataFrame:
37+ design_dir = Path(design_dir)
38+ rows = []
39+ for man in sorted(design_dir.glob("*/seed*/manifest.json")):
40+ r = load_run(man.parent)
41+ oc = run_outcomes(r, **thresholds)
42+ oc["run_dir"] = str(man.parent)
43+ rows.append(oc)
44+ df = pd.DataFrame(rows)
45+ if write and not thresholds:
46+ df.to_parquet(design_dir / "outcomes.parquet", index=False)
47+ for r in rows:
48+ with open(Path(r["run_dir"]) / "outcomes.json", "w") as f:
49+ json.dump(r, f, indent=1, default=float)
50+ return df
modified src/market_agents/experiments/config.py +7 −1
@@ -189,13 +189,19 @@ class RunConfig(BaseModel):
189 yaml.safe_dump(self.model_dump(mode="json"), f, sort_keys=False) 189 yaml.safe_dump(self.model_dump(mode="json"), f, sort_keys=False)
190 190
191 191
192+SECTIONS = {"assets", "fundamentals", "news", "exchange", "population", "llm", "endowment", "latency", "output", "treatment"}
193+
194+
192 def deep_update(base: dict, upd: dict) -> dict: 195 def deep_update(base: dict, upd: dict) -> dict:
196+ """Recursive override. Config *sections* (nested models) are merged key by key; *leaf* dictionaries
197+ (provider_mix, mix, activity, models, policy_kwargs, price_assumptions, ...) are REPLACED wholesale, so
198+ `population.llm.provider_mix: {openai: 1.0}` yields exactly {openai: 1.0} and not a mock/openai mixture."""
193 out = dict(base) 199 out = dict(base)
194 for k, v in upd.items(): 200 for k, v in upd.items():
195 if "." in k: # dotted override: population.llm_share=0.25 201 if "." in k: # dotted override: population.llm_share=0.25
196 head, rest = k.split(".", 1) 202 head, rest = k.split(".", 1)
197 out[head] = deep_update(out.get(head, {}) or {}, {rest: v}) 203 out[head] = deep_update(out.get(head, {}) or {}, {rest: v})
198− elif isinstance(v, dict) and isinstance(out.get(k), dict): 204+ elif isinstance(v, dict) and isinstance(out.get(k), dict) and k in SECTIONS:
199 out[k] = deep_update(out[k], v) 205 out[k] = deep_update(out[k], v)
200 else: 206 else:
201 out[k] = v 207 out[k] = v
modified src/market_agents/metrics/outcomes.py +27 −0
@@ -259,6 +259,32 @@ def pairwise_sign_corr(d: pd.DataFrame, window: int = 20) -> float:
259 return float(np.nanmean(vals)) if np.isfinite(vals).any() else np.nan 259 return float(np.nanmean(vals)) if np.isfinite(vals).any() else np.nan
260 260
261 261
262+def flow_corr_by_policy(trades: pd.DataFrame, agents: pd.DataFrame, window: int = 20) -> dict:
263+ """Average pairwise correlation of agents' net signed traded volume per `window` ticks, by policy group
264+ (a classical analogue of llm_pairwise_corr that needs no decision log)."""
265+ if len(trades) < 50:
266+ return {}
267+ t = trades.copy()
268+ t["w"] = (t["time"] // window).astype(int)
269+ buy = t.groupby(["w", "buyer"])["qty"].sum().rename("q").reset_index().rename(columns={"buyer": "agent_id"})
270+ sell = t.groupby(["w", "seller"])["qty"].sum().rename("q").reset_index().rename(columns={"seller": "agent_id"})
271+ sell["q"] = -sell["q"]
272+ flow = pd.concat([buy, sell]).groupby(["w", "agent_id"])["q"].sum().reset_index()
273+ piv = flow.pivot(index="w", columns="agent_id", values="q").fillna(0.0)
274+ pol = agents.set_index("agent_id")["policy"]
275+ out = {}
276+ for name, grp in pol.groupby(pol):
277+ ids = [i for i in grp.index if i in piv.columns]
278+ if len(ids) < 3 or piv.shape[0] < 4:
279+ continue
280+ c = piv[ids].corr().to_numpy()
281+ iu = np.triu_indices(len(ids), 1)
282+ vals = c[iu]
283+ if np.isfinite(vals).any():
284+ out[f"flow_corr_{name}"] = float(np.nanmean(vals))
285+ return out
286+
287+
262 def run_outcomes(res, bubble_thr: float = 0.05, bubble_min_len: int = 10, crash_thr: float = 0.10, crash_window: int = 20) -> dict: 288 def run_outcomes(res, bubble_thr: float = 0.05, bubble_min_len: int = 10, crash_thr: float = 0.10, crash_window: int = 20) -> dict:
263 cfg = res.config 289 cfg = res.config
264 out = {"name": cfg.name, "seed": cfg.seed, "config_hash": cfg.config_hash(), "n_traders": cfg.population.n_traders, 290 out = {"name": cfg.name, "seed": cfg.seed, "config_hash": cfg.config_hash(), "n_traders": cfg.population.n_traders,
@@ -266,4 +292,5 @@ def run_outcomes(res, bubble_thr: float = 0.05, bubble_min_len: int = 10, crash_
266 out.update({k: res.manifest[k] for k in ("llm_share_traders", "llm_share_orders", "llm_share_volume", "n_llm_decisions", "n_trades", "wall_s")}) 292 out.update({k: res.manifest[k] for k in ("llm_share_traders", "llm_share_orders", "llm_share_volume", "n_llm_decisions", "n_trades", "wall_s")})
267 out.update(series_outcomes(res.ticks, cfg.warmup, bubble_thr, bubble_min_len, crash_thr, crash_window, res.manifest.get("shocks"))) 293 out.update(series_outcomes(res.ticks, cfg.warmup, bubble_thr, bubble_min_len, crash_thr, crash_window, res.manifest.get("shocks")))
268 out.update(agent_outcomes(res.agents, res.trades, res.llm, cfg.n_ticks)) 294 out.update(agent_outcomes(res.agents, res.trades, res.llm, cfg.n_ticks))
295+ out.update(flow_corr_by_policy(res.trades, res.agents))
269 return out 296 return out
added tests/unit/test_config_overrides.py +11 −0
@@ -0,0 +1,11 @@
1+from market_agents.experiments.config import RunConfig
2+
3+
4+def test_leaf_dict_overrides_replace_and_sections_merge():
5+ cfg = RunConfig()
6+ t = cfg.with_overrides(**{"population.llm.provider_mix": {"openai": 1.0}, "population.llm_share": 0.25, "exchange.halt_threshold": 0.05})
7+ assert t.population.llm.provider_mix == {"openai": 1.0}
8+ assert t.population.llm_share == 0.25 and t.exchange.halt_threshold == 0.05
9+ assert t.exchange.taker_fee_bps == cfg.exchange.taker_fee_bps # section merge keeps the rest
10+ t2 = cfg.with_overrides(population={"mix": {"market_maker": 1.0}, "activity": {"market_maker": 0.0}})
11+ assert t2.population.mix == {"market_maker": 1.0}
12
Menu

Theme