MBO 與 MBP 訂單簿數據差異解析
深入解析 MBO 按訂單揭示市場與 MBP 按價格揭示市場的數據結構。說明兩者在事件流處理、訂單簿構建方式、流量需求及運作成本上的關鍵差異,協助您正確選擇市場數據源。
MBO 與 MBP 訂單簿數據是隱藏在同一個小標籤下的重大區別。兩家供應商都可以向您販售名為「Level 2」的數據:MBP(按價格揭示市場,Market by Price)發送每個價格水準的總掛單量,而 MBO(按訂單揭示市場,Market by Order)則將每筆個別訂單視為一個獨立事件發送,並附帶其專屬 ID。前者是訂單簿的摘要,後者則是構建訂單簿的原始分類帳,其傳輸所需的流量高出數個數量級。
MBP 與 MBO 訂單簿數據的實際內容
MBP(按價格揭示市場)是聚合後的深度數據。每次更新會標明買賣方向、價格水準、該價位上的總掛單量,有時還會包含該價位後的訂單筆數。作為 MBP-10 販售的產品會提供買賣雙方各十個最佳價格水準,這就是交易平台上的報價梯(ladder)以及每個深度圖表中的階梯。
MBO(按訂單揭示市場)是一個事件流。每則訊息標明一筆訂單:其 ID、買賣方向、價格、顯示數量,以及該訂單剛發生的變動。內容未經任何預先聚合。如果同一價格上有四十筆訂單,則會有四十則獨立訊息將它們置於該處,您必須將這四十筆訂單全部存入記憶體,才能得知該價位的總量。
我們的 Level 1 與 Level 2 市場數據指南 涵蓋了券商零售層級標籤的含義。當供應商說「Level 2」時,MBO 與 MBP 才是盒內數據的精確名稱,而架構名稱(schema name)才是值得詢問的重點。
MBO 數據源承載的訊息動作
MBO 數據源是一套應用於訂單 ID 的動作分類法。其中四種動作佔據了大部分流量:
- 新增(Add):一筆新訂單以新的 ID 加入特定價格的訂單簿。
- 修改(Modify):現有 ID 的價格或數量發生變動。增加數量或變動價格會將該訂單移至該價位隊列的末端;減少數量通常會維持其原有的隊列位置。
- 取消(Cancel):一個 ID 全部或部分離開訂單簿。
- 交易或成交(Trade or fill):一筆積極型訂單與一筆或多筆掛單成交,導致掛單數量減少或消失。
MBP 完全不具備這些詞彙。MBP 的更新是對價格水準的陳述:此價格現在有多少掛單量。無論該數量是因為取消還是成交而減少,更新後的結果看起來都一樣。下方的面板顯示了最精簡訂單簿上的限制,即合併後的最佳買賣價(top of book),每個方向僅一個價格水準,在此命名法中稱為 MBP-1。
每個數據背後的精確 SQL 語法
WITH
ordered AS
(
SELECT
row_number() OVER (ORDER BY sip_timestamp, sequence_number) AS msg_index,
bid_price,
bid_size,
lagInFrame(bid_price) OVER (ORDER BY sip_timestamp, sequence_number) AS prev_bid_price,
lagInFrame(bid_size) OVER (ORDER BY sip_timestamp, sequence_number) AS prev_bid_size
FROM global_markets.cache_stocks_quotes
WHERE ticker = 'AAPL'
AND sip_timestamp >= '2026-06-16 14:00:00'
AND sip_timestamp < '2026-06-16 14:30:00'
AND bid_price > 0
),
classified AS
(
SELECT multiIf(
bid_price != prev_bid_price, 'best bid price changed',
bid_size > prev_bid_size, 'size joined at the best bid',
bid_size < prev_bid_size, 'size left the best bid',
'bid untouched, ask side updated') AS message_type
FROM ordered
WHERE msg_index > 1
)
SELECT
message_type,
count() AS message_count,
round(100 * count() / sum(count()) OVER (), 1) AS share_pct
FROM classified
GROUP BY message_type
ORDER BY indexOf(['best bid price changed', 'size joined at the best bid', 'size left the best bid', 'bid untouched, ask side updated'], message_type)在那半小時內,17.6% 的訊息將最佳買價移至不同價格,17.4% 在買價不變的情況下增加了數量,12% 在買價不變的情況下減少了數量,而 53% 則在另一側變動時保持買價不變。每一組數據都是關於價格水準的淨值陳述。沒有任何訊息標明訂單 ID,也無法透過算術還原遺失的 ID。
各架構能與不能回答的問題
MBP-10 可以回答「該處有多少掛單量」這類問題:報價梯的形狀、訂單簿失衡(book imbalance)、中間價附近的流動性,以及深度圖表本身。聚合後的價格水準足以滿足上述所有需求。
MBO 則能回答「這筆訂單發生了什麼事」這類問題:當您加入時,您前面有多少掛單量、訂單在取消前存活了多久,以及在觸及價(touch)的被動訂單在價格變動前成交的機率。這些數量在聚合形式下並不存在,將訂單加總為價位總量會破壞定義它們的序列。
隊列位置(queue position)是最顯著的例子,它僅在 價格-時間優先與比例分配撮合 下才有意義,因為到達順序決定了誰先成交。讓它變得重要因素的是成交量(print size):一個價位是由許多小額執行所填補,而非單一的大額執行。
每個數據背後的精確 SQL 語法
SELECT
multiIf(size < 100, '1 to 99 shares',
size < 200, '100 to 199 shares',
size < 500, '200 to 499 shares',
size < 1000, '500 to 999 shares',
'1000 or more shares') AS trade_size_bucket,
count() AS trade_count,
round(100 * count() / sum(count()) OVER (), 1) AS share_pct,
round(avg(size)) AS avg_shares
FROM global_markets.stocks_trades
WHERE ticker = 'AAPL'
AND sip_timestamp >= '2026-06-16 14:00:00'
AND sip_timestamp < '2026-06-16 14:30:00'
AND size > 0
GROUP BY trade_size_bucket
ORDER BY min(size)低於一百股的零股交易(odd lot)佔了該時段 92.3% 的交易,而最大的交易區間 1000 or more shares 則佔了 0.1%。若將該規模的成交傳送至顯示四千股掛單的價位,最後加入隊列的訂單可能會在經歷數十次執行後仍未成交。MBP 顯示給您的是四千股,MBO 顯示給您的是隊列。
兩種架構都無法顯示隱藏數量。冰山訂單(iceberg order) 只顯示一小部分,且每次填補後都會以新 ID 刷新,因此隱藏的儲備量永遠不會出現在任何訊息中。
從 MBO 重建訂單簿是一個狀態機
MBP 數據源直接給您答案。MBO 數據源則給您輸入值,並要求您必須完全正確:
- 從快照開始,或從空訂單簿加上交易所的清除訊息開始。
- 依照訂單 ID 為鍵值,嚴格按順序應用每一筆新增、修改、取消與成交。
- 維護第二個以價格水準為索引的表,因為這是您的策略所讀取的內容。
- 監控序列號,一旦遺失,立即從最新的快照重新同步。
失敗模式是靜默的。遺漏一筆取消訊息,一筆幽靈訂單就會在剩餘的時段內留在您的訂單簿中,虛增該價位的數量,且不會觸發任何異常。MBP 的降級則溫和得多:每次更新都會重述該價位的總量,因此損壞的數值會在幾則訊息內被覆蓋。
MBO 也僅存在於直接的交易所數據源中,每個交易所對應一個訂單簿,這意味著必須運行並合併多個數據源。合併後的磁帶(consolidated tape)本質上是摘要,關於其拆分請參閱 SIP 與直接交易所數據源。
額外細節在頻寬上的成本
訊息數量是衡量差異最誠實的方式。下方的面板統計了五個熱門標的在同一半小時內,合併後最佳買賣價的訊息數量與實際成交筆數。
每個數據背後的精確 SQL 語法
WITH
quote_load AS
(
SELECT ticker, count() AS quote_messages
FROM global_markets.cache_stocks_quotes
WHERE ticker IN ('SPY', 'AAPL', 'NVDA', 'MSFT', 'KO')
AND sip_timestamp >= '2026-06-16 14:00:00'
AND sip_timestamp < '2026-06-16 14:30:00'
GROUP BY ticker
),
trade_load AS
(
SELECT ticker, count() AS trades
FROM global_markets.stocks_trades
WHERE ticker IN ('SPY', 'AAPL', 'NVDA', 'MSFT', 'KO')
AND sip_timestamp >= '2026-06-16 14:00:00'
AND sip_timestamp < '2026-06-16 14:30:00'
GROUP BY ticker
)
SELECT
q.ticker AS ticker,
round(q.quote_messages / 1000, 1) AS quote_messages_thousands,
round(t.trades / 1000, 2) AS trades_thousands,
round(q.quote_messages / t.trades, 1) AS quotes_per_trade_ratio
FROM quote_load AS q
INNER JOIN trade_load AS t ON t.ticker = q.ticker
ORDER BY quotes_per_trade_ratio DESCSPY 的每筆成交報價流量最重,每筆交易對應 9.6 則訊息,三十分鐘內共 510 千則訊息。這五個標的之間的價差很大:在面板底部,MSFT 每筆成交僅運行 0.7 則報價訊息,不到每筆交易一則訊息。請記住該欄位的統計內容:每個方向一個價格水準,且是在已經將所有交易所合併為單一最佳買賣價的數據源上。十層深度產品會將其倍增,而逐筆訂單數據源則會再次倍增,因為每個交易所、每個價位後的每一筆訂單,無論是否成交,都會產生自己的新增、修改與取消訊息。同樣的算術在 選擇權報價數據源規模 中以更大規模呈現。
策略需要哪種訂單簿數據源?
大多數工作都在 MBP-10 上運行。深度圖表、失衡特徵、價格流動性測量、執行成本模型,以及幾乎所有關於「某處掛單量有多少」的研究問題,都可以從聚合後的價格水準中得到解答,且訊息量僅為一小部分。
當答案取決於特定訂單時,才需要 MBO:隊列位置、訂單存續時間、取消行為、觸及價的被動成交機率。如果一個策略的成敗取決於隊列深度是兩百股還是兩萬股,那麼聚合數據就無法滿足需求,且必須為此支付授權費、頻寬、儲存空間,以及維持重建訂單簿全天正確運作的工程成本。
這些面板是如何構建的
- 每個面板背後的數據源皆為合併後的最佳買賣價(每個方向一個價格水準),加上交易磁帶。這不是深度數據源,也不是逐筆訂單數據源,因此這些面板旨在說明訊息量的論點,而非取樣 MBO 本身。
- 時間視窗固定在過去的特定日期,即 2026年6月16日 美東時間上午 10:00 至 10:30,儲存為 14:00 至 14:30 UTC。固定視窗可確保數據在重新生成時保持穩定。
- 分類面板將每則訊息與序列中的前一則進行對比標記。它無法區分取消與成交,這正是本文所描述的限制。
常見問題
MBO 與 MBP 市場數據有何區別?
MBP(按價格揭示市場)聚合了每個價格水準的顯示數量,並為每個價位發送一則更新。MBO(按訂單揭示市場)則發送每一筆個別訂單及其專屬 ID,以及發生在該訂單上的新增、修改、取消與成交事件。
Level 2 數據與 MBO 數據相同嗎?
通常不同。零售券商的「Level 2」幾乎總是意味著聚合後的深度數據,即包含五到二十個價格水準的 MBP。少數供應商會在同一個層級名稱下銷售逐筆訂單數據源,因此架構名稱(而非層級名稱)才是決定傳輸內容的關鍵。
MBO 數據源比 MBP 數據源大多少?
大數個數量級,具體取決於交易所與標的。僅合併後的最佳買賣價,上述面板中最繁忙的標的每筆成交就運行了 9.6 則訊息。逐筆訂單數據源會增加每個交易所、每個價位後的所有新增、修改與取消訊息,包括絕大多數從未成交的訂單。
可以從 MBO 數據重建 MBP 訂單簿嗎?
可以,這也是標準的處理流程:將每個訂單事件應用於以訂單 ID 為鍵值的訂單簿,然後發布價位總量。反之則不可能:一旦訂單被加總為價位總量,個別 ID 及其到達順序就會消失。
此處的每個面板皆附帶其底層的精確 SQL。若要統計不同標的或時段的相同訊息,請在 Strasmore 終端機以簡單的英文提問。