交易機器人的熔斷機制與每日虧損上限
了解交易機器人如何透過每日虧損上限及波動度調整部位,在異常交易時停止送單,降低單一交易時段的損失擴大風險。
交易機器人的交易熔斷機制,是指在達到既定限額後,阻止自動化策略繼續送出委託的規則。這些機制位於策略與券商之間的風險控管層,並會套用至每一筆委託,不論策略本身是否同意。策略決定交易標的與方向;風險控管層則決定是否允許交易發生。
這種分離正是整體設計的核心。由策略自行監控自身風險,代表在自身假設失效的當下,沒有獨立的檢查機制;而那正是最需要檢查的時刻。
交易機器人的斷路器作用
風險控管層包含四個部分。每一個部分都用來防止一種特定且常見的故障。
- 硬性上限:限制部位規模、每一檔標的的名目曝險,以及下單頻率。這些上限能控制原本可能無限擴大的程式錯誤損失。
- 回撤斷路器:當帳戶在本交易時段的跌幅達到既定金額,或從權益峰值回撤達到既定金額時,停止接受新訂單。
- 按比例調整的下單規模:根據近期波動度,或依 Kelly bet 的一部分設定下單規模,而不是固定股數。即使市場波動區間持續變化,也能大致維持每筆交易的風險。
- 僅可追加的稽核日誌:記錄每一項決策,包括遭風險控管層拒絕的訂單。這是唯一能區分「策略判斷錯誤」與「檢查程序根本未執行」的紀錄。
以下內容都屬於上述四個部分之一,並將其具體化。
交易機器人的合理每日虧損上限是多少?
每日虧損上限會在當日交易時段的虧損超過門檻後,停止送出新訂單。門檻的設定是校準問題,而不是偏好問題:若設在一般市場雜訊範圍內,機器人多數星期都會處於停用狀態;若設得遠高於一般波動,則幾乎永遠不會觸發。起點在於觀察市場本身以特定幅度下跌的交易日出現頻率。
每個數據背後的精確 SQL 語法
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
argMax(toFloat64(close), window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2017-12-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY d
),
with_prev AS (
SELECT d,
close_px,
any(close_px) OVER (ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_close
FROM daily
)
SELECT toYear(d) AS year,
countIf(close_px / prev_close - 1 <= -0.01) AS down_1pct_days,
countIf(close_px / prev_close - 1 <= -0.02) AS down_2pct_days,
countIf(close_px / prev_close - 1 <= -0.03) AS down_3pct_days
FROM with_prev
WHERE prev_close > 0
AND d >= toDate('2018-01-01')
GROUP BY year
ORDER BY year跌幅達 1% 或以上的交易日,在 2019 和 2020 中分別有 15 與 45 個;一年約有 250 個交易日。跌幅達 3% 或以上的交易日則完全不同:2019 中有 0 個,2020 中有 16 個。9 的最後一列僅涵蓋截至 2026年7月31日的交易日。
這條分布線呈現的是不均勻的群聚,而非穩定的平均分布。這種群聚正是設計每日虧損上限時的關鍵。劇烈下跌的交易日往往會接連出現。若機器人在群聚的第一天停用、第二天便恢復交易,實際上並沒有真正停用。
兩種門檻各自發揮不同作用。每日虧損上限通常設為帳戶權益的 2%,用來結束當日交易。從權益高點計算的移動回撤上限通常約為 10%,達到後則停止策略,等待人工審查。前者是日常防護,後者預期很少觸發。若機器人只有每日虧損上限,帳戶可能每次下跌 2%,持續累積虧損,卻始終不會觸發任何其他停損機制。
波動率縮放如何改變部位規模?
波動率目標法會根據近期實現波動率,反向調整部位規模:當每日價格區間擴大一倍時,部位大致減半,讓每筆交易的美元風險維持在接近固定的水準。此處的實現波動率,是每日報酬率標準差的年化值;其變化幅度往往超出多數人的預期。
每個數據背後的精確 SQL 語法
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
argMax(toFloat64(close), window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2023-12-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY d
),
rets AS (
SELECT d,
close_px / any(close_px) OVER (ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) - 1 AS ret
FROM daily
)
SELECT formatDateTime(toStartOfMonth(d), '%Y-%m') AS month,
round(stddevSamp(ret) * sqrt(252) * 100, 1) AS realized_vol_pct,
round(least(100.0, 1200.0 / (stddevSamp(ret) * sqrt(252) * 100)), 1) AS vol_target_size_pct
FROM rets
WHERE d >= toDate('2024-01-01')
AND isFinite(ret)
GROUP BY toStartOfMonth(d)
HAVING count() >= 15
ORDER BY toStartOfMonth(d)實現波動率以年化方式衡量,數值為 11.1%,出現在 2024-01 與 12% 的 2026-07,涵蓋 31 個月。第二欄將每個讀值換算為採用 12% 波動率目標時的部位規模,並以完整部位為上限:相較於 99.7% 的 2026-07,為 100% 的 2024-01。策略相同、信念相同,但持有股數可能大不相同。
Kelly criterion 則從另一端處理相同問題,根據估計優勢與變異數決定部位規模,而不僅依賴波動率。多數系統化交易者只採用 Kelly criterion 的一部分,通常為 half Kelly 或 quarter Kelly,因為這兩項輸入值都是根據有限樣本估計而來。Kelly criterion 部位規模會說明相關計算方式。
為什麼交易機器人在停損後持續重新進場?
停損觸發,部位平倉。九十秒後,進場條件再次成立,機器人重新進場,再度承受相同虧損,如此反覆。沒有任何單一元件故障。策略依照設計執行,停損也依照設計執行,但帳戶仍逐趟交易持續失血。
交易頻率直接來自價格路徑。本面板按交易時段統計 SPY 從高於開盤價 0.1% 以上的位置,移動至低於開盤價 0.1% 以上的位置,或反向移動的次數。
每個數據背後的精確 SQL 語法
WITH mins AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
window_start AS ts,
toFloat64(close) AS px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2025-08-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
),
opens AS (
SELECT d, argMin(px, ts) AS open_px
FROM mins
GROUP BY d
),
zoned AS (
SELECT m.d AS d,
m.ts AS ts,
multiIf(m.px >= o.open_px * 1.001, 1,
m.px <= o.open_px * 0.999, -1,
0) AS zone
FROM mins AS m
INNER JOIN opens AS o ON m.d = o.d
),
flips AS (
SELECT d,
zone,
any(zone) OVER (PARTITION BY d ORDER BY ts ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_zone
FROM zoned
WHERE zone != 0
),
per_day AS (
SELECT d, countIf(prev_zone != 0 AND zone != prev_zone) AS crossings
FROM flips
GROUP BY d
)
SELECT formatDateTime(toStartOfMonth(d), '%Y-%m') AS month,
round(avg(crossings), 1) AS avg_crossings_per_session,
max(crossings) AS max_crossings_in_a_session
FROM per_day
GROUP BY toStartOfMonth(d)
ORDER BY toStartOfMonth(d)SPY 在 2025-08 每個交易時段平均穿越該區間 0.7 次,並在 2026-07 平均穿越 1.5 次;其中有一個交易時段在 2026-07 記錄到 5 次穿越。任何在價格位階一側開倉、另一側停損的規則,單日都有同樣多次的觸發機會。
四項機制可以抑制這種情況。
- 每次停損後設定冷卻期,以分鐘或 K 棒計算;在此期間,該標的不得有新訂單通過風險控管層。
- 設定單一標的的每日交易次數上限,將無限循環轉為有上限的循環。
- 設定具鎖存功能的暫停旗標。每日虧損上限一旦觸發,旗標就會維持啟用,直到人員手動清除。
- 將該旗標持久化儲存在程序記憶體之外。監督程序重新啟動當機的交易機器人時,若交給它一個全新的狀態,就會繞過這個旗標原本要防止的情況。
最後一項最容易被忽略,即使其他措施都已正確實施。網格交易機器人 本來就會分層掛出多筆訂單,因此交易次數上限是核心控制機制,而不是裝飾性設定。
當機器人依據過時的價格資料流交易時,會發生什麼事?
停止更新的報價看起來仍然是一個數字。機器人讀取該報價,據此為委託定價,然後將委託送進已經變動的市場。這類故障通常不易察覺:系統不會拋出例外,也不會記錄錯誤;只有事後才會發現成交結果異常。
最容易清楚量化的情況是隔夜跳空。此時,已知價格在數小時內維持不變,但可交易價格持續變動。
每個數據背後的精確 SQL 語法
WITH daily AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
argMin(toFloat64(open), window_start) AS open_px,
argMax(toFloat64(close), window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'KO', 'MSFT', 'AAPL', 'NVDA', 'TSLA')
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2024-01-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY ticker, d
),
gaps AS (
SELECT ticker,
d,
open_px,
any(close_px) OVER (PARTITION BY ticker ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_close
FROM daily
)
SELECT ticker,
round(quantileDeterministic(0.5)(abs(open_px / prev_close - 1) * 100, cityHash64(ticker, d)), 2) AS median_gap_pct,
round(quantileDeterministic(0.95)(abs(open_px / prev_close - 1) * 100, cityHash64(ticker, d)), 2) AS p95_gap_pct,
round(max(abs(open_px / prev_close - 1) * 100), 2) AS max_gap_pct
FROM gaps
WHERE prev_close > 0
GROUP BY ticker
ORDER BY p95_gap_pct DESC以第95百分位跳空幅度計算,幅度最大的標的為 TSLA,達 4.41%;相較之下,KO 為 1%。一般夜間的波動小得多:兩者的跳空中位數分別為 1.01% 與 0.24%。風險控管層的設計,就是為了處理這些尾端情境;在所測量的期間內,TSLA 出現的單次最大跳空為 14.57%。這些就是機器人依據一段時間前讀取的價格行動時可能面臨的價差。為什麼股票會在隔夜跳空說明了其中的運作機制。
防禦措施成本低廉。為每一筆風險控管層將據以定價的報價設定最長允許存續時間;對日內策略而言,通常是幾秒。除資料本身外,也要個別接收資料流的心跳訊號,以區分連線無回應與市場交投清淡。應將資料缺失視為停牌,而不是持續持有原值,因為機器人在沒有價格的情況下,也無法評估出場條件。
風險層應設定哪些硬性上限?
- 單一標的的最大名目金額,占帳戶權益的比重。設定10%的上限,可避免單一標的出現重大虧損時拖累整個帳戶。
- 所有未平倉部位的最大總名目金額。將上限設為權益的100%,代表不使用槓桿。這項決策應明確訂定,而不是沿用券商的預設值。
- 每分鐘及每日的最大下單筆數。每分鐘10筆對多數零售策略而言已相當寬鬆,同時仍能限制失控迴圈在一分鐘內的影響。
- 單筆訂單金額上限,占該標的平均每日成交量的比重。設定1%的上限,可避免交易機器人推動自己試圖交易的價格;平均每日成交量就是分母。
上述每一項都應歸入風險層,而非策略層;在回測、紙上交易與實盤交易中,也都應執行相同的程式碼路徑。只有實盤交易才存在的限制,就是從未經過測試的限制。
交易機器人的稽核日誌需要記錄哪些內容?
僅可附加的日誌會為每項決策寫入一筆紀錄,且從不修改或刪除。每筆紀錄都應包含時間戳記、所採用的報價及其時效、所有已執行的限額檢查及各自的判定結果、送出的委託,以及券商的回覆。遭拒的委託與成交委託應以同等重要性記錄。
重建決策過程才是重點。糟糕的交易時段過了六週後,問題從來不是損益是多少,而是哪項檢查通過,以及當時採用了什麼輸入。若沒有記錄輸入,最後就只能根據市場狀態重新推導機器人的狀態。這與回測中的 前視偏誤 是同一種錯誤:使用系統在決策當下尚未掌握的資訊。
riskguard 專案是這種分離設計的一項開源實作。它將限額檢查放在策略呼叫的元件中,而不是把邏輯分散在策略本身。這只是多種設計之一,值得閱讀,但不宜未經評估就直接採用。無論依賴哪個專案,都應固定使用標記版本,而不是預設分支。同一項回測若分兩次執行,分支內容可能已經改變;而悄悄變動的風險層,甚至比沒有風險層更糟。
為何首次部署會在模擬交易券商上運行
券商介接器預設使用模擬交易環境,而實盤交易則必須明確設定旗標。這項設計是為了避免一個常見但嚴重的錯誤:複製設定檔,或未被覆寫的環境變數,導致系統以真實資金送出實際訂單。
模擬交易也會產生一項重要成果:在即時價格上,透過與實盤相同的風險層所建立的決策紀錄。這份紀錄能顯示哪些限制條件被觸發、哪些未被觸發。它可用來驗證風險層,但這與策略能否獲利是兩個不同問題。投入真實資金前先進行模擬交易說明模擬交易紀錄能證明什麼、不能證明什麼;多代理 AI 交易系統則說明,當多個代理都能下單時,停止交易的權限為何必須置於所有代理之外。
交易機器人斷路器常見問答
交易機器人中的斷路器是什麼?
這是風險控制層中的一項規則。當達到設定的限制時,規則會停止機器人送出新訂單。最常見的限制是單日虧損門檻,或帳戶權益相對於峰值的回撤。它獨立於交易策略運作,會套用至每筆訂單,且在解除條件成立前維持觸發狀態。
市場多久會出現一次下跌2%的交易日?
SPY 在 2019 有 5 個交易日下跌至少2%,而 2020 的相同交易日數為 25;每年約有250個交易日。平靜年份與壓力年份之間存在這種差異,因此虧損限制應根據歷史資料校準,而不是憑直覺設定。
如何避免機器人在停損後重新進場?
每次停損後設定冷卻期間,並限制每個標的的單日交易次數,就能將無上限的迴圈轉為有界流程。停止交易的旗標也必須鎖定,並持久化儲存在程序記憶體之外。否則,監控程式重新啟動當機的機器人時,會將它恢復為全新的未停止狀態。
機器人如何判斷價格資料是否已經過時?
機器人應在依據報價為訂單定價前,檢查每筆報價的資料年齡,並將資料流的心跳訊號與資料內容分開監控。隔夜跳空顯示了過時價格可能掩蓋的幅度:2024年1月至2026年7月期間,隔夜價格變動的第95百分位在 TSLA 達到 4.41%。
小型交易機器人真的需要稽核日誌嗎?
成交日誌會記錄實際發生的交易。決策日誌則會記錄機器人認為自己獲准執行的操作。只有後者能協助區分錯誤的策略與根本未執行的風險檢查。採用僅追加寫入的形式,並納入遭拒訂單,是最低限度且具實用價值的版本。
以上每個數值都來自以分鐘線資料執行的儲存查詢,每個面板都能開啟其背後的 SQL。你也可以在 Strasmore 終端機上,將相同查詢套用至自己的標的清單。