114 筆同刻合成事件的 Hawkes 評分:pre-batch 事件項 183.475922 nats,逐筆更新為 396.770155 nats,多出 213.294233 nats;補償積分同為 48.237046 nats。
圖:同刻事件的兩種評分規則;非 AAPL 參數擬合。

整理 NASDAQ ITCH 訂單流樣本時,有一個數字讓我無法放心把資料直接丟給逐事件的 Hawkes 迴圈:114。

2019 年 7 月 30 日,AAPL 在正常交易時段的一個奈秒時間戳下,記錄了 114 筆 execution 訊息;131 筆與 187 筆的批次也各出現一次。當天 49,172 筆執行類訊息中,有 30,080 筆(61.17%)與其他紀錄共用時間戳。並列很常見,上百筆同刻訊息卻屬於極端尾端。

這裡的執行事件是本研究定義的 ITCH 訊息列,不等於 114 張不同訂單,更不是 114 筆交易在物理時間上同時完成的證據。

如果程式每讀一列就更新激勵歷史,時間差即使都是零,第 114 列仍可能被前 113 列自激;多類型的非對稱矩陣甚至會讓評分取決於檔案列序。問題不是效能,而是:同一個記錄時間戳內,模型究竟允許什麼先後假設?

我們在擬合前固定 pre-batch 規則:依股票與整數奈秒時間戳成批,以批次之前的歷史為整批評分,最後才依每類的實際數量更新歷史。交易所的傳送順序有其資訊價值,但不能未經建模便視為奈秒以下的物理時間。

並列時間戳常見,114 筆卻是尾端大批次

依 Nasdaq TotalView-ITCH 5.0 官方規格,時間戳為「午夜起算的奈秒數」。E 代表 Order Executed,C 代表 Order Executed With Price;同一訂單參照號也可能有多筆部分執行訊息。

本研究自行映射三類事件:add=A/F、cancel_delete=X/D、execution=E/C。C 的 Printable=Y/N 兩種都包含,不是只計入可列印成交;P 與 Q 訊息不在此模型中。這是研究的事件定義,不是 Nasdaq 對全部交易的通用分類。

以下為 2019-07-30 AAPL 美東交易所時間 09:30–16:00 完整常規交易時段的既有內部聚合:

指標觀測值
execution 訊息紀錄數49,172
不同奈秒時間戳數29,379
含多筆紀錄的時間戳數10,287
位於並列時間戳的紀錄數30,080(61.17%)
並列批次大小中位數/眾數2 筆/2 筆
大小為 2–3 筆的並列批次8,439(佔並列批次 82.04%)
恰好 114 筆的時間戳批次1
更大的 131、187 筆批次各 1

不能把這份全時段統計與先前 09:30–11:00 的跨日共同視窗混用。現有直方圖能確認批次大小,無法恢復這 114 筆各自的訂單身分或微觀先後。

全部時間戳平均 1.67 筆/時間戳;只看 10,287 個並列批次則平均 2.92 筆,中位數與眾數都是 2 筆。114 約為並列批次平均的 39 倍,達 114 筆以上只有 114、131、187 三個批次。它適合揭露計算陷阱,卻不代表典型規模。61.17% 的並列比例也不能單獨推論參數不可識別;不同批次間的間隔與類型組合仍然重要。

同一時間戳,誰能先激勵誰?

三類型指數核 Hawkes 的條件強度如下:

lambda_k(t-) = mu_k(t)
             + sum_j [alpha[k,j] / tau
               * sum_{u<t} m_j(u) * exp(-(t-u)/tau)]

k 是目標類型、j 是來源類型,m_j(u) 是時間戳 u 上的實際筆數。矩陣方向為 目標 × 來源。基準 mu_k 的單位是事件/秒,tau 是秒;alpha[k,j] 為無量綱的積分激勵量,瞬時核係數才是每秒 alpha[k,j]/tau。補償積分出現 alpha 而非 alpha/tau,是因為已對指數核積分。

關鍵是嚴格的 u<t:本研究不允許當前批次提前進入自己的歷史。批次事件項因此為:

event_term(t) = sum_k m_k(t) * log(lambda_k(t-))

各類事件都先讀取同一份 t- 歷史,再用真正的 m_add、m_cancel_delete、m_execution 更新一次。不能把 114 筆當成一筆。測試也要檢查同批換序不變、股票隔離與跨日重置。

依交易所訊息傳送順序逐列評分可以是另一套模型假設,但不是同一工作似然的無害程式最佳化。

114 筆人工紀錄算出多大的差距

以下純屬 Python 標準函式庫教學反例,不是 AAPL 的參數擬合。假設會話起點有 114 筆相同類型事件、起點前無激勵歷史,mu=5 次/秒、alpha=0.6、tau=1 秒,觀察起點後的一秒:

import math

m, mu, alpha, tau, horizon = 114, 5.0, 0.6, 1.0, 1.0

# 整批都使用批次前的強度
pre_batch = m * math.log(mu)

# 錯誤對照:假設同奈秒前面的列已激勵後面的列
row_ordered = math.fsum(
    math.log(mu + alpha * i / tau) for i in range(m)
)

# 完整似然還須扣除整個觀測窗的強度積分
baseline_area = mu * horizon
excitation_area = alpha * m * (-math.expm1(-horizon / tau))
compensator = baseline_area + excitation_area

print(f"prebatch_event_log_term: {pre_batch:.6f}")
print(f"row_ordered_event_log_term: {row_ordered:.6f}")
print(f"artificial_excess: {row_ordered - pre_batch:.6f}")
print(f"one_second_compensator: {compensator:.6f}")
print(f"one_second_full_LL: {pre_batch - compensator:.6f}")

在隔離 Linux 的 Python 3.13.5 實際執行、退出碼 0,得到:

prebatch_event_log_term: 183.475922
row_ordered_event_log_term: 396.770155
artificial_excess: 213.294233
one_second_compensator: 48.237046
one_second_full_LL: 135.238876

同刻逐列更新讓事件對數項人為增加 213.294233 nats。但兩種規則在整批評分後都保留相同的 114 筆激勵歷史;零時長批次後一秒的補償積分同為 48.237046。逐列規則的完整 LL 是 348.533109,pre-batch 為 135.238876,完整差額仍是 213.294233 nats。

這不是市場預測績效,也不是兩種方法在同一精確連續時間觀測模型下的精確似然比較。pre-batch 並未丟棄批次的未來作用:一秒後 114 筆事件對自身類型的激勵仍為 114 × 0.6 × exp(-1) ≈ 25.163 次/秒。

事件項之外,還要補償積分

光把每筆事件的 log(lambda) 相加,並非完整的點過程似然;必須扣掉整個有效會話的強度積分:

LL = sum_k sum_batches m_k(t) * log(lambda_k(t-))
     - sum_k integral_session lambda_k(t) dt

我們事先固定 09:30–16:00 的 390 分鐘為 78 個五分鐘區間。日內基準按與會話半開區間的精確重疊積分;指數核則依每批實際 multiplicity 計算:

baseline_area[k] = sum_r mu[k,r] * overlap_seconds(r, session)

excitation_area[k] = sum_j sum_{u in session}
    alpha[k,j] * m_j(u) * (1 - exp(-(end-u)/tau))

實作使用 -expm1(-(end-u)/tau),避免小時間差時的浮點消減。人工一秒案例的基準面積為 5、激勵面積約 43.237046,補償項 48.237046,完整 LL 才是 135.238876,不是事件項的 183.475922。

真實批次直方圖能支持什麼情境比較?

114 筆人工案例解釋機制;另一組分析只取前述 AAPL 完整常規時段、已保存的執行批次大小直方圖,把它當成人工參數情境的 multiplicity 輸入。沒有重新下載原始 ITCH,也沒有擬合真實參數。

只考慮執行類型的正向自激,假設批次前強度 lambda^- 不低於人工給定的 mu>0,大小 m 的批次有:

0 <= Delta(m) = sum_{i=0}^{m-1} log(1 + alpha*i/(tau*lambda^-))
   <= sum_{i=0}^{m-1} log(1 + alpha*i/(tau*mu))

右式只在這個同類型條件情境下成立的上界,並非三類型 Hawkes 的完整誤差上界。未知的真實批次前強度、同刻其他類型都未納入。

設 mu=5 次/秒,對各批次上界按直方圖實際出現次數加總:

人工 alphatau=0.1 秒tau=1 秒tau=10 秒
0.18,392.651,436.32178.46
0.317,088.263,472.79500.41
0.625,186.195,837.61928.45

數值單位為 nats,alpha 與 tau 全是人工假設。中間情境 mu=5, alpha=0.3, tau=1 的累計條件上界 3,472.79 nats,除以 49,172 筆得到 0.0706 nats/筆。同參數下典型 2 筆、3 筆批次的單批上界分別是 0.0583、0.1716 nats;把人工強度下界改成 1 或 20,總上界改為 11,044.42 或 1,125.70 nats。

九組情境的條件上界為 178.46–25,186.19 nats,即 0.00363–0.51221 nats/筆。不能據此推回真實 AAPL 似然偏差。

對中間情境排除極端批次:

排除最大批次上界減少(nats)佔原情境上界
187 筆(top 1)321.549.26%
187、131、114 筆(top 3)665.6219.17%
最大 10 個批次1,123.5732.35%

最大三批共 432 筆,在該人工情境的上界中接近五分之一。已保存的直方圖未保留發生時刻,不能判定它們集中於開盤、收盤,或歸因於撮合與時間戳編碼。

這批計算另有 13/13 項測試與對帳;與後面研究用的 99 項合成測試是不同執行。

99 項測試真正驗收了什麼?

AAPL 聚合只能證明同刻訊息的存在與規模;已知參數的合成測試才核對評分規則、補償積分與歷史更新是否實作一致。

合成測試範圍實際驗證內容
批次評分(10 項)同奈秒統一評分、保留 multiplicity,輸入列順序不影響結果
完整似然(33 項)基準與指數核補償積分、解析與數值積分交叉驗證
M0/M1/M2 契約(34 項)齊次 Poisson、78 段季節性 NHPP、三類型 Hawkes 已知參數評分
合成事件流(22 項)固定種子 Ogata thinning、獨立歷史求和與雙程序確定性
合計99/99 項研究切片測試通過(Python 3.13.5、隔離 Linux x86_64)

專門構造的壓力夾具有 209 筆合成事件、4 個時間戳批次:起點 90 筆 Add,+1 秒 114 筆 Execution,+2 秒 3 筆 Cancel/Delete,+3 秒同批 1 筆 Add 與 1 筆 Execution。批次大小 90/114/3/2。與獨立撰寫的直接歷史求和/積分路徑差值最多約 1.42e-14,輸入列序反轉也不改變評分。

另外兩條以 Ogata thinning 產生的連續時間合成事件流各有 285、265 筆,獨立似然差值最多約 7.11e-15。它們不會自然產生 114 筆完全並列;大批次是特意製作的壓力輸入。

99 項是在 Python 3.13.5、隔離 Linux x86_64 執行的歷史回執,不是目前編輯 HEAD 的 GitHub Actions PASS。真實交易日擬合、留出日評分與 Hawkes 相對季節性 NHPP 的優勢都尚未測得。

工作似然的觀測邊界

簡單連續時間點過程通常不會以正機率產生精確同時到達。ITCH 的奈秒標記是記錄後的時間戳;有訊息傳送順序,不表示知道更細的物理到達時刻。因此這是 pre-batch 工作似然/偽似然評分,不是已推導出的時間量化觀測資料精確聯合密度。沒有定義組成密度與相依處理,也不能隨意稱它為 composite likelihood。

固定時間桶中的筆數可考慮離散時間計數模型;若要推斷桶內未知到達時刻,則需要區間設限假設。小批次排序可做敏感度分析,但不是無條件替換方案。

若兩個候選模型使用同一資料、分組與觀測模型,遺漏相同、與參數無關的 C(D),則差值中 (LL_A+C(D))-(LL_B+C(D))=LL_A-LL_B 可以抵消。某些離散計數模型的 -sum log(m!) 可能屬於此類。這不代表絕對 LL 不變,更不能只補階乘項便宣稱獲得精確觀測似然。更換分組或時間規則時不一定能抵消。

此外,激勵參數的非負邊界與虛無假設下衰減參數可能不可識別,也使經典卡方似然比檢定不宜直接套用。

並列時間戳下如何檢查殘差?

若把同奈秒的 114 筆紀錄當成 114 次連續到達,時間重標度診斷就會出現大量零間隔。我們預先規劃:按每類事件的唯一時間戳建立分組時間殘差,另列每批 multiplicity。QQ 圖、殘差自相關、KS 距離用來描述不符合程度;不把普通無並列連續到達假設下的 KS p 值當成正式推論。將來若做 bootstrap 或置換檢定,仍須先定義虛無假設、生成機制與保留批次相依性的重抽樣單位。

先讓檔案列序不再偷偷充當模型因果時間,再談漂亮的 Hawkes 參數。

公開重現材料:Python 程式、直方圖、測試與 SHA-256 校驗.