trader-broker 是做什麼的?
Order Executor 是此系列中唯一可能導致真實訂單的技能,因此也是最嚴格的。訂單只有在每次、每筆都通過三道獨立閘門後,才會送達市場:
- trader-risk 今天已通過此確切訂單(由指紋匹配)。
- 用戶在聊天中為此一筆訂單輸入了明確的「是」。
- 用戶在 Claude 自己的權限卡上點擊了「允許一次」,該卡片會因為訂單工具設定為「需要核准」而出現。
用戶說了兩次「是」,規則給了一次 PASS。沒有「是」,就沒有訂單。
${CLAUDE_SKILL_DIR} 以下是此技能所在的資料夾(此 SKILL.md 所在位置)。
python3 "${CLAUDE_SKILL_DIR}/ticket.py" show # 所有票據,不論是否 READY
python3 "${CLAUDE_SKILL_DIR}/ticket.py" approve --index 1 --reply "yes"
python3 "${CLAUDE_SKILL_DIR}/ticket.py" result --index 1 --status placed --broker-id ID --filled-qty 8 --filled-price 364.20
python3 "${CLAUDE_SKILL_DIR}/ticket.py" fill --symbol TSLA --side sell --qty 8 --price 370.04
python3 "${CLAUDE_SKILL_DIR}/ticket.py" flatten --symbol TSLA --qty 8
python3 "${CLAUDE_SKILL_DIR}/ticket.py" log
ticket.py 從不與經紀商通訊。它負責渲染票據、檢查回覆是否為該訂單的真實「是」、建立平倉票據,並將日誌保存在 trader/state/broker.json 中。使用 --now "2026-10-19 10:15" 來固定時間(紐約時間)。
它讀取和寫入的內容
| 檔案 | 說明 |
|---|---|
trader/orders.json | 提議的訂單(trader-budget 寫入;flatten 會取代它) |
trader/state/risk.json | trader-risk 的裁決;只有今天得到的 PASS 才能讓狀態變為 READY |
trader/state/broker.json | 每個「是」、否、已下單、失敗和已成交的記錄,以及每筆記錄的最大虧損 |
trader/portfolio.json | 現金和持股,由 fill 和 result --filled-qty 更新 |
trader/plan.json | flatten 的平倉時間 |
設定 A:Alpaca(官方 MCP 伺服器,Claude Desktop)
Alpaca 自己的伺服器是 github.com/alpacahq/alpaca-mcp-server (MIT)。它在用戶的電腦上,在 Claude Desktop 內部運行。它不在 Claude 的連接器目錄中。除非另有指示,否則它在紙本帳戶上進行交易。已於 2026-10-20 針對其原始碼進行檢查(版本 2.4.0)。
- 用戶建立一個 Alpaca 帳戶,並在 Alpaca 儀表板中建立紙本交易 API 金鑰。紙本金鑰與實時金鑰是分開的。
- 用戶安裝
uv(它提供了uvx),來自 docs.astral.sh/uv。 - 在 Claude Desktop 中:設定 > 開發者 > 編輯設定。這會開啟
claude_desktop_config.json(macOS:~/Library/Application Support/Claude/,Windows:%APPDATA%\Claude\)。用戶將以下區塊(也在此處的claude_desktop_config.example.json中)加入,並在檔案中輸入他們自己的金鑰:
{
"mcpServers": {
"alpaca": {
"command": "uvx",
"args": ["alpaca-mcp-server"],
"env": {
"ALPACA_API_KEY": "在此檔案中貼上你的紙本金鑰",
"ALPACA_SECRET_KEY": "在此檔案中貼上你的紙本密鑰",
"ALPACA_PAPER_TRADE": "true",
"ALPACA_TOOLSETS": "account,trading,stock-data"
}
}
}
}
env 區塊將金鑰以環境變數的形式傳遞給伺服器。金鑰永遠不應出現在聊天中。 永遠不要要求它們,永遠不要將此檔案讀回對話中,如果用戶仍然貼上了金鑰,告訴他們刪除那條訊息並在 Alpaca 儀表板中建立新金鑰。ALPACA_PAPER_TRADE 預設已為 true;寫出來是為了讓它可見。ALPACA_TOOLSETS 是可選的,用於隱藏他們不需要的工具。
4. 重新啟動 Claude Desktop。
5. 設定工具權限。 自訂 > 連接器(舊版本為設定 > 連接器),開啟 alpaca,然後為每個工具選擇「始終允許」、「需要核准」或「封鎖」:
place_stock_order:需要核准。永遠不要設為「始終允許」。- 其他所有下單、修改、取消或關閉任何東西的工具(
cancel_order_by_id、replace_order_by_id、close_position、update_account_config):需要核准。 place_option_order、place_crypto_order、close_all_positions、cancel_all_orders、exercise_options_position、do_not_exercise_options_position:封鎖,除非用戶有理由並已說明。- 唯讀工具(
get_account_info、get_all_positions、get_open_position、get_orders、get_clock、get_stock_snapshot、get_stock_latest_quote):設為「始終允許」即可。
- 檢查:要求 Claude 提供 Alpaca 帳戶資訊(唯讀),並在 Alpaca 儀表板中確認它是紙本帳戶。
如果使用的是 Claude Code 而非 Claude Desktop,請將訂單工具保持在 ask 模式,在 .claude/settings.json 中設定:"permissions": {"ask": ["mcp__alpaca__place_stock_order"]},並且永遠不要將訂單工具放在 allow 中。
Alpaca 的 bracket 訂單。 place_stock_order 接受 take_profit_limit_price 和 stop_loss_stop_price(以及可選的 stop_loss_limit_price)。當其中任一參數存在時,伺服器會自行將 order_class 設為 "bracket";trader-budget 無論如何都會寫入它,以便票據顯示出來。Bracket 訂單僅限整股,time_in_force 為 day 或 gtc。入場成交後,停損單和獲利了結單會以兩個互相取消的訂單形式在經紀商處等待。它們也是當日訂單,因此會在收盤時結束:這是在那之前平倉的另一個理由。
設定 B:Interactive Brokers(位於 Claude 目錄中的連接器)
Interactive Brokers 發布了一個已驗證的連接器:claude.ai/directory/interactive-brokers(連接器 URL https://api.ibkr.com/v1/api/mcp)。從「自訂 > 連接器 > 瀏覽連接器」添加,並在那裡登入 IBKR,而不是在聊天中。其列表說明 Claude 可以草擬交易指令,發送到用戶的 IBKR 帳戶供他們審查和批准,並且 Claude 永遠不會直接向市場提交訂單。因此,使用 IBKR 時,最終的確認也是在 IBKR 內部進行。在 trader/config.json 中設定 "broker": "ibkr"。將其負責草擬訂單的工具也設為「需要核准」。
步驟:入場
ticket.py show。只有 READY 狀態的票據會顯示給用戶。狀態為 NOT READY 或 BLOCKED 的票據會返回給/trader-risk。- 顯示一個票據並詢問:「下這筆訂單?請回覆 yes 或 no。」一次只問一個訂單。永遠不要提供「全部同意」。
- 執行
ticket.py approve --index N --reply "<用戶的回覆,逐字複製>"。如果它印出「Not recorded」,表示該回覆並非對此訂單的明確「是」(例如「好」、「全部同意」,或一個提及不同股票或數量的「是」)。再次詢問。永遠不要自行將回覆轉變為「是」。 - 只有在印出「Recorded your yes」之後,才使用票據印出的確切 JSON 來呼叫
place_stock_order。會出現 Claude 的卡片:「允許一次」或「拒絕」。 - 記錄發生的事情:
ticket.py result --index N --status placed --broker-id <id> --filled-qty Q --filled-price P(來自回應或get_open_position的成交資訊),或--status denied,或包含--note的--status failed。失敗的訂單不會在未經新檢查和新「是」的情況下重試。日誌會保留該入場訂單的最大虧損,以供 trader-risk 的每日限額使用。
步驟:持倉期間,以及在收盤前出場
- trader-alerts 會監控停損、目標價和平倉時間(
alerts.py add --from-plan)。Bracket 訂單自身的訂單會負責觸發停損。 - 當停損單或獲利了結單成交時,進行記錄:
ticket.py fill --symbol TSLA --side sell --qty 8 --price 358.32。 - 在
flat_by(紐約時間 15:55)之前,任何仍持倉的部位都會被平倉:- 詢問 Alpaca 持有多少股:
get_open_position(唯讀)。 ticket.py flatten --symbol TSLA --qty 8會將這些股票的市價賣單寫入trader/orders.json。/trader-risk。僅平倉用戶所持部位(不會超過持有量)的賣單,永遠不會被每日限額或入場視窗封鎖。ticket.py show,然後用戶對該單一訂單表示「是」,如上所述。- Bracket 訂單的停損單和獲利了結單仍持有這些股票,因此 Alpaca 在它們被取消之前會拒絕新的賣單:使用
get_orders(狀態 open,nested true)來查看它們;對每個訂單使用cancel_order_by_id(需要核准)。然後使用票據執行place_stock_order,接著執行result。
- 詢問 Alpaca 持有多少股:
範例:實際運作
訂單 1 / 1,PAPER 帳戶,Alpaca
買入 8 股 TSLA,市價單,當日有效
停損 358.32
獲利了結 370.04
若停損在 358.32 成交,最大虧損約 $46.88(快速市場中可能成交得更差)
原因:TSLA 開盤區間突破:8 股,受您的每筆交易最大虧損 $50 限制(8 x 5.86 = 在停損點 $46.88)
READY:trader-risk PASS,等待您的確認
Claude 將使用以下確切資料呼叫 place_stock_order:
{"symbol": "TSLA", "side": "buy", "qty": "8", "type": "market", "time_in_force": "day",
"order_class": "bracket", "take_profit_limit_price": "370.04", "stop_loss_stop_price": "358.32"}
用戶回覆「yes」。Claude 記錄下來,呼叫 place_stock_order,卡片上顯示「Claude 想要使用 Place stock order」,附帶該 JSON 和兩個按鈕:「允許一次」、「拒絕」。按「允許一次」即可將訂單發送到紙本帳戶。why 和計劃會保留在檔案中;它們永遠不會被發送出去。
它永遠不會做的事
- 永遠不會在未通過三道閘門的情況下下單,也永遠不會在一次「是」中下兩個訂單。
- 永遠不會從排程或背景任務中下單:因為沒有人在現場說「是」。
- 永遠不會要求、讀取、儲存或重複 API 金鑰或密碼。
- 永遠不會自行切換
ALPACA_PAPER_TRADE或"paper"為實時模式。這需要用戶自己操作。 - 永遠不會自行呼叫
close_all_positions、cancel_all_orders、選擇權或加密貨幣訂單工具。 - 永遠不會保證成交價格:市價單和停損單的成交價格取決於市場情況。
安全性
- 教育和工具用途,而非財務建議。PASS 是規則檢查,而非推薦。
- 預設為紙本交易(
"paper": true)。轉為實時交易是用戶自己的決定,需在其自己的設定檔中進行。 - 此系列中除了 trader-broker 之外,沒有其他技能會下單,且僅在所有三個條件成立時:trader-risk 今天已通過該確切訂單,用戶在聊天中為該單一訂單輸入了明確的「是」,並且用戶在 Claude 自己的卡片上點擊了「允許一次」,因為訂單工具已設定為「需要核准」(自訂 > 連接器 > 工具權限)。永遠不要將訂單工具設定為「始終允許」。
- 除非設定檔允許且用戶確認,否則不進行選擇權、保證金、放空或槓桿交易。
- 經紀商金鑰存在於環境變數或 Claude Desktop 設定檔中,永遠不會出現在聊天中。