Qiqi Duan1,*, Changlun Li1,2,*, Chen Wang1,*, Fan Zhang2,4, Mengxiang Wang1, Dayi Miao1, Peixian Ma2, Jiangpeng Yan3, Liyuan Chen3, Shuoling Liu3, Preslav Nakov4, Yuyu Luo1,2, Nan Tang1,2
1HKUST(GZ) 2Paradoox AI Research 3E Fund Management Co., Ltd 4MBZUAI
*Equal contribution. Β Β Contact: nantang@hkust-gz.edu.cn
π₯ Our work is accepted by EMNLP 2026 Findings. Welcome to star and cite our work! β¨
TradeLens is a trace-grounded toolkit for measuring and diagnosing the profit vs. cost of agentic trading systems.
Large language model (LLM) agents are increasingly used in trading systems, where reasoning, tool use, and repeated portfolio decisions introduce non-negligible deployment costs. A system can look profitable on returns yet still fail to create useful value once costs are accounted for, and diagnosing the root cause is hard because profit and cost arise from intertwined mechanisms.
We argue that agentic viability should be a central evaluation criterion: dynamic LLM-mediated decisions should generate enough incremental profit to justify the costs they induce. TradeLens reconstructs trading trajectories from records and traces, attributes profit and cost to interpretable evidence, and diagnoses whether, where, and why an agent succeeds or fails to pay for its own intelligence.
Overall, TradeLens supports:
- Measurement β profit and cost attribution for multi-factor agentic trading deployments.
- Diagnosis β trading performance analysis and system-level diagnosis with evidence-grounded revision suggestions.
@inproceedings{duan2026can,
title={Can Agentic Trading Systems Pay for Their Own Intelligence?},
author={Duan, Qiqi and Li, Changlun and Wang, Chen and Zhang, Fan and Wang, Mengxiang and Miao, Dayi and Ma, Peixian and Yan, Jiangpeng and Chen, Liyuan and Liu, Shuoling and Nakov, Preslav and Luo, Yuyu and Tang, Nan},
booktitle={The 2026 Conference on Empirical Methods in Natural Language Processing},
year={2026},
url={https://openreview.net/forum?id=4AWZckdl2J}
}The toolkit loads experiment records and static config from data/, computes trading costs (commission, token usage, infra, monthly data subscription, and a per-day uncertain add-on), reconstructs portfolio value, and decomposes profit into market / selection / timing effects (full-cash and invested-only benchmarks).
It writes reports under result/ and, when configured, runs LLM diagnosis on top of the financial report.
TradeLens/
βββ π data/ # Input: records, static configs, price JSONL
βββ π toolkit/ # Toolkit: measurement + diagnosis
β βββ π main.py # CLI and end-to-end pipeline
β βββ π cost/ # Commission, token/infra/monthly/uncertain costs
β βββ π profit/ # Records, portfolio valuation, profit breakdown
β βββ π report/ # Financial report, plots, LLM agent, HTML render
β βββ π config.py # Load config.json, static config, LLM pricing
βββ π result/ # Output: one folder per run (gitignored)
βββ π main.py # Entry: python main.py β toolkit.main
βββ π config_llm.json # Per-model token pricing
βββ π config.json # Paths into data diagnosis settings
βββ π env.example # API keys for LLM diagnosis
- π Overview
- π Citations
- π Introduction
- π Usage
- π Integrate with your agentic trading system
- π§ Troubleshooting
python -m venv .venv&&source .venv/bin/activatepip install -r requirements.txt- Edit
config.json, and pointrecords_path/static_pathto your files underdata/ - Edit
config_llm.jsonso each model in your records has a pricing row (otherwise token cost will be 0) - Copy
.env.example' to.env' and set your URL and API key - Run:
python main.py- (optional overrides)
python main.py --records data/...jsonl --static data/...jsonl --out result/my-run
python main.py --help
python main.py [--config CONFIG] [--records RECORDS] [--static STATIC] [--out OUT] [--benchmark SYMBOL]
| Field | Description |
|---|---|
records_path |
Experiment records JSONL, e.g. data/experiment_records_*.jsonl |
static_path |
Static config JSON/JSONL, e.g. data/static-*.jsonl |
prices_path |
Daily prices JSONL, e.g. data/price-data.jsonl |
market_base_path |
Optional benchmark price JSONL, e.g. data/market-base.jsonl |
agent_model |
LLM model for diagnosis (optional) |
benchmark_symbol |
Benchmark symbol (default SPY) |
llm_call_success_rate |
Scales token costs (default 1.0) |
- Records (JSONL): each line is a trading-day record; key fields include
date,llm_usage,trades(withdecision_type,ticker,quantity, and prices). - Static (JSON or JSONL): deployment metadata such as
initial_cash,decision_frequency,data_subscription_monthly,start_time,end_time, andllm_model. - Prices (JSONL): Alpha Vantageβstyle daily buy prices per symbol (see
data/price-data*.jsonl).
Default output directory:
result/<llm_model>-<initial_cash>-<frequency>/(or pass--out)
Common files:
*-action.txt: daily actions and cost ledger*-financial-report.mdand*-financial-report.html: financial report + embedded charts*-llm-analysis.mdand*-llm-analysis.html: LLM diagnosis (when enabled)charts/*.png: charts referenced by the markdown reports
TradeLens is an after-the-fact analysis toolkit: you run your own agentic trading system, export its records/traces, then run TradeLens to attribute profit & cost and generate reports.
Write one JSON object per line (JSONL). Each line corresponds to one decision day (recommended date format: YYYY-MM-DD).
Minimal example:
{"date":"2026-01-02","model":"gpt-5.2","llm_usage":{"model":"gpt-5.2","input_tokens":1200,"output_tokens":450,"cached_tokens":0,"latency_ms":820},"trades":[{"decision_type":"BUY","ticker":"AAPL","quantity":10,"analysis_price":188.12,"execution_price":188.40,"timestamp":{"analysis_time":"2026-01-02T14:30:00Z","decision_time":"2026-01-02T14:30:01Z"}}]}Notes:
llm_usage.modelmust match a key inconfig_llm.json(otherwise token cost cannot be priced).- If you provide both
analysis_priceandexecution_price, TradeLens can estimate slippage/opportunity cost. - If you provide
timestamp.analysis_timeandtimestamp.decision_time, TradeLens can compute analysisβdecision latency.
TradeLens expects a JSON file with a required structure field. Fields in structure are merged into the top-level config.
Minimal example:
{
"structure": {
"llm_model": "gpt-5.2",
"initial_cash": 100000,
"decision_frequency": "daily",
"data_subscription_monthly": 100.0,
"start_time": "2026-01-01",
"end_time": "2026-01-30"
}
}Provide trading asset prices for your predefined time window from the same data source as your system.
{"Meta Data":{"2. Symbol":"AAPL"},"Time Series (Daily)":{"2026-01-02":{"1. buy price":"188.12"},"2026-01-03":{"1. buy price":"190.05"}}}python main.py --records /path/to/experiment_records.jsonl --static /path/to/static.json --out result/my-runIf your system makes multiple intraday decisions, pre-aggregate records to hourly entries.
records_path not found/static_path not found: ensureconfig.jsonpoints to existing files underdata/, or pass--records/--staticexplicitly.- Profit breakdown warning about BUY/SELL: if your records contain only
HOLDdays (no executed trades), profit breakdown charts/attribution may be skipped. - Plotting warnings (
matplotlib/numpy): reinstall dependencies in a fresh venv (e.g. recreate.venv, thenpip install -r requirements.txt). - Uncertain cost changes between runs: the per-day uncertain add-on in
toolkit/main.pyhas no default seed. Callrandom.seed(<int>)at process start (or immediately before that line) if you want comparable reports across runs.

