2021 年,我在一個數位資產錢包內從 0→1 長出美股/港股交易線 —— 走的是
Interactive Brokers(IB 盈透)券商通道,委託單真的送到美/港交易所搓合,用戶持有的是實盤股票部位。
這代表我們必須完整承接交易所的每一條規則:只有開市時段能下單、T+2 清算交割、印花稅與 SEC/FINRA 規費、熔斷與 VCM、拆股與配息。
2026 年,我在受監管的 CFD 交易平台接手公司行動(Corporate Action)引擎,再一次面對同一批規則 —— 這次是把「生效日市價平倉」重寫為損益中性的就地換算。
這是我設計的美股/港股下單頁 —— 委託單走 IB 盈透券商通道送交易所實盤搓合,所以介面上每一個約束都來自真實市場規則。 切換左側自選股會同步切換市場(美股帶 USD、港股帶 HKD)、時區與市場狀態橫幅;港股最小單位是 100 股一手,不接受零股; 切換市價/限價會改變保證金計算方式;輸入股數會即時反算訂單費用明細。港股觸發 VCM 冷卻時,送單鈕會被鎖住並顯示限價區間。
同一條主線做了兩次。2021 年是「怎麼把真實股票市場塞進幣圈產品」,2026 年是「怎麼把股票規則寫對到不會傷到客戶」。
2026 年的今天,多數加密交易所提供的「美股」是股票代幣(tokenized / 合成資產) —— 鏈上代幣、7×24 交易、由平台或做市商報價。 那是一個規則由平台自己定義的產品。
2021 年我做的是另一件事:透過 Interactive Brokers(IB 盈透)券商通道,把用戶的委託單送到美股/港股交易所實際搓合, 用戶帳上是真實的股票部位。這代表規則不是我們定的,是交易所定的,我們只能完整承接。 兩者在產品設計上的難度差距,幾乎全部落在下面這張表。
| 面向 | 真實美股(本案 · 2021) | 股票代幣(多數交易所現況) |
|---|---|---|
| 標的 | 交易所實盤股票部位 | 鏈上代幣 / 合成資產 |
| 成交通道 | IB 盈透券商 → 送美/港交易所搓合 | 平台自營盤或做市商報價 |
| 交易時段 | 只有開市時段可下單;休市送單直接擋下,當日未完成掛單全數取消 | 7×24 全時段 |
| 清算交割 | T+2 真實清算;款項先入凍結,交割完成才解凍 | 即時結算 |
| 最小交易單位 | 美股 1 股;港股依股價 100/500/1000/2000 股一手 | 可拆分至小數 |
| 稅費結構 | 印花稅、交易徵費、交收費、SEC/FINRA 規費、DTC 保管費、H 股股息預扣 | 平台自訂費率 |
| 市場中斷機制 | 美股三級熔斷、港股 VCM 冷卻期,必須完整承接並前移到下單頁攔截 | 平台自訂或無 |
| 公司行動 | 拆股、合股、紅股、配息實際反映到持倉與帳務 | 依平台合約模擬,或不提供 |
| 產品工作的本質 | 把交易所規章翻譯成系統規格 | 定義自家規則 |
接真實券商通道,意味著沒有任何一條規則可以「產品說了算」。休市就是不能交易、T+2 就是要等兩天、印花稅就是要無條件進位。 產品能做的,是把這些硬約束翻譯成用戶看得懂、系統跑得動、客服解釋得清的規格 —— 這正是下面 Part A 的全部內容。
幣是 7×24、即時交割、單位可無限小。股票有開收盤、有休市、有 T+2 清算、有最小交易單位、有政府稅費、有熔斷與冷卻期、還會拆股配息。把這兩套模型接在同一個 App、同一個資產頁面裡,才是整個專案真正的設計工作。
而且因為走的是券商實盤通道,這些差異沒有一項可以「用產品邏輯繞過去」。最直接的一個例子:用戶昨天還能在同一個 App 裡半夜買賣 BTC,今天打開股票頁卻被擋下來 ——「為什麼現在不能買」本身就是一個必須被設計的產品問題,而不是一句錯誤訊息。
介面不難畫,難的是把每一條規則落到資金狀態、訂單狀態、通知落點三件事上。舉例:
這四題的答案,就是後面 Part A 全部規格的骨架。
第二段經歷是在一個受監管的 CFD 交易平台,接手公司行動(Corporate Action)產品線 — 拆股、合股、紅股、派息。
平台既有的處理方式,是在生效日以市價把用戶持倉平掉再重開。工程上最省事,但對用戶是災難:平倉會實現損益、觸發課稅事件、重置持有期間,等於平台單方面替客戶「賣掉又買回」。
既有股息服務也是同一套 close-out 邏輯;換算排在盤後執行,意味著生效日盤中價格已經除權、持倉卻還沒換算 — 用戶會看到憑空出現的假虧損,保證金也會算錯。
我把它重新定義成一條產品鐵則,貫穿整個 release train:就地修改持倉,禁止平倉再開。細節在 Part B。
T+2 交割、凍結/解凍、保證金預扣與返還、分批成交的起算基準。
美股與港股兩套費率,逐項拆解後才收斂成對外話術。
美股三級熔斷、港股 VCM 冷卻期、休市,全部做成事前攔截。
拆股/合股/紅股/派息,一律價值中性、就地換算。
冪等、斷點續跑、整批回滾、成交競態、失敗隔離。
不可逆操作收斂到權限旗標,後端強制鑑權,全程留痕。
在既有的數位資產私人銀行 App 內,從 0→1 長出一條完整股票交易線 —— 走 IB 盈透券商通道送交易所實盤搓合, 用戶只需持有 USDT,無須開立傳統券商帳戶。產出為 24–28 頁高保真原型與需求規格(兩版迭代), 涵蓋行情、下單、持倉與帳單、費用揭露、用戶教育 H5 與分享機制。
美股/港股分市場、三大指數、搜尋與最近查看、熱門標的後台可配置。
市價/限價、買入/賣出、觸發單,含下單前的攔截與提示彈窗。
持倉詳情、買入詳情、賣出詳情、成交記錄、盈虧分析。
美股/港股兩套訂單費用說明頁,逐項列出稅費與服務費。
股票交易指南(交易時間、熔斷、VCM、拆股、最小單位、清算交割)、牌照公告、資費對照。
Push + 站內信 8 類情境,每類指定跳轉落點。
個股績效/持倉/收益率/資產分布曬單,帶邀請碼與下載 QR。
資產頁重構(法幣/數字貨幣/股票/理財/合約/槓桿/借貸統一總覽)。
版本強更彈窗(依版本號僅出現一次)、募集進度、官方頻道與客服入口。
「T+2 清算交割」不能只寫在說明頁。我把它拆成資金狀態與訂單狀態兩條線,並明訂起算基準:
買入賣出的保證金一律先凍結;以最後一張完成單的時間起算 T+2 放款(避免分批成交造成的爭議);訂單狀態機擴充為 待觸發 → 交易中 → 撤銷中 → 已成交/已撤銷/部分撤銷。
股票市價波動大,下單當下無法知道最終成交金額。規則定為預扣 1.3 倍保證金,成交後依實際金額歸還餘額。
但真正的產品工作是把這條規則反推回用戶端 — 如果只在後端擋,用戶會一直送單失敗。所以在下單頁即時顯示可買股數:
可買股數 = 可用餘額 ÷ 股價 ÷ 1.3195 (1.3 倍保證金 + 手續費預留,向下取整至最小交易單位)
例:可用餘額 1,000 元、股價 100 元 → 市價保證金 131.95 元/股 → 可買 7 股,而不是用戶直覺的 10 股。這個數字直接顯示在「可買」欄位,點擊即帶入。
不做「總手續費」黑箱。美股與港股各自一頁費用說明,逐項列出後才收斂成對外的「約成交額 1.5%」話術。
| 市場 | 費用項目 | 規則 |
|---|---|---|
| 美股 USD | 我方服務費 | 交易金額 0.05% |
| 外部機構費 | 交易所、SEC、FINRA 等外部機構收取之交收費 | |
| 保管費 | 信託公司 DTC 收取 | |
| 平台使用費 | 依筆計收,與佣金合計上限為交易金額 1% | |
| 港股 HKD | 印花稅 | 交易金額 0.13%,小數點無條件進位 |
| 交易徵費 | 成交金額 0.0027%,最低 0.01 港幣 | |
| 交收費 | 依成交金額計收,最低 2 港幣、最高 100 港幣 | |
| 代收股息稅 | H 股按股息 10%,派發時預扣 | |
| 平台使用費 / 手續費 | 15 港幣/筆;平台手續費 0.4% |
因為委託單真的會送到交易所,這些機制不是我們可以選擇要不要做的。 而用戶剛從幣圈的 7×24 世界過來,最不能接受的就是「按下去沒反應」。 所以規則一律前移到下單頁校驗,而不是等交易所拒單才報錯。三種情境、三種處理:
| 情境 | 規則 | 系統行為 |
|---|---|---|
| 休市 | 非交易時段不得送單 | 下單頁直接擋下並提示「目前市場休市中,請開市後再下單」;當日未完成掛單全數取消並發通知 |
| 港股 VCM | 價格觸及參考價變動幅度時觸發,啟動 5 分鐘冷靜期,交易限於指定價格區間 | 偵測用戶下單是否超出限價區間 → 跳彈窗提示並鎖住送單;全市發送冷卻通知 |
| 美股熔斷 | 三級:跌 5% 暫停 15 分鐘 / 跌 10% 暫停 / 跌 20% 當日不再開放 | 下單頁全域提示,並依級別推送對應文案的 Push + 站內信 |
Push + 站內信共 8 類情境,每一類都指定跳轉落點(行情該股/資產持倉/訂單詳情),而不是丟一則沒有出口的訊息。
高送轉/拆股採總價值不變原則:原持倉 100 股 × 10 元 → 拆股後 200 股 × 5 元,數量與均價同比例調整,並主動發信說明變動原因。
因為持有的是真實股票部位,這些權益必須實際反映到持倉與帳務,而不是「顯示一個數字」。
2026 年在 CFD 平台再次遇到同一題 — 見 Part B。
第二版集中補齊「同一筆交易在不同頁面顯示不一致」這類缺口:
接手一個受監管 CFD 交易平台的 Corporate Action 產品線(拆股/合股/紅股/派息), 主導核心規格改寫、跨 Sprint release train 規劃,以及後台資訊架構與權限治理重構。
公司行動牽動帳務、風控、稅務與流動性提供商對帳,每一項都必須拍板並留下理由。以下為我主導收斂的規格決策:
| 議題 | 決策 | 理由 |
|---|---|---|
| 未成交掛單 | 取消並通知用戶重掛,不自動換算 | 換算掛單價格易生爭議;取消+主動通知最無歧義 |
| 持倉上的 SL / TP | 自動換算(÷比例 / ×比例),跟著價格走 | 不換算會在除權後立即誤觸停損 |
| 零股尾數 | 無條件捨去 + 現金找補,以執行當下價格計價 | 持倉不得出現非整數股;差額必須退還用戶 |
| 引擎涵蓋範圍 | 拆股 / 合股 + 港股紅股(Bonus Issue) | 紅股屬價值中性,須比照拆股就地換算均價,而非只加股數 |
| 資料來源 | 第三方自動匯入 + 後台人工建檔並存 | 自動源有覆蓋缺口,需人工補位且可回溯 |
| 零股找補入帳 | 記入資金管理記錄,與佣金 / 入金同一本帳 | 對齊既有派息帳務慣例,可稽核、可對帳 |
| 換算觸發時點 | 由盤後改為盤前維護窗 | 生效日盤中價格已除權、持倉未換算=假虧損、保證金錯亂、誤砍倉 |
| 四眼原則 | 移出 MVP,改以模組權限收斂 + 全程稽核 | 降低單人卡關風險,同時保留可追溯性;風控由權限與日誌承擔 |
這是規格中我花最多力氣的部分。公司行動很容易被做成一套漂亮的獨立子系統,最後跟主帳務對不上。我逐項盤點既有服務,明確標註「沿用/改寫/補強」:
| 既有機制 | 處置 | 說明 |
|---|---|---|
| 資格快照 | 沿用 | 沿用既有 EOD 持倉快照(生效日前一交易日收盤),不另建一套 |
| 市場時區與交易日曆 | 沿用 | 沿用既有時鐘服務(已支援 7 個市場、自動處理夏令時),把拆股掛進同一排程 |
| 狀態機 / 冪等 / 回滾 / 匯率 | 沿用 | 沿用既有 lifecycle 與冪等鍵,拆股僅補上 applied 語意 |
| 資料不全防呆 | 補強 | 缺生效日/比例/幣別時不自動執行,一律轉人工,比照既有機制 |
| 換算執行時點 | 改寫 | 由盤後 close job 改為盤前維護窗 |
| 持倉調整方式 | 改寫 | 由市價平倉再開改為損益中性就地換算 |
| K 線回調 | 新增 | 採物化調整後 OHLC、不換表、tick 不調,App 與官網共用同一資料源 |
公司行動是不可逆的批次寫帳。規格若只寫「要快」等於沒寫,所以我把它定成可被 QA 量測的數字:
該交易所開盤前 ≥15 分鐘完成換算。趕不上=假虧損、誤砍倉。
開盤前 10 分鐘尚未完成即發告警,留出人工介入時間。
≥5,000 部位/分,由 QA 以壓測工具對 5 萬部位實測回填。
批次引擎另訂五條可靠性規則:冪等(同事件不二次套用)、斷點續跑、整批回滾一致、成交競態處理(市價單在途/平倉中)、失敗隔離。
| 項目 | 規格 |
|---|---|
| 範本矩陣 | 三類(拆股預告 / 持倉已調整 / 掛單取消)× 三種帳戶類型 × 中英雙語 = 18 份 |
| 發送規則 | 每帳戶每 Symbol 彙總一封;換算完成後才發(換算失敗不發);依語系+帳戶類型選範本 |
| 可靠性 | 變數填充、發送冪等、失敗重試(沿用既有派息通知服務的重試機制) |
| 倉位標記 | 受調整部位掛上標記「於 YYYY-MM-DD 經公司行動(拆股 X:Y)調整」,點擊連到事件主檔與帳務 Journal |
引擎之外,我另寫了一份後台重構規格。原本公司行動散落在「各別商品 › Corporate Action 分頁」底下 — 營運要看「本週有哪些公司行動」得逐檔商品點進去。
收進後台 Task 模組,派息與拆股並列為兩個分頁,提供跨商品集中清單:預設依除權日排序,支援 Symbol 搜尋、狀態篩選、日期區間。
移除彙總層級用不到的欄位、Symbol 顯示可讀股名並可跳轉、新增「持倉數」彙總欄,點數字開右側抽屜列出該檔所有受影響持倉逐筆明細。
表頭一顆「+」,依當前分頁開對應流程:派息表單,或拆股精靈三步(建檔 → 預覽影響 → 確認執行)。入口不再散落各處。
新增模組層級權限旗標,不寫死帳號 ID;掛進既有角色權限樹,對管理員角色預設不勾。無權限者整個模組完全隱藏(非反灰、非 403 空殼),且後端 API 必須同步鑑權 — 前端隱藏不可作為唯一防線。授權變更與每次執行皆寫日誌。
下方四個決策都是 trade-off — 沒有「對」的答案,只有「為這個產品最合適」的答案。
最省事的做法是只顯示一個總數。但股票的稅費結構是用戶最容易產生客訴的地方 — 印花稅無條件進位、交收費有上下限、H 股股息預扣 10%,任何一項沒講清楚都會變成「你們亂扣錢」。我決定逐項列出,再收斂成對外的「約成交額 1.5%」。揭露成本換信任,長期划算。
讓交易所拒單是零開發成本的做法。但用戶收到的是一句看不懂的錯誤碼,客服要一筆一筆解釋。我決定把休市、VCM 冷卻區間、熔斷狀態全部前移到下單頁校驗 — 多寫一套規則,換掉一整條客訴路徑。
平倉再開在工程上簡單得多,而且既有系統已經那樣跑了。但它會替客戶觸發課稅事件、重置持有期間 — 這是產品替用戶做了不該做的決定。我把「損益中性、禁止平倉再開」定為鐵則,並要求既有派息服務一併對齊。改寫成本高,但這條線不能讓。
公司行動一次動上萬筆持倉且不可逆,直覺是加雙人覆核。但實務上覆核者常常只是按下確認,而流程卡關的代價很高。我決定把操作權收斂到模組層級權限旗標、要求後端強制鑑權、全程留痕 — 把風險壓在系統上,而不是人的謹慎上。
兩案的風控思路是同一套:把不可逆的動作,收斂到系統可強制執行的地方。
| 風險 | 設計 |
|---|---|
| 重複執行 | 冪等鍵=事件 ID + 部位 ID,同事件不二次套用 |
| 執行中斷 | 斷點續跑,不需從頭重來 |
| 部分成功 | 整批回滾一致;回滾含找補的反向沖銷 |
| 成交競態 | 市價單在途/平倉中的部位另行處理,不與換算搶寫 |
| 單筆失敗拖垮整批 | 失敗隔離,其餘部位照常完成並記錄失敗清單 |
| 資料不全 | 缺關鍵欄位一律轉人工,不自動執行 |
每條規則都附 Given / When / Then + Edge Case,並在每個章節末尾明寫 Out of Scope。
Happy path 誰都寫得出來;決定產品能不能上線的,是休市怎麼辦、零股怎麼辦、分批成交的 T+2 從哪天起算、換算跑到一半掛了怎麼辦。沒寫的邊界,最後都會變成客訴或損失。