trader-in-broker 是做什麼的?
Order Executor 是本套件中唯一可能導致真實訂單的技能,因此最為嚴格。訂單必須通過以下所有關卡,才能進入市場,每次、每筆訂單皆然:
- trader-in-risk 已在今天通過此確切訂單(透過指紋比對;使用與
trader-in-risk/check.py相同的ORDER_FIELDS和雜湊值)。 trader-in/config.json中的"paper": false。若為模擬模式(預設),則不會發送任何內容,成交記錄會寫入本地模擬帳本。- 使用者在對話中針對此訂單明確輸入「是」。
- 使用者點擊了 Claude 自己的權限卡片上的「允許一次」,用於每次的
place_order呼叫,因為訂單工具已設為「需要核准」。
沒有「是」,就沒有訂單。一個「是」涵蓋一張委託單(包含其買入、停損和目標部分),而非一批訂單。
${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" paper-fill --index 1 --price 1196.30 # 模擬:買入
python3 "${CLAUDE_SKILL_DIR}/ticket.py" paper-fill --symbol RELIANCE --side sell --qty 12 --price 1212.70 --leg target
python3 "${CLAUDE_SKILL_DIR}/ticket.py" paper # 模擬帳本與損益
python3 "${CLAUDE_SKILL_DIR}/ticket.py" result --index 1 --leg entry --status placed --broker-id ID --filled-qty 12 --filled-price 1196.30
python3 "${CLAUDE_SKILL_DIR}/ticket.py" result --index 1 --leg stop --status placed --broker-id ID
python3 "${CLAUDE_SKILL_DIR}/ticket.py" fill --symbol RELIANCE --side sell --qty 12 --price 1212.70 --leg target
python3 "${CLAUDE_SKILL_DIR}/ticket.py" flatten --symbol RELIANCE --qty 12
python3 "${CLAUDE_SKILL_DIR}/ticket.py" log
ticket.py 從不直接與券商溝通。它負責渲染委託單、檢查回覆是否為該訂單的真正「是」、維護模擬帳本、建立平倉委託單,並將紀錄保存在 trader-in/state/broker.json 中。參數 --now "2026-10-27 10:15"(或單純的 10:15)可將時間固定在 IST 時區。支援的股票代號格式包含 RELIANCE、RELIANCE.NS、NSE:RELIANCE、M&M、BSE:500325、500325.BO。
讀取與寫入的檔案
| 檔案 | 用途 |
|---|---|
trader-in/orders.json | 建議的訂單(由 trader-in-budget 寫入;flatten 會取代它) |
trader-in/config.json | broker(kite 或 upstox)、paper、product、flat_by、costs、capital_inr |
trader-in/state/risk.json | trader-in-risk 的審查結果;只有今天通過的 PASS 狀態才會是 READY |
trader-in/state/broker.json | 所有「是」、「否」、「已送出」、「已下達部分」和「已成交」的記錄,以及每筆交易包含成本的預估最大虧損 |
trader-in/state/paper.json | 模擬帳本:現金、未平倉部位、已平倉交易、扣除估算成本後的已實現損益 |
trader-in/portfolio.json | 現金與股票庫存(部位以 symbol 如 RELIANCE.NS 為鍵,包含 exchange) |
trader-in/plan.json | flatten 的強制平倉時間 |
trader-in/universe.json | (Upstox)掃描器產生的 ISIN,若有則使用 |
trader-in/state/EQUITY_L.csv | (Upstox)NSE 的股票清單,在需要 ISIN 時下載一次 |
一筆交易,三個訂單(在每次 bracket 前閱讀此說明)
trader-in-budget 寫入一個「bracket」(進場、停損、目標)。Zerodha 和 Upstox 已不再提供 bracket 訂單功能,因此委託單會將其轉換為:
| 部分 | 訂單 | 時機 |
|---|---|---|
| 1 | 以進場價(或市價)買入限價單,MIS 或 CNC | 現在 |
| 2 | 賣出,SL-M 並設定 trigger_price = 停損價 | 僅在部分 1 成交後 |
| 3 | 賣出,LIMIT 限價單於目標價 | 僅在部分 1 成交後 |
部分 2 和部分 3 之間沒有關聯(無 OCO)。 當其中一個成交時,另一個仍為有效訂單。必須立即取消它,否則它也可能成交,導致使用者放空(若是 MIS)或被拒絕(若是 CNC)。/trader-in-alerts 可以監控停損和目標價位,並在觸及時發出警報。若在部分 1 成交前送出,部分 2 和部分 3 是純粹的賣出訂單,可能會開出空頭部位。
每張委託單都會顯示估算成本(§6 規範:每筆 MIS 部分手續費 min(₹20, 0.03%)、STT、交易所與 SEBI 費用、印花稅、18% GST)以及包含往返成本的停損點最大虧損。該數字也會被記錄,供 trader-in-risk 的每日虧損上限使用。成本始終為估算值:實際數字以合約書為準。
模擬模式(預設)
印度券商沒有模擬帳戶,因此模擬模式使用位於 trader-in/state/paper.json 的本地帳本。不會向任何地方發送任何內容。
ticket.py show,顯示一張 READY 委託單,使用者回覆「是」,然後ticket.py approve。- 當價格觸及進場價時,使用
ticket.py paper-fill --index N(限價單價格)或--price P。買入限價單的成交價不能高於其限價。 - 當停損價或目標價觸及時,記錄該筆賣出:
paper-fill --symbol RELIANCE --side sell --qty 12 --price 1188.10 --leg stop。帳本會記錄毛損益、估算的往返成本及淨損益。 ticket.py paper會列印現金、未平倉部位和已實現損益。
模擬模式的交易會以 placed 狀態記錄(帶有 "paper": true),因此 trader-in-risk 會將它與真實交易一樣,計入每日交易次數和每日虧損上限。
設定 A:Zerodha Kite(官方 MCP 伺服器)— 預設
Zerodha 的伺服器位於 github.com/zerodha/kite-mcp-server(MIT 授權,Go 語言)。已於 2026-10-27 對照其原始碼和 README 進行檢查(最新提交為 5e044dc,標籤 v0.4.0-dev24)。
託管伺服器無法下單。 README 指出託管的 https://mcp.kite.trade/mcp「出於安全考量,排除了潛在破壞性的交易操作」,且 Zerodha 自己的頁面將其描述為唯讀(一篇 Z-Connect 文章曾說 GTT 訂單是例外;其範圍會隨時間改變,請在連接後透過 Claude 的工具清單確認)。它是免費的,且不需要 API 金鑰:login 工具會回傳一個 Kite 連結,使用者在瀏覽器中使用自己的 Kite 密碼和雙因素驗證登入,絕不在對話中進行。
託管、唯讀(報價、庫存、部位、保證金、訂單、歷史記錄):
- Claude Desktop:設定 > 開發人員 > 編輯設定,從
claude_desktop_config.example.json加入"kite"區塊(它會執行npx mcp-remote https://mcp.kite.trade/mcp;需要 Node.js),重新啟動。 - Claude Code:
claude mcp add --transport http kite https://mcp.kite.trade/mcp(或將相同的npx mcp-remote命令作為 stdio 伺服器:claude mcp add kite -- npx mcp-remote https://mcp.kite.trade/mcp)。
若要透過 Claude 下單,使用者需要執行他們自己的伺服器副本,並使用他們自己的 Kite Connect 應用程式:
- 在 developers.kite.trade 建立一個 Kite Connect 應用程式(請查看目前的價格)。其重新導向 URL 必須指向本地伺服器的回呼路徑;在伺服器原始碼中,回呼路徑是
APP_HOST:APP_PORT(預設為http://localhost:8080/callback)上的/callback。我們沒有完整測試過這整個流程。 - 從 2026 年 4 月 1 日起,Zerodha 的支援頁面指出,透過 API 下單需要一個已在 Zerodha 白名單中的靜態 IP(NSE/SEBI 零售演算法規則)。沒有靜態 IP 的家庭網路連線可能會導致訂單被拒絕。在啟用真實交易前,請確認 Zerodha 的最新規定。
- 建置它:
git clone https://github.com/zerodha/kite-mcp-server && cd kite-mcp-server && go build -o kite-mcp-server(需要 Go 1.21+)。 - 從
claude_desktop_config.example.json加入"kite-orders"區塊:二進位檔案的完整路徑、APP_MODE為stdio,然後使用者將KITE_API_KEY和KITE_API_SECRET自行輸入到該檔案中。在 Claude Code 中:claude mcp add kite-orders -e APP_MODE=stdio -e KITE_API_KEY="$KITE_API_KEY" -e KITE_API_SECRET="$KITE_API_SECRET" -- /full/path/to/kite-mcp-server,並先在使用者自己的 shell 中匯出這些值。 如果不需要兩者,請僅保留kite或kite-orders其中一個。 - 重新啟動,要求 Claude 呼叫
login,使用者開啟連結並登入。Kite 連線會在每天到期(Kite Connect 存取權杖的有效期限到隔天早上),因此每個交易日都需重新登入。
金鑰和權杖絕不能出現在對話中。 絕不要要求它們,也絕不要將設定檔內容讀回對話中。如果使用者貼出了金鑰或權杖,請告知他們刪除該訊息並在 developers.kite.trade 重新產生。
工具權限。 自訂 > 連線(Claude Desktop),開啟 Kite 伺服器,設定:
place_order、modify_order、cancel_order、place_gtt_order、modify_gtt_order、delete_gtt_order:需要核准。永遠不要設為「永遠允許」。- 唯讀工具(
get_profile、get_margins、get_holdings、get_positions、get_orders、get_order_history、get_order_trades、get_trades、get_gtts、get_quotes、get_ltp、get_ohlc、get_historical_data、search_instruments、login):設為「永遠允許」即可。 - 在 Claude Code 中,將它們設為 ask 模式,位於
.claude/settings.json:"permissions": {"ask": ["mcp__kite-orders__place_order", "mcp__kite-orders__modify_order", "mcp__kite-orders__cancel_order"]};絕不要將任何訂單工具放入allow中。伺服器也支援使用EXCLUDED_TOOLS=place_order,modify_order,cancel_order來建立唯讀副本。
place_order 參數(來自伺服器原始碼):variety(regular)、exchange(NSE/BSE)、tradingsymbol、transaction_type(BUY/SELL)、quantity(整數)、product(MIS/CNC)、order_type(MARKET/LIMIT/SL/SL-M)、price(LIMIT, SL)、trigger_price(SL, SL-M)、validity(DAY)、可選的 tag(≤ 20 個字元;委託單會加入 trin + 指紋的 12 位十六進位值,以便日後找到該訂單)。伺服器的工具沒有 market_protection 參數;NSE 現在會對 API 的 MARKET 和 SL-M 訂單套用市場保護機制,因此市價單可能會被券商轉換為受保護的限價單。使用限價單進場可以避免此情況。對於 BSE,Kite 的 tradingsymbol 是股票名稱,而非數位代碼:請使用 search_instruments 查詢。
設定 B:Upstox("broker": "upstox")
- Upstox 的官方 MCP 伺服器(
https://mcp.upstox.com/mcp,從upstox/upstox-plugin-marketplace外掛的upstox-mcp安裝)是唯讀的:Upstox 的頁面說明無法透過它下單。連線會每天到期(在瀏覽器中進行 OAuth 授權)。 - Upstox 的官方代理技能(在 Claude Code 中使用
/plugin install upstox-skill@upstox-plugins-official安裝,需先執行/plugin marketplace add upstox/upstox-plugin-marketplace)可以使用 v3 訂單 API 下單。它會從UPSTOX_ACCESS_TOKEN環境變數(由使用者在其自己的 shell 中設定,絕不在對話中設定)讀取每日存取權杖,顯示其自己的預覽並等待確認。Upstox 表示它不能在一般的 Claude Desktop 對話中執行。 - 或者,使用者可以從委託單在 Upstox 應用程式中手動下單。
委託單會列印出用於 POST https://api-hft.upstox.com/v3/order/place 的請求主體(v2 /v2/order/place 已被標記為棄用;它接受相同的欄位,但不包含 slice):quantity(整數)、product(I 當日衝銷 = MIS,D 交割 = CNC)、validity DAY、price(MARKET / SL-M 設為 0)、instrument_token、order_type、transaction_type、disclosed_quantity 0、trigger_price(除非是 SL / SL-M,否則設為 0)、is_amo false(Upstox 忽略它)、tag,以及 market_protection: -1(自動)用於 MARKET 和 SL-M 訂單,因為設為 0 時 API 市價單會被拒絕。
instrument_token 的格式為 NSE_EQ|<ISIN>(或 BSE_EQ|<ISIN>)。ISIN 的來源依序為:--isin、訂單中的 isin、來自掃描器的 trader-in/universe.json,否則從 NSE 的 EQUITY_L.csv 取得(使用瀏覽器 User-Agent 下載一次到 trader-in/state/EQUITY_L.csv,依序嘗試 archives. 和 nsearchives. 網域)。BSE 限制: NSE 清單僅對應 NSE 股票代號。BSE 股票代碼(如 500325.BO)無法對應,因此請傳遞 --isin;若為 .BO 名稱的股票代號,則使用 NSE 上市的 ISIN(同一家公司),但請確認。我們在此未驗證 Upstox 的金融工具檔案格式。如果沒有 ISIN,則真實交易的 Upstox 委託單不會是 READY 狀態;模擬交易的委託單則不需要。
步驟:進場
ticket.py show。僅將 READY 狀態的委託單顯示給使用者。不是 READY 或 BLOCKED 狀態的委託單應送回/trader-in-risk(它沒有 broker JSON)。- 顯示一張委託單,包含非 OCO 的警告,並詢問:「下這筆單嗎?回覆 yes 或 no。」每次只問一筆訂單。永遠不要提供「全部同意」的選項。
ticket.py approve --index N --reply "<使用者逐字回覆的內容>"。「未記錄」表示回覆並非該訂單的明確「是」(例如「sure」、「haan」、「全部同意」、提到其他股票或數量的「是」)。請再次詢問。永遠不要自行將回覆解讀為「是」。- 模擬模式: 如上所述使用
paper-fill。真實交易,Kite: 使用完全符合部分 1 的 JSON 呼叫place_order;使用者會點擊「允許一次」。確認成交狀態(使用get_order_history/get_positions),然後針對部分 2 和部分 3 分別呼叫place_order,每次都需要點擊「允許一次」。真實交易,Upstox: 將請求主體一次一部分地交給 Upstox 代理技能或應用程式,順序相同。 - 記錄每個真實交易部分:
ticket.py result --index N --leg entry|stop|target --status placed|denied|failed --broker-id <id>(進場部分加上--filled-qty、--filled-price)。只有進場部分會被 trader-in-risk 視為一筆訂單;其他部分會以leg_placed狀態記錄。失敗的訂單不會在未經新的檢查和新的「是」確認的情況下重試。
步驟:持倉期間與強制平倉時間前平倉
/trader-in-alerts會監控停損價、目標價和強制平倉時間。- 當停損或目標成交時:真實交易中,使用
ticket.py fill ... --leg stop(它會提醒你立即取消另一個部分:使用get_orders,然後cancel_order,需要核准);模擬交易中,使用paper-fill ... --leg stop。 - 在
flat_by時間(預設 15:10 IST)之前,任何仍未平倉的部位都會被平倉。券商大約在 15:20 IST 開始自動沖銷未平倉的 MIS 部位,並對此收取費用(Zerodha 列出的費用為每筆訂單 ₹50 + GST),因此不要留給券商處理:- 真實交易:向券商查詢持有的股數:
get_positions(唯讀)。 ticket.py flatten --symbol RELIANCE --qty 12會將一個 MARKET 賣單(相同產品)寫入trader-in/orders.json。
- 真實交易:向券商查詢持有的股數:
…(此處內容因原文截斷而省略)