SPB Git forge

spb/wp13_uqo

Public
3commits 1branches 1releases
1.2 MBsize
maindefault branch
59 min agolast push
TeX 93.9% Python 6%

révision scientifique complète (editorial board, 2026-10-17)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed 59 min ago (Oct 18, 2026) parent f736fcc

24 changed files +2,199 −778

modified README.md +70 −52
@@ -3,21 +3,25 @@
3 3
4 4 **UQO Working Paper No. 13** — *Reasoning-Augmented Tool Orchestration, In-Loop Numerical Computation, and Multi-Format Reporting*
5 5
6 −[![Paper](https://img.shields.io/badge/paper-PDF%20(28%20p.)-b31b1b?logo=latex&logoColor=white)](paper/main.pdf)
6 +[![Paper](https://img.shields.io/badge/paper-PDF%20(41%20p.)-b31b1b?logo=latex&logoColor=white)](paper/main.pdf)
7 7 [![Type](https://img.shields.io/badge/type-system%20%2F%20methodology%20paper-4051b5)](paper/main.tex)
8 8 [![Platform](https://img.shields.io/badge/platform-VQuant%20(spbgit%20vquant.git)-4051b5)](#-data)
9 9 [![Institution](https://img.shields.io/badge/UQO-D%C3%A9pt.%20des%20sciences%20administratives-16365c)](https://uqo.ca)
10 10 [![Author](https://img.shields.io/badge/author-Simon--Pierre%20Boucher-16365c)](mailto:simon-pierre.boucher@uqo.ca)
11 11
12 −> **TL;DR** — VQuant is a production web platform that turns a natural-language request into a
13 −> complete, reproducible quantitative financial report. A reasoning-augmented LLM acts as planner
14 −> and synthesizer; all numerical work is delegated to a deterministic execution substrate: an
15 −> agentic orchestration loop over 200+ tools (265+ market-data endpoints, four web-research
16 −> services, a 17-library Python sandbox), a two-stage context-management algorithm for unbounded
17 −> conversations, a single-call computation paradigm (data → estimation → figures in one sandboxed
18 −> execution), and a unified document pipeline emitting PDF, DOCX, Beamer and spreadsheets with live
19 −> formulas from one Markdown artifact. The paper documents each mechanism as implemented so the
20 −> design can be reproduced.
12 +> **TL;DR** — VQuant is a deployed web platform that turns a natural-language request into a
13 +> quantitative financial report in which every number comes from live data retrieval or auditable
14 +> code rather than from the model. This is a **design-science system description, audited line by
15 +> line against the platform's source code** (spbgit `vquant.git`, commit `e2a148a`, 2026-10-02):
16 +> a recursive, batched, streaming tool-calling loop over **245 schema-defined tools** (two
17 +> market-data providers, 249 typed wrappers over 233 endpoint paths; three web-research services;
18 +> a Python sandbox pre-loading 29 packages), a **three-stage context-management procedure**
19 +> (3,000/15,000-char truncation at execution, 5,000-char re-send cap, adaptive summarisation at
20 +> 10^5 tokens keeping the last 5 messages), a **single-call computation convention**, and a
21 +> document pipeline (PDF via Puppeteer+KaTeX, DOCX via Pandoc, Beamer via a second model call +
22 +> two pdflatex passes, live-formula XLSX). **No empirical evaluation is reported** (no accuracy,
23 +> hallucination, latency or cost measurements); a pre-registered evaluation protocol is specified
24 +> as future work.
21 25
22 26 ---
23 27
@@ -25,55 +29,64 @@
25 29
26 30 | Item | Value |
27 31 |---|---|
28 −| Version | 1.0 (June 2026) |
32 +| Version | **1.1 (October 2026)** — revised 2026-10-17 (editorial-board review; `docs/REVIEW-REPORT.md`, `docs/CHANGELOG-REVISION.md`). v1.0 = June 2026 (`docs/main_pre-revision-20261017.pdf`, 28 p.) |
29 33 | SSRN | not yet submitted |
30 −| Journal | — |
31 −| Code & data | methodology / system paper — no empirical pipeline; the platform's source code lives in the spbgit repository `vquant.git` |
34 +| Journal | not yet submitted; candidate venues *Journal of Financial Data Science*, *Decision Support Systems*, *Expert Systems with Applications* — **only after the evaluation protocol of §6.6 has been executed** |
35 +| Code & data | design/system paper — no empirical pipeline. The platform's source code lives in the spbgit repository `vquant.git`; the paper describes commit `e2a148a` (2026-10-02). The audit script and its outputs are in `docs/verify/` |
32 36
33 37 ## 🎯 What this paper does
34 38
35 39 Large language models are fluent in financial discourse, but fluency does not guarantee
36 40 numerically rigorous, reproducible or citable analysis. This paper describes the **architecture**
37 −of VQuant, a platform that couples a reasoning-augmented LLM with a deterministic execution
38 −substrate, and argues that the resulting design pattern — *the model plans and synthesizes, auditable
39 −code computes* — is reusable beyond finance.
40 −
41 −Four mechanisms are documented at implementation level:
42 −
43 −1. an **agentic orchestration loop** exposing 200+ financial and analytical tools through a
44 − constrained function-calling protocol (recursive tool-calling loop, tool-use/tool-result
45 − invariant, batched-execution throttle);
46 −2. a **context-management algorithm** preserving coherence over effectively unbounded histories
47 − via adaptive summarization under a token budget (two-stage machinery, token-accounting correction);
48 −3. a **single-call computation paradigm** that consolidates data acquisition, estimation and figure
49 − rendering into one sandboxed Python execution (inter-process sandbox that exec's model-authored
50 − code and captures its figures);
51 −4. a **unified document pipeline** emitting PDF, DOCX, LaTeX Beamer decks and spreadsheet workbooks
52 − with live formulas from a single Markdown artifact, streamed through a Server-Sent-Event protocol
53 − with eight-way event dispatch.
54 −
55 −The classical quantitative methods the platform automates are conventional and relegated to the appendix.
41 +of VQuant, a platform that couples a reasoning-capable LLM with a deterministic execution
42 +substrate, under the principle *the model plans and synthesises, auditable code computes*. It is
43 +written as a design-science contribution (Hevner et al. 2004; Gregor & Hevner 2013): a situated
44 +implementation plus a demonstration, with the evaluation step specified but not performed.
45 +
46 +Four mechanisms are documented at implementation level, with their actual constants, and audited
47 +against the code (Appendix E maps every claim to a source file):
48 +
49 +1. an **agentic orchestration loop** over 245 tools (recursive tool-calling, batches of 5 with
50 + 500 ms spacing, tool-use/tool-result pairing, prompt-level routing by request complexity);
51 +2. a **three-stage context-management procedure** (per-result truncation at execution, re-send
52 + cap, adaptive summarisation under a 10^5-token budget) and a **token-accounting correction**
53 + (max of provider count and a local BPE count — an approximation, not an exact count);
54 +3. a **single-call computation convention** (data → estimation → figures in one sandboxed Python
55 + execution; process-isolated child, 90 s timeout, figure sweep at 150 dpi);
56 +4. a **document pipeline** (PDF, DOCX, Beamer, live-formula XLSX from one Markdown artifact).
57 +
58 +The revision corrected several statements of v1.0 that the code audit contradicted: tool count,
59 +tokenizer, reachability of the pre-built numerical routines (only the option pricer is in the
60 +catalogue), the model layer (now multi-provider), and three features (SSO, daily caps,
61 +bring-your-own-keys) that do not exist in any committed version.
56 62
57 63 ## 🏆 Headline results
58 64
59 −| Object | Value |
65 +There are **no empirical results**. The table lists verified design facts (commit `e2a148a`).
66 +
67 +| Object | Value (audited) |
60 68 |---|---|
61 −| Tools exposed to the model | 200+ (265+ market-data endpoints, 4 web-research services, Python sandbox) |
62 −| Scientific libraries in the sandbox | 17 |
63 −| Model round trips per computation | 1 (single-call paradigm) vs. several in a naïve agent |
69 +| Tools exposed to the model | 245 schema-defined tools (17 families, Table 3) |
70 +| Market-data wrappers | 249 typed functions over 233 endpoint paths (FMP) + 8 EODHD tools |
71 +| Web-research tools | 14 (Firecrawl 7, Tavily 5, Exa 2) |
72 +| Sandbox packages attempted at start-up | 29 (platform docs say 17) |
73 +| Loop constants | batches of 5, 500 ms; truncation 3,000/15,000 chars; re-send cap 5,000; τ = 10^5 tokens, k = 5 |
74 +| Model layer | Anthropic reference path (default `claude-fable-5`, adaptive thinking on 5 models, 64,000-token cap, temperature 1); OpenAI-compatible adapter limited to the first 128 tools |
64 75 | Output formats from one artifact | PDF, DOCX, Beamer, XLSX (live formulas) |
65 −| Streaming protocol | SSE, 8 event types |
76 +| Measurements of accuracy, hallucination, latency, cost | none (protocol in §6.6, not executed) |
66 77
67 78 ## 🗂 Repository layout
68 79
69 80 ```
70 81 vquant-llm-quant-platform/
71 −└── paper/ # main.tex + sections/ + figures/ (TikZ diagrams) + tables/ + appendix/ → main.pdf
72 − ├── figures/ # architecture, loop, context, sandbox, streaming, docpipeline (TikZ)
73 − └── tables/ # tools, models, events, robustness
82 +├── paper/ # main.tex + sections/ + figures/ (TikZ diagrams) + tables/ + appendix/ → main.pdf
83 +│ ├── figures/ # architecture, loop, context, sandbox, streaming, docpipeline (TikZ)
84 +│ └── tables/ # tools (generated by docs/verify/audit_vquant_code.py), models, events, robustness (= design rationale)
85 +└── docs/ # REVIEW-REPORT.md, CHANGELOG-REVISION.md, main_pre-revision-20261017.pdf, verify/ (audit script + JSON)
74 86 ```
75 87
76 −No `src/`, `scripts/` or `data/`: the paper has no empirical pipeline.
88 +No `src/`, `scripts/` or `data/`: the paper has no empirical pipeline. `docs/verify/audit_vquant_code.py <clone of vquant.git>`
89 +regenerates `paper/tables/tools.tex` and the code facts used in the text.
77 90
78 91 ## 🚀 Quick start
79 92
@@ -88,10 +101,11 @@ is maintained in the spbgit repository `vquant.git` and deployed on the MacLustr
88 101
89 102 ## 🔬 Methodology
90 103
91 −1. **Architecture description** — components, invariants and protocols are specified as implemented (§3–§4).
92 −2. **Mechanism walkthroughs** — orchestration loop, context management, single-call computation, document pipeline (§4).
93 −3. **Design evaluation** — qualitative robustness discussion of failure modes and mitigations (§6).
94 −4. **Appendix** — the conventional quantitative methods automated by the platform.
104 +1. **Architecture description** — components, data layer, model layer, as implemented at commit `e2a148a` (§3).
105 +2. **Mechanism specification** — transport, recursive loop (Algorithm 1), batching, routing, three-stage context management (Algorithm 2), token correction, single-call convention (§4).
106 +3. **Execution substrate, document pipeline, illustrative walk-through** — no numbers reported (§5).
107 +4. **Design rationale, threats to validity, reproducibility, proposed evaluation protocol (not executed)** — task suite, metrics (incl. unsupported-number rate), ablations, baselines, controls (§6).
108 +5. **Appendix** — prompt structure, persistence schema, numerical closed forms, event types, and the claim-by-claim **audit table against the code**.
95 109
96 110 ## 🖼 Figures & tables inventory
97 111
@@ -104,13 +118,15 @@ is maintained in the spbgit repository `vquant.git` and deployed on the MacLustr
104 118 | `figures/streaming.tex` | SSE event dispatch |
105 119 | `figures/docpipeline.tex` | unified document pipeline |
106 120
107 −Tables (`paper/tables/*.tex`): tool catalogue, models, streaming events, robustness.
121 +Tables (`paper/tables/*.tex`): tool catalogue (generated), model layer, streaming events, design rationale; appendix tables: persisted entities, code audit (longtable).
108 122
109 123 ## ⚠️ Limitations
110 124
111 −- Descriptive system paper: no benchmark against alternative agent frameworks is reported.
112 −- Tool counts and endpoint inventories reflect the platform as of June 2026.
113 −- Reproducibility of the *design* is documented; reproducing the *platform* requires the private `vquant.git` code base and API keys.
125 +- Design-science description only: **no evaluation** (accuracy, hallucination rate, latency, cost, ablations, baselines). The protocol of §6.6 is pre-registered in the text but has not been run.
126 +- Describes one commit (`e2a148a`, 2026-10-02) of a system that keeps changing; counts and constants are facts about that commit.
127 +- Outputs are not strictly reproducible (temperature 1, no seeds, model-authored code); the design is.
128 +- Known defects surfaced by the audit and not yet fixed in the code: no recursion-depth bound; single $3/$15 price schedule for all models; six numerical handlers unreachable (not in the catalogue) while the prompt still advertises two of them; the sandbox is process isolation, not a security boundary.
129 +- Reproducing the *platform* requires the private `vquant.git` code base and API keys.
114 130
115 131 ## 📝 Citation
116 132
@@ -122,7 +138,8 @@ Tables (`paper/tables/*.tex`): tool catalogue, models, streaming events, robustn
122 138 type = {Working Paper},
123 139 number = {13},
124 140 year = {2026},
125 − month = {June}
141 + month = {October},
142 + note = {Version 1.1}
126 143 }
127 144 ```
128 145
@@ -134,6 +151,7 @@ Université du Québec en Outaouais (UQO), Gatineau, QC.
134 151
135 152 ## 🗒 Notes
136 153
154 +- **Revision 2026-10-17 (v1.1)**: full editorial-board review — `docs/REVIEW-REPORT.md` (diagnosis, methodology verdicts, literature, maturity) and `docs/CHANGELOG-REVISION.md` (every corrected statement with its evidence in the code, references added, items not executed). Pre-revision state: git tag `pre-revision-20261017`, `docs/main_pre-revision-20261017.pdf`. Bibliography 20 → 46 entries, all verified (Crossref, arXiv, conference proceedings; one entry flagged as withdrawn by its authors). Sections 5 and 6 were renamed from "Results"/"Performance, Reliability, and Security" to "Execution Substrate … and an Illustrative Walk-Through" and "Design Rationale, Threats to Validity, and a Proposed Evaluation".
137 155 - Numbering: first circulated as “Working Paper No. 10” (June 2026); renumbered **13** on 2026-10-17 because No. 10 is *The Assessment Gap in Quebec* (see `Recherche-UQO/HARMONISATION.md`).
138 −- Cover date normalised from “June 13, 2026” to “June 2026”.
139 −- The VQuant platform code is not in this repository (spbgit `vquant.git`).
156 +- Cover date normalised from “June 13, 2026” to “June 2026” (harmonisation), then “October 2026” (revision).
157 +- The VQuant platform code is not in this repository (spbgit `vquant.git`); `docs/verify/` contains the audit script and its JSON outputs, not the code.
added docs/CHANGELOG-REVISION.md +197 −0
@@ -0,0 +1,197 @@
1 +<!--
2 +Author: Simon-Pierre Boucher
3 +Contact: simon-pierre.boucher@uqo.ca
4 +-->
5 +
6 +# CHANGELOG — Révision scientifique complète (editorial board, 2026-10-17)
7 +
8 +Papier : **WP 13 — VQuant: An Agentic Large Language Model Architecture for Automated Quantitative
9 +Financial Analysis and Document Generation** (`finance/vquant-llm-quant-platform`, dépôt `wp13_uqo.git`).
10 +État de départ figé : tag `pre-revision-20261017`, PDF `docs/main_pre-revision-20261017.pdf` (28 pages, v1.0, June 2026).
11 +État d'arrivée : `paper/main.pdf` (41 pages, v1.1, October 2026). Pas de `main_anon.tex` (papier jamais soumis).
12 +Rapport scientifique : `docs/REVIEW-REPORT.md`.
13 +
14 +Le papier ne contient ni données ni code ; la « réanalyse » possible était l'**audit de la description
15 +contre le code réel** de la plateforme. Il a été fait sur un clone en lecture seule de `gitsrv:srv/git/vquant.git`
16 +(HEAD `e2a148a`, « adopt: état déployé sur M2U64 … », 2026-10-02 ; commits antérieurs `cfe8ef7` et `9215dce`,
17 +2026-08-05). Script versionné : `docs/verify/audit_vquant_code.py` ; sorties : `docs/verify/code_facts.json`,
18 +`docs/verify/tool_families.json` ; table générée : `paper/tables/tools.tex`.
19 +
20 +Convention : **C** = correction (énoncé démontrablement faux), **A** = ajout/renforcement, **E** = éditorial.
21 +
22 +---
23 +
24 +## 1. Corrections majeures (où, avant → après, preuve)
25 +
26 +### C1 — Le papier se présentait comme rapportant des « résultats » et une « robustesse » sans aucune mesure
27 +- **Où** : titres de §5 (« Execution Substrate and Document Generation » dans un fichier `results.tex`) et §6
28 + (« Performance, Reliability, and Security », fichier `robustness.tex`), Table 4 (« Operational characteristics »
29 + avec latences « indicatives »), résumé (« principal innovations »), conclusion.
30 +- **Avant** : Table 4 donnait « sub-second perceived response », « several seconds », « roughly ten seconds »
31 + sans aucune mesure ; §6.1 affirmait que le single-call « removes the dominant source of latency ».
32 +- **Après** : §5 renommée « Execution Substrate, Document Generation, and an Illustrative Walk-Through »
33 + (walk-through = *demonstration* au sens design science, sans chiffre) ; §6 renommée « Design Rationale,
34 + Threats to Validity, and a Proposed Evaluation » ; Table 4 → « Design rationale » (mécanisme, constante
35 + réelle, propriété visée, mesure qui la testerait) ; toutes les latences chiffrées retirées ; §6.6
36 + « A proposed evaluation protocol (not executed) » (suite de tâches, métriques dont le *unsupported-number
37 + rate*, ablations, baselines, contrôles). Le résumé dit explicitement « The paper reports no empirical
38 + evaluation ».
39 +- **Preuve** : absence totale de script, de données ou de journal de mesure dans le dépôt du papier et dans
40 + `vquant.git` (6 suites de tests unitaires seulement).
41 +
42 +### C2 — Comptes d'outils et de bibliothèques
43 +- **Avant** : « more than two hundred tools », « over 265 market-data endpoints, wrapped by roughly 230 typed
44 + functions », « seventeen scientific libraries », « four web-research services », Table 3 avec des « 40+ », « 8+ ».
45 +- **Après** : **245** outils définis par schéma (`toolDefinitions.ts`, noms uniques), **249** fonctions exportées
46 + sur **233** chemins d'endpoint distincts (`fmpService.ts`), **29** paquets tentés à l'import par le sandbox
47 + (`customPythonExecutor.py` ; la doc de la plateforme dit 17), **3** services web exposés en **14** outils
48 + (Firecrawl 7, Tavily 5, Exa 2 ; SerpAPI est intégré côté serveur mais sans définition d'outil). Table 3
49 + régénérée par script avec des comptes exacts par famille (17 familles).
50 +- **Preuve** : `docs/verify/code_facts.json`, `docs/verify/tool_families.json`.
51 +
52 +### C3 — « Exact tokenizer for billing » / le tokenizer piloterait le déclencheur de contexte
53 +- **Avant** (§4.7 et §6.2) : « an exact tokenizer for billing » ; §6.2 : « VQuant estimates token counts locally
54 + with a tokenizer before each call, which both drives the context-management trigger … ».
55 +- **Après** : le comptage local utilise le paquet npm `gpt-tokenizer` (BPE OpenAI), donc une **approximation**
56 + dont le signe d'erreur n'est pas fixé ; il ne couvre que le texte de réponse (pas les tokens de raisonnement) ;
57 + le déclencheur de contexte utilise l'heuristique chars/4, pas le tokenizer. Barème de coût unique 3 $/15 $ par
58 + million pour **tous** les modèles → le grand livre est faux pour tout modèle au prix différent (limite ajoutée).
59 +- **Preuve** : `claudeService.ts` l. 2, 44–47, 112–114, 160–175.
60 +
61 +### C4 — Outils numériques « exposés au modèle »
62 +- **Avant** (§5.2) : « the platform exposes a small set of pre-built numerical tools … a Monte Carlo path simulator,
63 + a closed-form European option pricer, a GARCH(1,1) estimator, and a Value-at-Risk calculator ».
64 +- **Après** : seul `calculate_options_price` est dans le catalogue ; les handlers `run_monte_carlo_simulation`,
65 + `estimate_garch_volatility`, `calculate_var`, `optimize_portfolio`, `analyze_risk_metrics`, `create_plot`
66 + existent dans `routes.ts` (l. 764–1019) mais n'ont **aucune définition d'outil** → injoignables ; le prompt
67 + système cite encore `run_monte_carlo_simulation` et `create_volatility_surface` (`systemPrompt.ts` l. 67, 80).
68 + §5.2 réécrite ; Appendix C précise que ces routines servent de référence pour le protocole d'évaluation.
69 +
70 +### C5 — Couche modèle « Claude only »
71 +- **Avant** (§3.5, Table 1) : « model-agnostic within the Claude family », modèles non nommés.
72 +- **Après** : chemin de référence Anthropic (défaut `claude-fable-5` ; thinking adaptatif pour fable-5,
73 + opus-4-8/4-7/4-6, sonnet-4-6 ; haiku-4-5 sans ; `max_tokens` 64 000 ; température 1) **et** un second
74 + adaptateur OpenAI-compatible (OpenAI + Google) limité aux **128 premiers outils** ; appel Beamer épinglé à
75 + `claude-opus-4-8`. Identifiants Anthropic vérifiés (liste de modèles du fournisseur) ; identifiants
76 + OpenAI/Google reproduits sans audit et signalés comme tels.
77 +- **Preuve** : `client/src/lib/models.ts`, `claudeService.ts` l. 18–21, 84–96, `openaiService.ts` l. 14–16, 60–63,
78 + `beamerSlidesService.ts` l. 236 ; `git show 9215dce` confirme que le multi-fournisseur existait déjà en août 2026.
79 +
80 +### C6 — Authentification, limites, BYOK, schéma de persistance
81 +- **Avant** (§6.3, Appendix B) : « local accounts and third-party single sign-on », « daily limits that differ for
82 + anonymous and authenticated users », « bring-your-own-keys », entité Users avec « optional encrypted custom API
83 + keys », entité « Daily usage ».
84 +- **Après** : aucune de ces fonctions n'existe dans **aucun** commit (`shared/schema.ts`, `schema-sqlite.ts`,
85 + `auth.ts`, grep `daily|apiKey|oauth|google` vide, y compris sur `9215dce`). Réel : comptes locaux
86 + e-mail + mot de passe, code à usage unique par courriel, appareils de confiance, limitation des tentatives,
87 + journal de sécurité ; 12 entités persistées. §6.2 et Appendix B réécrites ; retrait explicite des trois affirmations.
88 +
89 +### C7 — Contexte : troisième étage manquant et constantes
90 +- **Avant** : deux étapes (cap 5 000 chars, puis résumé).
91 +- **Après** : **trois** étapes : (1) troncature à l'exécution 3 000 chars (15 000 pour les 14 outils d'extraction
92 + et le Python) `routes.ts` l. 1860–1885 ; (2) cap de renvoi 5 000 ; (3) résumé si > 10^5 tokens, 5 derniers
93 + messages, entrée ≤ 10 000 chars, `max_tokens` 2 000, température 0,5, repli 500 premiers caractères
94 + (`tokenManagement.ts` l. 64–105). Algorithme 2 réécrit avec ces constantes ; Algorithme 1 intègre
95 + `PrepareContext`, l'événement `status` par lot et la troncature.
96 +
97 +### C8 — Boucle : contenu du tour assistant et absence de borne
98 +- **Ajouté** : le message assistant ne contient que les blocs `tool_use` (ni texte ni blocs de raisonnement),
99 + la récursion n'a pas de profondeur maximale (`routes.ts` l. 420–495). Signalés comme points de durcissement.
100 +
101 +### C9 — Référence Kim–Muhn–Nikolaev (2024)
102 +- **Avant** : citée comme preuve que « LLMs can analyze financial statements at a level competitive with human
103 + analysts ».
104 +- **Après** : l'arXiv 2407.17866 a été **retiré par les auteurs le 2025-02-20** (« inconsistencies in the data and
105 + analyses ») ; l'affirmation est retirée du texte, la référence conservée en note de bas de page avec le statut
106 + de retrait (SSRN 4835311). Preuve : page arXiv consultée le 2026-10-17.
107 +
108 +### C10 — Lopez-Lira & Tang : publié
109 +- **Avant** : arXiv 2304.07619 (2023). **Après** : *Journal of Financial Economics* 184 (2026) 104335,
110 + DOI 10.1016/j.jfineco.2026.104335 (Crossref). Clé `lopezlira2026chatgpt`.
111 +
112 +## 2. Ajouts (A)
113 +
114 +- **A1** Cadrage design science (Hevner et al. 2004 ; Peffers et al. 2007 ; Gregor & Hevner 2013) : §1 « What kind
115 + of paper this is », §2.1, conclusion.
116 +- **A2** Paragraphe « Terminology » (agentic, tool use, reasoning-capable) en §1.
117 +- **A3** Paragraphe « Audit against the code » en §1 + **Appendix E** : table de 33 énoncés → fichier:lignes →
118 + énoncé v1.0 (longtable).
119 +- **A4** §2.3 « Evaluating LLM agents » (AgentBench, Reflexion, WebGPT, LLM-as-a-judge, FinanceBench, FinBen,
120 + survey Chang et al.) ; §2.2 enrichie (PoT, Mialon, Gorilla, ToolLLM, Lost in the Middle, MCP) ; §2.4 enrichie
121 + (Loughran–McDonald, Gentzkow–Kelly–Taddy, Li–Mai–Shen–Yan, Chen–Kelly–Xiu, Hansen–Kazinnik, Li et al. ICAIF,
122 + Fatouros et al., Korinek, Dell).
123 +- **A5** §5.4 « An illustrative walk-through » (flux de contrôle d'une requête, aucun chiffre).
124 +- **A6** §6.4 « Threats to validity » (design vs description), §6.5 « Reproducibility » (température 1 / 0,5,
125 + pas de graine, code écrit par le modèle, dépendance CDN KaTeX et TeX local), §6.6 protocole d'évaluation.
126 +- **A7** Équations numérotées en Appendix C (GBM, d1/d2, GARCH) ; demi-vie explicitée.
127 +- **A8** Figures : compteurs mis à jour (architecture : « 2 providers · 233 endpoints », « 29 packages »,
128 + « 3 services · 14 tools » ; sandbox : « 29 pkgs »).
129 +
130 +## 3. Éditorial (E)
131 +
132 +- Résumé réécrit (« design-science description », « reports no empirical evaluation ») ; mots-clés et JEL (+O33).
133 +- Suppression du vocabulaire promotionnel (« production-grade », « remarkable », « unusually broad », « strategically
134 + engineered », « innovations ») ; « agentic financial intelligence » retiré de la conclusion.
135 +- Orthographe britannique uniformisée (summarise, visualisation…) ; `\path` pour les chemins de fichiers ; tables en
136 + `\footnotesize` avec colonnes `p{}` (0 Overfull > 10 pt ; un Overfull résiduel de 5,8 pt dans l'Appendix B).
137 +- Métadonnées : `\WPversion` 1.0 → 1.1, `\WPdate` June 2026 → October 2026 ; page titre canonique inchangée.
138 +
139 +## 4. Références
140 +
141 +Avant : 20 entrées, aucune avec DOI. Après : **46 entrées**, DOI ou identifiant arXiv/SSRN pour toutes celles qui
142 +en ont. Vérification le 2026-10-17 : Crossref `api.crossref.org/works?query.bibliographic=` (30 requêtes),
143 +API arXiv `export.arxiv.org/api/query?id_list=` (22 identifiants), OpenAlex, pages PMLR / ICLR / TMLR
144 +(mlanthology, proceedings.iclr.cc), page docs Anthropic, spécification MCP, registre npm (gpt-tokenizer).
145 +
146 +| Référence ajoutée | Vérification |
147 +|---|---|
148 +| Hevner, March, Park, Ram 2004 MISQ 28(1) 75–105 | Crossref 10.2307/25148625 |
149 +| Peffers et al. 2007 JMIS 24(3) 45–77 | Crossref 10.2753/MIS0742-1222240302 |
150 +| Gregor & Hevner 2013 MISQ 37(2) 337–355 | Crossref 10.25300/MISQ/2013/37.2.01 |
151 +| Liu et al. 2024 TACL 12 157–173 (Lost in the Middle) | Crossref 10.1162/tacl_a_00638 |
152 +| Ji et al. 2023 ACM CSUR 55(12) | Crossref 10.1145/3571730 |
153 +| Chen, Ma, Wang, Cohen 2023 TMLR (Program of Thoughts) | arXiv 2211.12588 + mlanthology TMLR 2023 |
154 +| Mialon et al. 2023 TMLR (Augmented LMs survey) | arXiv 2302.07842 + mlanthology TMLR 2023 |
155 +| Patil et al. 2024 NeurIPS 37 (Gorilla) | Crossref 10.52202/079017-4020 |
156 +| Qin et al. 2024 ICLR (ToolLLM) | arXiv 2307.16789 + proceedings.iclr.cc 2024 |
157 +| Liu et al. 2024 ICLR (AgentBench) | arXiv 2308.03688 + proceedings.iclr.cc 2024 |
158 +| Shinn et al. 2023 NeurIPS 36 (Reflexion) | Crossref 10.52202/075280-0377 |
159 +| Nakano et al. 2021 arXiv (WebGPT) | arXiv 2112.09332 |
160 +| Wang et al. 2024 Frontiers of Computer Science 18(6) | Crossref 10.1007/s11704-024-40231-1 |
161 +| Anthropic 2026, « Tool use with Claude » (docs) | page consultée (platform.claude.com) |
162 +| Model Context Protocol, spécification 2025-06-18 | page consultée (modelcontextprotocol.io) |
163 +| Zheng et al. 2023 NeurIPS 36 (LLM-as-a-judge) | Crossref 10.52202/075280-2020 |
164 +| Chang et al. 2024 ACM TIST 15(3) | Crossref 10.1145/3641289 |
165 +| Islam et al. 2023 arXiv (FinanceBench) | arXiv 2311.11944 |
166 +| Xie et al. 2024 NeurIPS 37 (FinBen) | OpenAlex / Crossref 10.52202/079017-3033 |
167 +| Loughran & McDonald 2016 JAR 54(4) 1187–1230 | Crossref 10.1111/1475-679X.12123 |
168 +| Gentzkow, Kelly, Taddy 2019 JEL 57(3) 535–574 | Crossref 10.1257/jel.20181020 |
169 +| Li, Mai, Shen, Yan 2021 RFS 34(7) 3265–3315 | Crossref 10.1093/rfs/hhaa079 |
170 +| Li, Wang, Ding, Chen 2023 ICAIF 374–382 | Crossref 10.1145/3604237.3626869 |
171 +| Chen, Kelly, Xiu 2023 (working paper) | titre/auteurs confirmés par la présentation Wharton Jacobs Levy (sept. 2024) et listes de séminaires ; page SSRN inaccessible (403) → pas de numéro SSRN cité |
172 +| Hansen & Kazinnik 2023 SSRN 4399406 | Crossref 10.2139/ssrn.4399406 |
173 +| Fatouros et al. 2025 Neural Computing and Applications 37(30) 24893–24918 | Crossref 10.1007/s00521-024-10613-4 (print 2025-10) |
174 +| Korinek 2023 JEL 61(4) 1281–1317 | Crossref 10.1257/jel.20231736 |
175 +| Dell 2025 JEL 63(1) 5–58 | Crossref 10.1257/jel.20241733 |
176 +
177 +Références existantes corrigées : Vaswani (pages 5998–6008), Wei (DOI), Toolformer (pages 68539–68551, DOI), PAL
178 +(PMLR 202), Lopez-Lira & Tang (JFE 2026, C10), Kim et al. (statut retiré, C9), Black–Scholes, Merton, Engle,
179 +Bollerslev, Glasserman (DOI ajoutés), Anthropic doc (titre/URL actuels). Aucune référence retirée ; aucune non vérifiée.
180 +
181 +## 5. Réanalyses exécutées
182 +
183 +| Analyse | Script / commande | Durée | Sortie |
184 +|---|---|---|---|
185 +| Audit du code (comptes, constantes, handlers injoignables, familles d'outils) | `docs/verify/audit_vquant_code.py /tmp/vquant` | < 5 s | `code_facts.json`, `tool_families.json`, `paper/tables/tools.tex` |
186 +| Vérification de l'historique git de `vquant.git` (3 commits ; multi-fournisseur et EODHD présents dès `9215dce`) | `git log`, `git show 9215dce --stat`, `git show 9215dce:client/src/lib/models.ts` | — | consigné ici |
187 +
188 +## 6. Non modifié / non exécuté (faute de données ou hors périmètre)
189 +
190 +- **Protocole d'évaluation de §6.6** : non exécuté (nécessite des clés API, un instantané de données figé, deux
191 + évaluateurs humains). Décrit comme pré-enregistrement.
192 +- **Corrections du code** (borne de récursion, barème de prix par modèle, réintégration des outils numériques dans le
193 + catalogue, cohérence prompt/catalogue, conteneurisation du sandbox) : relèvent de `vquant.git` (remote-first,
194 + nœud M2U64), **non faites** dans le cadre de la révision du papier ; listées en §7 et en conclusion.
195 +- Identifiants de modèles OpenAI/Google du sélecteur : non audités (hors connaissance vérifiable), signalés comme tels.
196 +- Pas de version anonyme (`main_anon.tex`) : le papier n'a jamais été soumis ; à créer avant soumission selon
197 + `HARMONISATION.md` §7.
added docs/REVIEW-REPORT.md +120 −0
@@ -0,0 +1,120 @@
1 +<!--
2 +Author: Simon-Pierre Boucher
3 +Contact: simon-pierre.boucher@uqo.ca
4 +-->
5 +
6 +# REVIEW REPORT — Editorial board, révision scientifique complète (2026-10-17)
7 +
8 +**Papier** : WP 13 — *VQuant: An Agentic Large Language Model Architecture for Automated Quantitative Financial
9 +Analysis and Document Generation* (v1.0, June 2026 → v1.1, October 2026 ; ex « WP 10 », jamais audité, jamais soumis).
10 +**Board** : systèmes d'information (design science), LLM et agents, finance computationnelle, méthodologie de la
11 +recherche en systèmes.
12 +**Revues de référence** : *Journal of Financial Data Science*, *Decision Support Systems*, *Expert Systems with
13 +Applications*, *ACM TMIS*, *Information Systems Research* ; *JEL* pour la littérature IA-économie.
14 +**Journal des modifications** : `docs/CHANGELOG-REVISION.md`. **Preuves** : `docs/verify/` (script d'audit, JSON),
15 +clone lecture seule de `vquant.git` (commit `e2a148a`).
16 +
17 +---
18 +
19 +## 1. Verdict d'ensemble
20 +
21 +Le manuscrit v1.0 est un **papier système sans évaluation**. Il décrit avec soin et, pour l'essentiel, exactement
22 +une architecture réelle (boucle d'outils récursive en streaming, gestion de contexte, sandbox Python, pipeline
23 +documentaire), mais il présentait cette description sous les étiquettes d'un papier empirique — fichiers
24 +`results.tex`/`robustness.tex`, section « Performance, Reliability, and Security », table de « caractéristiques
25 +opérationnelles » avec des latences non mesurées, résumé parlant d'« innovations » — sans aucune mesure
26 +d'exactitude numérique, de taux d'hallucination, de latence, de coût, d'ablation ni de baseline. Il n'y a rien à
27 +recalculer : il n'y a ni données ni scripts. La seule vérification possible — **confronter la description au
28 +code** — a été faite ligne par ligne et a révélé une dizaine d'écarts, dont trois substantiels : (i) des fonctions
29 +décrites (SSO, plafonds quotidiens, bring-your-own-keys, clés API chiffrées) **n'existent dans aucun commit** ;
30 +(ii) quatre « outils numériques exposés au modèle » n'ont **pas de définition d'outil** et sont donc injoignables
31 +(seul le pricer d'options l'est) ; (iii) la « correction exacte » du comptage de tokens repose sur un tokenizer
32 +OpenAI appliqué à des sorties Claude. La couche modèle décrite comme « Claude only » est multi-fournisseur depuis
33 +au moins août 2026, et une référence centrale de la revue de littérature (Kim–Muhn–Nikolaev 2024) a été retirée par
34 +ses auteurs en février 2025.
35 +
36 +La révision a (1) **requalifié** le papier en contribution de design science (implémentation située +
37 +démonstration, évaluation spécifiée mais non exécutée), avec un résumé qui dit ce qu'il ne contient pas ;
38 +(2) **corrigé** chaque écart avec le code et ajouté une table d'audit (33 énoncés → fichier:lignes) ;
39 +(3) remplacé les « résultats » par une table de **rationale** (mécanisme, constante, propriété visée, mesure qui
40 +la testerait), un **walk-through** sans chiffre, des **menaces à la validité** et une section **reproductibilité**
41 +honnête (température 1, pas de graine, code écrit par le modèle) ; (4) rédigé un **protocole d'évaluation
42 +pré-enregistré** (suite de tâches, métriques dont le taux de nombres non étayés, ablations, baselines, contrôles),
43 +explicitement non exécuté ; (5) vérifié les 20 références et porté la bibliographie à 46 entrées toutes vérifiées.
44 +
45 +**Le papier révisé est honnête et reproductible dans sa description, mais il n'est pas publiable en l'état dans une
46 +revue empirique** : sa valeur scientifique dépend de l'exécution du protocole de §6.6. Voir §7.
47 +
48 +## 2. Diagnostic par section (v1.0 → v1.1)
49 +
50 +| Section | Forces (v1.0) | Faiblesses / erreurs trouvées | Traitement |
51 +|---|---|---|---|
52 +| Titre / résumé | Problème (grounding) bien posé | « production-grade », « innovations », « remarkable » ; aucune mention de l'absence d'évaluation ; comptes faux (200+/265+/17/4) | Résumé réécrit : design science, comptes audités, « reports no empirical evaluation » ; titre et sous-titre conservés |
53 +| Introduction | Division du travail modèle/code claire ; 4 contributions | « Contributions … methodological and architectural rather than empirical » mais le reste du texte parle de résultats ; termes « agentic », « tool use », « reasoning » non définis ; pas de genre déclaré | Paragraphes « What kind of paper this is », « Audit against the code », « Terminology » ; contributions reformulées + protocole comme 5e contribution |
54 +| Related work | Quatre axes pertinents ; classiques présents | 20 réf., 0 DOI ; rien sur l'évaluation des agents, sur la sélection d'outils à grande échelle (Gorilla, ToolLLM), sur les longs contextes, sur le design science ; Kim et al. retiré ; Lopez-Lira & Tang publié depuis | 5 sous-sections, 46 réf. vérifiées ; §2.1 design science ; §2.3 évaluation ; note sur le retrait de Kim et al. |
55 +| Architecture (§3) | Trois tiers, SSE, ORM bien décrits | « Claude family » (faux depuis août 2026) ; second fournisseur EODHD absent ; « four web services » (3 exposés) ; schéma inventé (clés chiffrées, daily usage) ; comptes approximatifs | Tout réaligné sur `e2a148a` ; Table 1 avec identifiants Anthropic vérifiés, adaptateur OpenAI-compatible (cap 128 outils), appel Beamer épinglé |
56 +| Méthodologie (§4) | Description fidèle du parseur SSE, de la récursion, du batching, de la summarisation | Troncature à l'exécution (3 000/15 000) omise ; constantes du résumé (2 000 tokens, T = 0,5, repli 500) non données ; « exact tokenizer » faux ; barème de coût unique non dit ; tour assistant sans texte ni thinking non dit ; pas de borne de récursion ; outils cités dans le prompt mais absents du catalogue | Algorithmes 1–2 réécrits avec les constantes réelles ; §4.7 corrigée ; §4.8 « convention » (appliquée par instruction, pas par code) ; incohérence prompt/catalogue signalée |
57 +| « Results » (§5) | Sandbox et pipeline PDF/Beamer/DOCX exacts | Section nommée comme des résultats ; 17 bibliothèques (29 tentées) ; quatre outils numériques « exposés » (un seul l'est) ; dépendance CDN KaTeX et figures éphémères non dites | Renommée ; §5.2 corrigée ; §5.4 walk-through de contrôle (sans chiffre) |
58 +| « Robustness » (§6) | §6.5 Limitations déjà honnête | Table 4 de latences « indicatives » sans mesure ; §6.2 contredit §4.7 ; §6.3 décrit SSO/limites/BYOK inexistants ; « sandbox » présenté comme sécurité | Renommée ; Table 4 → rationale ; §6.2 authentification réelle ; §6.3 sécurité avec modèle de menace ; §6.4 menaces ; §6.5 reproductibilité ; §6.6 protocole |
59 +| Conclusion | Agenda d'évaluation esquissé | Reprend « innovations », « agentic financial intelligence » | Réécrite : situated implementation + demonstration ; trois corrections de code recommandées ; pattern présenté comme hypothèse |
60 +| Annexes | Structure du prompt, formules classiques | Schéma faux (C6) ; événements client incomplets (15 types émis) ; pas d'équations numérotées | Appendix B corrigée (12 entités) ; D : 15 types ; C : équations (1)–(3) ; **E : table d'audit** |
61 +| Figures (TikZ) | Lisibles, cohérentes | Compteurs périmés (265+, 17, 4) | Mis à jour ; un Overfull de 16 pt corrigé |
62 +
63 +## 3. Méthodologie — verdict motivé (points du §3 du master prompt, adaptés à un papier système)
64 +
65 +| Point | Verdict | Motif / action |
66 +|---|---|---|
67 +| Spécification de l'artefact justifiée | Oui (v1.1) | Chaque décision reliée à une propriété visée et à une mesure (Table 4) ; genre design science déclaré |
68 +| Hypothèses explicites | Oui (v1.1) | Constantes réelles (5/500 ms ; 3 000/15 000/5 000 ; 10^5 ; k = 5 ; 2 000 ; 0,5 ; 64 000 ; T = 1 ; 90 s ; 150 dpi) et leur origine (jugement, pas mesure) |
69 +| Définitions correctes | Oui | « agentic », « tool use », « reasoning-capable » définis ; « convention » vs « mécanisme » distingués |
70 +| Correspondance description ↔ implémentation | **Non en v1.0 → Oui en v1.1** | 33 énoncés tracés (Appendix E) ; 10 corrections |
71 +| Inférence / robustesse | Sans objet | Aucune statistique dans le papier ; aucune n'a été inventée |
72 +| Interprétation vs mécanisme établi | Oui (v1.1) | Toute affirmation de gain (latence, hallucination) reformulée en hypothèse testable |
73 +| Claims causaux / de supériorité | Retirés | « materially reduces latency », « largest latency saving », « eliminates » → hypothèses du protocole |
74 +| Reproductibilité | Partielle, documentée | Design reproductible ; sorties non (T = 1, pas de graine, code généré) ; chaque nombre d'un rapport l'est à partir des entrées persistées |
75 +| Sécurité (spécifique) | Qualifiée | Isolation par processus ≠ frontière de sécurité ; guardrail de prompt sans garantie |
76 +
77 +## 4. Littérature
78 +
79 +- **Vérifiées** : les 20 références initiales (Crossref/arXiv/PMLR) ; corrections de pages/DOI pour 9 d'entre elles ;
80 + Lopez-Lira & Tang passée en JFE 2026 ; Kim et al. marquée retirée.
81 +- **Ajoutées (26)** : design science (3), LLM/agents/contexte (9), évaluation (6), finance-économie (8) — toutes avec
82 + DOI ou identifiant arXiv/SSRN/venue (liste et sources dans le changelog §4).
83 +- **Non ajoutées faute de vérification complète** : aucune ; Chen–Kelly–Xiu citée comme working paper sans numéro SSRN
84 + (page SSRN inaccessible), existence confirmée par la présentation Wharton Jacobs Levy et des listes de séminaires.
85 +- **Retirées** : aucune.
86 +
87 +## 5. Résultats — incohérences trouvées
88 +
89 +Il n'y a pas de résultats empiriques. Incohérences internes de v1.0 corrigées : §6.2 vs §4.7 sur le rôle du
90 +tokenizer ; Appendix D (9 types d'événements « principaux ») vs code (15) ; Table 3 (« 200+ ») vs README de la
91 +plateforme (213) vs code (245) ; §3.5 « Claude family » vs sélecteur à trois fournisseurs ; §5.2 vs catalogue
92 +d'outils ; §6.3/Appendix B vs schéma.
93 +
94 +## 6. Analyses recommandées non exécutées
95 +
96 +1. **Protocole §6.6** (≈ 350 tâches, 3 répétitions, 6 ablations, 4 baselines, instantané de données figé) — le
97 + cœur de ce qui manque. Coût estimé : quelques centaines de dollars d'API et deux évaluateurs humains pour les
98 + 50 rapports.
99 +2. **Rétention d'information après summarisation** (faits plantés en début de session, seuils 5·10^4 / 10^5 / 2·10^5,
100 + k = 3/5/10).
101 +3. **Taux de désobéissance à la convention single-call** et taux d'échec du sandbox par cause.
102 +4. **Audit de facturation** : grand livre vs facture fournisseur sur un mois (le barème unique 3 $/15 $ est faux
103 + pour plusieurs modèles).
104 +5. **Test de pénétration du sandbox** (le processus enfant a les privilèges et le réseau du serveur).
105 +
106 +## 7. Maturité pour publication
107 +
108 +- **État** : description de système honnête, précise et auditée ; aucune preuve empirique. En vocabulaire design
109 + science : *situated implementation* + *demonstration* ; *evaluation* manquante.
110 +- **Revue cible réaliste aujourd'hui** : aucune revue empirique n'acceptera le papier sans §6.6 exécutée. Options :
111 + (a) **exécuter le protocole** puis viser *Decision Support Systems* ou *Expert Systems with Applications* (papier
112 + système + évaluation) ou *Journal of Financial Data Science* (angle finance) ; (b) en l'état, un atelier
113 + « systems/demo » (ICAIF demo track, FinNLP) ou un dépôt comme *working paper* technique.
114 +- **Risques de rejet** : absence d'évaluation (rédhibitoire en revue) ; dépendance à des API propriétaires et à un
115 + code privé (reproductibilité limitée au design) ; contribution perçue comme ingénierie plutôt que comme
116 + connaissance de design (il faudrait au moins formuler des principes de design testables, ce que la Table 4
117 + amorce) ; évolution rapide des modèles (identifiants et constantes datés).
118 +- **Corrections de code à faire avant toute évaluation** (dans `vquant.git`, remote-first) : borne de récursion ;
119 + barème de prix par modèle ; réintégration des outils numériques dans le catalogue ou retrait du prompt ;
120 + vérification au démarrage des dépendances (TeX, CDN KaTeX) ; graine optionnelle pour le Monte Carlo.
added docs/verify/audit_vquant_code.py +97 −0
@@ -0,0 +1,97 @@
1 +#!/usr/bin/env python3
2 +"""Audit of the VQuant description against the platform code (vquant.git, commit e2a148a, 2026-10-02).
3 +
4 +Usage: python3 audit_vquant_code.py /path/to/vquant-clone
5 +Writes: tool_families.json, code_facts.json and ../../paper/tables/tools.tex (generated table).
6 +Run on 2026-10-17 for the editorial-board revision of UQO WP 13.
7 +"""
8 +import re, json, sys, os, collections, pathlib
9 +root = pathlib.Path(sys.argv[1] if len(sys.argv) > 1 else '/tmp/vquant')
10 +here = pathlib.Path(__file__).resolve().parent
11 +paper_tables = here.parent.parent / 'paper' / 'tables'
12 +
13 +src = (root / 'server/services/claude/toolDefinitions.ts').read_text()
14 +names = sorted(set(re.findall(r"name: '([a-zA-Z0-9_]+)'", src)))
15 +rules = [
16 + ('Global market data (EODHD)', r'eodhd'),
17 + ('Fundamentals, valuation and classification', r'(income_statement|balance_sheet|cash_?flow|key_metrics|ratios|financial_(growth|scores|statement)|enterprise_values|owner_earnings|dcf|revenue_|market_capitalization|shares_float|company_profile|company_outlook|key_executives|profile_by_cik|latest_financial_statements|peers|stock_screener|stock_price_change|industry_pe|sector_pe|industry_performance|sector_performance|industry_classification|available_|exchange|sec_company_full_profile)'),
18 + ('SEC filings, transcripts and ownership', r'(sec_filings|8k|cik|company_notes|transcript|form_13f|institutional|mutual_fund_disclosure|holder|positions_summary|beneficial_ownership|crowdfunding|equity_offering|ipo_prospectus|ipo_disclosures|filings_extract)'),
19 + ('Events, calendars and corporate actions', r'(calendar|dividend|split|ipo|earnings_report|mergers_acquisitions|symbol_change|delisted|market_hours|holidays)'),
20 + ('Forex, crypto and commodities', r'(forex|crypto|commodit)'),
21 + ('Web research (Firecrawl, Tavily, Exa)', r'^(firecrawl_|tavily_|web_search_exa|get_contents_exa)'),
22 + ('Insider and congressional trading', r'(insider|congressional|senate|house_)'),
23 + ('Indices, ETFs and funds', r'(constituent|etf_|index_list|sp500|nasdaq|dow_jones|mutualfund)'),
24 + ('Quotes, prices and market movers', r'(quote|historical_price|intraday|gainers|losers|actives|actively_trading|stock_list|batch_|aftermarket)'),
25 + ('Technical indicators', r'^get_(rsi|macd|ema|sma|wma|dema|tema|adx|cci|stochastic|williams_r|standard_deviation)$'),
26 + ('News and press releases', r'(news|press_release|fmp_articles)'),
27 + ('Analysts, ratings and price targets', r'(analyst|price_target|grades|ratings_snapshot|historical_ratings|upgrades_downgrades|earnings_surprises)'),
28 + ('ESG, compensation and alternative data', r'(esg|social_sentiment|employee|executive_comp)'),
29 + ('Economic and macro', r'(treasury|economic|cot_|market_risk_premium)'),
30 + ('Search and identifiers', r'^(search_|get_cik_list)'),
31 + ('Options', r'option'),
32 + ('Advanced analysis', r'^(download_fmp_data|execute_custom_python_analysis|extract_sec_filings)$'),
33 +]
34 +fam = collections.OrderedDict((r[0], []) for r in rules); other = []
35 +for n in names:
36 + for lab, pat in rules:
37 + if re.search(pat, n):
38 + fam[lab].append(n); break
39 + else:
40 + other.append(n)
41 +assert not other, other
42 +assert sum(len(v) for v in fam.values()) == len(names)
43 +
44 +fmp = (root / 'server/services/fmpService.ts').read_text()
45 +fmp_funcs = len(re.findall(r'^export (?:async )?function [a-zA-Z0-9_]+', fmp, re.M))
46 +fmp_paths = len(set(re.findall(r"'/[a-z0-9-]+(?:/[a-z0-9-]+)*'", fmp)))
47 +py = (root / 'server/services/python/customPythonExecutor.py').read_text()
48 +std = {'sys','json','io','base64','traceback','os','re','time','tempfile','contextlib','datetime','warnings','typing','math','collections','functools','itertools','random','string','pathlib','subprocess'}
49 +pk = sorted({m.group(1) for m in re.finditer(r'^\s*(?:import|from)\s+([a-zA-Z_][a-zA-Z0-9_]*)', py, re.M)} - std)
50 +routes = (root / 'server/routes.ts').read_text()
51 +handlers = sorted(set(re.findall(r"toolCall\.name === '([a-zA-Z0-9_]+)'", routes)))
52 +unreachable = sorted(set(handlers) - set(names))
53 +facts = {
54 + 'commit': 'e2a148a (2026-10-02)', 'tools_defined': len(names), 'families': {k: len(v) for k, v in fam.items()},
55 + 'fmp_wrapper_functions': fmp_funcs, 'fmp_distinct_endpoint_paths': fmp_paths,
56 + 'sandbox_packages_preimported': pk, 'sandbox_packages_count': len(pk),
57 + 'handlers_in_routes_not_in_catalogue': unreachable,
58 + 'batch_size': int(re.search(r'MAX_TOOLS_PER_BATCH = (\d+)', routes).group(1)),
59 + 'inter_batch_delay_ms': 500,
60 + 'per_tool_truncation_chars': [3000, 15000], 'resend_cap_chars': 5000, 'token_threshold': 100000,
61 + 'recent_messages_kept': 5, 'summary_input_cap_chars': 10000, 'summary_max_tokens': 2000, 'summary_temperature': 0.5,
62 + 'main_max_tokens': 64000, 'main_temperature': 1, 'sandbox_timeout_s': 90, 'figure_dpi': 150,
63 + 'openai_tool_cap': 128,
64 +}
65 +json.dump({'families': fam, 'total': len(names)}, open(here / 'tool_families.json', 'w'), indent=1)
66 +json.dump(facts, open(here / 'code_facts.json', 'w'), indent=1)
67 +
68 +ex = {
69 + 'Fundamentals, valuation and classification': 'profile, income statement, balance sheet, cash flow, key metrics, DCF, screener',
70 + 'SEC filings, transcripts and ownership': 'filings by form/CIK/symbol, 8-K, call transcripts, 13F, institutional holders',
71 + 'Events, calendars and corporate actions': 'earnings, dividends, splits, IPO calendars, M\\&A, market hours',
72 + 'Forex, crypto and commodities': 'FX and crypto quotes and lists, commodity quotes, batch quotes',
73 + 'Web research (Firecrawl, Tavily, Exa)': 'scrape, crawl, map, extract, agent; search, research; neural search',
74 + 'Insider and congressional trading': 'insider trades and statistics, House and Senate disclosures',
75 + 'Indices, ETFs and funds': 'S\\&P 500 / Nasdaq / Dow constituents, ETF holdings and weightings',
76 + 'Quotes, prices and market movers': 'quote, historical and intraday prices, gainers, losers, actives',
77 + 'Technical indicators': 'RSI, MACD, SMA/EMA/WMA/DEMA/TEMA, ADX, CCI, stochastic, Williams \\%R',
78 + 'News and press releases': 'stock, forex, crypto and general news; press releases',
79 + 'Analysts, ratings and price targets': 'estimates, price targets, grades, ratings, upgrades/downgrades',
80 + 'ESG, compensation and alternative data': 'ESG scores and benchmarks, social sentiment, headcount, executive pay',
81 + 'Global market data (EODHD)': 'symbol search, EOD and intraday bars, fundamentals, news (70+ exchanges)',
82 + 'Economic and macro': 'treasury rates, indicators, economic calendar, COT reports, risk premium',
83 + 'Search and identifiers': 'company, symbol, CUSIP, ISIN and CIK lookup',
84 + 'Options': 'option chain, contract prices, Greeks (EODHD); Black--Scholes pricer',
85 + 'Advanced analysis': 'custom Python execution, bulk data download, SEC filing extraction',
86 +}
87 +rows = sorted(fam.items(), key=lambda kv: -len(kv[1]))
88 +with open(paper_tables / 'tools.tex', 'w') as f:
89 + f.write("% Generated by docs/verify/audit_vquant_code.py from vquant.git commit e2a148a (2026-10-17). Do not edit by hand.\n")
90 + f.write("\\begin{table}[htbp]\n\\centering\n")
91 + f.write("\\caption{Tool catalogue exposed to the model, by family. Counts are exact and were extracted programmatically from the tool-definition module of the audited code (vquant.git, commit e2a148a, 2 October 2026): %d schema-defined tools. The financial families wrap two commercial market-data providers (%d typed wrapper functions over %d distinct endpoint paths of the primary provider, plus the EODHD family); the web-research family wraps three services. Models served through the OpenAI-compatible adapter receive only the first %d tools of the catalogue because of that interface's limit.}\n" % (len(names), fmp_funcs, fmp_paths, facts['openai_tool_cap']))
92 + f.write("\\label{tab:tools}\n\\begin{threeparttable}\n\\small\n\\begin{tabular}{@{}lrl@{}}\n\\toprule\nFamily & Tools & Representative tools \\\\\n\\midrule\n")
93 + for lab, v in rows:
94 + f.write("%s & %d & %s \\\\\n" % (lab, len(v), ex[lab]))
95 + f.write("\\midrule\nTotal & %d & \\\\\n\\bottomrule\n\\end{tabular}\n" % len(names))
96 + f.write("\\begin{tablenotes}[flushleft]\n\\footnotesize\n\\item \\textit{Notes.} Family assignment follows keyword rules on tool names (\\texttt{docs/verify/audit\\_vquant\\_code.py}); a tool belongs to exactly one family. The system prompt (Section~\\ref{subsec:routing}) describes only a subset of these tools explicitly; the full catalogue is transmitted as JSON schemas with every model call. Six server-side handlers for pre-built numerical routines (Monte Carlo, GARCH, VaR, portfolio optimisation, risk metrics, plotting) exist in the route module but are not in the catalogue at the audited commit and are therefore unreachable by the model (Section~\\ref{subsec:numerical}).\n\\end{tablenotes}\n\\end{threeparttable}\n\\end{table}\n")
97 +print(json.dumps(facts, indent=1)[:1500])
added docs/verify/code_facts.json +82 −0
@@ -0,0 +1,82 @@
1 +{
2 + "commit": "e2a148a (2026-10-02)",
3 + "tools_defined": 245,
4 + "families": {
5 + "Global market data (EODHD)": 8,
6 + "Fundamentals, valuation and classification": 56,
7 + "SEC filings, transcripts and ownership": 37,
8 + "Events, calendars and corporate actions": 15,
9 + "Forex, crypto and commodities": 15,
10 + "Web research (Firecrawl, Tavily, Exa)": 14,
11 + "Insider and congressional trading": 14,
12 + "Indices, ETFs and funds": 14,
13 + "Quotes, prices and market movers": 14,
14 + "Technical indicators": 12,
15 + "News and press releases": 9,
16 + "Analysts, ratings and price targets": 11,
17 + "ESG, compensation and alternative data": 9,
18 + "Economic and macro": 6,
19 + "Search and identifiers": 5,
20 + "Options": 4,
21 + "Advanced analysis": 2
22 + },
23 + "fmp_wrapper_functions": 249,
24 + "fmp_distinct_endpoint_paths": 233,
25 + "sandbox_packages_preimported": [
26 + "arch",
27 + "cvxpy",
28 + "docx",
29 + "duckdb",
30 + "hmmlearn",
31 + "lightgbm",
32 + "matplotlib",
33 + "mplfinance",
34 + "networkx",
35 + "numba",
36 + "numpy",
37 + "openpyxl",
38 + "pandas",
39 + "plotly",
40 + "pmdarima",
41 + "polars",
42 + "prophet",
43 + "pypfopt",
44 + "requests",
45 + "riskfolio",
46 + "scipy",
47 + "seaborn",
48 + "sklearn",
49 + "statsmodels",
50 + "sympy",
51 + "ta",
52 + "vectorbt",
53 + "xgboost",
54 + "yfinance"
55 + ],
56 + "sandbox_packages_count": 29,
57 + "handlers_in_routes_not_in_catalogue": [
58 + "analyze_risk_metrics",
59 + "calculate_var",
60 + "create_plot",
61 + "estimate_garch_volatility",
62 + "optimize_portfolio",
63 + "run_monte_carlo_simulation"
64 + ],
65 + "batch_size": 5,
66 + "inter_batch_delay_ms": 500,
67 + "per_tool_truncation_chars": [
68 + 3000,
69 + 15000
70 + ],
71 + "resend_cap_chars": 5000,
72 + "token_threshold": 100000,
73 + "recent_messages_kept": 5,
74 + "summary_input_cap_chars": 10000,
75 + "summary_max_tokens": 2000,
76 + "summary_temperature": 0.5,
77 + "main_max_tokens": 64000,
78 + "main_temperature": 1,
79 + "sandbox_timeout_s": 90,
80 + "figure_dpi": 150,
81 + "openai_tool_cap": 128
82 +}
\ No newline at end of file
added docs/verify/tool_families.json +284 −0
@@ -0,0 +1,284 @@
1 +{
2 + "families": {
3 + "Global market data (EODHD)": [
4 + "get_eodhd_dividends",
5 + "get_eodhd_fundamentals",
6 + "get_eodhd_historical",
7 + "get_eodhd_intraday",
8 + "get_eodhd_news",
9 + "get_eodhd_quote",
10 + "get_eodhd_splits",
11 + "search_eodhd"
12 + ],
13 + "Fundamentals, valuation and classification": [
14 + "get_all_exchange_market_hours",
15 + "get_all_industry_classification",
16 + "get_all_shares_float",
17 + "get_available_countries",
18 + "get_available_exchanges",
19 + "get_available_industries",
20 + "get_available_sectors",
21 + "get_balance_sheet",
22 + "get_balance_sheet_ttm",
23 + "get_batch_exchange_quote",
24 + "get_batch_market_capitalization",
25 + "get_cash_flow",
26 + "get_cashflow_statement_ttm",
27 + "get_company_outlook",
28 + "get_company_profile",
29 + "get_custom_dcf",
30 + "get_custom_levered_dcf",
31 + "get_dcf_valuation",
32 + "get_enterprise_values",
33 + "get_exchange_market_hours",
34 + "get_financial_growth",
35 + "get_financial_ratios",
36 + "get_financial_scores",
37 + "get_financial_statement_symbol_list",
38 + "get_historical_industry_pe",
39 + "get_historical_industry_performance",
40 + "get_historical_market_capitalization",
41 + "get_historical_sector_pe",
42 + "get_historical_sector_performance",
43 + "get_holidays_by_exchange",
44 + "get_income_statement",
45 + "get_income_statement_ttm",
46 + "get_industry_classification_list",
47 + "get_industry_pe_snapshot",
48 + "get_industry_performance_snapshot",
49 + "get_industry_performance_summary",
50 + "get_key_executives",
51 + "get_key_metrics",
52 + "get_key_metrics_ttm",
53 + "get_latest_financial_statements",
54 + "get_levered_dcf",
55 + "get_market_capitalization",
56 + "get_market_sector_performance_snapshot",
57 + "get_owner_earnings",
58 + "get_profile_by_cik",
59 + "get_ratios_ttm",
60 + "get_revenue_geographic_segmentation",
61 + "get_revenue_product_segmentation",
62 + "get_sec_company_full_profile",
63 + "get_sector_pe_snapshot",
64 + "get_shares_float",
65 + "get_stock_peers",
66 + "get_stock_price_change",
67 + "get_stock_screener",
68 + "search_exchange_variants",
69 + "search_industry_classification"
70 + ],
71 + "SEC filings, transcripts and ownership": [
72 + "extract_sec_filings",
73 + "get_acquisition_of_beneficial_ownership",
74 + "get_cik_list",
75 + "get_company_equity_offerings_by_cik",
76 + "get_company_notes",
77 + "get_crowdfunding_by_cik",
78 + "get_earning_call_transcript_dates",
79 + "get_earnings_call_transcript",
80 + "get_earnings_transcript_list",
81 + "get_equity_offering_updates",
82 + "get_filings_extract_with_analytics",
83 + "get_form_13f_filings_dates",
84 + "get_holder_performance_summary",
85 + "get_holders_industry_breakdown",
86 + "get_institutional_holders",
87 + "get_institutional_ownership_filings",
88 + "get_ipo_disclosures",
89 + "get_ipo_prospectus",
90 + "get_latest_8k_sec_filings",
91 + "get_latest_crowdfunding_campaigns",
92 + "get_latest_earning_transcripts",
93 + "get_latest_sec_filings",
94 + "get_mutual_fund_disclosure",
95 + "get_mutual_fund_disclosure_dates",
96 + "get_mutual_fund_disclosure_latest",
97 + "get_mutual_fund_disclosure_search",
98 + "get_positions_summary",
99 + "get_sec_filings",
100 + "get_sec_filings_by_cik",
101 + "get_sec_filings_by_form_type",
102 + "get_sec_filings_by_name",
103 + "get_sec_filings_by_symbol",
104 + "get_sec_filings_company_search_by_cik",
105 + "get_sec_filings_company_search_by_symbol",
106 + "search_by_cik",
107 + "search_crowdfunding_campaigns",
108 + "search_equity_offerings"
109 + ],
110 + "Events, calendars and corporate actions": [
111 + "get_delisted_companies",
112 + "get_dividend_history",
113 + "get_dividends_calendar",
114 + "get_dividends_company",
115 + "get_earnings_calendar",
116 + "get_earnings_report",
117 + "get_economic_calendar",
118 + "get_ipo_calendar",
119 + "get_latest_mergers_acquisitions",
120 + "get_market_hours",
121 + "get_splits",
122 + "get_splits_calendar",
123 + "get_stock_split_history",
124 + "get_symbol_change",
125 + "search_mergers_acquisitions"
126 + ],
127 + "Forex, crypto and commodities": [
128 + "get_batch_commodity_quotes",
129 + "get_batch_crypto_quotes",
130 + "get_batch_forex_quotes",
131 + "get_commodities_list",
132 + "get_commodity_quotes",
133 + "get_crypto_list",
134 + "get_crypto_news",
135 + "get_crypto_quote",
136 + "get_forex_currency_pairs",
137 + "get_forex_historical",
138 + "get_forex_list",
139 + "get_forex_news",
140 + "get_forex_quote",
141 + "search_crypto_news",
142 + "search_forex_news"
143 + ],
144 + "Web research (Firecrawl, Tavily, Exa)": [
145 + "firecrawl_agent",
146 + "firecrawl_batch_scrape",
147 + "firecrawl_crawl",
148 + "firecrawl_extract",
149 + "firecrawl_map",
150 + "firecrawl_scrape",
151 + "firecrawl_search",
152 + "get_contents_exa",
153 + "tavily_crawl",
154 + "tavily_extract",
155 + "tavily_map",
156 + "tavily_research",
157 + "tavily_search",
158 + "web_search_exa"
159 + ],
160 + "Insider and congressional trading": [
161 + "get_all_insider_transaction_types",
162 + "get_congressional_trading",
163 + "get_house_trades_by_name",
164 + "get_house_trades_symbol",
165 + "get_insider_trade_statistics",
166 + "get_insider_trading",
167 + "get_latest_house_disclosures",
168 + "get_latest_insider_trading",
169 + "get_latest_senate_disclosures",
170 + "get_senate_trades_by_name",
171 + "get_senate_trades_symbol",
172 + "get_senate_trading",
173 + "search_insider_trades",
174 + "search_insider_trades_by_name"
175 + ],
176 + "Indices, ETFs and funds": [
177 + "get_batch_etf_quotes",
178 + "get_batch_mutualfund_quotes",
179 + "get_dow_jones_constituent",
180 + "get_etf_asset_exposure",
181 + "get_etf_country_weightings",
182 + "get_etf_holdings",
183 + "get_etf_list",
184 + "get_etf_sector_weightings",
185 + "get_historical_dow_jones_constituent",
186 + "get_historical_nasdaq_constituent",
187 + "get_historical_sp500_constituent",
188 + "get_index_list",
189 + "get_nasdaq_constituent",
190 + "get_sp500_constituent"
191 + ],
192 + "Quotes, prices and market movers": [
193 + "get_actively_trading_list",
194 + "get_actives",
195 + "get_aftermarket_quote",
196 + "get_aftermarket_trade",
197 + "get_batch_index_quotes",
198 + "get_batch_quote",
199 + "get_batch_quote_short",
200 + "get_gainers",
201 + "get_historical_price",
202 + "get_intraday_price",
203 + "get_losers",
204 + "get_quote_short",
205 + "get_stock_list",
206 + "get_stock_quote"
207 + ],
208 + "Technical indicators": [
209 + "get_adx",
210 + "get_cci",
211 + "get_dema",
212 + "get_ema",
213 + "get_macd",
214 + "get_rsi",
215 + "get_sma",
216 + "get_standard_deviation",
217 + "get_stochastic",
218 + "get_tema",
219 + "get_williams_r",
220 + "get_wma"
221 + ],
222 + "News and press releases": [
223 + "get_financial_news",
224 + "get_fmp_articles",
225 + "get_general_news",
226 + "get_press_releases",
227 + "get_press_releases_latest",
228 + "get_stock_news_latest",
229 + "get_stock_news_sentiment",
230 + "search_press_releases_new",
231 + "search_stock_news"
232 + ],
233 + "Analysts, ratings and price targets": [
234 + "get_analyst_estimates",
235 + "get_earnings_surprises",
236 + "get_grades",
237 + "get_grades_summary",
238 + "get_historical_grades",
239 + "get_historical_ratings",
240 + "get_price_target",
241 + "get_price_target_consensus",
242 + "get_price_target_summary",
243 + "get_ratings_snapshot",
244 + "get_upgrades_downgrades"
245 + ],
246 + "ESG, compensation and alternative data": [
247 + "get_employee_count",
248 + "get_esg_benchmark",
249 + "get_esg_disclosures",
250 + "get_esg_ratings",
251 + "get_esg_score",
252 + "get_executive_compensation",
253 + "get_executive_compensation_benchmark",
254 + "get_historical_employee_count",
255 + "get_social_sentiment"
256 + ],
257 + "Economic and macro": [
258 + "get_cot_analysis",
259 + "get_cot_list",
260 + "get_cot_report",
261 + "get_economic_indicator",
262 + "get_market_risk_premium",
263 + "get_treasury_rates"
264 + ],
265 + "Search and identifiers": [
266 + "search_by_cusip",
267 + "search_by_isin",
268 + "search_companies",
269 + "search_name",
270 + "search_symbol"
271 + ],
272 + "Options": [
273 + "calculate_options_price",
274 + "get_option_chain",
275 + "get_option_greeks",
276 + "get_option_prices"
277 + ],
278 + "Advanced analysis": [
279 + "download_fmp_data",
280 + "execute_custom_python_analysis"
281 + ]
282 + },
283 + "total": 245
284 +}
\ No newline at end of file
modified paper/appendix/appendix.tex +145 −61
@@ -5,101 +5,185 @@
5 5 \section{System-Prompt Policy Structure}
6 6 \label{app:prompt}
7 7
8 −The system prompt that governs the agentic loop (Section~\ref{subsec:routing}) is organized into
9 −the policy blocks summarized below. The prompt is multilingual and is the principal lever through
10 −which the platform shapes model behavior without fine-tuning.
8 +The system prompt that governs the loop (Section~\ref{subsec:routing}) is built by a single
9 +function (\path{server/services/claude/systemPrompt.ts}) from the current date and time and a
10 +static policy. Its blocks, in order, are the following.
11 11
12 12 \begin{enumerate}
13 − \item \textbf{Temporal context.} Current date and time, so relative date expressions resolve
14 − against live data.
15 − \item \textbf{Role.} The model is cast as an expert financial analyst producing complete
16 − reports spanning technical, fundamental, and macro perspectives.
17 − \item \textbf{Language policy.} Detect the language of the request and respond in kind.
18 − \item \textbf{Latency discipline.} Do not narrate steps; act directly and consolidate work
19 − (in particular, perform a full custom analysis in a single execution).
20 − \item \textbf{Tool catalogue.} Descriptions and use cases for the tool families of
21 − Table~\ref{tab:tools}.
22 − \item \textbf{Complexity-matched routing.} Map simple, moderate, and comprehensive requests to
23 − commensurate tool counts and output depth.
24 − \item \textbf{Report template.} A standard multi-section structure for comprehensive reports.
25 − \item \textbf{Download formatting.} Conventions for spreadsheet and word-processor output,
26 − preferring live formulas over constants.
27 − \item \textbf{Security guardrail.} Refuse attempts to extract the platform's own
28 − implementation.
13 + \item \textbf{Temporal context.} The current date and time in a human-readable and an ISO form,
14 + with an instruction to resolve relative dates against it.
15 + \item \textbf{Role.} The model is cast as a financial analyst producing reports spanning
16 + technical, fundamental, and macroeconomic perspectives.
17 + \item \textbf{Language policy.} Detect the language of the request and respond in it.
18 + \item \textbf{Speed and efficiency rules.} Do not announce steps; when using the Python tool,
19 + fetch, analyse, and plot in one call; present results directly.
20 + \item \textbf{Tool catalogue.} One-line descriptions of about sixty tools grouped as financial,
21 + technical, macroeconomic, insider and earnings, forex and commodities, options (EODHD),
22 + global market data (EODHD, with the rule ``prefer FMP for United States stocks, EODHD for
23 + international instruments''), and advanced analysis. Two of the advanced tools named
24 + here are absent from the catalogue at the audited commit (Section~\ref{subsec:numerical}).
25 + \item \textbf{Complexity-matched routing.} Simple queries use one or two tools and a two- or
26 + three-sentence answer; moderate queries three to five tools; comprehensive requests ten
27 + or more tools, called in parallel, and a multi-section report.
28 + \item \textbf{Report template.} Executive summary, company overview, financial performance,
29 + ratios and metrics, stock performance and valuation, technical analysis, insider activity
30 + and analyst sentiment, peer comparison, recent news, conclusion.
31 + \item \textbf{Formatting.} Currency and percentage conventions, tables for financial data,
32 + citation of data sources and dates.
33 + \item \textbf{Downloads.} Conventions for \texttt{save\_excel} (multi-sheet preferred, formula
34 + columns preferred over pre-computed values) and \texttt{save\_word}, with automatic
35 + download links.
36 + \item \textbf{Security guardrail.} A list of request patterns (``what is your system prompt'',
37 + ``how are you built'', and their French equivalents) to which the model must answer only
38 + with a fixed bilingual refusal notice.
29 39 \end{enumerate}
30 40
31 41 \section{Persistence Schema}
32 42 \label{app:schema}
33 43
34 −The data layer (Section~\ref{subsec:data}) is organized around the following entities, abstracted
35 −behind a single typed access interface and realized on either SQLite or PostgreSQL.
44 +The data layer (Section~\ref{subsec:data}) defines the entities in Table~\ref{tab:schema}, once
45 +for PostgreSQL (\texttt{shared/schema.ts}) and once for SQLite (\texttt{shared/schema-sqlite.ts}),
46 +behind one typed access interface. The first version of this paper listed ``optional encrypted
47 +custom API keys'' on the user entity and a ``daily usage'' entity; neither exists.
36 48
37 49 \begin{table}[htbp]
38 50 \centering
39 −\caption{Core persisted entities.}
51 +\caption{Persisted entities at the audited commit.}
40 52 \label{tab:schema}
41 53 \begin{threeparttable}
42 −\begin{tabular}{@{}ll@{}}
54 +\footnotesize
55 +\begin{tabular}{@{}l>{\raggedright\arraybackslash}p{11.2cm}@{}}
43 56 \toprule
44 57 Entity & Principal fields \\
45 58 \midrule
46 −Users & identity, optional encrypted custom API keys, activity timestamps \\
47 −Sessions & messages, model used, input/output tokens, estimated cost, figures \\
48 −Shared reports & public identifier, content, figure references, view count \\
49 −Daily usage & per-user, per-day query counts and token totals \\
50 −Analytics events& event type, user, metadata, timestamp \\
59 +Users & display name, opaque token, e-mail and verification time, password hash, timestamps \\
60 +Authentication codes & one-time e-mail codes with purpose and expiry \\
61 +Trusted devices & device identifiers that skip the code on later logins \\
62 +Authentication events & security log (login, failure, code sent, device trusted) \\
63 +Conversation sessions & serialised messages, model, input and output tokens, estimated cost \\
64 +Messages & individual turns with tool results and figure references \\
65 +Shared reports & eight-character public identifier, content, figure references, view count \\
66 +Active users & presence, current query, heartbeat, user agent, address \\
67 +Analytics metrics & aggregated request, failure, user, and response-time counters \\
68 +Request logs & per-request path, status, duration \\
69 +Crawled pages, embeddings & cached web content and vector embeddings for research tools \\
51 70 \bottomrule
52 71 \end{tabular}
53 −\begin{tablenotes}[flushleft]
54 −\footnotesize
55 −\item \textit{Notes.} The schema supports authentication, daily rate limiting, report sharing,
56 −session continuity, and the operational observability discussed in
57 −Section~\ref{subsec:security}.
58 −\end{tablenotes}
59 72 \end{threeparttable}
60 73 \end{table}
61 74
62 75 \section{Embedded Numerical Methods}
63 76 \label{app:numerical}
64 77
65 −For completeness we record the closed forms behind the pre-built numerical tools of
66 −Section~\ref{subsec:numerical}. They are standard; the architectural point is only that each is a
67 −deterministic computation over live data, exposed through the same sandbox contract.
78 +For completeness we record the closed forms behind the pre-built numerical routines of
79 +Section~\ref{subsec:numerical}. They are standard, and at the audited commit only the option
80 +pricer is reachable by the model; the others are available to the server and are the natural
81 +reference implementations for the computation tasks of the evaluation protocol.
68 82
69 83 \paragraph{Monte Carlo.} Prices are simulated under geometric Brownian motion
70 −\citep{glasserman2004monte}, discretized exactly as
71 −$
84 +\citep{glasserman2004monte}, discretised exactly as
85 +\begin{equation}
72 86 S_{t+\Delta t} = S_t \exp\!\big[(\mu - \tfrac{1}{2}\sigma^{2})\Delta t + \sigma\sqrt{\Delta t}\,Z_t\big],
73 −$
74 −with $Z_t \sim \mathcal{N}(0,1)$ and $(\mu,\sigma)$ estimated from historical closes; the default
75 −run generates $10{,}000$ paths over a $252$-day horizon and reports the terminal mean, empirical
76 −confidence intervals, and exceedance probabilities.
87 + \qquad Z_t \sim \mathcal{N}(0,1),
88 + \label{eq:gbm}
89 +\end{equation}
90 +with $(\mu,\sigma)$ estimated from historical log returns; the default run generates $10{,}000$
91 +paths over a $252$-day horizon and reports the terminal mean, empirical quantiles, and exceedance
92 +probabilities. The routine does not fix a random seed (Section~\ref{subsec:repro}).
77 93
78 94 \paragraph{Option pricing.} European options use Black--Scholes--Merton
79 −\citep{black1973pricing,merton1973theory}: with
80 −$d_1 = [\ln(S/K) + (r+\tfrac{1}{2}\sigma^{2})T]/(\sigma\sqrt{T})$ and $d_2 = d_1 - \sigma\sqrt{T}$,
81 −the call price is $C = S\,\Phi(d_1) - Ke^{-rT}\Phi(d_2)$, with the put by parity and the full set
82 −of Greeks ($\Delta,\Gamma,\mathcal{V},\Theta,\rho$) returned analytically.
95 +\citep{black1973pricing,merton1973theory}. With
96 +\begin{equation}
97 + d_1 = \frac{\ln(S/K) + (r+\tfrac{1}{2}\sigma^{2})T}{\sigma\sqrt{T}}, \qquad d_2 = d_1 - \sigma\sqrt{T},
98 + \label{eq:bsm_d}
99 +\end{equation}
100 +the call price is $C = S\,\Phi(d_1) - Ke^{-rT}\Phi(d_2)$, the put follows from put--call parity,
101 +and the Greeks ($\Delta,\Gamma,\mathcal{V},\Theta,\rho$) are returned analytically.
83 102
84 103 \paragraph{Conditional volatility.} A GARCH(1,1) model
85 −\citep{engle1982autoregressive,bollerslev1986generalized} estimates
86 −$h_t = \omega + \alpha\varepsilon_{t-1}^{2} + \beta h_{t-1}$, reporting the parameters,
87 −persistence $\alpha+\beta$, and shock half-life.
104 +\citep{engle1982autoregressive,bollerslev1986generalized},
105 +\begin{equation}
106 + h_t = \omega + \alpha\varepsilon_{t-1}^{2} + \beta h_{t-1},
107 + \label{eq:garch}
108 +\end{equation}
109 +is estimated by maximum likelihood (the \texttt{arch} package), reporting the parameters, the
110 +persistence $\alpha+\beta$, and the shock half-life $\ln(0.5)/\ln(\alpha+\beta)$.
88 111
89 −\paragraph{Value-at-Risk.} VaR \citep{jorion2007value} is computed by historical, parametric
90 −($\mu + \sigma\,\Phi^{-1}(1-\alpha)$), and Monte Carlo methods, with expected shortfall and the
91 −Sharpe, Sortino, and Calmar ratios.
112 +\paragraph{Value-at-Risk.} VaR \citep{jorion2007value} at level $\alpha$ is computed by the
113 +historical method (empirical quantile of returns), the parametric method
114 +$\mu + \sigma\,\Phi^{-1}(1-\alpha)$, and simulation under~\eqref{eq:gbm}, with expected
115 +shortfall and the Sharpe, Sortino, and Calmar ratios.
92 116
93 −\section{Streaming Event Types}
117 +\section{Client-Side Streaming Event Types}
94 118 \label{app:events}
95 119
96 120 The client--server channel (Section~\ref{subsec:frontend}) transmits discrete Server-Sent Events,
97 −each dispatched to a dedicated renderer. The principal types are: incremental \emph{text};
98 −reasoning \emph{thinking} summaries; \emph{tools} announcements that drive the progress indicator;
99 −\emph{tool-result} payloads; \emph{sources} for web research; \emph{Python code} that was
100 −executed; \emph{figure} references as images are produced; specialized result objects with bespoke
101 −visualizations; and a terminal \emph{done} event carrying the session identifier and token usage.
102 −This taxonomy is the client-side counterpart to the provider-event dispatch of
103 −Table~\ref{tab:events}.
121 +each dispatched to a dedicated renderer. The server emits fifteen types at the audited commit:
122 +\emph{text} (incremental answer), \emph{thinking} (reasoning summary), \emph{tools} (the list of
123 +requested calls), \emph{tool\_use}, \emph{tool\_start}, \emph{tool\_complete}, \emph{tool\_error},
124 +and \emph{tool\_result} (per-call progress and payloads), \emph{status} (batch progress),
125 +\emph{sources} (web-research citations), \emph{python\_code} (the code that was executed),
126 +\emph{custom\_python\_figures} and \emph{image} (figure references), \emph{done} (session
127 +identifier and token usage), and \emph{error}. The client additionally handles three
128 +search-progress types. This taxonomy is the client-side counterpart of the provider-event
129 +dispatch of Table~\ref{tab:events}.
130 +
131 +\section{Audit of the Description Against the Code}
132 +\label{app:audit}
133 +
134 +Table~\ref{tab:audit} lists the principal statements of the paper with the file in
135 +\texttt{vquant.git} (commit \texttt{e2a148a}, 2 October 2026) that supports each, and flags the
136 +statements of the first version (v1.0, June 2026) that the audit found to be inaccurate. Counts
137 +were produced by the script \path{docs/verify/audit_vquant_code.py} distributed with the paper.
138 +
139 +\begin{footnotesize}
140 +\begin{longtable}{@{}>{\raggedright\arraybackslash}p{4.9cm}>{\raggedright\arraybackslash}p{6.3cm}>{\raggedright\arraybackslash}p{4.3cm}@{}}
141 +\caption{Claims and their sources in the audited code.}
142 +\label{tab:audit}\\
143 +\toprule
144 +Statement in this paper & Source (file) & v1.0 statement \\
145 +\midrule
146 +\endfirsthead
147 +\toprule
148 +Statement in this paper & Source (file) & v1.0 statement \\
149 +\midrule
150 +\endhead
151 +\bottomrule
152 +\endfoot
153 +245 schema-defined tools & \path{server/services/claude/toolDefinitions.ts} & ``more than two hundred'' \\
154 +249 wrapper functions, 233 endpoint paths & \path{server/services/fmpService.ts} & ``265+ endpoints, roughly 230 functions'' \\
155 +Second provider (EODHD), 8 tools & \path{server/services/eodhdService.ts} & not mentioned \\
156 +Three web services, 14 tools & \path{toolDefinitions.ts}; \texttt{firecrawlService}, \texttt{tavilyService}, \texttt{exaService} & ``four services'' (SerpAPI has no tool) \\
157 +Raw HTTP to provider, no SDK & \path{server/services/claudeService.ts} l.~14--15 & same \\
158 +Buffer, split, keep partial line & \path{claudeService.ts} l.~118--125 & same \\
159 +Eight provider event cases & \path{claudeService.ts} l.~133--210 & same \\
160 +Adaptive thinking list; \texttt{display: summarized} & \path{claudeService.ts} l.~19, 90 & same (models unnamed) \\
161 +\texttt{max\_tokens} 64{,}000; temperature 1 & \path{claudeService.ts} l.~88--89 & cap stated; temperature not \\
162 +Default model \texttt{claude-fable-5} & \path{claudeService.ts} l.~18; \path{client/src/lib/models.ts} & ``Claude family'' only \\
163 +OpenAI-compatible adapter, 128-tool cap & \path{server/services/openaiService.ts} l.~14--16, 60--63 & not mentioned \\
164 +Recursion; assistant turn has tool-use blocks only & \path{server/routes.ts} l.~420--495 & recursion stated; block content not \\
165 +Batches of 5; 500 ms between batches & \path{routes.ts} l.~470, 1933 & same \\
166 +\texttt{status} event per batch & \path{routes.ts} l.~499--504 & ``progress event'' \\
167 +Per-result truncation 3{,}000 / 15{,}000 & \path{routes.ts} l.~1860--1885 & not mentioned \\
168 +Re-send cap 5{,}000; threshold $10^{5}$; last 5 messages & \path{claudeService.ts} l.~41--66 & same \\
169 +Estimate $\lceil$chars/4$\rceil$ & \path{server/services/claude/tokenManagement.ts} l.~10--12 & same \\
170 +Summary: 2{,}000 tokens, temperature 0.5, 10{,}000-char input, 500-char fallback & \path{tokenManagement.ts} l.~64--105 & ``low temperature, tight cap'' \\
171 +Local count with \texttt{gpt-tokenizer}; max rule & \path{claudeService.ts} l.~2, 160--175 & ``exact tokenizer'' (incorrect) \\
172 +Fixed \$3 / \$15 schedule for all models & \path{claudeService.ts} l.~112--114 & ``linear schedule'' (model dependence not stated) \\
173 +Tokenizer does not drive the context trigger & \path{claudeService.ts} l.~44 & \S6.2 said it did (incorrect) \\
174 +Child process, stdin JSON, 90 s timeout, unbuffered & \path{server/services/python/var.ts} l.~1285--1300 & same \\
175 +29 packages attempted; \texttt{exec}; \texttt{main()} & \path{server/services/python/customPythonExecutor.py} l.~17--360, 946--980 & ``seventeen libraries'' \\
176 +Figure sweep, PNG 150 dpi, base64 & \path{customPythonExecutor.py} l.~1018--1035 & same \\
177 +Only the option pricer is in the catalogue & \path{toolDefinitions.ts} vs.\ \path{routes.ts} l.~764--1019 & four routines ``exposed'' (incorrect) \\
178 +Prompt names Monte Carlo and surface tools & \path{server/services/claude/systemPrompt.ts} l.~67, 80 & not mentioned \\
179 +Protect--parse--restore; Puppeteer; KaTeX; wait & \path{server/services/pdfService.ts} l.~71--107, 298--317 & same \\
180 +Pandoc for DOCX & \path{pdfService.ts} l.~383 & ``document converter'' \\
181 +Beamer: second call pinned to \texttt{claude-opus-4-8}; two \texttt{pdflatex} passes & \path{server/services/beamerSlidesService.ts} l.~236, 496--540 & model not stated \\
182 +Share identifier of 8 characters; figures ephemeral & \path{server/routes/reports.ts} l.~45--70 & same, without the caveat \\
183 +Twelve persisted entities; no API keys, no daily usage & \path{shared/schema.ts}, \path{shared/schema-sqlite.ts} & five entities incl.\ keys and daily usage (incorrect) \\
184 +E-mail code login, trusted devices, rate limiting & \path{server/services/auth.ts} & ``SSO'', ``daily limits'', ``BYOK'' (not in code) \\
185 +Six test suites & \path{*.test.ts(x)} & not mentioned \\
186 +\end{longtable}
187 +\end{footnotesize}
104 188
105 189 \end{appendices}
modified paper/figures/architecture.tex +3 −3
@@ -17,11 +17,11 @@
17 17
18 18 % ---- Executor row ----
19 19 \node[vqblue, below left=1.15cm and -0.2cm of loop, minimum width=2.7cm] (fin)
20 − {\textbf{Financial tools}\\[1pt]\vqsmall 265+ endpoints};
20 + {\textbf{Financial tools}\\[1pt]\vqsmall 2 providers $\cdot$ 233 endpoints};
21 21 \node[vqblue, below=1.15cm of loop, minimum width=2.7cm] (py)
22 − {\textbf{Python sandbox}\\[1pt]\vqsmall 17 libraries};
22 + {\textbf{Python sandbox}\\[1pt]\vqsmall 29 packages};
23 23 \node[vqblue, below right=1.15cm and -0.2cm of loop, minimum width=2.7cm] (web)
24 − {\textbf{Web research}\\[1pt]\vqsmall 4 services};
24 + {\textbf{Web research}\\[1pt]\vqsmall 3 services $\cdot$ 14 tools};
25 25
26 26 % ---- External tier ----
27 27 \node[vqpurple, below=of fin, minimum width=2.7cm] (fmp)
modified paper/figures/sandbox.tex +1 −1
@@ -9,7 +9,7 @@
9 9
10 10 % ---- Child inner stages ----
11 11 \node[vqgreen, text width=4.5cm] (ns) at (8.0,2.05)
12 − {\textbf{Build namespace}\\\vqsmall 17 libs $\cdot$ \texttt{save\_excel}/\texttt{save\_word} $\cdot$ \texttt{fmp} client $\cdot$ context vars};
12 + {\textbf{Build namespace}\\\vqsmall 29 pkgs $\cdot$ \texttt{save\_excel}/\texttt{save\_word} $\cdot$ \texttt{fmp} client $\cdot$ context vars};
13 13 \node[vqorange, text width=4.5cm] (ex) at (8.0,0.35)
14 14 {\textbf{\texttt{exec(code, ns)}}\\\vqsmall \texttt{stdout}/\texttt{stderr} $\to$ string buffers $\cdot$ optional \texttt{main()}};
15 15 \node[vqpurple, text width=4.5cm] (cap) at (8.0,-1.35)
modified paper/figures/streaming.tex +1 −1
@@ -19,7 +19,7 @@
19 19 \node[vqorange, text width=3.0cm] (tool) at (11.0,-0.65)
20 20 {\textbf{Tool assembler}\\\vqsmall \texttt{start} $\cdot$ \texttt{input\_json\_delta}$^\ast$ $\cdot$ \texttt{stop} $\to$ args};
21 21 \node[vqred, text width=3.0cm] (tok) at (11.0,-2.35)
22 − {\textbf{Token ledger}\\\vqsmall \texttt{message\_start/delta/stop} $\to$ usage};
22 + {\textbf{Token ledger}\\\vqsmall \texttt{message\_start/}\allowbreak\texttt{delta/}\allowbreak\texttt{stop} $\to$ usage};
23 23
24 24 % Backbone arrows
25 25 \draw[vqflow] (prov) -- node[vqtag, above]{raw bytes} (buf);
modified paper/main.pdf +0 −0

Binary file not shown.

modified paper/main.tex +26 −30
@@ -47,6 +47,7 @@
47 47
48 48 % --- Tables ---
49 49 \usepackage{booktabs}
50 +\usepackage{array}
50 51 \usepackage{tabularx}
51 52 \usepackage{multirow}
52 53 \usepackage{threeparttable}
@@ -108,6 +109,7 @@
108 109 % --- Misc ---
109 110 \usepackage{enumitem}
110 111 \setlist{nosep,leftmargin=*}
112 +\usepackage{longtable}
111 113
112 114 % --- Custom colors (VQuant palette) ---
113 115 \definecolor{VQTeal}{HTML}{119993}
@@ -155,38 +157,32 @@
155 157 \newcommand{\WPnumber}{13}
156 158 \newcommand{\WPtitle}{VQuant: An Agentic Large Language Model Architecture for Automated Quantitative Financial Analysis and Document Generation}
157 159 \newcommand{\WPsubtitle}{Reasoning-Augmented Tool Orchestration, In-Loop Numerical Computation, and Multi-Format Reporting}
158 −\newcommand{\WPdate}{June 2026}
159 −\newcommand{\WPversion}{1.0}
160 +\newcommand{\WPdate}{October 2026}
161 +\newcommand{\WPversion}{1.1}
160 162 \newcommand{\WPabstract}{%
161 − Large language models (LLMs) have shown remarkable fluency in financial discourse, yet
162 − conversational fluency alone does not guarantee numerically rigorous, reproducible, or
163 − citable analysis. This paper presents \textbf{VQuant}, a production-grade web platform that
164 − couples a reasoning-augmented LLM with a deterministic execution substrate to transform a
165 − natural-language request into a complete quantitative financial report. We document the
166 − system's methodology and its principal innovations: (i)~an \emph{agentic orchestration loop}
167 − that exposes more than two hundred financial and analytical tools---spanning over 265
168 − market-data endpoints, four web-research services, and an arbitrary-code Python sandbox of
169 − seventeen scientific libraries---to the model through a constrained function-calling protocol;
170 − (ii)~a \emph{context-management algorithm} that preserves conversational coherence over
171 − effectively unbounded histories via adaptive summarization under a token budget;
172 − (iii)~a \emph{single-call computation paradigm} that consolidates data acquisition, numerical
173 − estimation, and figure rendering into one sandboxed Python execution, collapsing what would
174 − otherwise be several model round trips into one; and (iv)~a \emph{unified document pipeline}
175 − that emits publication-ready PDF, DOCX, \LaTeX{}~Beamer slide decks, and spreadsheet workbooks
176 − with live formulas from a single Markdown artifact. We describe each mechanism as it is
177 − implemented---the streaming Server-Sent-Event protocol and its eight-way event dispatch, the
178 − recursive tool-calling loop and its tool-use/tool-result invariant, the batched-execution
179 − throttle, the two-stage context-management machinery, the token-accounting correction, and the
180 − inter-process sandbox that exec's model-authored code and captures its figures---so that the
181 − design can be reproduced. The classical quantitative methods the platform automates are
182 − conventional and relegated to an appendix; our contribution is the \emph{architecture} that
183 − makes them accessible through natural language while preserving reproducibility. We argue that
184 − VQuant illustrates a reusable design pattern in which the language model is positioned as a
185 − planner and synthesizer rather than as a calculator, with all numerical work delegated to
186 − auditable, deterministic code.
163 + Large language models (LLMs) write fluently about finance, but fluency does not make a number
164 + correct, current, or reproducible. This paper is a design-science description of \textbf{VQuant},
165 + a deployed web platform that couples a reasoning-capable LLM with a deterministic execution
166 + substrate so that a natural-language request (``analyse NVDA's fundamentals and run a Monte Carlo
167 + simulation'') is turned into a report in which every figure is produced by live data retrieval or
168 + auditable code rather than by the model. We document four mechanisms as they are implemented and
169 + audit the description line by line against the platform's source code (vquant.git, commit
170 + e2a148a): (i)~an agentic orchestration loop that exposes 245 schema-defined tools---wrapping two
171 + market-data providers (249 typed functions over 233 endpoint paths), three web-research services,
172 + and a Python sandbox pre-loading 29 scientific packages---through a recursive, batched,
173 + streaming tool-calling protocol; (ii)~a three-stage context-management procedure (per-result
174 + truncation at execution, a re-send cap, and adaptive summarisation under a token budget) that
175 + keeps long sessions within the model's window; (iii)~a single-call computation convention that
176 + consolidates data acquisition, estimation, and figure rendering into one sandboxed execution; and
177 + (iv)~a document pipeline that renders one Markdown artifact into PDF, DOCX, \LaTeX{} Beamer, and
178 + spreadsheets with live formulas. The paper reports no empirical evaluation: it contains no
179 + measurements of numerical accuracy, hallucination rates, latency, or cost, and makes no comparative
180 + claims. Its contribution is a reproducible specification of the architecture, an honest account of
181 + where the implementation departs from its own documentation, and a pre-registered evaluation
182 + protocol---benchmark, metrics, ablations, and baselines---that has not yet been executed.
187 183 }
188 −\newcommand{\WPkeywords}{Large language models, agentic systems, tool use, quantitative finance, automated reporting, retrieval-augmented generation, financial NLP}
189 −\newcommand{\WPjel}{C45, C63, C88, G17}
184 +\newcommand{\WPkeywords}{large language models, LLM agents, tool use, design science, quantitative finance, automated report generation, reproducibility}
185 +\newcommand{\WPjel}{C45, C63, C88, G17, O33}
190 186
191 187 % --- Author ---
192 188 \newcommand{\WPauthor}{Simon-Pierre Boucher}
modified paper/references.bib +330 −31
@@ -1,7 +1,42 @@
1 1 % ============================================================================
2 −% References — BibTeX Database
2 +% References — UQO WP 13 (VQuant). All entries verified on 2026-10-17
3 +% (Crossref, arXiv API, publisher or conference pages); see docs/CHANGELOG-REVISION.md.
3 4 % ============================================================================
4 5
6 +% --- Design science ---
7 +@article{hevner2004design,
8 + author = {Hevner, Alan R. and March, Salvatore T. and Park, Jinsoo and Ram, Sudha},
9 + title = {Design Science in Information Systems Research},
10 + journal = {MIS Quarterly},
11 + volume = {28},
12 + number = {1},
13 + pages = {75--105},
14 + year = {2004},
15 + doi = {10.2307/25148625}
16 +}
17 +
18 +@article{peffers2007design,
19 + author = {Peffers, Ken and Tuunanen, Tuure and Rothenberger, Marcus A. and Chatterjee, Samir},
20 + title = {A Design Science Research Methodology for Information Systems Research},
21 + journal = {Journal of Management Information Systems},
22 + volume = {24},
23 + number = {3},
24 + pages = {45--77},
25 + year = {2007},
26 + doi = {10.2753/MIS0742-1222240302}
27 +}
28 +
29 +@article{gregor2013positioning,
30 + author = {Gregor, Shirley and Hevner, Alan R.},
31 + title = {Positioning and Presenting Design Science Research for Maximum Impact},
32 + journal = {MIS Quarterly},
33 + volume = {37},
34 + number = {2},
35 + pages = {337--355},
36 + year = {2013},
37 + doi = {10.25300/MISQ/2013/37.2.01}
38 +}
39 +
5 40 % --- Language models and reasoning ---
6 41 @inproceedings{vaswani2017attention,
7 42 author = {Vaswani, Ashish and Shazeer, Noam and Parmar, Niki and Uszkoreit, Jakob and
@@ -9,11 +44,14 @@
9 44 title = {Attention Is All You Need},
10 45 booktitle = {Advances in Neural Information Processing Systems},
11 46 volume = {30},
47 + pages = {5998--6008},
12 48 year = {2017}
13 49 }
14 50
15 51 @inproceedings{brown2020language,
16 − author = {Brown, Tom B. and Mann, Benjamin and Ryder, Nick and Subbiah, Melanie and others},
52 + author = {Brown, Tom B. and Mann, Benjamin and Ryder, Nick and Subbiah, Melanie and Kaplan, Jared and
53 + Dhariwal, Prafulla and Neelakantan, Arvind and Shyam, Pranav and Sastry, Girish and
54 + Askell, Amanda and others},
17 55 title = {Language Models Are Few-Shot Learners},
18 56 booktitle = {Advances in Neural Information Processing Systems},
19 57 volume = {33},
@@ -28,14 +66,31 @@
28 66 booktitle = {Advances in Neural Information Processing Systems},
29 67 volume = {35},
30 68 pages = {24824--24837},
31 − year = {2022}
69 + year = {2022},
70 + doi = {10.52202/068431-1800}
32 71 }
33 72
34 −@article{bommasani2021opportunities,
35 − author = {Bommasani, Rishi and Hudson, Drew A. and Adeli, Ehsan and Altman, Russ and others},
36 − title = {On the Opportunities and Risks of Foundation Models},
37 − journal = {arXiv preprint arXiv:2108.07258},
38 − year = {2021}
73 +@article{liu2024lost,
74 + author = {Liu, Nelson F. and Lin, Kevin and Hewitt, John and Paranjape, Ashwin and
75 + Bevilacqua, Michele and Petroni, Fabio and Liang, Percy},
76 + title = {Lost in the Middle: How Language Models Use Long Contexts},
77 + journal = {Transactions of the Association for Computational Linguistics},
78 + volume = {12},
79 + pages = {157--173},
80 + year = {2024},
81 + doi = {10.1162/tacl_a_00638}
82 +}
83 +
84 +@article{ji2023hallucination,
85 + author = {Ji, Ziwei and Lee, Nayeon and Frieske, Rita and Yu, Tiezheng and Su, Dan and Xu, Yan and
86 + Ishii, Etsuko and Bang, Ye Jin and Madotto, Andrea and Fung, Pascale},
87 + title = {Survey of Hallucination in Natural Language Generation},
88 + journal = {ACM Computing Surveys},
89 + volume = {55},
90 + number = {12},
91 + pages = {1--38},
92 + year = {2023},
93 + doi = {10.1145/3571730}
39 94 }
40 95
41 96 % --- Tool use and agents ---
@@ -46,7 +101,9 @@
46 101 title = {Toolformer: Language Models Can Teach Themselves to Use Tools},
47 102 booktitle = {Advances in Neural Information Processing Systems},
48 103 volume = {36},
49 − year = {2023}
104 + pages = {68539--68551},
105 + year = {2023},
106 + doi = {10.52202/075280-2997}
50 107 }
51 108
52 109 @inproceedings{yao2023react,
@@ -54,23 +111,166 @@
54 111 Narasimhan, Karthik and Cao, Yuan},
55 112 title = {{ReAct}: Synergizing Reasoning and Acting in Language Models},
56 113 booktitle = {International Conference on Learning Representations (ICLR)},
57 − year = {2023}
114 + year = {2023},
115 + note = {arXiv:2210.03629}
58 116 }
59 117
60 118 @inproceedings{gao2023pal,
61 119 author = {Gao, Luyu and Madaan, Aman and Zhou, Shuyan and Alon, Uri and Liu, Pengfei and
62 120 Yang, Yiming and Callan, Jamie and Neubig, Graham},
63 121 title = {{PAL}: Program-Aided Language Models},
64 − booktitle = {International Conference on Machine Learning (ICML)},
122 + booktitle = {Proceedings of the 40th International Conference on Machine Learning},
123 + series = {Proceedings of Machine Learning Research},
124 + volume = {202},
65 125 pages = {10764--10799},
66 126 year = {2023}
67 127 }
68 128
69 −@misc{anthropic2024tooluse,
129 +@article{chen2023pot,
130 + author = {Chen, Wenhu and Ma, Xueguang and Wang, Xinyi and Cohen, William W.},
131 + title = {Program of Thoughts Prompting: Disentangling Computation from Reasoning for Numerical Reasoning Tasks},
132 + journal = {Transactions on Machine Learning Research},
133 + year = {2023},
134 + note = {arXiv:2211.12588}
135 +}
136 +
137 +@article{mialon2023augmented,
138 + author = {Mialon, Gr{\'e}goire and Dess{\`i}, Roberto and Lomeli, Maria and Nalmpantis, Christoforos and
139 + Pasunuru, Ram and Raileanu, Roberta and Rozi{\`e}re, Baptiste and Schick, Timo and
140 + Dwivedi-Yu, Jane and Celikyilmaz, Asli and Grave, Edouard and LeCun, Yann and Scialom, Thomas},
141 + title = {Augmented Language Models: A Survey},
142 + journal = {Transactions on Machine Learning Research},
143 + year = {2023},
144 + note = {arXiv:2302.07842}
145 +}
146 +
147 +@inproceedings{patil2024gorilla,
148 + author = {Patil, Shishir G. and Zhang, Tianjun and Wang, Xin and Gonzalez, Joseph E.},
149 + title = {Gorilla: Large Language Model Connected with Massive {APIs}},
150 + booktitle = {Advances in Neural Information Processing Systems},
151 + volume = {37},
152 + pages = {126544--126565},
153 + year = {2024},
154 + doi = {10.52202/079017-4020}
155 +}
156 +
157 +@inproceedings{qin2024toolllm,
158 + author = {Qin, Yujia and Liang, Shihao and Ye, Yining and Zhu, Kunlun and Yan, Lan and Lu, Yaxi and
159 + Lin, Yankai and Cong, Xin and Tang, Xiangru and Qian, Bill and Zhao, Sihan and Hong, Lauren and
160 + Tian, Runchu and Xie, Ruobing and Zhou, Jie and Gerstein, Mark and Li, Dahai and Liu, Zhiyuan and
161 + Sun, Maosong},
162 + title = {{ToolLLM}: Facilitating Large Language Models to Master 16000+ Real-World {APIs}},
163 + booktitle = {International Conference on Learning Representations (ICLR)},
164 + year = {2024},
165 + note = {arXiv:2307.16789}
166 +}
167 +
168 +@inproceedings{liu2024agentbench,
169 + author = {Liu, Xiao and Yu, Hao and Zhang, Hanchen and Xu, Yifan and Lei, Xuanyu and Lai, Hanyu and
170 + Gu, Yu and Ding, Hangliang and Men, Kaiwen and Yang, Kejuan and Zhang, Shudan and Deng, Xiang and
171 + Zeng, Aohan and Du, Zhengxiao and Zhang, Chenhui and Shen, Sheng and Zhang, Tianjun and
172 + Su, Yu and Sun, Huan and Huang, Minlie and Dong, Yuxiao and Tang, Jie},
173 + title = {{AgentBench}: Evaluating {LLMs} as Agents},
174 + booktitle = {International Conference on Learning Representations (ICLR)},
175 + year = {2024},
176 + note = {arXiv:2308.03688}
177 +}
178 +
179 +@inproceedings{shinn2023reflexion,
180 + author = {Shinn, Noah and Cassano, Federico and Gopinath, Ashwin and Narasimhan, Karthik and Yao, Shunyu},
181 + title = {Reflexion: Language Agents with Verbal Reinforcement Learning},
182 + booktitle = {Advances in Neural Information Processing Systems},
183 + volume = {36},
184 + pages = {8634--8652},
185 + year = {2023},
186 + doi = {10.52202/075280-0377}
187 +}
188 +
189 +@article{nakano2021webgpt,
190 + author = {Nakano, Reiichiro and Hilton, Jacob and Balaji, Suchir and Wu, Jeff and Ouyang, Long and
191 + Kim, Christina and Hesse, Christopher and Jain, Shantanu and Kosaraju, Vineet and
192 + Saunders, William and Jiang, Xu and Cobbe, Karl and Eloundou, Tyna and Krueger, Gretchen and
193 + Button, Kevin and Knight, Matthew and Chess, Benjamin and Schulman, John},
194 + title = {{WebGPT}: Browser-Assisted Question-Answering with Human Feedback},
195 + journal = {arXiv preprint arXiv:2112.09332},
196 + year = {2021}
197 +}
198 +
199 +@article{wang2024agents,
200 + author = {Wang, Lei and Ma, Chen and Feng, Xueyang and Zhang, Zeyu and Yang, Hao and Zhang, Jingsen and
201 + Chen, Zhiyuan and Tang, Jiakai and Chen, Xu and Lin, Yankai and Zhao, Wayne Xin and
202 + Wei, Zhewei and Wen, Ji-Rong},
203 + title = {A Survey on Large Language Model Based Autonomous Agents},
204 + journal = {Frontiers of Computer Science},
205 + volume = {18},
206 + number = {6},
207 + pages = {186345},
208 + year = {2024},
209 + doi = {10.1007/s11704-024-40231-1}
210 +}
211 +
212 +@misc{anthropic2026tooluse,
70 213 author = {{Anthropic}},
71 − title = {Tool Use (Function Calling) with the {Claude} {API}},
72 − howpublished = {Anthropic Documentation},
73 − year = {2024}
214 + title = {Tool Use with {Claude}},
215 + howpublished = {Claude Developer Platform documentation, \url{https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview}},
216 + year = {2026},
217 + note = {Accessed 17 October 2026}
218 +}
219 +
220 +@misc{mcp2025spec,
221 + author = {{Model Context Protocol}},
222 + title = {Model Context Protocol Specification, Revision 2025-06-18},
223 + howpublished = {\url{https://modelcontextprotocol.io/specification/2025-06-18}},
224 + year = {2025},
225 + note = {Accessed 17 October 2026}
226 +}
227 +
228 +% --- Evaluation ---
229 +@inproceedings{zheng2023judge,
230 + author = {Zheng, Lianmin and Chiang, Wei-Lin and Sheng, Ying and Zhuang, Siyuan and Wu, Zhanghao and
231 + Zhuang, Yonghao and Lin, Zi and Li, Zhuohan and Li, Dacheng and Xing, Eric P. and
232 + Zhang, Hao and Gonzalez, Joseph E. and Stoica, Ion},
233 + title = {Judging {LLM}-as-a-Judge with {MT-Bench} and {Chatbot Arena}},
234 + booktitle = {Advances in Neural Information Processing Systems},
235 + volume = {36},
236 + pages = {46595--46623},
237 + year = {2023},
238 + doi = {10.52202/075280-2020}
239 +}
240 +
241 +@article{chang2024survey,
242 + author = {Chang, Yupeng and Wang, Xu and Wang, Jindong and Wu, Yuan and Yang, Linyi and Zhu, Kaijie and
243 + Chen, Hao and Yi, Xiaoyuan and Wang, Cunxiang and Wang, Yidong and Ye, Wei and Zhang, Yue and
244 + Chang, Yi and Yu, Philip S. and Yang, Qiang and Xie, Xing},
245 + title = {A Survey on Evaluation of Large Language Models},
246 + journal = {ACM Transactions on Intelligent Systems and Technology},
247 + volume = {15},
248 + number = {3},
249 + pages = {1--45},
250 + year = {2024},
251 + doi = {10.1145/3641289}
252 +}
253 +
254 +@article{islam2023financebench,
255 + author = {Islam, Pranab and Kannappan, Anand and Kiela, Douwe and Qian, Rebecca and Scherrer, Nino and
256 + Vidgen, Bertie},
257 + title = {{FinanceBench}: A New Benchmark for Financial Question Answering},
258 + journal = {arXiv preprint arXiv:2311.11944},
259 + year = {2023}
260 +}
261 +
262 +@inproceedings{xie2024finben,
263 + author = {Xie, Qianqian and Han, Weiguang and Chen, Zhengyu and Xiang, Ruoyu and Zhang, Xiao and
264 + He, Yueru and Xiao, Mengxi and Li, Dong and Dai, Yongfu and Feng, Duanyu and Xu, Yijing and
265 + Kang, Haoqiang and Kuang, Ziyan and Yuan, Chenhan and Yang, Kailai and Luo, Zheheng and
266 + Zhang, Tianlin and Liu, Zhiwei and Xiong, Guojun and Zhang, Zhiyang and Lopez-Lira, Alejandro and
267 + others},
268 + title = {{FinBen}: A Holistic Financial Benchmark for Large Language Models},
269 + booktitle = {Advances in Neural Information Processing Systems},
270 + volume = {37},
271 + pages = {95716--95743},
272 + year = {2024},
273 + doi = {10.52202/079017-3033}
74 274 }
75 275
76 276 % --- Retrieval and grounding ---
@@ -89,10 +289,44 @@
89 289 author = {L{\'o}pez de Prado, Marcos},
90 290 title = {Advances in Financial Machine Learning},
91 291 publisher = {John Wiley \& Sons},
292 + address = {Hoboken, NJ},
92 293 year = {2018}
93 294 }
94 295
95 −% --- LLMs in finance ---
296 +% --- LLMs and text in finance and economics ---
297 +@article{loughran2016textual,
298 + author = {Loughran, Tim and McDonald, Bill},
299 + title = {Textual Analysis in Accounting and Finance: A Survey},
300 + journal = {Journal of Accounting Research},
301 + volume = {54},
302 + number = {4},
303 + pages = {1187--1230},
304 + year = {2016},
305 + doi = {10.1111/1475-679X.12123}
306 +}
307 +
308 +@article{gentzkow2019text,
309 + author = {Gentzkow, Matthew and Kelly, Bryan and Taddy, Matt},
310 + title = {Text as Data},
311 + journal = {Journal of Economic Literature},
312 + volume = {57},
313 + number = {3},
314 + pages = {535--574},
315 + year = {2019},
316 + doi = {10.1257/jel.20181020}
317 +}
318 +
319 +@article{li2021culture,
320 + author = {Li, Kai and Mai, Feng and Shen, Rui and Yan, Xinyan},
321 + title = {Measuring Corporate Culture Using Machine Learning},
322 + journal = {Review of Financial Studies},
323 + volume = {34},
324 + number = {7},
325 + pages = {3265--3315},
326 + year = {2021},
327 + doi = {10.1093/rfs/hhaa079}
328 +}
329 +
96 330 @article{wu2023bloomberggpt,
97 331 author = {Wu, Shijie and Irsoy, Ozan and Lu, Steven and Dabravolski, Vadim and Dredze, Mark and
98 332 Gehrmann, Sebastian and Kambadur, Prabhanjan and Rosenberg, David and Mann, Gideon},
@@ -108,19 +342,77 @@
108 342 year = {2023}
109 343 }
110 344
111 −@article{lopezlira2023chatgpt,
345 +@inproceedings{li2023survey,
346 + author = {Li, Yinheng and Wang, Shaofei and Ding, Han and Chen, Hang},
347 + title = {Large Language Models in Finance: A Survey},
348 + booktitle = {Proceedings of the Fourth ACM International Conference on AI in Finance (ICAIF '23)},
349 + pages = {374--382},
350 + year = {2023},
351 + doi = {10.1145/3604237.3626869}
352 +}
353 +
354 +@article{lopezlira2026chatgpt,
112 355 author = {Lopez-Lira, Alejandro and Tang, Yuehua},
113 − title = {Can {ChatGPT} Forecast Stock Price Movements? Return Predictability and Large
114 − Language Models},
115 − journal = {arXiv preprint arXiv:2304.07619},
116 − year = {2023}
356 + title = {Can {ChatGPT} Forecast Stock Price Movements? Return Predictability and Large Language Models},
357 + journal = {Journal of Financial Economics},
358 + volume = {184},
359 + pages = {104335},
360 + year = {2026},
361 + doi = {10.1016/j.jfineco.2026.104335}
362 +}
363 +
364 +@unpublished{chen2023expected,
365 + author = {Chen, Yifei and Kelly, Bryan and Xiu, Dacheng},
366 + title = {Expected Returns and Large Language Models},
367 + note = {Working paper, Yale University and University of Chicago Booth School of Business},
368 + year = {2023}
369 +}
370 +
371 +@unpublished{hansen2023fedspeak,
372 + author = {Hansen, Anne Lundgaard and Kazinnik, Sophia},
373 + title = {Can {ChatGPT} Decipher {Fedspeak}?},
374 + note = {SSRN working paper 4399406, \url{https://doi.org/10.2139/ssrn.4399406}},
375 + year = {2023}
376 +}
377 +
378 +@unpublished{kim2024financial,
379 + author = {Kim, Alex and Muhn, Maximilian and Nikolaev, Valeri},
380 + title = {Financial Statement Analysis with Large Language Models},
381 + note = {Chicago Booth Research Paper, SSRN 4835311, \url{https://doi.org/10.2139/ssrn.4835311}; arXiv:2407.17866, withdrawn by the authors on 20 February 2025 pending a review of data inconsistencies},
382 + year = {2024}
383 +}
384 +
385 +@article{fatouros2025marketsenseai,
386 + author = {Fatouros, Georgios and Metaxas, Konstantinos and Soldatos, John and Kyriazis, Dimosthenis},
387 + title = {Can Large Language Models Beat {Wall Street}? Evaluating {GPT-4}'s Impact on Financial Decision-Making with {MarketSenseAI}},
388 + journal = {Neural Computing and Applications},
389 + volume = {37},
390 + number = {30},
391 + pages = {24893--24918},
392 + year = {2025},
393 + doi = {10.1007/s00521-024-10613-4}
117 394 }
118 395
119 −@article{kim2024financial,
120 − author = {Kim, Alex and Muhn, Maximilian and Nikolaev, Valeri},
121 − title = {Financial Statement Analysis with Large Language Models},
122 − journal = {arXiv preprint arXiv:2407.17866},
123 − year = {2024}
396 +@article{korinek2023generative,
397 + author = {Korinek, Anton},
398 + title = {Generative {AI} for Economic Research: Use Cases and Implications for Economists},
399 + journal = {Journal of Economic Literature},
400 + volume = {61},
401 + number = {4},
402 + pages = {1281--1317},
403 + year = {2023},
404 + doi = {10.1257/jel.20231736}
405 +}
406 +
407 +@article{dell2025deep,
408 + author = {Dell, Melissa},
409 + title = {Deep Learning for Economists},
410 + journal = {Journal of Economic Literature},
411 + volume = {63},
412 + number = {1},
413 + pages = {5--58},
414 + year = {2025},
415 + doi = {10.1257/jel.20241733}
124 416 }
125 417
126 418 % --- Classical quantitative finance ---
@@ -131,7 +423,8 @@
131 423 volume = {81},
132 424 number = {3},
133 425 pages = {637--654},
134 − year = {1973}
426 + year = {1973},
427 + doi = {10.1086/260062}
135 428 }
136 429
137 430 @article{merton1973theory,
@@ -141,7 +434,8 @@
141 434 volume = {4},
142 435 number = {1},
143 436 pages = {141--183},
144 − year = {1973}
437 + year = {1973},
438 + doi = {10.2307/3003143}
145 439 }
146 440
147 441 @article{engle1982autoregressive,
@@ -152,7 +446,8 @@
152 446 volume = {50},
153 447 number = {4},
154 448 pages = {987--1007},
155 − year = {1982}
449 + year = {1982},
450 + doi = {10.2307/1912773}
156 451 }
157 452
158 453 @article{bollerslev1986generalized,
@@ -162,14 +457,17 @@
162 457 volume = {31},
163 458 number = {3},
164 459 pages = {307--327},
165 − year = {1986}
460 + year = {1986},
461 + doi = {10.1016/0304-4076(86)90063-1}
166 462 }
167 463
168 464 @book{glasserman2004monte,
169 465 author = {Glasserman, Paul},
170 466 title = {Monte Carlo Methods in Financial Engineering},
171 467 publisher = {Springer},
172 − year = {2004}
468 + address = {New York},
469 + year = {2004},
470 + doi = {10.1007/978-0-387-21617-1}
173 471 }
174 472
175 473 @book{jorion2007value,
@@ -177,5 +475,6 @@
177 475 title = {Value at Risk: The New Benchmark for Managing Financial Risk},
178 476 edition = {3rd},
179 477 publisher = {McGraw-Hill},
478 + address = {New York},
180 479 year = {2007}
181 480 }
modified paper/sections/conclusion.tex +25 −37
@@ -3,41 +3,29 @@
3 3 \label{sec:conclusion}
4 4 % ============================================================================
5 5
6 −This paper has documented the methodology and innovations of VQuant, a production-grade platform
7 −that turns a natural-language request into a complete, reproducible quantitative financial
8 −report. The system's organizing principle is a strict division of labor: the large language
9 −model plans and synthesizes, while deterministic code retrieves data and performs computation.
10 −This separation is what allows VQuant to combine the accessibility of a conversational interface
11 −with the rigor demanded by financial analysis.
6 +This paper has described VQuant, a deployed platform that turns a natural-language request into
7 +a quantitative financial report under one organising principle: the language model plans and
8 +synthesises, and deterministic code retrieves data and performs computation. We specified four
9 +mechanisms as implemented and audited against the source code---a recursive, batched, streaming
10 +tool-calling loop over a 245-tool catalogue; a three-stage context-management procedure with its
11 +actual constants; a single-call computation convention and the process-isolated sandbox that
12 +executes it; and a document pipeline from one Markdown artifact to PDF, DOCX, Beamer, and
13 +live-formula spreadsheets---and we corrected the earlier description of the system where the
14 +code differs from it. In the vocabulary of design science, the paper contributes a situated
15 +implementation and a demonstration; the evaluation step is specified but not performed.
12 16
13 −We highlighted four methodological contributions. The \emph{agentic orchestration loop}
14 −(Section~\ref{subsec:loop}) exposes a curated catalogue of more than two hundred tools to the
15 −model through a constrained, batched, fully streaming protocol, with a system prompt that routes
16 −requests by complexity. The \emph{context-management algorithm} (Section~\ref{subsec:context})
17 −keeps arbitrarily long conversations within the model's window by adaptively summarizing older
18 −history while preserving recent turns verbatim. The \emph{single-call computation paradigm}
19 −(Section~\ref{subsec:onecall}) consolidates data acquisition, estimation, and visualization into
20 −one sandboxed Python execution, materially reducing latency relative to sequential tool calling.
21 −And the \emph{unified document pipeline} (Section~\ref{subsec:docs}) emits PDF, Word, Beamer
22 −slides, and live-formula spreadsheets from a single Markdown artifact. We described each of these
23 −at the mechanism level---the eight-way event dispatch, the recursive loop and its
24 −tool-use/tool-result invariant, the batching throttle, the two-stage context machinery, the
25 −token-accounting correction, and the inter-process sandbox that exec's model-authored code and
26 −captures its figures---together with the streaming experience, multi-model selection, cost
27 −discipline, and security measures that make the system practical. The classical quantitative
28 −methods the platform automates are conventional and recorded compactly in the appendix; the
29 −contribution is the architecture, not the formulae.
30 −
31 −The natural next step is empirical. A rigorous evaluation would benchmark VQuant against
32 −baseline agentic patterns along three axes: \emph{quality}, via expert assessment of report
33 −accuracy and completeness on a fixed task suite; \emph{efficiency}, via controlled measurement of
34 −latency, token consumption, and dollar cost, isolating the contribution of the single-call
35 −paradigm and the context-management algorithm; and \emph{reliability}, via systematic probing
36 −for numerical and interpretive errors. Methodologically, the design admits several extensions:
37 −incorporating provider-agnostic tool exposure to broaden the model layer; adding a verification
38 −pass in which a second model audits the first model's narrative against the computed numbers; and
39 −generalizing the deterministic-computation substrate beyond finance to any domain where
40 −auditable numbers matter. We offer VQuant as a concrete, reproducible instance of \emph{agentic
41 −financial intelligence}---a design pattern in which the language model is a disciplined
42 −orchestrator of trustworthy tools rather than an unverified oracle---and as a foundation for the
43 −evaluation agenda above.
17 +The limits of what has been shown are therefore clear. The architecture removes numbers from
18 +the model's remit, but whether this reduces unsupported numbers to near zero, by how much the
19 +single-call convention reduces round trips and at what cost in failed executions, how much the
20 +summarisation procedure loses, and what the design costs relative to simpler agents are empirical
21 +questions that the protocol of Section~\ref{subsec:protocol} is written to answer and that this
22 +paper does not. Executing that protocol is the natural next step and the one on which any claim
23 +of superiority must wait. Three engineering changes are also warranted by the audit: a bound on
24 +recursion depth, a per-model price table in the ledger, and the restoration of the pre-built
25 +numerical routines to the tool catalogue. Beyond these, the design admits extensions that the
26 +protocol could also evaluate: a verification pass in which a second model audits the first's
27 +narrative against the computed numbers, provider-independent tool exposure through the Model
28 +Context Protocol, and generalisation of the deterministic-computation substrate to other domains
29 +in which auditable numbers matter. We offer the specification, the audit, and the protocol as the
30 +contribution, and the pattern they describe---a language model as a disciplined orchestrator of
31 +trustworthy tools rather than as an unverified oracle---as a hypothesis to be tested.
modified paper/sections/data.tex +77 −62
@@ -1,90 +1,105 @@
1 1 % ============================================================================
2 −\section{System Architecture and Data Layer}
2 +\section{System Architecture, Data Layer, and Model Layer}
3 3 \label{sec:architecture}
4 4 % ============================================================================
5 5
6 −This section describes VQuant's architecture, the data it consumes, and the external services
7 −it integrates. We treat the architecture as the ``setting'' of the paper: the methodology of
8 −Section~\ref{sec:methodology} is a set of algorithms that run \emph{within} the structure
9 −described here.
6 +This section describes the setting within which the mechanisms of Section~\ref{sec:methodology}
7 +operate: the three tiers of the platform, the external data and services it integrates, its
8 +persistence layer, and the model layer. All statements refer to the audited commit; where the
9 +first version of this paper described a different state, the difference is noted.
10 10
11 11 \subsection{Overview}
12 12 \label{subsec:overview}
13 13
14 −VQuant is a full-stack TypeScript monorepo comprising three cooperating tiers
15 −(Figure~\ref{fig:architecture}). A \textbf{React front end} renders a conversational interface
16 −and streams results to the user as they are produced. A \textbf{modular Express back end}
17 −orchestrates the LLM, executes tool calls, manages context and authentication, and persists
18 −sessions. An \textbf{isolated Python layer} performs numerical computation in a sandboxed
19 −subprocess. The three tiers communicate over HTTP, with the client--server channel using
20 −Server-Sent Events (SSE) to stream incremental output. The data layer is abstracted through an
21 −object-relational mapper that targets SQLite in development and PostgreSQL in production behind
22 −a single typed access interface, so that storage logic is identical across environments.
14 +VQuant is a TypeScript monorepo with three cooperating tiers (Figure~\ref{fig:architecture}). A
15 +\textbf{React front end} renders a conversational interface and updates it as events arrive. A
16 +\textbf{modular Express back end} orchestrates the model, executes tool calls, manages context
17 +and authentication, and persists sessions. An \textbf{isolated Python layer} performs numerical
18 +computation in a sandboxed child process. The client--server channel uses Server-Sent Events (SSE)
19 +to stream incremental output. Persistence is abstracted through an object-relational mapper
20 +(Drizzle) with two parallel schema definitions---SQLite for development and single-node
21 +deployment, PostgreSQL for hosted deployment---behind one typed access interface, so that storage
22 +logic is identical across environments. The code base is organised into six route modules
23 +(authentication, administration, analytics, market-data proxying, report management, and the chat
24 +stream) and a set of services, each encapsulating one external capability; the repository ships
25 +with six automated test suites covering request validation and client state.
23 26
24 27 \input{figures/architecture}
25 28
26 29 \subsection{The front end}
27 30 \label{subsec:frontend}
28 31
29 −The client is a single-page application. Its central abstraction is a session hook that owns
30 −the full conversational state---the streaming answer, the model's intermediate reasoning, the
31 −ordered list of tool invocations, retrieved sources, generated figures, and the results of
32 −specialized computations such as Monte Carlo simulations and option-pricing tables. A companion
33 −mutation hook manages the SSE connection: it issues the request, reads the byte stream, decodes
34 −discrete events, and dispatches each to the appropriate state setter. Because state updates are
35 −event-driven, the interface renders the agent's behavior \emph{as it happens}---text appears
36 −token by token, tool calls populate a progress indicator, reasoning expands in a collapsible
37 −panel, and figures materialize as the Python layer emits them. This streaming design is central
38 −to the user experience and is discussed further in Section~\ref{sec:evaluation}.
32 +The client is a single-page application whose central abstraction is a session hook owning the
33 +full conversational state: the streaming answer, the model's reasoning summary, the ordered list of
34 +tool invocations with their status, retrieved sources, generated figures, and the results of
35 +specialised computations. A companion mutation hook manages the SSE connection: it issues the
36 +request, reads the byte stream, decodes discrete events, and dispatches each to the appropriate
37 +state setter. Because state updates are event-driven, the interface renders the agent's behaviour
38 +as it happens---text appears incrementally, tool calls populate a progress indicator, reasoning
39 +expands in a collapsible panel, and figures appear as the Python layer emits them. The client-side
40 +event taxonomy is listed in Appendix~\ref{app:events}.
39 41
40 42 \subsection{The back end}
41 43 \label{subsec:backend}
42 44
43 −The server is organized into route modules (authentication, administration, analytics,
44 −market-data proxying, report management, and the chat stream) and a set of isolated services
45 −that encapsulate business logic. The most important service mediates all communication with the
46 −LLM: it assembles the system prompt and tool catalogue, enforces the token budget, opens the
47 −streaming connection, parses the provider's event stream, dispatches tool calls, and relays
48 −results back to the client. Document generation, web research, and the quantitative-method
49 −wrappers are each implemented as separate services, so that the orchestration logic remains
50 −decoupled from the mechanics of any single capability. All request bodies are validated against
51 −schemas at the boundary, eliminating untyped inputs and yielding uniform error handling.
45 +The most important service mediates all communication with the model provider: it assembles the
46 +system prompt and tool catalogue, applies the context-management procedure, opens the streaming
47 +connection, parses the provider's event stream, and returns text, tool requests, and usage to the
48 +route that owns the recursive loop (Section~\ref{subsec:loop}). Document generation, web research,
49 +the two market-data clients, and the Python executors are separate services, so that orchestration
50 +logic is decoupled from the mechanics of any single capability. Request bodies are validated
51 +against Zod schemas at the boundary, which rejects malformed input uniformly before it reaches
52 +business logic.
52 53
53 −\subsection{The data layer and external integrations}
54 +\subsection{Data layer and external integrations}
54 55 \label{subsec:data}
55 56
56 −VQuant is grounded in live data; it stores essentially no market data itself. Its primary
57 −financial source is a commercial market-data provider exposing more than 265 endpoints, wrapped
58 −by roughly 230 typed functions on the server and mirrored by a Python client used inside the
59 −sandbox. These endpoints cover company fundamentals (income statements, balance sheets, cash
60 −flows, key metrics and ratios), market data (real-time and historical quotes, intraday series,
61 −market movers), technical indicators (RSI, MACD, moving averages, ADX, stochastics, and
62 −others), analyst data (estimates, price targets, upgrades and downgrades, rating histories),
63 −insider and institutional activity (insider transactions, 13F filings, congressional and
64 −senate trading), macroeconomic series (treasury rates, economic indicators, the economic
65 −calendar, COT reports), foreign exchange and commodities, SEC filings and earnings-call
66 −transcripts, corporate events (earnings, dividends, splits, IPOs), and ESG and alternative-data
67 −signals. Table~\ref{tab:tools} in Section~\ref{sec:methodology} summarizes the resulting tool
68 −taxonomy.
57 +VQuant stores essentially no market data; it is grounded in live retrieval. Its primary financial
58 +source is a commercial market-data provider (Financial Modeling Prep) whose ``stable'' API is
59 +wrapped by 249 exported, typed server functions spanning 233 distinct endpoint paths, and
60 +mirrored by a small Python client injected into the sandbox. A second provider (EODHD) supplies
61 +end-of-day and intraday history, fundamentals, and news for instruments on more than seventy
62 +exchanges outside the United States, and is the source of the platform's options chains and Greeks.
63 +Together these endpoints cover company fundamentals, quotes and intraday series, technical
64 +indicators (several of which, such as MACD and CCI, are computed server-side from price history
65 +because the provider does not expose them), analyst data, insider and institutional activity,
66 +macroeconomic series, foreign exchange and commodities, SEC filings and earnings-call transcripts,
67 +corporate events, indices and funds, and ESG and alternative data. Table~\ref{tab:tools} in
68 +Section~\ref{sec:methodology} gives the resulting tool taxonomy with exact counts.
69 69
70 −Beyond structured financial data, VQuant integrates four complementary web-research services---a
71 −web-scraping and extraction service, an AI search service, a neural semantic-search service, and
72 −a general search-engine API---so that the agent can incorporate qualitative and breaking
73 −information that no structured endpoint captures. The persistence layer stores users (with
74 −optional encrypted custom API keys), conversation sessions (including token accounting and cost
75 −estimates), shared reports addressable by a unique public identifier, daily-usage counters, and
76 −analytics events. This schema supports the platform's authentication, rate-limiting,
77 −report-sharing, and observability features, which we revisit in Section~\ref{sec:evaluation}.
70 +Beyond structured data, three web-research services are exposed to the model as fourteen tools: a
71 +scraping, crawling, and extraction service (Firecrawl), an AI search and research service
72 +(Tavily), and a neural search service (Exa). A fourth service (a search-engine API) and a
73 +text-to-speech service are integrated server-side but have no tool definitions at the audited
74 +commit and are therefore not reachable by the model.
75 +
76 +The persistence layer defines twelve entities (Appendix~\ref{app:schema}): users, one-time
77 +authentication codes, trusted devices, a security event log, conversation sessions with their
78 +serialised messages and token and cost ledgers, individual messages, shared reports addressable by
79 +a public identifier, live-user presence, aggregated analytics metrics, request logs, and two
80 +tables for crawled pages and their embeddings. The first version of this paper described
81 +per-user encrypted API keys and daily usage counters; neither exists in any committed version of
82 +the schema, and the corresponding ``bring-your-own-keys'' feature described there is not
83 +implemented. We correct the record in Section~\ref{subsec:auth}.
78 84
79 85 \subsection{Model layer}
80 86 \label{subsec:models}
81 87
82 −VQuant is model-agnostic within the Claude family and exposes a user-facing selector
83 −(Table~\ref{tab:models}). The default is a reasoning-augmented model with a very large context
84 −window; users may instead select higher-capability or lower-latency alternatives to trade off
85 −quality, speed, and cost per query. The orchestration service detects which models support
86 −adaptive extended thinking and enables it only for those, so that the same code path serves the
87 −full model range. This abstraction is what allows the methodology of the next section to be
88 −stated independently of any particular model.
88 +The platform exposes a user-facing model selector (Table~\ref{tab:models}). The reference path,
89 +and the one described in Section~\ref{sec:methodology}, targets the Anthropic Messages API: the
90 +default model is \texttt{claude-fable-5}, and the orchestration service enables adaptive extended
91 +thinking for the five models that support it (Table~\ref{tab:models}) by attaching a thinking
92 +directive of type \texttt{adaptive} with a summarised display; the Haiku model is served without
93 +it. A uniform generation cap of 64{,}000 output tokens applies, and the request
94 +sets the sampling temperature to~1 (the provider default). At the audited commit the selector
95 +also lists OpenAI and Google models, served through a second adapter that speaks the
96 +OpenAI-compatible chat-completions interface, converts the Anthropic-style tool schemas and
97 +message history into that interface's function-calling format, and---because that interface caps
98 +the number of tools at 128---transmits only the first 128 tools of the catalogue. We do not audit
99 +those model identifiers or that path further; the first version of this paper described the
100 +platform as Claude-only, which was accurate for the version then deployed but is no longer so.
101 +What matters for the methodology is that the loop of Section~\ref{sec:methodology} is written
102 +against one internal representation (Anthropic-style content blocks) and that provider
103 +differences are confined to the two transport adapters.
89 104
90 105 \input{tables/models}
modified paper/sections/introduction.tex +85 −74
@@ -3,82 +3,93 @@
3 3 \label{sec:introduction}
4 4 % ============================================================================
5 5
6 −The rapid maturation of large language models (LLMs) has transformed expectations about
7 −what conversational software can accomplish in finance. Models such as the Claude, GPT, and
8 −Gemini families now produce fluent commentary on earnings, valuations, and macroeconomic
9 −conditions, and a growing literature documents their ability to extract signal from financial
10 −text \citep{lopezlira2023chatgpt,kim2024financial,wu2023bloomberggpt}. Yet fluency is not the
11 −same as rigor. A model that \emph{describes} a value-at-risk calculation in prose has not
12 −\emph{computed} one; a model that \emph{recalls} a stale price from pre-training has not
13 −\emph{retrieved} the current quote; and a model that narrates a Monte Carlo experiment has
14 −not run the simulation whose numbers a portfolio manager would act upon. The central
15 −engineering problem in applied financial AI is therefore not generation but
16 −\emph{grounding}: how to bind a probabilistic text generator to live data, deterministic
17 −computation, and reproducible artifacts without sacrificing the conversational interface that
18 −makes the technology accessible.
6 +Large language models (LLMs) now produce fluent commentary on earnings, valuations, and
7 +macroeconomic conditions, and a growing literature documents their ability to extract signal
8 +from financial text \citep{lopezlira2026chatgpt,wu2023bloomberggpt,hansen2023fedspeak}. Fluency,
9 +however, is not rigour. A model that \emph{describes} a value-at-risk calculation has not
10 +\emph{computed} one; a model that \emph{recalls} a price from its training data has not
11 +\emph{retrieved} the current quote; and a model that narrates a Monte Carlo experiment has not run
12 +the simulation whose numbers a portfolio manager would act upon. Surveys of hallucination in
13 +natural-language generation \citep{ji2023hallucination} and of LLM evaluation
14 +\citep{chang2024survey} make the same point from the other side: generated numbers are not
15 +trustworthy unless they are produced, or at least checked, outside the model. The central
16 +engineering problem in applied financial AI is therefore \emph{grounding}: how to bind a
17 +probabilistic text generator to live data, deterministic computation, and reproducible artifacts
18 +without giving up the conversational interface that makes the technology accessible.
19 19
20 −This paper documents the methodology and innovations of \textbf{VQuant}, a production-grade
21 −web platform built to address precisely this problem. VQuant accepts a natural-language
22 −request---``analyze NVDA's fundamentals, technicals, and run a Monte Carlo simulation,'' for
23 −example---and returns a complete, multi-section quantitative report containing live data,
24 −computed figures, and downloadable documents. The platform is implemented as a full-stack
25 −TypeScript monorepo: a React front end, a modular Express back end, and an isolated Python
26 −scientific-computing layer. At its core, the system orchestrates a reasoning-augmented LLM
27 −through an \emph{agentic loop} that exposes more than two hundred financial and analytical
28 −tools to the model, executes the model's tool calls deterministically, streams the results
29 −back in real time, and synthesizes a final report that can be exported in five document
30 −formats.
20 +This paper describes \textbf{VQuant}, a deployed web platform built around one answer to that
21 +problem. VQuant accepts a natural-language request---``analyse NVDA's fundamentals, technicals,
22 +and run a Monte Carlo simulation,'' for example---and returns a multi-section report with live
23 +data, computed figures, and downloadable documents. The platform is a full-stack TypeScript
24 +monorepo: a React front end, a modular Express back end, and an isolated Python
25 +scientific-computing layer. Its organising principle is a division of labour: the language model
26 +\emph{plans and synthesises}, while deterministic server code \emph{retrieves, schedules,
27 +computes, and accounts}. Every number in a VQuant report is meant to originate from a market-data
28 +endpoint, a closed-form formula, or Python code that the reader can inspect. The design belongs to
29 +the family of program-aided and tool-augmented language models
30 +\citep{gao2023pal,chen2023pot,schick2023toolformer,yao2023react,mialon2023augmented}; its
31 +specific contribution is to work out, at the level of a production system, what that family's
32 +principles require when the tool surface is large, the data are live, and the deliverable is a
33 +document.
31 34
32 −The motivation for studying this system is fourfold. \emph{First}, VQuant operationalizes a
33 −design philosophy that we believe is the correct one for high-stakes numerical domains: the
34 −LLM is a \emph{planner and synthesizer}, never a calculator. Every number in a VQuant report
35 −originates from a deterministic source---a market-data API, a closed-form pricing formula, or
36 −auditable Python code---so that the analysis is reproducible and the model's well-known
37 −propensity for numerical hallucination is structurally contained. \emph{Second}, the platform
38 −confronts the practical constraints of agentic systems---bounded context windows, tool-call
39 −latency, rate limits, and cost---with concrete algorithmic solutions whose logic generalizes
40 −beyond finance. \emph{Third}, VQuant integrates an unusually broad tool ecosystem (over 265
41 −market-data endpoints, four web-research services, and a seventeen-library Python sandbox)
42 −under a single function-calling protocol, providing a useful case study in tool taxonomy and
43 −prompt-level routing. \emph{Fourth}, the system closes the loop from query to deliverable by
44 −generating publication-ready PDF, Word, \LaTeX{} Beamer, and spreadsheet outputs from a single
45 −internal representation, illustrating a reusable pattern for automated report generation.
35 +\paragraph{What kind of paper this is.} This is a \emph{design-science} paper in the sense of
36 +\citet{hevner2004design} and \citet{gregor2013positioning}: it presents an artifact, states the
37 +problem it addresses, and specifies its construction precisely enough to be reproduced and later
38 +evaluated. It is \emph{not} an empirical evaluation. We report no measurements of numerical
39 +accuracy against ground truth, no hallucination rates, no latency or cost benchmarks, and no
40 +ablations; where the first version of this paper used the words ``results'' and ``robustness'', the
41 +present version uses ``design rationale'' and ``threats to validity''. Section~\ref{sec:evaluation}
42 +instead specifies the evaluation we think the artifact warrants---benchmark, metrics, ablations,
43 +and baselines---and marks it explicitly as not yet executed. We regard this separation as a
44 +matter of research integrity: a system paper that reports qualitative impressions as results
45 +invites exactly the kind of unverifiable claim that the system itself is designed to prevent.
46 46
47 −Our contributions are methodological and architectural rather than empirical. We make four
48 −specific contributions. \textbf{(1)~Agentic orchestration with constrained tool use.} We
49 −describe a streaming tool-calling loop (Section~\ref{sec:methodology}) in which a strategically
50 −engineered system prompt routes requests to an appropriate subset of more than two hundred
51 −tools, batches tool execution to respect external rate limits, and surfaces the model's
52 −intermediate reasoning to the user in real time. \textbf{(2)~Context management under a token
53 −budget.} We formalize an adaptive-summarization algorithm that preserves coherence across
54 −effectively unbounded conversation histories by compressing older turns once a token threshold
55 −is crossed, while retaining the most recent exchanges verbatim. \textbf{(3)~A single-call
56 −computation paradigm.} We argue that consolidating data acquisition, numerical estimation, and
57 −visualization into one sandboxed Python execution---rather than the sequential
58 −fetch-then-analyze pattern typical of naive agents---materially reduces end-to-end latency, and
59 −we describe the sandbox and its safety properties (Section~\ref{sec:capabilities}). \textbf{(4)~A
60 −unified multi-format document pipeline.} We detail how a single Markdown artifact is
61 −transformed into PDF (headless-browser rendering with mathematical typesetting), DOCX (document
62 −converter), Beamer slides (model-structured \LaTeX{} compiled to PDF), and spreadsheets with
63 −live formulas.
47 +\paragraph{Audit against the code.} A second feature of this version is that every mechanism
48 +described has been checked against the platform's source code at a fixed commit
49 +(\texttt{vquant.git}, commit \texttt{e2a148a}, 2 October 2026, hereafter ``the audited
50 +commit''). Where the implementation differs from the platform's own documentation, or from the
51 +first version of this paper, we say so. Three such discrepancies are material and are reported in
52 +the text: the tool catalogue contains 245 tools rather than the ``200+'' and ``213'' figures used in
53 +earlier descriptions; the token-accounting correction uses a general-purpose byte-pair tokenizer
54 +whose vocabulary differs from the provider's, so the ``exact'' count of the earlier description is
55 +an approximation; and several pre-built numerical routines (Monte Carlo, GARCH, VaR, portfolio
56 +optimisation) have server-side handlers but are absent from the tool catalogue, so the model cannot
57 +invoke them. Appendix~\ref{app:audit} tabulates each claim of the paper with the file that
58 +supports it.
64 59
65 −Our emphasis throughout is on \emph{mechanism}. We describe each component as it is actually
66 −built---the byte-level streaming protocol, the recursion that drives the loop, the throttle that
67 −batches tool calls, the two-stage machinery that keeps the context within budget, the correction
68 −that keeps token accounting honest, and the inter-process boundary that executes model-authored
69 −code---so that the design is reproducible rather than merely sketched. The classical quantitative
70 −methods the platform automates (option pricing, volatility modeling, simulation, and risk
71 −metrics) are standard and not the contribution of this paper; we record them compactly in an
72 −appendix and otherwise keep the focus on the architecture.
60 +\paragraph{Terminology.} Three terms recur and are used in a fixed sense. An \emph{agentic} loop is
61 +a control structure in which the model's output can request actions (tool calls) whose results are
62 +fed back to the model, repeatedly, until it produces a final answer
63 +\citep{yao2023react,wang2024agents}; the loop is agentic in this operational sense and no claim
64 +about autonomy is implied. \emph{Tool use} (or function calling) is the provider-level protocol by
65 +which a model emits a structured call against a declared JSON schema and receives a structured
66 +result \citep{anthropic2026tooluse,schick2023toolformer}. A \emph{reasoning-capable} model is one
67 +that can allocate an adaptive budget of private intermediate tokens to deliberation before and
68 +between its visible outputs \citep{wei2022chain}; the platform surfaces a summary of this
69 +deliberation to the user but does not depend on its content.
73 70
74 −The remainder of the paper is organized as follows.
75 −Section~\ref{sec:literature} situates VQuant within the literatures on LLM agents, tool use,
76 −retrieval augmentation, and AI in finance.
77 −Section~\ref{sec:architecture} presents the system architecture, data layer, and external
78 −integrations.
79 −Section~\ref{sec:methodology} develops the agentic orchestration methodology, including the
80 −tool taxonomy, context-management algorithm, and single-call execution paradigm.
81 −Section~\ref{sec:capabilities} formalizes the embedded quantitative methods and the
82 −document-generation pipeline.
83 −Section~\ref{sec:evaluation} discusses performance, reliability, security, and limitations.
84 −Section~\ref{sec:conclusion} concludes and outlines directions for evaluation and extension.
71 +\paragraph{Contributions.} Within these bounds the paper makes four contributions.
72 +\textbf{(1)~A specified orchestration loop.} Section~\ref{sec:methodology} gives the streaming
73 +transport, the recursive tool-calling procedure, the batching throttle, and the prompt-level
74 +routing that let a model navigate a catalogue of 245 tools without an explicit planner.
75 +\textbf{(2)~A specified context-management procedure.} We state, as an algorithm with its actual
76 +constants, the three-stage mechanism---per-result truncation at execution time, a re-send cap, and
77 +adaptive summarisation under a token budget---that keeps long sessions within the model's context
78 +window, and we relate it to the known degradation of long-context attention
79 +\citep{liu2024lost}. \textbf{(3)~A single-call computation convention and its substrate.} We argue
80 +that consolidating data acquisition, estimation, and visualisation into one sandboxed execution
81 +removes model round trips, and we specify the inter-process sandbox that executes model-authored
82 +code. \textbf{(4)~A document pipeline.} We describe how one Markdown artifact becomes PDF, DOCX,
83 +Beamer slides, and spreadsheets with live formulas. A fifth, methodological, contribution is the
84 +evaluation protocol of Section~\ref{subsec:protocol}.
85 +
86 +The classical quantitative methods the platform automates---option pricing, conditional-volatility
87 +modelling, simulation, and risk metrics---are standard and are recorded compactly in
88 +Appendix~\ref{app:numerical}. The remainder of the paper is organised as follows.
89 +Section~\ref{sec:literature} situates the artifact in the literatures on tool-augmented LLMs, LLM
90 +agents and their evaluation, and LLMs in finance and economics. Section~\ref{sec:architecture}
91 +describes the architecture, data layer, and model layer. Section~\ref{sec:methodology} develops
92 +the orchestration mechanisms. Section~\ref{sec:capabilities} describes the execution substrate and
93 +the document pipeline and walks through one request as an illustration.
94 +Section~\ref{sec:evaluation} gives the design rationale, threats to validity, reproducibility
95 +information, and the proposed evaluation protocol. Section~\ref{sec:conclusion} concludes.
modified paper/sections/literature.tex +97 −61
@@ -3,78 +3,114 @@
3 3 \label{sec:literature}
4 4 % ============================================================================
5 5
6 −VQuant sits at the intersection of four research strands: (i)~large language models and
7 −reasoning, (ii)~tool-augmented and agentic systems, (iii)~retrieval augmentation and grounding,
8 −and (iv)~the application of LLMs to finance. We review each in turn and position our
9 −contribution accordingly.
6 +VQuant draws on four strands of research: the design-science tradition in information systems,
7 +which supplies the paper's genre; the literature on tool-augmented language models and LLM
8 +agents, which supplies the mechanisms; work on the evaluation of such agents, which supplies the
9 +standard the paper does not yet meet; and the rapidly growing literature on LLMs in finance and
10 +economics, which supplies the application and its risks.
10 11
11 −\subsection{Language models and reasoning}
12 −\label{subsec:lit_lms}
12 +\subsection{Design science and system descriptions}
13 +\label{subsec:lit_ds}
13 14
14 −The transformer architecture of \citet{vaswani2017attention} and the demonstration of
15 −in-context, few-shot learning at scale by \citet{brown2020language} established the modern
16 −paradigm of general-purpose language models. A complementary line of work showed that
17 −intermediate ``chain-of-thought'' reasoning improves performance on multi-step problems
18 −\citep{wei2022chain}, motivating a generation of models that allocate explicit computation to
19 −deliberation before answering. VQuant builds directly on this development: it targets
20 −reasoning-augmented models that can ``think'' under an adaptive token budget prior to
21 −responding, and it surfaces this intermediate reasoning to the user. We treat the foundation
22 −model as a fixed, externally provided capability \citep{bommasani2021opportunities} and study
23 −the \emph{system} that must be engineered around it.
15 +Information-systems research distinguishes behavioural studies, which test theories about the use
16 +of artifacts, from design-science studies, which build and evaluate artifacts that solve
17 +identified problems \citep{hevner2004design}. \citet{peffers2007design} give the canonical
18 +process---problem identification, objectives, design and development, demonstration, evaluation,
19 +communication---and \citet{gregor2013positioning} classify contributions by their maturity, from
20 +situated implementations to nascent design theories. In those terms the present paper reports a
21 +\emph{situated implementation} together with a \emph{demonstration} (a walk-through of one
22 +request); the \emph{evaluation} step is specified but not performed. We adopt this vocabulary
23 +deliberately: it lets us describe a working system in detail while making clear which of the
24 +process's steps remain open.
24 25
25 −\subsection{Tool use and agentic systems}
26 +\subsection{Tool-augmented language models and agents}
26 27 \label{subsec:lit_agents}
27 28
28 −A model confined to its parametric memory cannot retrieve live prices or perform exact
29 −arithmetic. The tool-use literature addresses this by teaching models to call external
30 −functions. \citet{schick2023toolformer} showed that models can learn to invoke APIs, while the
31 −ReAct framework of \citet{yao2023react} interleaved reasoning traces with actions in an
32 −observe--think--act loop that has become the template for modern agents. Program-aided
33 −approaches \citep{gao2023pal} delegate computation to a code interpreter, offloading exact
34 −arithmetic from the language model to a deterministic runtime---a principle that VQuant adopts
35 −as a first-class design constraint. Industrial function-calling protocols
36 −\citep{anthropic2024tooluse} standardized the schema-driven invocation of tools, and the Model
37 −Context Protocol generalized tool exposure across providers. VQuant operationalizes these ideas
38 −at scale: rather than a handful of tools, it exposes a curated catalogue of more than two
39 −hundred, and it contributes practical mechanisms---prompt-level routing, execution batching,
40 −and a single-call computation paradigm---for managing the resulting orchestration complexity.
29 +A model confined to its parameters cannot retrieve a current price or perform exact arithmetic.
30 +Chain-of-thought prompting \citep{wei2022chain} improved multi-step reasoning but left
31 +computation inside the model; program-aided language models \citep{gao2023pal} and
32 +program-of-thoughts prompting \citep{chen2023pot} moved it out, having the model write code that a
33 +deterministic interpreter executes, and showed large gains on numerical benchmarks including
34 +financial question answering. Toolformer \citep{schick2023toolformer} taught models to insert API
35 +calls into their own text, and ReAct \citep{yao2023react} interleaved reasoning traces with
36 +actions in an observe--think--act loop that has become the template for agents. The survey of
37 +\citet{mialon2023augmented} names this family \emph{augmented language models} and organises it
38 +along the two axes---reasoning and tool use---that VQuant combines; \citet{wang2024agents} survey
39 +the resulting agent architectures. Retrieval-augmented generation \citep{lewis2020retrieval} is the
40 +special case in which the tool is a document retriever; VQuant's ``retrieval'' surface is
41 +structured (market-data endpoints), textual (web search and extraction), and computational
42 +(code), and the auditability it seeks is the financial analogue of citation grounding.
41 43
42 −\subsection{Retrieval augmentation and grounding}
43 −\label{subsec:lit_rag}
44 +Two practical problems arise when the tool surface grows. The first is selection: Gorilla
45 +\citep{patil2024gorilla} and ToolLLM \citep{qin2024toolllm} fine-tune models to choose among
46 +thousands of APIs and introduce retrievers over tool documentation, whereas VQuant transmits its
47 +entire 245-tool catalogue on every call and relies on schema descriptions and a routing prompt.
48 +The second is context: tool results are verbose, and \citet{liu2024lost} show that models use
49 +information in the middle of long contexts poorly even when it fits. Provider-level
50 +function-calling protocols \citep{anthropic2026tooluse} and the Model Context Protocol
51 +\citep{mcp2025spec} standardise how tools are declared and invoked but leave both problems to the
52 +application. VQuant's prompt-level routing (Section~\ref{subsec:routing}) and three-stage
53 +context management (Section~\ref{subsec:context}) are its answers; neither is claimed to be
54 +optimal, and the evaluation protocol of Section~\ref{subsec:protocol} is designed to test them.
44 55
45 −Retrieval-augmented generation \citep{lewis2020retrieval} grounds model outputs in external
46 −documents, mitigating hallucination and staleness. VQuant generalizes grounding beyond text
47 −retrieval: its ``retrieval'' surface includes structured market-data endpoints, semantic and
48 −keyword web search, and on-demand numerical computation. Every quantitative claim in a VQuant
49 −report is traceable to a deterministic source, which we view as the financial-domain analogue
50 −of citation-grounded generation. This emphasis on auditability connects to broader concerns
51 −about reliability and provenance in machine learning for finance \citep{lopezdeprado2018advances}.
56 +\subsection{Evaluating LLM agents}
57 +\label{subsec:lit_eval}
52 58
53 −\subsection{Large language models in finance}
59 +The agent literature has converged on benchmark suites with executable environments and
60 +automatic scoring: AgentBench \citep{liu2024agentbench} spans eight environments, Reflexion
61 +\citep{shinn2023reflexion} evaluates self-correction over repeated episodes, and WebGPT
62 +\citep{nakano2021webgpt} pioneered human-preference evaluation of browser-assisted answers. For
63 +open-ended outputs such as reports, model-based grading has become standard, with
64 +\citet{zheng2023judge} documenting both its agreement with human raters and its biases.
65 +\citet{chang2024survey} survey the resulting evaluation landscape. In finance specifically,
66 +FinanceBench \citep{islam2023financebench} supplies questions over public filings with
67 +human-verified answers and reports that unaided retrieval-augmented models answer a majority of
68 +them incorrectly, and FinBen \citep{xie2024finben} assembles a multi-task financial benchmark that
69 +includes agent and quantitative-reasoning tasks. These resources are the natural starting point
70 +for an evaluation of VQuant; the protocol in Section~\ref{subsec:protocol} builds on them.
71 +
72 +\subsection{Large language models in finance and economics}
54 73 \label{subsec:lit_finance}
55 74
56 −Domain-adapted models such as BloombergGPT \citep{wu2023bloomberggpt} and open frameworks such
57 −as FinGPT \citep{yang2023fingpt} demonstrated the value of finance-specific training data.
58 −On the application side, \citet{lopezlira2023chatgpt} found that LLM-derived sentiment from
59 −news headlines predicts subsequent returns, and \citet{kim2024financial} showed that LLMs can
60 −analyze financial statements at a level competitive with human analysts. These studies largely
61 −treat the LLM as a \emph{forecasting or classification} engine operating on text. VQuant takes
62 −a different stance: it uses the LLM as an \emph{orchestrator} that assembles live data,
63 −delegates numerical work to deterministic code, and composes the results into a report. The
64 −classical quantitative methods it automates---option pricing \citep{black1973pricing,
65 −merton1973theory}, conditional-volatility modeling \citep{engle1982autoregressive,
66 −bollerslev1986generalized}, Monte Carlo valuation \citep{glasserman2004monte}, and
67 −Value-at-Risk \citep{jorion2007value}---are well established; the contribution is the
68 −\emph{architecture} that makes them accessible through natural language while preserving
69 −reproducibility.
75 +Text has long been a source of financial signals: \citet{loughran2016textual} survey
76 +dictionary-based textual analysis, \citet{gentzkow2019text} review text-as-data methods for
77 +economists, and \citet{li2021culture} show that embedding-based methods recover latent constructs
78 +such as corporate culture from earnings calls. LLMs extend this line. \citet{lopezlira2026chatgpt}
79 +find that ChatGPT-derived headline sentiment predicts subsequent returns; \citet{chen2023expected}
80 +use LLM representations of news to forecast returns across sixteen markets; and
81 +\citet{hansen2023fedspeak} show that GPT models classify the stance of FOMC communications more
82 +accurately than dictionary and smaller supervised methods.\footnote{A widely circulated study of
83 +LLM-based financial statement analysis \citep{kim2024financial} was withdrawn from arXiv by its
84 +authors in February 2025 pending a review of data inconsistencies; we therefore do not rely on it.}
85 +Domain-adapted models such as BloombergGPT \citep{wu2023bloomberggpt} and FinGPT
86 +\citep{yang2023fingpt} demonstrate the value of finance-specific training data, and
87 +\citet{li2023survey} survey the field. On the applied side, \citet{fatouros2025marketsenseai}
88 +build an LLM-driven stock-selection framework from news, fundamentals, and prices and evaluate it
89 +on realised performance, while \citet{korinek2023generative} and \citet{dell2025deep} assess
90 +what generative and deep-learning methods offer to economic research.
91 +
92 +Most of this work treats the LLM as a \emph{forecasting or classification} engine operating on
93 +text. VQuant takes a different stance: the model is an \emph{orchestrator} that assembles live
94 +data, delegates numerical work to deterministic code, and composes the results into a document.
95 +The classical methods it automates---option pricing \citep{black1973pricing,merton1973theory},
96 +conditional volatility \citep{engle1982autoregressive,bollerslev1986generalized}, Monte Carlo
97 +valuation \citep{glasserman2004monte}, and Value-at-Risk \citep{jorion2007value}---are
98 +established; the broader concern with reproducibility and provenance in financial machine
99 +learning is articulated by \citet{lopezdeprado2018advances}. The point of contact with the
100 +forecasting literature is the risk, documented there, that LLM outputs about numbers are
101 +confidently wrong; VQuant's architecture is an attempt to remove numbers from the model's remit
102 +altogether.
70 103
71 104 \subsection{Positioning}
72 105 \label{subsec:lit_positioning}
73 106
74 −Relative to prior work, VQuant is distinctive in three respects. First, it integrates an
75 −unusually broad and heterogeneous tool ecosystem under one protocol, and it contributes
76 −concrete methodology for routing and rate-managing that ecosystem. Second, it enforces a strict
77 −separation between reasoning (performed by the LLM) and computation (performed by deterministic
78 −code), which we argue is the appropriate design for numerically sensitive domains. Third, it
79 −treats the \emph{deliverable}---a citable, exportable, reproducible document---as a primary
80 −artifact rather than an afterthought. The remainder of the paper develops each of these points.
107 +Relative to this work, the artifact described here is distinctive in three respects, none of
108 +which is an empirical claim. First, it exposes a broad and heterogeneous catalogue of tools under
109 +one protocol and documents the practical mechanisms---routing, batching, truncation,
110 +summarisation---needed to operate it. Second, it enforces a strict separation between reasoning
111 +(performed by the model) and computation (performed by deterministic code), a separation that
112 +\citet{gao2023pal} and \citet{chen2023pot} showed to be beneficial on benchmarks and that VQuant
113 +carries into a production setting with live data. Third, it treats the deliverable---an
114 +exportable, shareable document---as a primary artifact. What the paper does not establish is
115 +whether these choices improve accuracy, latency, or cost relative to simpler designs; that is the
116 +question Section~\ref{subsec:protocol} is written to answer.
modified paper/sections/methodology.tex +191 −144
@@ -1,56 +1,55 @@
1 1 % ============================================================================
2 −\section{Methodology: Orchestration Mechanisms}
2 +\section{Orchestration Mechanisms}
3 3 \label{sec:methodology}
4 4 % ============================================================================
5 5
6 −This section is the technical core of the paper. We describe, mechanism by mechanism, how
7 −VQuant drives a language model through a complete analysis: the streaming transport and its
8 −event protocol, the recursive tool-calling loop, the batching policy, the context-management
9 −machinery, and the token-accounting correction. Each mechanism is described as it is actually
10 −implemented, so that the design can be reproduced. Throughout, the guiding principle is a strict
11 −division of labor: the model \emph{plans and synthesizes}, while deterministic server code
12 −\emph{transports, schedules, computes, and accounts}.
6 +This section is the technical core of the paper. We describe, mechanism by mechanism, how VQuant
7 +drives a language model through a complete analysis: the streaming transport and its event
8 +protocol, the recursive tool-calling loop, the batching policy, the routing prompt, the
9 +context-management procedure, the token-accounting correction, and the single-call computation
10 +convention. Each mechanism is described as implemented at the audited commit, with its actual
11 +constants, so that the design can be reproduced; Appendix~\ref{app:audit} gives the source
12 +location of every statement.
13 13
14 −\subsection{The streaming transport and event protocol}
14 +\subsection{Streaming transport and event protocol}
15 15 \label{subsec:transport}
16 16
17 −VQuant does not use a model-provider SDK. It opens a raw HTTP connection to the provider's
18 −messages endpoint with a streaming response type, and parses the resulting Server-Sent Event
19 −(SSE) byte stream itself. This choice gives the server full control over how partial output is
17 +On the reference path VQuant does not use the provider's software development kit. It opens a
18 +raw HTTP connection to the provider's messages endpoint with a streaming response and parses the
19 +resulting SSE byte stream itself, which gives the server full control over how partial output is
20 20 interpreted and re-emitted.
21 21
22 22 The parser maintains a single growing string buffer. On each network chunk it appends the bytes,
23 −splits the buffer on newlines, and \emph{retains the final, possibly incomplete, line} in the
24 −buffer for the next chunk---a detail that is essential for correctness, because SSE frames do not
25 −align with TCP segment boundaries. Each complete line beginning with the \texttt{data:} prefix is
26 −stripped and parsed as JSON into a typed event. The parser dispatches on the event's
27 −\texttt{type} field; the eight relevant cases are summarized in Table~\ref{tab:events} and the
28 −overall flow is shown in Figure~\ref{fig:streaming}.
23 +splits the buffer on newlines, and \emph{retains the final, possibly incomplete, line} for the next
24 +chunk---a detail that is essential for correctness because SSE frames do not align with TCP
25 +segment boundaries. Each complete line beginning with the \texttt{data:} prefix is stripped and
26 +parsed as JSON into a typed event, and the parser dispatches on the event's \texttt{type} field.
27 +The eight relevant cases are summarised in Table~\ref{tab:events} and the flow is shown in
28 +Figure~\ref{fig:streaming}.
29 29
30 30 \input{figures/streaming}
31 31
32 32 \input{tables/events}
33 33
34 −Three behaviors of this dispatcher deserve emphasis. First, the model's output travels on
35 −\emph{two independent channels}: ordinary answer text arrives as \texttt{text\_delta} events and
36 −is accumulated into the answer while being forwarded to the client, whereas the model's private
37 −reasoning arrives as \texttt{thinking\_delta} events on a separate callback that the client
38 −renders in a distinct panel. Second, a tool call is not delivered atomically: the tool's name
39 −and identifier arrive in a \texttt{content\_block\_start}, but its arguments stream in as a
40 −sequence of \texttt{input\_json\_delta} fragments that the parser concatenates into a partial
41 −JSON string; only at \texttt{content\_block\_stop} is that string parsed into the structured
42 −argument object. The loop must therefore wait for the block to close before a tool becomes
43 −executable. Third, every forwarded event is flushed to the client immediately, so that the
44 −user perceives output token by token rather than in batches.
34 +Three behaviours of this dispatcher deserve emphasis. First, the model's output travels on two
35 +independent channels: answer text arrives as \texttt{text\_delta} events and is accumulated into
36 +the answer while being forwarded to the client, whereas the model's reasoning summary arrives as
37 +\texttt{thinking\_delta} events on a separate callback that the client renders in a distinct
38 +panel. Second, a tool call is not delivered atomically: the tool's name and identifier arrive in a
39 +\texttt{content\_block\_start}, its arguments stream in as a sequence of
40 +\texttt{input\_json\_delta} fragments that the parser concatenates into a partial JSON string, and
41 +only at \texttt{content\_block\_stop} is that string parsed into the structured argument object.
42 +The loop must therefore wait for the block to close before a tool becomes executable. Third, every
43 +forwarded event is flushed to the client immediately, so the user perceives output as it is
44 +generated rather than in batches.
45 45
46 46 \subsection{The recursive tool-calling loop}
47 47 \label{subsec:loop}
48 48
49 −The agentic loop is implemented as \emph{recursion} rather than iteration. A single routine
50 −issues one streaming model call, and when that call resolves it either terminates---if the model
51 −requested no tools---or executes the requested tools, appends their results to the conversation,
52 −and \emph{calls itself again}. Algorithm~\ref{alg:loop} states the procedure and
53 −Figure~\ref{fig:loop} depicts it.
49 +The agentic loop is implemented as recursion. A single routine issues one streaming model call;
50 +when the call resolves it either terminates---if the model requested no tools---or executes the
51 +requested tools, appends their results to the conversation, and calls itself again.
52 +Algorithm~\ref{alg:loop} states the procedure and Figure~\ref{fig:loop} depicts it.
54 53
55 54 \input{figures/loop}
56 55
@@ -58,162 +57,207 @@ Figure~\ref{fig:loop} depicts it.
58 57 \caption{Recursive tool-calling loop (\textsc{ProcessResponse})}
59 58 \label{alg:loop}
60 59 \begin{algorithmic}[1]
61 −\Require message list $M$ (mutated in place), model $m$, tool catalogue $\mathcal{T}$
62 −\State $(\textit{text}, R, \textit{usage}) \gets \textsc{StreamModel}(m, M, \mathcal{T})$
63 − \Comment{Section~\ref{subsec:transport}}
64 −\State accumulate \textit{usage}; stream \textit{text} and thinking to the client
60 +\Require message list $M$ (mutated in place), model $m$, tool catalogue $\mathcal{T}$ ($|\mathcal{T}|=245$)
61 +\State $M \gets \textsc{PrepareContext}(M, m)$ \Comment{Algorithm~\ref{alg:context}}
62 +\State $(\textit{text}, R, \textit{usage}) \gets \textsc{StreamModel}(m, M, \mathcal{T})$ \Comment{Section~\ref{subsec:transport}}
63 +\State accumulate \textit{usage}; stream \textit{text} and reasoning summary to the client
65 64 \If{$R = \varnothing$} \Comment{no tool calls $\Rightarrow$ final answer}
66 65 \State \Return
67 66 \EndIf
68 −\State append $\langle\text{assistant}: \text{tool\_use blocks of } R\rangle$ to $M$
67 +\State append $\langle\text{assistant}: \text{tool\_use blocks of } R\rangle$ to $M$ \Comment{tool-use blocks only; no text or thinking blocks}
69 68 \ForAll{batch $B$ in $\textsc{Chunk}(R, 5)$} \Comment{Section~\ref{subsec:batching}}
69 + \State emit a \texttt{status} event naming the tools in $B$ if more than one batch
70 70 \ForAll{tool call $r \in B$}
71 71 \State $\textit{res} \gets \textsc{Execute}(r)$; stream a typed result event to the client
72 − \State collect $\textit{res}$ as a tool\_result block
72 + \State $\textit{res} \gets \textsc{Truncate}(\textit{res}, c_1(r))$ \Comment{$c_1 = 3{,}000$ chars; $15{,}000$ for extraction and Python tools}
73 + \State collect $\textit{res}$ as a tool\_result block keyed to $r$'s identifier
73 74 \EndFor
74 − \State \textsc{Wait}(500\,\text{ms})
75 + \State \textsc{Wait}(500\,\text{ms}) if another batch follows
75 76 \EndFor
76 77 \State append $\langle\text{user}: \text{all tool\_result blocks}\rangle$ to $M$
77 78 \State \textsc{ProcessResponse}($M, m, \mathcal{T}$) \Comment{recurse with augmented context}
78 79 \end{algorithmic}
79 80 \end{algorithm}
80 81
81 −The conversation is represented as a list of messages that is mutated as the loop proceeds. When
82 −the model requests tools, the server first appends an \emph{assistant} message containing the
83 −model's tool-use blocks, then---after execution---appends a \emph{user} message whose content is
84 −the corresponding array of tool-result blocks, each keyed to its call identifier. This
85 −strict pairing of tool-use and tool-result blocks is what the provider's protocol requires, and
86 −maintaining it correctly across the recursion is the loop's central invariant. Recursion
87 −terminates naturally when a model call returns no tool requests, at which point the accumulated
88 −text is the report. Multimodal inputs are handled at the entry point: an uploaded image is
89 −attached to the first user message as a base64 block alongside the text query.
82 +The conversation is represented as a list of messages mutated as the loop proceeds. When the model
83 +requests tools, the server first appends an \emph{assistant} message containing the model's
84 +tool-use blocks, then---after execution---appends a \emph{user} message whose content is the array
85 +of tool-result blocks, each keyed to its call identifier. This pairing of tool-use and tool-result
86 +blocks is what the provider's protocol requires, and maintaining it across the recursion is the
87 +loop's central invariant. Two consequences of the implementation should be noted. The assistant
88 +message carries only the tool-use blocks: any answer text the model emitted in the same turn is
89 +streamed to the user but not re-sent to the model, and reasoning blocks are not replayed, so the
90 +model re-derives its plan from the tool results on the next turn rather than from its own prior
91 +deliberation. And because the routine recurses without a depth bound, termination relies on the
92 +model eventually returning no tool requests; the first version of this paper did not state this,
93 +and a maximum recursion depth is a reasonable hardening (Section~\ref{subsec:threats}). Recursion
94 +terminates when a call returns no tool requests, at which point the accumulated text is the
95 +report. Multimodal input is handled at the entry point: an uploaded image is attached to the
96 +first user message as a base64 block alongside the query.
90 97
91 98 \subsection{Batched tool execution}
92 99 \label{subsec:batching}
93 100
94 −Within a single turn the model frequently requests many tools at once---a comprehensive report
95 −may trigger a dozen or more. Executing all of them simultaneously would risk provider rate
96 −limits and connection timeouts. VQuant therefore partitions the requested calls into
97 −\emph{batches of at most five} and executes the batches \emph{sequentially}, inserting a
98 −500-millisecond pause between consecutive batches. Results from all batches are accumulated and
99 −returned to the model together in the single tool-result message of Algorithm~\ref{alg:loop}, so
100 −that the model sees a complete result set on the next turn rather than a fragmented one. The
101 −batch boundary thus serves purely as a rate-limiting throttle; it does not change what the model
102 −observes. When more than one batch is required the server emits a progress event naming the
103 −tools in flight, so the throttling is visible to the user rather than appearing as a stall.
101 +Within a single turn the model frequently requests many tools at once; a comprehensive report may
102 +trigger a dozen or more. Executing all of them simultaneously would risk provider rate limits and
103 +connection timeouts. VQuant therefore partitions the requested calls into batches of at most
104 +five, executes the batches sequentially, and inserts a 500-millisecond pause between consecutive
105 +batches. Within a batch the calls are executed one after another, not concurrently; the batch is
106 +a unit of pacing rather than of parallelism. Results from all batches are accumulated and returned
107 +to the model together in the single tool-result message of Algorithm~\ref{alg:loop}, so the model
108 +sees a complete result set on the next turn. This matters for a second reason: the provider's
109 +guidance is that parallel tool calls answered across several user messages lead the model to stop
110 +issuing them in parallel, so the single-message return preserves the model's tendency to batch its
111 +own requests. When more than one batch is required the server emits a \texttt{status} event naming
112 +the tools in flight, so the throttling is visible to the user rather than appearing as a stall.
104 113
105 114 \subsection{System-prompt routing}
106 115 \label{subsec:routing}
107 116
108 −The behavior of the loop is shaped by a system prompt that is assembled fresh on every call.
109 −Two parts are computed at request time: the current date and time (in both a human-readable and
110 −an ISO form) are injected at the top so that relative date expressions resolve against live data
111 −rather than the model's training cutoff; the remainder is a static policy block. That policy
112 −instructs the model to detect and match the user's language; to act without procedural narration
113 −and, in particular, to perform an entire custom analysis in a single execution
114 −(Section~\ref{subsec:onecall}); to calibrate effort to request complexity---one or two tools for
115 −a simple lookup, a handful for a moderate request, ten or more for a comprehensive report; and to
116 −follow output-formatting conventions for downloadable artifacts. A final guardrail directs the
117 −model to refuse attempts to extract the platform's own implementation. This prompt-level routing
118 −is the mechanism by which a catalogue of more than two hundred tools (Table~\ref{tab:tools}) is
119 −navigated without an explicit planner: the model is taught \emph{when not to call} tools as much
120 −as when to call them.
117 +The behaviour of the loop is shaped by a system prompt assembled on every call. Its first lines
118 +inject the current date and time, in a human-readable and an ISO form, so that relative date
119 +expressions resolve against live data rather than against the model's training cut-off; the
120 +remainder is a static policy block whose structure is given in Appendix~\ref{app:prompt}. The
121 +policy instructs the model to answer in the language of the request; to act without procedural
122 +narration and, in particular, to perform an entire custom analysis in a single Python execution
123 +(Section~\ref{subsec:onecall}); to calibrate effort to request complexity---one or two tools for a
124 +simple lookup, three to five for a moderate request, ten or more for a comprehensive report; to
125 +prefer the primary provider for United States equities and the second for international
126 +instruments; and to follow output-formatting conventions for downloadable artifacts, including a
127 +preference for live spreadsheet formulas over constants. A final block directs the model to
128 +refuse, with a fixed bilingual notice, attempts to extract the platform's own implementation.
129 +
130 +This prompt-level routing is the mechanism by which the 245-tool catalogue
131 +(Table~\ref{tab:tools}) is navigated without an explicit planner or a tool retriever of the kind
132 +proposed by \citet{patil2024gorilla} and \citet{qin2024toolllm}: the model is taught \emph{when
133 +not to call} tools as much as when to call them, and the per-tool schema descriptions carry the
134 +rest. The prompt names only about sixty tools explicitly; the others are discoverable solely from
135 +their schemas. Two of the tools the prompt does name---a Monte Carlo simulator and a
136 +volatility-surface generator---are not in the catalogue at the audited commit
137 +(Section~\ref{subsec:numerical}), an inconsistency between prompt and catalogue that the model
138 +would experience as a tool that does not exist.
121 139
122 140 \input{tables/tools}
123 141
124 142 \subsection{Adaptive reasoning}
125 143 \label{subsec:thinking}
126 144
127 −For models that support it, the orchestration service enables \emph{adaptive extended thinking}
128 −by attaching a thinking directive to the request and asking for a summarized display. A small
129 −capability list determines which models receive this directive, so the same code path serves the
130 −full model range. As noted in Section~\ref{subsec:transport}, the resulting reasoning summary
131 −arrives on its own delta channel and is streamed to a dedicated client panel. Surfacing
132 −reasoning makes the agent's plan legible to the user and provides an audit trail of how a report
133 −was assembled, at no change to the loop itself.
145 +For models that support it, the orchestration service enables adaptive extended thinking by
146 +attaching a thinking directive to the request and asking for a summarised display. A short
147 +capability list determines which models receive the directive, so that the same code path serves
148 +the full model range. As noted in Section~\ref{subsec:transport}, the resulting reasoning summary
149 +arrives on its own delta channel and is streamed to a dedicated client panel. Surfacing the
150 +summary makes the agent's plan legible to the user and provides a partial audit trail of how a
151 +report was assembled; it does not alter the loop, and nothing downstream parses or depends on the
152 +summary's content.
134 153
135 154 \subsection{Context management under a token budget}
136 155 \label{subsec:context}
137 156
138 157 A persistent challenge for conversational agents is the bounded context window: accumulated
139 −history---especially verbose tool results---eventually exceeds what the model can attend to.
140 −VQuant addresses this with a two-stage mechanism applied before every model call.
141 −
142 −\paragraph{Result truncation.} First, the server walks every message and caps any individual
143 −tool-result block at a fixed character budget (5{,}000 characters), appending a truncation
144 −marker. Raw data payloads are frequently far larger than the analysis requires, and this step
145 −removes that bloat before it is ever re-sent on a subsequent turn.
146 −
147 −\paragraph{Adaptive summarization.} Second, the server estimates the total token count of the
148 −prepared messages. The estimate uses a deliberately cheap heuristic---approximately one token per
149 −four characters, summed over text and tool-result blocks---because it is only a trigger, not an
150 −accounting figure. If the estimate exceeds a conservative threshold (set at $10^{5}$ tokens, well
151 −below the hard context limit to leave room for the response and new tool results), the server
152 −retains the most recent five messages verbatim and replaces the older history with a
153 −model-generated summary, reinserted as a single synthetic user message. Algorithm~\ref{alg:context}
154 −states the procedure and Figure~\ref{fig:context} illustrates the transformation.
158 +history---especially verbose tool results---eventually exceeds what the model can attend to, and
159 +attention over long contexts degrades before the hard limit is reached \citep{liu2024lost}.
160 +VQuant addresses this with a three-stage procedure. The first stage operates at execution time
161 +inside Algorithm~\ref{alg:loop}; the other two are applied immediately before every model call
162 +and are stated as Algorithm~\ref{alg:context}.
163 +
164 +\paragraph{Stage 1: per-result truncation at execution.} When a tool result is serialised for the
165 +model, it is cut at 3{,}000 characters, or 15{,}000 characters for the fourteen web-extraction
166 +tools and the Python tool, whose outputs carry extracted text or figure references that must not
167 +be lost; a marker recording the original length is appended. The full result is retained for
168 +session persistence and for the client.
169 +
170 +\paragraph{Stage 2: re-send cap.} Before each call the server walks every message and caps any
171 +individual tool-result block at 5{,}000 characters. This second cap is reached only by results
172 +that were admitted under the higher 15{,}000-character limit at Stage~1 and are now being re-sent
173 +on a later turn; it removes bulk that the analysis no longer needs.
174 +
175 +\paragraph{Stage 3: adaptive summarisation.} The server then estimates the token count of the
176 +prepared messages with a deliberately cheap heuristic---one token per four characters, summed over
177 +text and tool-result blocks---because the estimate is a trigger, not an accounting figure. If it
178 +exceeds a threshold of $10^{5}$ tokens, the server retains the most recent five messages verbatim
179 +and replaces the older history with a model-generated summary, reinserted as a single synthetic
180 +user message. The threshold was chosen as a conservative fraction of a 200{,}000-token window; the
181 +reference models now offer windows five times larger, so the constant is tunable and its effect
182 +is one of the ablations proposed in Section~\ref{subsec:protocol}. Figure~\ref{fig:context}
183 +illustrates the transformation.
155 184
156 185 \input{figures/context}
157 186
158 187 \begin{algorithm}[htbp]
159 −\caption{Context management via truncation and adaptive summarization}
188 +\caption{Context preparation before each model call (\textsc{PrepareContext})}
160 189 \label{alg:context}
161 190 \begin{algorithmic}[1]
162 −\Require message list $M$, model $m$, threshold $\tau = 10^{5}$, recency $k = 5$, cap $c = 5000$ chars
163 −\State cap every tool-result block in $M$ at $c$ characters
164 −\State $t \gets \textsc{EstimateTokens}(M)$ \Comment{cheap $\approx$ chars$/4$ heuristic}
165 −\If{$t > \tau$}
191 +\Require message list $M$, model $m$, threshold $\tau = 10^{5}$ tokens, recency $k = 5$, cap $c_2 = 5{,}000$ chars, summary input cap $c_3 = 10{,}000$ chars
192 +\State cap every tool-result block in $M$ at $c_2$ characters \Comment{Stage 2}
193 +\State $t \gets \textsc{EstimateTokens}(M)$ \Comment{$\lceil \text{chars}/4 \rceil$ over text and tool-result blocks}
194 +\If{$t > \tau$} \Comment{Stage 3}
166 195 \State $M_{\text{recent}} \gets$ last $k$ messages of $M$;\quad $M_{\text{old}} \gets$ the rest
167 196 \If{$M_{\text{old}} \neq \varnothing$}
168 − \State $T \gets \textsc{ExtractText}(M_{\text{old}})$ \Comment{drop tool-use blocks; keep last 10k chars}
169 − \State $s \gets \textsc{Summarize}(T, m)$ \Comment{separate non-streaming call}
170 − \State $M \gets [\,\langle\text{user: ``[summary]: ''}+s\rangle\,] \mathbin{\Vert} M_{\text{recent}}$
197 + \State $T \gets \textsc{ExtractText}(M_{\text{old}})$ \Comment{natural-language turns only; last $c_3$ characters}
198 + \State $s \gets \textsc{Summarize}(T, m)$ \Comment{non-streaming call; 2{,}000-token cap; temperature 0.5}
199 + \If{the call fails} $s \gets$ first 500 characters of $T$ \Comment{graceful degradation}
200 + \EndIf
201 + \State $M \gets [\,\langle\text{user: ``[Previous conversation summary]: ''}+s\rangle\,] \mathbin{\Vert} M_{\text{recent}}$
171 202 \EndIf
172 203 \EndIf
173 204 \State \Return $M$
174 205 \end{algorithmic}
175 206 \end{algorithm}
176 207
177 −The summary is produced by a dedicated, \emph{non-streaming} model call with its own system
178 −prompt, a low temperature, and a tight output cap, instructed to preserve the analytically
179 −relevant context---the instruments under discussion, prior conclusions, and user preferences.
180 −Before summarizing, a helper extracts only the natural-language turns (discarding tool-use
181 −blocks) and keeps at most the last ten thousand characters, bounding the cost of summarization
182 −itself. Should the summarization call fail, the mechanism degrades gracefully to a truncated
183 −literal excerpt rather than aborting the request. The net effect is that conversation length is,
184 −for practical purposes, unbounded, at the cost of one additional model call whenever the
185 −threshold is crossed.
208 +The summary is produced by a dedicated non-streaming call to the same model with its own system
209 +prompt, a temperature of 0.5, and a 2{,}000-token output cap, instructed to preserve the
210 +analytically relevant context---instruments under discussion, prior conclusions, and user
211 +preferences. Before summarising, a helper extracts only the natural-language turns (discarding
212 +tool-use and tool-result blocks) and keeps at most the last 10{,}000 characters, bounding the cost
213 +of summarisation itself. Should the call fail, the mechanism degrades to a literal excerpt rather
214 +than aborting the request. The net effect is that conversation length is, for practical purposes,
215 +unbounded, at the cost of one additional model call whenever the threshold is crossed and of
216 +whatever the summary omits. The procedure is lossy by construction, and the paper makes no claim
217 +about how much analytically relevant information survives it; that is a measurable quantity and
218 +is included in the evaluation protocol.
186 219
187 220 \subsection{Token accounting and its correction}
188 221 \label{subsec:accounting}
189 222
190 −Accurate token accounting matters both for the budget trigger above and for per-session cost
191 −reporting, yet the streaming protocol does not reliably report output-token counts. VQuant
192 −therefore applies a correction mechanism. Input tokens are read from the provider's
193 −\texttt{message\_start} event; output tokens are taken from streaming usage updates \emph{but
194 −reconciled} against a local count obtained by running the accumulated answer text through a
195 −tokenizer at the end of the stream. The system records the \emph{maximum} of the provider's
196 −figure and the local count, guaranteeing that cost is never understated, and falls back to the
197 −provider's figure only if local encoding fails. Cost is then computed from a simple linear
198 −schedule (a fixed price per million input tokens and a higher price per million output tokens)
199 −and accumulated across all calls in a session, including the recursive tool-driven turns and any
200 −summarization calls. This separation---a cheap heuristic for the budget trigger, an exact
201 −tokenizer for billing---keeps the hot path inexpensive while keeping the ledger accurate.
202 −
203 −\subsection{The single-call computation paradigm}
223 +Token accounting matters for per-session cost reporting, and the streaming protocol does not
224 +always report final output-token counts reliably. VQuant therefore applies a correction. Input
225 +tokens are read from the provider's \texttt{message\_start} event; output tokens are taken from
226 +streaming usage updates but reconciled, at \texttt{message\_stop}, against a local count obtained
227 +by running the accumulated answer text through a tokenizer. The system records the \emph{maximum}
228 +of the provider's figure and the local count, so that cost is never understated, and falls back to
229 +the provider's figure if local encoding fails.
230 +
231 +Two qualifications correct the first version of this paper. First, the local tokenizer is a
232 +general-purpose byte-pair encoder for OpenAI models (the \texttt{gpt-tokenizer} package), not the
233 +provider's tokenizer; its count is an approximation whose direction of error is not fixed, so the
234 +``exact tokenizer for billing'' of the earlier description overstated what the mechanism
235 +achieves. Second, the local count covers answer text only, not the reasoning tokens that the
236 +provider bills, so the maximum rule guards against under-reporting of text but not of thinking.
237 +Cost is then computed from a single linear schedule---\$3 per million input tokens and \$15 per
238 +million output tokens---and accumulated across all calls in a session, including recursive turns
239 +and summarisation calls. The schedule is the same for every selectable model, so the ledger
240 +mis-states cost whenever a model with different list prices is selected; a per-model price table
241 +is a straightforward correction. The separation of a cheap heuristic for the context trigger from a
242 +tokenizer-based count for the ledger is sound; the earlier description's statement that the
243 +tokenizer also drives the context trigger was incorrect.
244 +
245 +\subsection{The single-call computation convention}
204 246 \label{subsec:onecall}
205 247
206 −The final orchestration mechanism concerns \emph{how} numerical work is delegated. A naive agent
207 −decomposes a quantitative task into a sequence of tool calls---fetch data, then in a separate
208 −turn analyze it, then in a third turn plot it---each of which incurs a full recursion through
248 +The final mechanism concerns \emph{how} numerical work is delegated. A naive agent decomposes a
249 +quantitative task into a sequence of tool calls---fetch data, then in a separate turn analyse it,
250 +then in a third turn plot it---each of which incurs a full recursion through
209 251 Algorithm~\ref{alg:loop} and therefore a full model round trip. VQuant instead instructs the
210 −model, through the system prompt, to perform an entire analysis in a \emph{single} execution of
211 −the Python tool: acquire data inside the sandbox, compute, and render all figures in one call
212 −(Listing~\ref{lst:onecall}).
252 +model, through the system prompt and the Python tool's own description, to perform an entire
253 +analysis in a single execution of the Python tool: acquire data inside the sandbox, compute, and
254 +render all figures in one call (Listing~\ref{lst:onecall}).
213 255
214 256 \begin{lstlisting}[language=Python,caption={Single-call execution: data acquisition,
215 −computation, and visualization are consolidated into one sandboxed run, collapsing what would
216 −otherwise be three recursive model round trips into one.},label={lst:onecall}]
257 +computation, and visualisation are consolidated into one sandboxed run, so that what would
258 +otherwise be three recursive model round trips becomes one. The \texttt{fmp} client,
259 +\texttt{pd}, \texttt{plt}, and \texttt{save\_excel} are injected by the sandbox
260 +(Section~\ref{subsec:sandbox}).},label={lst:onecall}]
217 261 # One tool call performs the whole analysis:
218 262 data = fmp.get_historical_prices("NVDA") # live fetch inside the sandbox
219 263 df = pd.DataFrame(data["historical"]).sort_values("date")
@@ -228,12 +272,15 @@ plt.hist(df["ret"].dropna(), bins=50); plt.tight_layout()
228 272 save_excel(df, "nvda.xlsx") # spreadsheet export in the same run
229 273 \end{lstlisting}
230 274
231 −Three rules, enforced through the prompt, make this paradigm effective. First, the model must
232 −\emph{never} hard-code data arrays: inlining hundreds of values both bloats the generated tokens
233 −(which must be streamed and accounted) and defeats reproducibility; data must be fetched
234 −programmatically through the in-process client. Second, each visualization must be a separate
235 −figure rather than a subplot grid, which yields cleanly captionable, individually referenceable
236 −images. Third, all artifacts---figures and spreadsheets---are produced within the same execution.
237 −By collapsing the recursion depth for an analytical task from three or more to one, this paradigm
238 −removes the dominant source of latency in the loop. The substrate that executes this code is the
239 −subject of the next section.
275 +Three rules, enforced through the prompt, make the convention effective. First, the model must not
276 +hard-code data arrays: inlining hundreds of values bloats the generated tokens, which must be
277 +streamed and paid for, and defeats reproducibility, since the provenance of the numbers is lost;
278 +data must be fetched programmatically through the injected client. Second, each visualisation
279 +must be a separate figure rather than a subplot grid, which yields individually captionable
280 +images under the capture sweep of Section~\ref{subsec:sandbox}. Third, all artifacts---figures
281 +and spreadsheets---are produced within the same execution. The convention reduces the recursion
282 +depth for an analytical task from three or more to one. We call it a convention rather than a
283 +mechanism because it is enforced by instruction, not by code: the model can disobey it, and the
284 +rate at which it does so is one of the quantities the evaluation protocol is designed to measure.
285 +Its cost is a loss of granularity---a single failed execution forfeits the whole analysis, whereas
286 +a decomposed agent can recover at a finer level---which Section~\ref{subsec:threats} discusses.
modified paper/sections/results.tex +134 −80
@@ -1,71 +1,84 @@
1 1 % ============================================================================
2 −\section{Execution Substrate and Document Generation}
2 +\section{Execution Substrate, Document Generation, and an Illustrative Walk-Through}
3 3 \label{sec:capabilities}
4 4 % ============================================================================
5 5
6 6 Having described how the agent is orchestrated, we now detail the two subsystems that turn its
7 −plans into artifacts: the sandboxed Python substrate that executes arbitrary model-authored code,
8 −and the pipeline that renders the resulting report into multiple document formats. Both are
9 −described at the mechanism level.
7 +plans into artifacts---the sandboxed Python substrate that executes model-authored code and the
8 +pipeline that renders the resulting report into several document formats---and then walk through
9 +one request end to end. The walk-through is a \emph{demonstration} in the design-science sense
10 +\citep{peffers2007design}: it shows that the mechanisms compose, and it reports no measurements.
10 11
11 12 \subsection{The Python execution sandbox}
12 13 \label{subsec:sandbox}
13 14
14 −When the model invokes the custom-analysis tool, the server does not evaluate the code in
15 −process. It spawns a separate Python interpreter (resolved to a project virtual environment) as
16 −a child process and communicates with it over standard streams, an isolation boundary that
17 −protects the server from faults in the executed code and bounds its blast radius
18 −(Figure~\ref{fig:sandbox}).
15 +When the model invokes the custom-analysis tool, the server does not evaluate the code in process.
16 +It spawns a separate Python interpreter---the project's virtual environment if present, otherwise
17 +the system interpreter---as a child process and communicates with it over standard streams. The
18 +process boundary protects the server from faults in the executed code and bounds their effect
19 +(Figure~\ref{fig:sandbox}); it is isolation by process, not by container, and
20 +Section~\ref{subsec:threats} returns to what that does and does not guarantee.
19 21
20 22 \input{figures/sandbox}
21 23
22 −\paragraph{Inter-process protocol.} The server serializes a single JSON object---the
24 +\paragraph{Inter-process protocol.} The server serialises a single JSON object---the
23 25 model-authored code, an optional context dictionary, and the market-data credential---and writes
24 26 it to the child's standard input, then closes the stream. The child reads the entire input,
25 −executes, and writes exactly one JSON object to standard output: a success flag, captured
26 −textual output, a list of base64-encoded figures, a list of generated files, and any error. The
27 −child is launched with output buffering disabled so that nothing is lost, and with a hard
28 −90-second wall-clock timeout. The parent collects standard output and standard error separately;
29 −a non-zero exit code, or error output with no standard output, is treated as failure and the
30 −error is surfaced to the model so that it can revise its code on the next turn. This single
31 −request / single response discipline keeps the boundary simple and makes failures explicit.
27 +executes, and writes exactly one JSON object to standard output: a success flag, captured textual
28 +output, a list of base64-encoded figures, a list of generated files, and any error. The child is
29 +launched with output buffering disabled and a hard 90-second wall-clock timeout. The parent
30 +collects standard output and standard error separately; a non-zero exit code, or error output with
31 +no standard output, is treated as failure, and the error text is returned to the model as the tool
32 +result so that it can revise its code on the next turn. This single-request, single-response
33 +discipline keeps the boundary simple and makes failures explicit.
32 34
33 35 \paragraph{Namespace construction.} Inside the child, execution is performed by building an
34 −\emph{execution namespace}---a dictionary---and calling the interpreter's \texttt{exec} against
35 −it. Into this namespace the runtime injects the scientific libraries (NumPy, pandas, matplotlib,
36 −and the broader set of seventeen), the two artifact helpers (\texttt{save\_excel},
37 −\texttt{save\_word}), and a market-data client constructed from the supplied credential; any
38 −context variables passed by the model are merged in last, so that the model can parameterize a
39 −reusable script without string interpolation. Matplotlib is configured for a non-interactive
40 −backend before any plotting occurs, so that figure rendering requires no display. As a
41 −convenience, if the executed code defines a callable named \texttt{main}, the runtime invokes it
42 −after execution and captures its return value.
43 −
44 −\paragraph{Output and figure capture.} Standard output and standard error produced by the code
45 −are redirected into in-memory string buffers for the duration of execution, so that the model's
46 −\texttt{print} statements become the textual result rather than corrupting the JSON protocol.
47 −Figures are captured \emph{after} execution by a deterministic sweep: the runtime enumerates all
48 −live matplotlib figure numbers, and for each, renders the figure to an in-memory buffer as a
49 −PNG at fixed resolution with tight bounding boxes, then base64-encodes the bytes. This is exactly
50 −why the single-call paradigm of Section~\ref{subsec:onecall} asks the model to emit each chart as
51 −a \emph{separate} figure: the capture sweep turns each one into an individually addressable image
52 −that the report can caption and reference. The encoded figures travel back through the JSON
53 −response, are written to a served directory by the server, and are streamed to the client as
54 −figure events.
55 −
56 −\subsection{Embedded numerical tools}
36 +execution namespace---a dictionary---and calling the interpreter's \texttt{exec} against it. The
37 +runtime attempts to import, and injects when available, 29 packages: the core scientific stack
38 +(NumPy, pandas, SciPy, Matplotlib, seaborn, Plotly), statistics and econometrics (statsmodels,
39 +\texttt{arch}, pmdarima, Prophet, hmmlearn), machine learning (scikit-learn, XGBoost, LightGBM),
40 +optimisation and portfolio construction (CVXPY, PyPortfolioOpt, Riskfolio-Lib), market and
41 +technical-analysis utilities (yfinance, \texttt{ta}, mplfinance, vectorbt), data engines (DuckDB,
42 +Polars), and symbolic and graph libraries (SymPy, NetworkX, Numba), together with the
43 +spreadsheet and word-processing writers. Each import is wrapped so that a missing package degrades
44 +to an absent name rather than a failed execution; the platform's own documentation advertises
45 +``17 libraries'', which undercounts what the executor attempts to load. The runtime also injects
46 +two artifact helpers (\texttt{save\_excel}, \texttt{save\_word}) and a market-data client
47 +constructed from the supplied credential; any context variables passed by the model are merged
48 +in last, so that the model can parameterise a reusable script without string interpolation.
49 +Matplotlib is configured for a non-interactive backend before any plotting occurs. If the executed
50 +code defines a callable named \texttt{main}, the runtime invokes it after execution and captures
51 +its return value.
52 +
53 +\paragraph{Output and figure capture.} Standard output and standard error produced by the code are
54 +redirected into in-memory buffers for the duration of execution, so that \texttt{print} statements
55 +become the textual result rather than corrupting the JSON protocol. Figures are captured after
56 +execution by a deterministic sweep: the runtime enumerates all live Matplotlib figure numbers and,
57 +for each, renders the figure to an in-memory PNG at 150 dots per inch with a tight bounding box
58 +and base64-encodes the bytes. This is why the single-call convention asks the model to emit each
59 +chart as a separate figure: the sweep turns each one into an individually addressable image. The
60 +encoded figures travel back through the JSON response, are written to a served directory, and are
61 +streamed to the client as figure events. Files written by the artifact helpers are returned as
62 +download links in the same way.
63 +
64 +\subsection{Pre-built numerical routines}
57 65 \label{subsec:numerical}
58 66
59 −Alongside the open-ended sandbox, the platform exposes a small set of pre-built numerical tools
60 −for common tasks, so that routine requests need not regenerate code: a Monte Carlo path simulator
61 −under a standard log-normal price model, a closed-form European option pricer that returns prices
62 −together with the full set of risk sensitivities, a GARCH(1,1) conditional-volatility estimator,
63 −and a Value-at-Risk calculator offering historical, parametric, and simulation-based variants
64 −with companion risk ratios. These tools are conventional in quantitative finance and we do not
65 −elaborate their formulae here; what matters for the architecture is that they share the sandbox's
66 −contract---deterministic computation over live data, returning structured results and figures
67 −through the same channels---so the model can mix them freely with custom code inside a single
68 −analysis. Their detailed inputs and outputs are summarized in Appendix~\ref{app:numerical}.
67 +Alongside the open-ended sandbox, the server contains Python implementations of several routine
68 +computations---a Monte Carlo path simulator under geometric Brownian motion, a Black--Scholes
69 +pricer returning prices and Greeks, a GARCH(1,1) estimator, historical, parametric, and simulated
70 +Value-at-Risk with expected shortfall and companion ratios, a mean--variance portfolio optimiser,
71 +a risk-metrics module, a plotting module, and a volatility-surface renderer---each exposed through
72 +the same child-process contract as the sandbox. Their closed forms are recorded in
73 +Appendix~\ref{app:numerical}. At the audited commit, however, only the option pricer is declared
74 +in the tool catalogue; the handlers for the Monte Carlo, GARCH, VaR, portfolio-optimisation,
75 +risk-metrics, and plotting routines exist in the route module but have no corresponding tool
76 +definition, so the model cannot invoke them, even though the system prompt still describes the
77 +Monte Carlo and volatility-surface tools. The practical consequence is that, at this commit, such
78 +analyses are performed through the custom-Python path of Listing~\ref{lst:onecall}, with the
79 +model writing the code, rather than through a fixed implementation. The first version of this
80 +paper presented the four routines as model-callable tools; we correct that here and note that
81 +restoring the definitions is a small change.
69 82
70 83 \subsection{The document-generation pipeline}
71 84 \label{subsec:docs}
@@ -76,37 +89,78 @@ output formats, each through a distinct mechanism (Figure~\ref{fig:docpipeline})
76 89
77 90 \input{figures/docpipeline}
78 91
79 −\paragraph{PDF via headless rendering.} The challenge in rendering Markdown that contains
80 −mathematics is that a Markdown parser will mangle mathematical syntax. The pipeline solves this
81 −with a \emph{protect--parse--restore} mechanism: before parsing, every block- and inline-math
82 −span is extracted and replaced by a unique placeholder token; the now math-free Markdown is
83 −parsed to HTML; the placeholders are then restored as spans destined for a client-side math
84 −renderer. The assembled HTML is loaded into a headless browser, which executes the math renderer;
85 −the server explicitly \emph{waits for the rendered output to appear} in the DOM before capturing
86 −the page to PDF with page furniture (headers, footers, pagination). Rendering in a real browser
87 −engine is what lets complex notation and styled tables reproduce faithfully.
88 −
89 −\paragraph{Slides via model restructuring and two-pass \LaTeX.} Presentation output is a
90 −two-phase mechanism. First, the platform issues a \emph{second} model call whose sole task is to
91 −restructure the report into slide content---one idea per slide, special characters escaped, key
92 −quantities emphasized---returning only body \LaTeX{}, not a full document. The server then wraps
93 −that body in a fixed, branded Beamer preamble and compiles it with two sequential passes of the
94 −\LaTeX{} engine, the second pass being required for cross-references and the table of contents to
95 −resolve. When the analysis produced figures, the server additionally synthesizes one slide per
96 −figure, integrating the visual output into the deck without further model involvement.
92 +\paragraph{PDF via headless rendering.} Rendering Markdown that contains mathematics is delicate
93 +because a Markdown parser will mangle mathematical syntax. The pipeline solves this with a
94 +protect--parse--restore step: before parsing, every display and inline mathematics span is
95 +extracted and replaced by a unique placeholder; the now mathematics-free Markdown is parsed to
96 +HTML (with \texttt{marked}); the placeholders are then restored as spans destined for a client-side
97 +renderer (KaTeX). The assembled HTML is loaded into a headless Chromium instance (Puppeteer), which
98 +executes the renderer; the server waits until rendered output appears in the document before
99 +printing the page to PDF with headers, footers, and pagination. Rendering in a real browser engine
100 +is what lets complex notation and styled tables reproduce faithfully; it also makes PDF generation
101 +depend on a content-delivery network for the renderer's assets, a deployment constraint noted in
102 +Section~\ref{subsec:threats}.
103 +
104 +\paragraph{Slides via model restructuring and two-pass \LaTeX.} Presentation output is a two-phase
105 +mechanism. First, the platform issues a second model call---pinned to \texttt{claude-opus-4-8}
106 +irrespective of the model that produced the report---whose sole task is to restructure the report
107 +into slide content, one idea per slide, with special characters escaped and key quantities
108 +emphasised, returning only body \LaTeX. The server wraps that body in a fixed Beamer preamble and
109 +compiles it with two sequential passes of \texttt{pdflatex}, the second being required for
110 +cross-references and the table of contents to resolve; a non-zero exit code is tolerated when a
111 +PDF was nonetheless produced, since \LaTeX{} returns one on warnings. When the analysis produced
112 +figures, the server synthesises one slide per figure without further model involvement.
97 113
98 114 \paragraph{Word via document conversion.} For an editable office format, the same Markdown is
99 −handed to a document converter that emits a word-processor file, preserving tables, lists, and
100 −heading structure.
115 +written to a temporary file and converted with Pandoc, which preserves tables, lists, and heading
116 +structure.
101 117
102 118 \paragraph{Spreadsheets with live formulas.} Within the sandbox, the spreadsheet helper writes
103 −multi-sheet workbooks containing \emph{live} formulas---sums, ratios, conditional formats, data
104 −bars---rather than pre-computed constants, so the recipient can audit and modify the calculations.
105 −This mirrors, at the spreadsheet level, the platform's broader commitment to auditable output:
106 −the deliverable carries its own derivation.
107 −
108 −\paragraph{Sharing and persistence.} Finally, any report can be published to a stable, unique URL;
109 −the server stores the report content and its figure references and serves them through a public
110 −viewer, so an analysis can be revisited or cited without re-running the computation. Sessions,
111 −token ledgers, and cost estimates are persisted per user, supporting both continuity and the
112 −operational analytics discussed next.
119 +multi-sheet workbooks that contain live formulas---column sums, averages, extrema, and counts,
120 +together with optional per-column formulas supplied by the model---and conditional formats, rather
121 +than pre-computed constants, so that the recipient can audit and modify the calculations. This
122 +mirrors, at the spreadsheet level, the platform's commitment to auditable output: the deliverable
123 +carries its own derivation.
124 +
125 +\paragraph{Sharing and persistence.} Any report can be published to a stable URL under an
126 +eight-character identifier; the server stores the report content and its figure references and
127 +serves them through a public viewer, so an analysis can be revisited or cited without re-running
128 +the computation. Figure files themselves live on the server's disk and are lost on redeployment, a
129 +limitation the code acknowledges. Sessions, token ledgers, and cost estimates are persisted per
130 +user.
131 +
132 +\subsection{An illustrative walk-through}
133 +\label{subsec:walkthrough}
134 +
135 +To show how the mechanisms compose, we trace the request ``analyse NVDA's fundamentals,
136 +technicals, and run a Monte Carlo simulation'' through the system as implemented. No numbers are
137 +reported, because none were measured; the trace describes control flow.
138 +
139 +The route handler appends the query to an empty message list and calls
140 +\textsc{ProcessResponse}. \textsc{PrepareContext} finds nothing to truncate or summarise. The
141 +streaming call opens with the date-stamped system prompt, the 245 tool schemas, and the single
142 +user message; the model's reasoning summary begins to arrive on the thinking channel and is
143 +rendered in the collapsible panel. Under the routing policy the request is ``comprehensive'', so
144 +the model requests on the order of ten tools in one turn---profile, income statement, balance
145 +sheet, cash flow, key metrics, quote, historical prices, RSI, MACD, peers, news---plus one call to
146 +the custom-Python tool whose code fetches the price history inside the sandbox, simulates
147 +geometric-Brownian paths, and emits a fan chart and a terminal-value histogram as separate
148 +figures. The server emits a \texttt{tools} event listing the requests, then executes them in three
149 +batches of at most five with 500-millisecond pauses, emitting \texttt{tool\_start},
150 +\texttt{tool\_complete}, and per-batch \texttt{status} events. The Python call spawns the child
151 +process, which returns captured output and two base64 figures; the server writes the images to the
152 +served directory, emits \texttt{python\_code} and \texttt{custom\_python\_figures} events, and
153 +returns the textual output---capped at 15{,}000 characters---as the tool result. All other results
154 +are capped at 3{,}000 characters. The assistant message with the tool-use blocks and the user
155 +message with the tool-result blocks are appended, and the routine recurses.
156 +
157 +On the second call the model has every result in context and, in the typical case, requests no
158 +further tools: it streams the report section by section, following the template in
159 +Appendix~\ref{app:prompt}, with Markdown tables for the financial statements and image references
160 +for the two figures. The accumulated text, figures, token totals, and cost are persisted with the
161 +session and a \texttt{done} event closes the stream. From the rendered report the user may request
162 +a PDF (headless rendering), a DOCX (Pandoc), a Beamer deck (a second model call, pinned to Opus
163 +4.8, then two \texttt{pdflatex} passes, with one synthesised slide per figure), or a share link.
164 +Had the model instead decomposed the analysis---fetching prices in one turn and simulating in
165 +another---the trace would contain one additional recursion, which is the round trip the
166 +single-call convention is designed to remove.
modified paper/sections/robustness.tex +152 −74
@@ -1,87 +1,165 @@
1 1 % ============================================================================
2 −\section{Performance, Reliability, and Security}
2 +\section{Design Rationale, Threats to Validity, and a Proposed Evaluation}
3 3 \label{sec:evaluation}
4 4 % ============================================================================
5 5
6 −This section discusses the engineering properties that make VQuant usable in production:
7 −its performance characteristics, cost discipline, reliability and security measures, and the
8 −limitations that bound the contribution. We frame these as the practical counterparts to the
9 −methodology of Section~\ref{sec:methodology}.
10 −
11 −\subsection{Performance and the streaming experience}
12 −\label{subsec:performance}
13 −
14 −The dominant cost in an agentic system is not raw computation but \emph{round trips}: every
15 −model invocation and every external request adds latency. VQuant's design attacks this on three
16 −fronts (Table~\ref{tab:robustness}). The single-call paradigm of Section~\ref{subsec:onecall}
17 −collapses what would be three or more model round trips---fetch, analyze, plot---into one,
18 −which is the platform's largest latency saving for analytically intensive queries. Execution
19 −batching overlaps independent tool calls within a turn while bounding instantaneous provider
20 −load. And end-to-end streaming decouples \emph{perceived} latency from \emph{total} latency: the
21 −user sees reasoning, text, tool progress, and figures appear incrementally, so a report that
22 −takes tens of seconds to complete begins responding within a second. This last property is why
23 −the streaming architecture of Section~\ref{subsec:frontend} is a performance feature and not
24 −merely a cosmetic one.
6 +This section replaces what the first version of this paper called ``Performance, Reliability,
7 +and Security''. It states the rationale for each design decision as a hypothesis about the
8 +property the decision is meant to secure and the measurement that would test it
9 +(Table~\ref{tab:rationale}); it enumerates threats to the validity of the design and of this
10 +description; it records what is and is not fixed for reproducibility; and it specifies the
11 +evaluation that has not yet been executed.
25 12
26 −\input{tables/robustness}
13 +\subsection{Design rationale}
14 +\label{subsec:rationale}
27 15
28 −\subsection{Cost discipline}
29 −\label{subsec:cost}
16 +The dominant cost in an agentic system is not raw computation but round trips: every model
17 +invocation and every external request adds latency and, for model calls, tokens. Three decisions
18 +address this. The single-call convention (Section~\ref{subsec:onecall}) is intended to collapse
19 +the fetch--analyse--plot sequence into one recursion level; batching
20 +(Section~\ref{subsec:batching}) bounds instantaneous provider load without changing what the
21 +model observes; and end-to-end streaming decouples perceived from total latency, so that the user
22 +sees reasoning, text, and progress while the report is still being assembled. Three further
23 +decisions address correctness and auditability: the process-isolated sandbox, the rule that data
24 +are fetched programmatically rather than inlined, and the live-formula spreadsheets. Two address
25 +scale: the three-stage context procedure and the tokenizer-based ledger. Table~\ref{tab:rationale}
26 +lists each with the property it targets and the measurement that would confirm it. None of these
27 +measurements has been made; the table is a statement of intent, and the first version's
28 +``indicative'' latency figures, which had no measurement behind them, have been removed.
30 29
31 −Because model usage is metered by token, cost control is a first-order concern. VQuant estimates
32 −token counts locally with a tokenizer before each call, which both drives the
33 −context-management trigger of Algorithm~\ref{alg:context} and yields accurate per-session
34 −accounting. The adaptive-summarization mechanism directly limits cost growth in long sessions by
35 −preventing the unbounded accumulation of history, and truncating oversized tool results removes
36 −payload bloat that would otherwise be re-sent on every turn. The user-facing model selector
37 −(Table~\ref{tab:models}) lets users match model capability to query difficulty, routing simple
38 −lookups to a fast, inexpensive tier and reserving the flagship model for the hardest analyses.
30 +\input{tables/robustness}
39 31
40 −\subsection{Authentication, limits, and bring-your-own-keys}
32 +\subsection{Authentication, usage limits, and observability}
41 33 \label{subsec:auth}
42 34
43 −VQuant supports both local accounts and third-party single sign-on, with sessions persisted in
44 −the same store used in either deployment environment. Usage is governed by daily limits that
45 −differ for anonymous and authenticated users, enforced through per-user counters in the data
46 −layer. A notable feature is \emph{bring-your-own-keys}: a user may supply personal API
47 −credentials for the model provider, the market-data provider, and the web-research services;
48 −when present, these are used in place of the platform defaults and exempt the user from the
49 −daily cap. This design cleanly separates the platform's orchestration value from the cost of the
50 −underlying APIs, and it lets power users operate at their own expense and rate limits.
35 +At the audited commit the platform supports local accounts with e-mail and password, e-mail
36 +verification by one-time code, trusted devices that skip the code on subsequent logins, rate
37 +limiting of authentication attempts per account and per connection, and a security event log.
38 +Anonymous use is permitted and, for anonymous users only, each completed analysis is
39 +automatically published as a shared report so that it remains retrievable. The platform records
40 +request logs and aggregated analytics (request counts, failures, active and unique users, response
41 +times) for operators. Three features described in the first version of this paper do not exist in
42 +any committed version of the code: third-party single sign-on, daily usage caps that differ for
43 +anonymous and authenticated users, and the ``bring-your-own-keys'' mechanism by which users
44 +would supply personal provider credentials. They may have been planned or deployed through
45 +configuration outside the repository, but they are not implemented in it, and we withdraw the
46 +corresponding claims.
51 47
52 −\subsection{Reliability and security}
48 +\subsection{Security measures}
53 49 \label{subsec:security}
54 50
55 −Several measures harden the system. All request bodies are validated against schemas at the
56 −boundary, so malformed or untyped input is rejected uniformly before reaching business logic.
57 −Database access is mediated by an object-relational mapper that parameterizes queries,
58 −mitigating injection. The front end escapes rendered content and parses Markdown through a safe
59 −pipeline, limiting cross-site scripting. Secrets are injected at runtime rather than committed,
60 −and the bring-your-own-keys path keeps user credentials out of shared configuration. At the
61 −model layer, the system prompt includes a guardrail that responds to attempts to extract the
62 −platform's own implementation with a refusal rather than disclosure, providing a measure of
63 −protection for the orchestration logic itself. Finally, the platform records analytics
64 −events---active users, query rates, tool-usage frequency, model selection, and
65 −document-generation breakdowns---giving operators the observability needed to detect anomalies
66 −and capacity-plan.
67 −
68 −\subsection{Limitations and threats to validity}
69 −\label{subsec:limitations}
70 −
71 −We close with an honest accounting of what this paper does and does not establish. First, the
72 −contribution is \emph{architectural and methodological}; we do not provide a controlled
73 −empirical evaluation of report quality, latency, or cost against baseline agents, and the
74 −operational figures in Table~\ref{tab:robustness} are indicative rather than benchmarked.
75 −Second, the platform inherits the limitations of its dependencies: the accuracy of any report is
76 −bounded by the correctness and timeliness of the upstream market-data provider, and the model's
77 −synthesis can still contain interpretive errors even when every number is computed
78 −deterministically. The strict separation of reasoning from computation contains numerical
79 −hallucination but does not eliminate the risk of a flawed \emph{narrative} around correct
80 −numbers. Third, the quantitative methods rest on classical modeling assumptions---log-normal
81 −prices, constant parameters over the estimation window, normally distributed returns in the
82 −parametric VaR---that may be violated in practice; the platform exposes these methods as tools
83 −and does not, by itself, certify their appropriateness for a given asset. Fourth, the
84 −single-call paradigm trades some robustness for speed: a single failed execution forfeits an
85 −entire analysis, whereas a decomposed agent can recover at a finer granularity. We regard the
86 −design as the right default for interactive use but note the trade-off. These limitations
87 −delineate a clear agenda for evaluation, which we sketch in the conclusion.
51 +Several measures harden the system. Request bodies are validated against schemas at the
52 +boundary. Database access is mediated by the object-relational mapper, which parameterises
53 +queries. The front end parses Markdown through a sanitising pipeline, limiting cross-site
54 +scripting from model output. Secrets are injected from the environment rather than committed.
55 +Model-authored code runs in a child process with a wall-clock timeout, so that an infinite loop or a
56 +crash cannot take the server down with it. The system prompt includes a guardrail that answers
57 +attempts to extract the platform's implementation with a fixed refusal notice; this is a
58 +prompt-level measure and, like all such measures, provides no guarantee against a determined
59 +adversary. We do not claim that the sandbox is a security boundary against malicious code: the
60 +child process runs with the server's privileges and network access, and the model is not an
61 +adversary in the threat model, but a user who can steer the model into writing arbitrary code
62 +is. Containerisation or a seccomp-style policy would be the appropriate hardening.
63 +
64 +\subsection{Threats to validity}
65 +\label{subsec:threats}
66 +
67 +We distinguish threats to the validity of the design from threats to the validity of this
68 +description.
69 +
70 +\paragraph{Design.} First, the separation of reasoning from computation contains \emph{numerical}
71 +hallucination but not \emph{interpretive} error: the model can still write a wrong narrative
72 +around correct numbers, select an inappropriate method, or mis-specify the code it writes, and
73 +nothing in the loop checks the narrative against the numbers. Second, the single-call convention
74 +trades granularity for speed; a failed execution forfeits the analysis, and the model's only
75 +recovery path is to rewrite the code on the next turn. Third, the recursion has no depth bound, so
76 +termination depends on the model; a bound is cheap and should be added. Fourth, the context
77 +procedure is lossy, and the threshold and recency constants were set by judgement rather than
78 +measurement. Fifth, the accuracy of every report is bounded by the correctness and timeliness of
79 +the upstream data providers, and the platform does not cross-check providers against each other.
80 +Sixth, the classical methods rest on standard assumptions---log-normal prices, constant parameters
81 +over the estimation window, normal returns for parametric VaR---that the platform exposes but
82 +does not certify for a given asset. Seventh, PDF rendering depends on externally hosted renderer
83 +assets, and the Beamer path on a local \TeX{} installation; both are deployment dependencies that
84 +the code does not verify at start-up.
85 +
86 +\paragraph{Description.} The paper describes one commit of a system that continues to change;
87 +the model identifiers, tool counts, and constants reported here are facts about that commit, and
88 +three of them (the tool count, the tokenizer, and the reachability of the numerical routines)
89 +already differed from the platform's own documentation at the time of the audit. Appendix~\ref{app:audit}
90 +lists the source of every statement so that a reader with access to the repository can re-check
91 +them, and the audit script that produced the counts is distributed with the paper.
92 +
93 +\subsection{Reproducibility}
94 +\label{subsec:repro}
95 +
96 +Reproducibility of a system of this kind has two layers. The \emph{design} is reproducible from
97 +this paper: Algorithms~\ref{alg:loop} and~\ref{alg:context}, the constants in
98 +Table~\ref{tab:rationale}, the prompt structure in Appendix~\ref{app:prompt}, and the
99 +inter-process contract of Section~\ref{subsec:sandbox} are sufficient to re-implement it. The
100 +\emph{outputs} are not reproducible in the strict sense, for four reasons that we record rather
101 +than conceal. The main model call sets the sampling temperature to~1 and the summarisation call
102 +to~0.5; the reference models are not seedable through the provider interface; the Python code is
103 +authored by the model and therefore differs across runs even for an identical request; and the
104 +pre-built Monte Carlo routine draws pseudo-random numbers without a fixed seed. What \emph{is}
105 +reproducible, given a report, is every number in it: the tool calls and the executed code are
106 +persisted with the session and displayed to the user, so any figure can be recomputed from its
107 +recorded inputs. The system prompt is reproduced structurally in Appendix~\ref{app:prompt}; its
108 +full text is in the repository.
109 +
110 +\subsection{A proposed evaluation protocol (not executed)}
111 +\label{subsec:protocol}
112 +
113 +The following protocol is the evaluation step that the design-science process requires
114 +\citep{peffers2007design} and that this paper does not perform. It is stated in enough detail to
115 +be pre-registered.
116 +
117 +\paragraph{Task suite.} Three task families, each with ground truth that does not depend on a
118 +model. (a)~\emph{Retrieval tasks}: 200 questions whose answers are single values obtainable from
119 +the market-data endpoints at a frozen date (``What was NVDA's trailing twelve-month revenue as
120 +of 30~June~2026?''), with the endpoint's value as ground truth; FinanceBench
121 +\citep{islam2023financebench} supplies a complementary set over public filings.
122 +(b)~\emph{Computation tasks}: 100 requests for standard quantities---Black--Scholes prices and
123 +Greeks, GARCH(1,1) parameters, historical and parametric VaR, Monte Carlo terminal-value
124 +quantiles---on frozen price histories, with ground truth from independent reference
125 +implementations and seeded simulation; the quantitative-reasoning tasks of FinBen
126 +\citep{xie2024finben} can be added. (c)~\emph{Report tasks}: 50 comprehensive requests graded by
127 +two human analysts on a fixed rubric (coverage, correctness of every stated number against the
128 +tool results, soundness of narrative, absence of unsupported claims), with an LLM judge
129 +\citep{zheng2023judge} calibrated against the human grades on a held-out subset before being used
130 +at scale.
131 +
132 +\paragraph{Metrics.} For (a) and (b): exact-match or tolerance-based accuracy; the
133 +\emph{unsupported-number rate}, defined as the share of numbers in the response that do not appear
134 +in any tool result or executed-code output, which operationalises numerical hallucination; and
135 +tool-selection precision and recall against a minimal correct tool set. For (c): rubric scores,
136 +inter-rater agreement, and the unsupported-claim rate. For all families: end-to-end latency
137 +(median and 95th percentile), time to first token, number of model round trips, input and output
138 +tokens (reasoning tokens reported separately), dollar cost from per-model list prices, and the
139 +sandbox failure rate with its causes.
140 +
141 +\paragraph{Ablations.} Each mechanism is removed or varied while the rest is held fixed:
142 +(i)~tools disabled (the model answers from parameters), which measures what grounding adds;
143 +(ii)~adaptive thinking disabled; (iii)~the single-call instruction removed, so the model is free
144 +to decompose, which measures the round trips and the failure rate the convention trades off;
145 +(iv)~the context procedure varied over thresholds of $5\times10^{4}$, $10^{5}$, and $2\times10^{5}$
146 +tokens and recency of 3, 5, and 10 messages on 20-turn sessions, scoring the retention of
147 +analytically relevant facts planted early in the session; (v)~batch size varied over 1, 5, and
148 +unbounded, measuring rate-limit errors and latency; and (vi)~model tier varied across the selector
149 +of Table~\ref{tab:models}.
150 +
151 +\paragraph{Baselines.} A plain model without tools; a ReAct-style loop \citep{yao2023react} with
152 +one tool per turn; a code-interpreter-only agent in the spirit of program-aided language models
153 +\citep{gao2023pal} with the same sandbox but no structured endpoints; and, as an upper reference
154 +on the computation tasks, the reference implementations themselves.
155 +
156 +\paragraph{Controls.} All runs at a frozen data snapshot (recorded endpoint responses replayed
157 +through a cache), three repetitions per task to estimate variance under temperature~1, and the
158 +same prompts and constants as the audited commit unless the ablation varies them. Reported
159 +outcomes would be accompanied by confidence intervals from the repetitions and by the full
160 +transcripts.
161 +
162 +The protocol would answer the questions the first version of this paper left as assertions:
163 +whether grounding reduces unsupported numbers to near zero, by how much the single-call
164 +convention reduces round trips and at what cost in failures, how much the context procedure
165 +loses, and what the architecture costs relative to simpler baselines.
modified paper/tables/events.tex +12 −12
@@ -1,31 +1,31 @@
1 1 \begin{table}[htbp]
2 2 \centering
3 −\caption{The streaming event protocol. The server parses the provider's Server-Sent Event stream
4 −and dispatches on each event's type; it then re-emits its own typed events to the client. This is
5 −the mechanism by which reasoning, text, tool calls, and computed artifacts are surfaced
6 −incrementally.}
3 +\caption{Provider-side streaming event protocol. The server parses the provider's Server-Sent
4 +Event stream and dispatches on each event's type; it then re-emits its own typed events to the
5 +client (Appendix~\ref{app:events}). This is the mechanism by which reasoning, text, tool calls, and
6 +computed artifacts are surfaced incrementally.}
7 7 \label{tab:events}
8 8 \begin{threeparttable}
9 +\small
9 10 \begin{tabular}{@{}lll@{}}
10 11 \toprule
11 12 Provider event & Sub-type & Server action \\
12 13 \midrule
13 −\texttt{message\_start} & --- & read input/output token usage \\
14 +\texttt{message\_start} & --- & read input and output token usage \\
14 15 \texttt{message\_delta} & --- & update running output-token count \\
15 −\texttt{content\_block\_start}& \texttt{tool\_use} & open a new tool call (name, id) \\
16 +\texttt{content\_block\_start}& \texttt{tool\_use} & open a new tool call (name, identifier) \\
16 17 \texttt{content\_block\_delta}& \texttt{text\_delta} & append to answer; forward to client \\
17 −\texttt{content\_block\_delta}& \texttt{thinking\_delta} & forward reasoning on a separate channel \\
18 +\texttt{content\_block\_delta}& \texttt{thinking\_delta} & forward reasoning summary on a separate channel \\
18 19 \texttt{content\_block\_delta}& \texttt{input\_json\_delta} & concatenate partial tool-argument JSON \\
19 20 \texttt{content\_block\_stop} & --- & parse accumulated JSON into tool arguments \\
20 −\texttt{message\_stop} & --- & reconcile tokens; resolve the call \\
21 +\texttt{message\_stop} & --- & reconcile output tokens; resolve the call \\
21 22 \bottomrule
22 23 \end{tabular}
23 24 \begin{tablenotes}[flushleft]
24 25 \footnotesize
25 −\item \textit{Notes.} The client (Section~\ref{subsec:frontend}) performs the symmetric
26 −operation: it reads the server's stream, splits on newlines retaining the trailing partial line,
27 −and dispatches the server's own event types (text, thinking, tools, tool results, sources,
28 −figures, specialized results, done) to dedicated renderers.
26 +\item \textit{Notes.} Source: \path{server/services/claudeService.ts}. The client performs the
27 +symmetric operation on the server's own stream: it reads bytes, splits on newlines retaining the
28 +trailing partial line, and dispatches the server's event types to dedicated renderers.
29 29 \end{tablenotes}
30 30 \end{threeparttable}
31 31 \end{table}
modified paper/tables/models.tex +24 −14
@@ -1,27 +1,37 @@
1 1 \begin{table}[htbp]
2 2 \centering
3 −\caption{User-selectable model tier. The orchestration service enables adaptive extended
4 −thinking only for models that support it, and applies a uniform per-response generation cap.
5 −The default is a reasoning-augmented model with a very large context window; alternatives let
6 −users trade off capability, latency, and cost per query.}
3 +\caption{Model layer at the audited commit. The reference path targets the Anthropic Messages API;
4 +adaptive extended thinking is enabled only for the models listed as supporting it. OpenAI and
5 +Google models are served through an OpenAI-compatible adapter that receives the first 128 tools of
6 +the 245-tool catalogue. Model identifiers are reproduced verbatim from the client configuration
7 +(\texttt{client/src/lib/models.ts}); the Anthropic identifiers were checked against the provider's
8 +current model list, the others were not audited.}
7 9 \label{tab:models}
8 10 \begin{threeparttable}
9 −\begin{tabular}{@{}llcc@{}}
11 +\footnotesize
12 +\begin{tabular}{@{}llccl@{}}
10 13 \toprule
11 −Role in platform & Model family & Adaptive thinking & Typical use \\
14 +Provider path & Model identifier & Adaptive thinking & Context & Role in selector \\
12 15 \midrule
13 −Default & Reasoning-augmented (1M ctx) & Yes & Comprehensive reports \\
14 −High capability & Flagship reasoning & Yes & Hardest analyses \\
15 −Balanced & Mid-tier reasoning & Yes & Moderate queries \\
16 −Low latency & Fast tier & No & Simple lookups \\
16 +Anthropic (reference) & \texttt{claude-fable-5} & yes & 1M & default \\
17 +Anthropic & \texttt{claude-opus-4-8} & yes & 1M & long-horizon agentic \\
18 +Anthropic & \texttt{claude-opus-4-7} & yes & 1M & balanced \\
19 +Anthropic & \texttt{claude-opus-4-6} & yes & 1M & fast and capable \\
20 +Anthropic & \texttt{claude-sonnet-4-6} & yes & 1M & general purpose \\
21 +Anthropic & \texttt{claude-haiku-4-5-20251001} & no & 200K & lowest latency \\
22 +OpenAI-compatible & twelve OpenAI identifiers & n/a & -- & not audited \\
23 +OpenAI-compatible & four Google identifiers & n/a & -- & not audited \\
17 24 \bottomrule
18 25 \end{tabular}
19 26 \begin{tablenotes}[flushleft]
20 27 \footnotesize
21 −\item \textit{Notes.} Per-response generation is capped at 64{,}000 tokens. Adaptive thinking
22 −lets the model allocate a variable budget of private reasoning before responding; its summary is
23 −streamed to the client and shown in a collapsible panel. Context-window sizes and per-token
24 −prices are determined by the model provider and abstracted away from the orchestration logic.
28 +\item \textit{Notes.} Per-response generation is capped at 64{,}000 tokens and the temperature is
29 +set to~1 on the reference path; the summarisation call of Algorithm~\ref{alg:context} uses a cap
30 +of 2{,}000 tokens and a temperature of 0.5. The Beamer restructuring call
31 +(Section~\ref{subsec:docs}) is pinned to \texttt{claude-opus-4-8} irrespective of the selected
32 +model. Cost is computed from a single fixed schedule (\$3 per million input tokens, \$15 per million
33 +output tokens) for every model, so the ledger does not reflect per-model prices
34 +(Section~\ref{subsec:accounting}).
25 35 \end{tablenotes}
26 36 \end{threeparttable}
27 37 \end{table}
modified paper/tables/robustness.tex +21 −18
@@ -1,30 +1,33 @@
1 1 \begin{table}[htbp]
2 2 \centering
3 −\caption{Operational characteristics of the platform. Latencies are indicative order-of-magnitude
4 −figures for the corresponding subsystems rather than benchmarked measurements; they motivate the
5 −streaming and single-call design choices discussed in the text.}
6 −\label{tab:robustness}
3 +\caption{Design rationale. Each mechanism is listed with the constant it uses at the audited
4 +commit, the property it is intended to secure, and the measurement in the protocol of
5 +Section~\ref{subsec:protocol} that would test it. No measurement has been made.}
6 +\label{tab:rationale}
7 7 \begin{threeparttable}
8 −\begin{tabular}{@{}lll@{}}
8 +\footnotesize
9 +\begin{tabular}{@{}>{\raggedright\arraybackslash}p{3.4cm}>{\raggedright\arraybackslash}p{2.7cm}>{\raggedright\arraybackslash}p{4.3cm}>{\raggedright\arraybackslash}p{4.6cm}@{}}
9 10 \toprule
10 −Dimension & Mechanism & Indicative characteristic \\
11 +Mechanism & Constant & Intended property & Would be measured by \\
11 12 \midrule
12 −First-token latency & SSE streaming & sub-second perceived response \\
13 −Tool concurrency & batched execution & $\leq 5$ tools / batch, 500\,ms spacing \\
14 −Context window & adaptive summarization & effectively unbounded history \\
15 −Generation cap & per-response limit & 64{,}000 tokens \\
16 −Python analysis & sandboxed subprocess & seconds per execution \\
17 −PDF rendering & headless browser & several seconds \\
18 −Slide compilation & two-pass \LaTeX{} & roughly ten seconds \\
19 −Cost control & local token estimation & per-session accounting \\
20 −Rate-limit safety & inter-batch delay & bounded provider load \\
13 +SSE streaming (\S\ref{subsec:transport}) & flush per event & perceived latency decoupled from total latency & time to first token vs.\ end-to-end latency \\
14 +Recursive loop (\S\ref{subsec:loop}) & no depth bound & tool-use/tool-result pairing preserved across turns & protocol errors per 1{,}000 calls; recursion depth distribution \\
15 +Batched execution (\S\ref{subsec:batching}) & 5 per batch; 500\,ms & bounded provider load without altering what the model sees & rate-limit errors and latency at batch sizes 1, 5, $\infty$ \\
16 +Prompt routing (\S\ref{subsec:routing}) & 1--2 / 3--5 / 10+ tools & effort proportional to request complexity & tool-selection precision and recall by request class \\
17 +Per-result truncation (\S\ref{subsec:context}) & 3{,}000 / 15{,}000 chars & verbose results do not crowd the window & accuracy loss on tasks whose answer lies past the cut \\
18 +Re-send cap & 5{,}000 chars & re-sent history stays compact & input tokens per turn over 20-turn sessions \\
19 +Adaptive summarisation & $\tau=10^{5}$; $k=5$ & coherence over long sessions & retention of planted facts after summarisation \\
20 +Token correction (\S\ref{subsec:accounting}) & max(provider, local) & cost never understated for text & ledger vs.\ provider invoice over a month \\
21 +Single-call convention (\S\ref{subsec:onecall}) & instruction only & one round trip per analysis & round trips and sandbox failure rate with vs.\ without the instruction \\
22 +Process sandbox (\S\ref{subsec:sandbox}) & 90\,s; 150\,dpi & server isolated from code faults & crash containment under fault injection \\
23 +Live-formula spreadsheets (\S\ref{subsec:docs}) & --- & deliverable carries its derivation & share of cells that are formulas \\
21 24 \bottomrule
22 25 \end{tabular}
23 26 \begin{tablenotes}[flushleft]
24 27 \footnotesize
25 −\item \textit{Notes.} Figures characterize the subsystems qualitatively to explain design
26 −trade-offs; a controlled performance evaluation is left to future work
27 −(Section~\ref{sec:conclusion}).
28 +\item \textit{Notes.} Constants are those of \path{server/routes.ts},
29 +\path{server/services/claudeService.ts}, \path{server/services/claude/tokenManagement.ts},
30 +and \path{server/services/python/var.ts} at commit \texttt{e2a148a}.
28 31 \end{tablenotes}
29 32 \end{threeparttable}
30 33 \end{table}
modified paper/tables/tools.tex +25 −23
@@ -1,36 +1,38 @@
1 +% Generated by docs/verify/audit_vquant_code.py from vquant.git commit e2a148a (2026-10-17). Do not edit by hand.
1 2 \begin{table}[htbp]
2 3 \centering
3 −\caption{Taxonomy of the tool catalogue exposed to the model. VQuant defines more than two
4 −hundred tools through a schema-driven function-calling protocol. Counts are approximate and
5 −group conceptually related endpoints; the financial families are backed by a market-data
6 −provider exposing over 265 endpoints, wrapped by roughly 230 typed server functions.}
4 +\caption{Tool catalogue exposed to the model, by family. Counts are exact and were extracted programmatically from the tool-definition module of the audited code (vquant.git, commit e2a148a, 2 October 2026): 245 schema-defined tools. The financial families wrap two commercial market-data providers (249 typed wrapper functions over 233 distinct endpoint paths of the primary provider, plus the EODHD family); the web-research family wraps three services. Models served through the OpenAI-compatible adapter receive only the first 128 tools of the catalogue because of that interface's limit.}
7 5 \label{tab:tools}
8 6 \begin{threeparttable}
9 −\begin{tabular}{@{}lll@{}}
7 +\footnotesize
8 +\begin{tabular}{@{}>{\raggedright\arraybackslash}p{5.0cm}r>{\raggedright\arraybackslash}p{8.6cm}@{}}
10 9 \toprule
11 −Family & Count & Representative tools \\
10 +Family & Tools & Representative tools \\
11 +\midrule
12 +Fundamentals, valuation and classification & 56 & profile, income statement, balance sheet, cash flow, key metrics, DCF, screener \\
13 +SEC filings, transcripts and ownership & 37 & filings by form/CIK/symbol, 8-K, call transcripts, 13F, institutional holders \\
14 +Events, calendars and corporate actions & 15 & earnings, dividends, splits, IPO calendars, M\&A, market hours \\
15 +Forex, crypto and commodities & 15 & FX and crypto quotes and lists, commodity quotes, batch quotes \\
16 +Web research (Firecrawl, Tavily, Exa) & 14 & scrape, crawl, map, extract, agent; search, research; neural search \\
17 +Insider and congressional trading & 14 & insider trades and statistics, House and Senate disclosures \\
18 +Indices, ETFs and funds & 14 & S\&P 500 / Nasdaq / Dow constituents, ETF holdings and weightings \\
19 +Quotes, prices and market movers & 14 & quote, historical and intraday prices, gainers, losers, actives \\
20 +Technical indicators & 12 & RSI, MACD, SMA/EMA/WMA/DEMA/TEMA, ADX, CCI, stochastic, Williams \%R \\
21 +Analysts, ratings and price targets & 11 & estimates, price targets, grades, ratings, upgrades/downgrades \\
22 +News and press releases & 9 & stock, forex, crypto and general news; press releases \\
23 +ESG, compensation and alternative data & 9 & ESG scores and benchmarks, social sentiment, headcount, executive pay \\
24 +Global market data (EODHD) & 8 & symbol search, EOD and intraday bars, fundamentals, news (70+ exchanges) \\
25 +Economic and macro & 6 & treasury rates, indicators, economic calendar, COT reports, risk premium \\
26 +Search and identifiers & 5 & company, symbol, CUSIP, ISIN and CIK lookup \\
27 +Options & 4 & option chain, contract prices, Greeks (EODHD); Black--Scholes pricer \\
28 +Advanced analysis & 2 & custom Python execution, bulk data download, SEC filing extraction \\
12 29 \midrule
13 −Company fundamentals & 40+ & profile, income statement, balance sheet, cash flow, ratios \\
14 −Market data & 30+ & quote, historical / intraday prices, market movers, batch quote \\
15 −Technical analysis & 8+ & RSI, MACD, EMA/SMA, ADX, CCI, stochastic, Williams \%R \\
16 −Analyst and ratings & 20+ & estimates, price targets, upgrades/downgrades, rating history \\
17 −Insider and institutional & 15+ & insider trades, 13F filings, congressional/senate trading \\
18 −Economic and macro & 15+ & treasury rates, indicators, calendar, COT reports \\
19 −Forex and crypto & 15+ & FX and crypto quotes, lists, historical series, commodities \\
20 −SEC and compliance & 25+ & filings by form type, company notes, call transcripts \\
21 −Events and calendars & 10+ & earnings, dividends, splits, IPO calendar and disclosures \\
22 −ESG and alternative & 20+ & ESG scores, social sentiment, headcount, executive pay \\
23 −Options & 4 & option chain, prices, Greeks, volatility surface \\
24 −Advanced analysis & 7 & Monte Carlo, Black--Scholes, custom Python, bulk download \\
25 −Web research & 6 & scrape, crawl, extract; AI / semantic / engine search \\
30 +Total & 245 & \\
26 31 \bottomrule
27 32 \end{tabular}
28 33 \begin{tablenotes}[flushleft]
29 34 \footnotesize
30 −\item \textit{Notes.} The system prompt instructs the model to select tools according to query
31 −complexity (Section~\ref{subsec:routing}); the most powerful entries---Monte Carlo simulation,
32 −option pricing, and arbitrary Python execution---are described in detail in
33 −Section~\ref{sec:capabilities}.
35 +\item \textit{Notes.} Family assignment follows keyword rules on tool names (\texttt{docs/verify/audit\_vquant\_code.py}); a tool belongs to exactly one family. The system prompt (Section~\ref{subsec:routing}) describes only a subset of these tools explicitly; the full catalogue is transmitted as JSON schemas with every model call. Six server-side handlers for pre-built numerical routines (Monte Carlo, GARCH, VaR, portfolio optimisation, risk metrics, plotting) exist in the route module but are not in the catalogue at the audited commit and are therefore unreachable by the model (Section~\ref{subsec:numerical}).
34 36 \end{tablenotes}
35 37 \end{threeparttable}
36 38 \end{table}
37 39