StockAgent 研究筆記¶
資料來源¶
| 項目 | 連結 |
|---|---|
| GitHub Repo | https://github.com/MingyuJ666/Stockagent |
| 論文(arXiv) | When AI Meets Finance (StockAgent), arXiv:2407.18957(v1 2024-07-15 → v5 2026-06-23,33 頁、10 圖) |
| 發表 | ACM Transactions on Intelligent Systems and Technology (TIST) |
| 相依工具 | PromptCoder / procoder(prompt 組裝 DSL,需自行 clone 安裝) |
作者群:Chong Zhang(Liverpool)、Xinyi Liu(北大)、Zhongmou Zhang(上財)、Mingyu Jin(Rutgers)等 13 人,跨英美中三地七所學校,通訊作者 Yongfeng Zhang(Rutgers)。
Repo 現況(2026-07-28):★ 684 / fork 162 / 無 LICENSE 檔 / Python / 建立 2024-02-02 / 最後 push 2026-06-16。程式碼本體只有 7 個 .py(約 60KB),其餘是 4 張架構圖與 .idea/、__pycache__/(未 gitignore)。
專案概述¶
StockAgent 問的是一個模擬問題而非預測問題:如果讓一群 LLM 扮演散戶、在一個沒有歷史行情可查的虛構市場裡自由交易,外部因素(利率、財報、政策事件、論壇八卦)會怎麼改變他們的行為與價格?
它的核心設計主張是「避開 test set leakage」。既有的 LLM 交易模擬多半直接餵真實歷史股價,於是模型可能是在回憶訓練資料而不是在決策——你分不出它是「判斷」還是「背答案」。StockAgent 的做法是造一個完全虛構的市場:公司 A/B(新版擴充到 A/B/C/D)、自編的財報數字、自編的政策事件,LLM 沒有任何先驗知識可用。
論文設定三個 research question:
| RQ | 問題 |
|---|---|
| RQ1 — Simulation Effectiveness | 換不同 LLM 驅動模擬,交易決策還可信嗎? |
| RQ2 — LLM Reliability | 股票推薦與交易策略會被所選 LLM 的內在傾向影響嗎? |
| RQ3 — External Conditions | 財務數據、市場指標、基準利率、突發事件、盤後 BBS 討論如何影響交易行為? |
論文實驗用的是 GPT-3.5-turbo-0125 與 Gemini-pro-1.0 兩個模型。
模擬機制¶
四階段流程¶
Initial Phase agent 隨機初始化(持股/現金/負債,性格四選一)
↓
Trading Phase 每日 N 個 session,隨機打亂交易順序,逐一問 LLM 下單
↓
Post-Trading Phase Daily: 論壇發文 + 預測明日行動
Quarterly: 財報發布
↓
Special Events 隨機交易日觸發(降準降息 / 升息)
每個 agent 的一天¶
# main.py 主迴圈(簡化)
for date in 1..TOTAL_DATE:
agent.loan_repayment(date) # 到期還本,cash<0 → is_bankrupt
if date in REPAYMENT_DAYS: 付息
if is_bankrupt: bankrupt_process() # 強制賣股補現金,補不足則退場
if date == EVENT_DAY: 改 LOAN_RATE + 往論壇塞一則官方訊息
agent.plan_loan(...) # LLM 決定要不要借錢
for session in 1..TOTAL_SESSION:
random.shuffle(交易順序)
for agent: action = agent.plan_stock(...) # LLM 回一個 JSON 下單
handle_action(...) # 撮合
stock.update_price(date) # 價格 = 該 session 最後一筆成交價
agent.next_day_estimate() # LLM 預測自己明天會不會買/賣/借
agent.post_message() # LLM 發論壇文 → 成為所有人明天的輸入
論壇(BBS)是這個模擬最關鍵的社會性設計:每個 agent 收盤後發一則貼文,隔天所有 agent 的 prompt 裡都會看到全部人的貼文。這是唯一的 agent 間資訊通道,也是後面「群體趨同」現象的來源。
Secretary:規則式格式守門員¶
Secretary 這個類別在論文裡聽起來像個 LLM 角色,但在釋出的程式碼裡它是純 Python 的 JSON 驗證器——check_loan / check_action / check_estimate 全是手寫的格式與額度檢查(大括號只能有一組、loan 只能 yes/no、買不能超過現金、賣不能超過持股)。驗證失敗就把錯誤訊息塞回 retry prompt,最多重試 3 次,仍失敗就當作「今天不動作」。
Secretary.run_api() 確實有一條 LLM 路徑,但它 openai.api_key = "" 寫死空字串,而且 agent.py 從頭到尾沒呼叫過 get_response()——是死程式碼。
撮合規則¶
handle_action() 的成交條件是價格完全相等(if action["price"] == sell_action["price"]),沒有價格穿越(買價 100 不會吃掉賣價 99 的單)。撮合不成的單留在當日 order book 裡,隔天全部清空。收盤價 = 該 session 最後一筆成交價;當日無成交則價格不變。
論文的實際結論¶
1. 換一個 LLM 就換一種市場(RQ1)¶
| GPT-3.5 驅動 | Gemini-pro 驅動 | |
|---|---|---|
| 交易頻率 | 較低 | 較高 |
| 單筆成交量 | 顯著較大 | 較小 |
| 對 Stock A | 更謹慎 | A 與 B 頻率相近,整體活躍 |
| 價格走勢 | ~1750 rounds,A 從 30 漲到 107 | ~470 rounds,A 從 30 漲到 48 |
論文對這件事的態度很直白:「使用 StockAgent 做測試的使用者與交易所應注意,模擬結果可能因 LLM 選擇而產生偏差。」
2. 群體行為的差異更值得注意(RQ2)¶
用 cluster analysis + t-SNE 看 agent 群體分布:
- Gemini agents 彼此高度相似、群體行為一致 → 明顯的羊群效應(herding)與趨勢跟隨
- GPT agents 在視覺化中分散 → 個體差異大、更獨立,論文形容為「能體現個人化的投資策略與風格」
這對「用 LLM multi-agent 模擬社會系統」是個一般性警訊:你觀察到的「群體現象」有多少是被模擬對象的性質,有多少只是底層模型的性格?
3. 外部條件消融實驗(RQ3)¶
論文逐一拿掉五種外部資訊,觀察價格與行為:
| 拿掉什麼 | 觀察到的效果 |
|---|---|
| 利率變動 | agent 對市場與公司表現更樂觀;Stock A 交易頻率顯著上升;部分 agent 由虧轉盈 |
| BBS 論壇討論 | 心理估值轉保守、壓低股價;agent 行為更謹慎、避免大額交易 |
| 非首輪貸款 | agent 更保守 |
| 財報 | 部分 agent 由虧轉盈 |
| 任一種財務資訊 | agent 之間的損益差距擴大(變異變大),市場競爭更激烈 |
另外 Stock B(新上市股)因為缺少 BBS 資訊流通,被 agent 壓到低於理想估值,並在第 21 個交易輪出現 flash crash。
4. 最重要的一句結論¶
儘管受外部因素影響,模型的內在交易傾向在單步交易中依然明顯,顯示 context learning 並未顯著改變它們面對市場的根本取徑。
換句話說:你可以用 prompt 改變 LLM 看到什麼,但改不掉它的交易性格。論文把「不同 LLM 能否可靠地擔任交易員」明確列為未解問題。
快速開始¶
conda create --name stockagent python=3.9 && conda activate stockagent
git clone https://github.com/dhh1995/PromptCoder && cd PromptCoder && pip install -e . && cd ..
git clone https://github.com/MingyuJ666/Stockagent && cd Stockagent
pip install -r requirements.txt
export OPENAI_API_KEY=... # 或 export GOOGLE_API_KEY=...
python main.py --model gemini-pro
目前限制與注意事項¶
以下都是實際讀 HEAD(e2a9c05,2026-06-16)程式碼交叉比對後的發現,不是推測。
A. 設定檔與執行程式碼已經對不上¶
2026-06-08 那兩個 commit(Update util.py、Update agent_prompt.py)把設定與 prompt 升級到一個四檔股票、含非 LLM baseline、多 seed 的新實驗設計,但 main.py / agent.py / stock.py 全部停在 2024 年版本:
| 檔案(新) | 宣告了什麼 | 檔案(舊) | 實際支援 |
|---|---|---|---|
util.py |
STOCK_NAMES = ["A","B","C","D"]、Table 3/5/7/9 財務常數、Table 10 理想價格區間、RQ1/RQ2/RQ3 run seeds |
main.py |
只建立 Stock("A") 與 Stock("B") |
util.py |
SUPPORTED_PROVIDER_MODELS = [gpt-5.5, Claude-4.6-Sonnet, gemini-3.1-flash-lite, DeepSeek-V4-flash, claude-haiku-4-5] + YunWu gateway + resolve_model_name() |
agent.py |
run_api() 只認模型名含 gpt 或 gemini,其餘回傳 None;resolve_model_name 從未被呼叫 |
util.py |
NON_LLM_BASELINES = [Fundamental Trader, Trend Follower, Noise Trader] |
— | 沒有任何 baseline 實作 |
util.py |
import settings as local_settings |
— | repo 裡沒有 settings.py,也沒有 settings.example.py |
agent_prompt.py |
模板需要 {stock_c_price}、{stock_d_price}、{stock_c_deals}、{stock_d_deals}、{stock_c}、{stock_d} |
agent.py |
inputs dict 完全沒提供這六個變數 |
最後一項最致命:format_prompt(prompt, inputs) 拿不到模板要求的變數。實際是 raise KeyError 還是留下未填佔位符取決於 procoder 的行為,但無論哪種,四檔股票的模擬都不會正確運作——main.py 只有兩檔股票、buy_stock() 裡還寫死 stock_name not in ['A','B']。
值得注意的是論文 v5(2026-06-23 修訂)附錄裡的 prompt 仍然是兩檔股票 A/B。所以 repo 的新設定是為某個尚未發表的擴充版準備的半成品,不是 v5 的對應實作。
B. 預設參數下所有事件都不會觸發¶
TOTAL_DATE = 10 # 模擬只跑 10 天
SEASON_REPORT_DAYS = [12, 78, 144, 210] # 財報最早第 12 天
EVENT_1_DAY = 78 ; EVENT_2_DAY = 144 # 降準/升息
REPAYMENT_DAYS = [22, 44, 66, ...] # 付息最早第 22 天
10 < 12 < 22 < 78 < 144。用預設值跑一次,會得到一個沒有財報、沒有政策事件、沒有付息的十天市場——也就是論文 RQ3 想研究的東西一個都不會出現。要重現論文結果必須自己把 TOTAL_DATE 調大。
C. 兩處參數順序不符的呼叫¶
1. 持股數量記成價格。 main.py 四個成交點都這樣呼叫:
# main.py
get_agent(...).buy_stock(stock.name, close_amount, action["price"])
# agent.py — 簽章是 (stock_name, price, amount)
def buy_stock(self, stock_name, price, amount):
self.cash -= price * amount # 乘法可交換,現金正確
if stock_name == 'A':
self.stock_a_amount += amount # ← amount 收到的是「價格」
現金因為乘法可交換所以算對了,但持股張數增加的是成交價、不是成交量。sell_stock 同樣。
2. 貸款重試路徑。 check_loan 的簽章是 (resp, max_loan),但重試分支呼叫 self.secretary.check_loan(date, resp)(agent.py:208)——把日期當成回應傳進去。
D. 其他¶
| 項目 | 說明 |
|---|---|
| 無 LICENSE | repo 沒有授權檔案。README 只給 citation,未授權任何使用條款。要在專案裡用它的程式碼需先聯繫作者 |
| 論文模型已過時 | 實驗用 GPT-3.5-turbo-0125 與 Gemini-pro-1.0(2024 年初)。今日模型的交易性格是否仍如論文所述,未經驗證 |
| 市場微結構極簡 | 撮合要求價格完全相等、無價格穿越、無做空、無流動性提供者、隔日清空所有掛單。價格由「最後一筆成交價」決定 |
| 無回測對照 | 虛構市場帶來的代價是沒有 ground truth。無法判斷 agent 的行為是否「合理」,只能做組間比較 |
| 版控衛生 | .idea/、__pycache__/(含 .pyc)都進了 git |
requirements.txt 僅 95 bytes |
未鎖版本,2024 年的 google.generativeai 與 openai API 介面在今日環境可能已不相容 |
研究價值與啟示¶
關鍵洞察¶
1. 「避開 test set leakage」這個設計動機,比模擬結果本身更重要。 LLM 做金融預測的評測有一個結構性難題:你餵它 2023 年的行情問它明天怎麼走,它可能只是記得。StockAgent 的解法是把整個市場虛構掉——自編公司、自編財報、自編政策。這確實斷開了記憶通道,但代價也是結構性的:沒有真實市場當基準,你只能做組間比較(GPT vs Gemini、有 BBS vs 無 BBS),永遠無法回答「哪一組更接近真實」。 這是 LLM 社會模擬類研究的共同困境,StockAgent 把它擺得特別清楚。
2. 「換一個 LLM 就換一種市場」對所有 LLM 社會模擬研究都是壞消息。 論文最紮實的發現不是「利率影響交易」(這是常識),而是 GPT 群體分散、Gemini 群體趨同這個對比。如果你想用 multi-agent LLM 模擬任何社會現象——市場、輿論、組織——你觀察到的「湧現行為」有一部分只是底層模型的性格投影。論文自己的結論「context learning 並未顯著改變模型面對市場的根本取徑」等於承認:prompt 改得動它看到什麼,改不動它是誰。 這也直接反駁了「換個 prompt 就能讓 LLM 扮演任意投資人型態」的直覺。
3. 消融實驗裡最反直覺的一條:拿掉利率資訊讓 agent 變樂觀。 一般預期是「資訊變少 → 更保守」,但實驗結果相反——移除利率變動後 agent 對市場與公司表現更樂觀、Stock A 交易頻率顯著上升,部分 agent 甚至由虧轉盈。合理的解讀是:利率資訊在這個模擬裡主要扮演風險提示的角色,拿掉它等於拿掉了唯一會定期提醒 agent「借錢有成本」的訊號。相對地,拿掉 BBS 反而讓估值轉保守——社群討論在這個系統裡是推升價格的力量,不是穩定力量。
4. Secretary 是規則式驗證器,而不是 LLM——這其實是正確的工程選擇,值得抄。
論文架構圖裡 Secretary 看起來像個代理角色,實作卻是純 Python 的格式與額度檢查 + 最多 3 次帶錯誤訊息的重試。這比「再叫一個 LLM 來檢查前一個 LLM」便宜幾個數量級,而且格式驗證本來就是確定性問題。任何要讓 LLM 輸出結構化動作的系統,都該把「格式合法性」與「額度合法性」放在確定性的守門員裡,不要浪費一次 API 呼叫。 唯一的缺陷是它留了一條 api_key = "" 的死程式碼路徑沒清掉。
5. 這個 repo 是「論文程式碼」這個品類的典型樣本,讀它要用不同的標準。 684 star、162 fork、ACM TIST 接收,同時有:無 LICENSE、參數順序寫反、預設參數下事件全不觸發、設定檔比執行程式碼超前一整個實驗設計。這不是作者不用心——是論文程式碼的目的是「支撐論文裡那組數字」,不是「讓別人跑」。162 個 fork 裡有多少人真的跑成功過,是個有意思的問題。想引用它的結論可以放心(論文經過同儕審查);想直接跑它的程式碼,得先自己修上面那幾處。
6. 把「模擬」與「賺錢」分開看,這個專案的定位才成立。 它不是交易系統、不預測任何真實標的、backtest 對它沒有意義。它是一個用來研究「LLM 當投資人時是什麼樣子」的實驗裝置。這個定位在 LLM 金融應用裡是少數派——多數專案在追報酬率,StockAgent 在追行為特徵。從風險管理角度看,後者可能更有用:在你把 LLM 放進交易決策鏈之前,先知道它的內建偏誤長什麼樣。
與其他專案的關聯¶
| 專案 | 關係 |
|---|---|
| AI Hedge Fund | 目的完全相反的鏡像。AI Hedge Fund 用多個 LLM 角色(各投資大師 agent)追求報酬,跑真實歷史資料;StockAgent 用多個 LLM 角色觀察行為,刻意避開真實資料。前者的 test set leakage 風險,正是後者要解決的問題 |
| TradingAgents、AI-Trader、Vibe-Trading | 同屬 LLM × 交易,但都是「決策系統」;StockAgent 是「市場模擬器」。這四個放在一起可以看出這個領域的兩條分岔:做決策 vs 研究決策者 |
| 多 Agent 辯論會 | 同樣關心「多個 LLM 互動時會湧現什麼」。StockAgent 的 BBS 論壇機制就是一個受限的辯論場——差別是它有價格這個客觀後果,可以量測「說服」的實際影響 |
| Prediction Market Analysis | 都在研究「群體如何把資訊變成價格」。StockAgent 的優勢是可以做消融(拿掉 BBS 看會怎樣),真實預測市場做不到 |
| 本站量化交易分類的 Kelly / Drawdown 系列 | 那些是規範性研究(最優策略應該長怎樣);StockAgent 是描述性研究(LLM 實際會怎麼做)。有意思的對照題:把 Kelly 準則寫進 system prompt,LLM agent 會遵守嗎?論文的「內在傾向不因 context learning 改變」暗示答案可能是否定的 |
| i-have-adhd、BYOA Core | 同樣提醒「模型選擇本身就是一個未受控變因」。BYOA 的 eval 用 system_prompt_hash 綁定提示詞版本;StockAgent 的教訓則是連模型本身都該被當成實驗條件記錄下來,因為 GPT 和 Gemini 跑出的是兩個不同的市場 |