# 同一奈秒出現 114 筆執行紀錄：Hawkes 似然容易在哪裡算錯？

> Canonical: https://vxi.me/zh-tw/posts/hawkes-itch-nanosecond-ties-likelihood/
> Locale: zh-tw
> Published: 2026-10-31
> Updated: 2026-10-31
> Markdown: https://vxi.me/zh-tw/posts/hawkes-itch-nanosecond-ties-likelihood.md

<figure class="hawkes-ties-hero not-prose" lang="zh-tw">
<picture>
  <source media="(prefers-reduced-motion: reduce) and (max-width: 640px)" srcset="/images/posts/hawkes-itch-nanosecond-ties-likelihood/hawkes-tie-scores.mobile.still.zh-tw.svg" type="image/svg+xml">
  <source media="(prefers-reduced-motion: reduce)" srcset="/images/posts/hawkes-itch-nanosecond-ties-likelihood/hawkes-tie-scores.still.zh-tw.svg" type="image/svg+xml">
  <source media="(max-width: 640px)" srcset="/images/posts/hawkes-itch-nanosecond-ties-likelihood/hawkes-tie-scores.mobile.zh-tw.svg" type="image/svg+xml">
  <img src="/images/posts/hawkes-itch-nanosecond-ties-likelihood/hawkes-tie-scores.zh-tw.svg" alt="114 筆同刻合成事件的 Hawkes 評分：pre-batch 事件項 183.475922 nats，逐筆更新為 396.770155 nats，多出 213.294233 nats；補償積分同為 48.237046 nats。" width="1200" height="700" loading="eager" fetchpriority="high" decoding="async" style="display:block;width:100%;height:auto">
</picture>
<figcaption>圖：同刻事件的兩種評分規則；非 AAPL 參數擬合。</figcaption>
</figure>

整理 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 官方規格](https://nasdaqtrader.com/content/technicalsupport/specifications/dataproducts/NQTVITCHSpecification.pdf)，時間戳為「午夜起算的奈秒數」。`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 的條件強度如下：

```text
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`**：本研究不允許當前批次提前進入自己的歷史。批次事件項因此為：

```text
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` 秒，觀察起點後的一秒：

```python
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，得到：

```text
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)` 相加，並非完整的點過程似然；必須扣掉**整個有效會話**的強度積分：

```text
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 計算：

```text
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` 的批次有：

```text
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` 次／秒，對各批次上界按直方圖實際出現次數加總：

| 人工 alpha | tau=0.1 秒 | tau=1 秒 | tau=10 秒 |
| --- | ---: | ---: | ---: |
| 0.1 | 8,392.65 | 1,436.32 | 178.46 |
| 0.3 | 17,088.26 | 3,472.79 | 500.41 |
| 0.6 | 25,186.19 | 5,837.61 | 928.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.54 | 9.26% |
| 187、131、114 筆（top 3） | 665.62 | 19.17% |
| 最大 10 個批次 | 1,123.57 | 32.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 校驗](/evidence/hawkes-itch-nanosecond-ties-likelihood/README.md).

## Verification context

- Level: first-party
- Verified: 2026-10-31T00:00:00.000Z
- Environment: Python 3.13.5; Linux x86_64; historical synthetic research tests
- Environment: Python 3 standard-library public reproducer and aggregated histogram
- Evidence mode: mixed
- Evidence receipt: https://vxi.me/evidence/hawkes-itch-nanosecond-ties-likelihood.json
