📝

Draft article

This draft is visible to admins and superusers only. Sign in with an authorized account.

← กลับไปยังบทความ
August 9, 2026
อ่าน 5 นาที

Hawkes Processes for Order Arrival and Market Event Modeling

Hawkes Processes for Order Arrival and Market Event Modeling
#microstructure
#Hawkes-process
#point-process
#order-arrival
#crypto
#HFT

The digital fingerprint article uses a three-number vector — hawkes_mu, hawkes_alpha, hawkes_beta — as the timing component of a participant's behavioral signature, and asserts that market makers exhibit strong self-excitation. It never says where those three numbers come from, what they are estimated from, or how much you should trust them. This article is the missing half: the estimator, the fit diagnostics, and the one derived quantity that turns out to matter more than the three parameters themselves — the branching ratio nn.

The claim being tested here is narrow and checkable. Order flow is self-exciting: an aggressive sell makes the next aggressive sell more likely, in a way that a Poisson model with any time-varying rate cannot reproduce. If that is true, a Hawkes process fitted to raw trade timestamps should (a) beat a Poisson baseline on held-out likelihood, (b) produce a branching ratio strictly between 0 and 1, and (c) pass a time-rescaling goodness-of-fit test. Points (a) and (b) are widely reported for equity futures. Point (c) is where published Hawkes papers usually go quiet, and it is where crypto tape has never been checked on this blog.

Two pieces of background this blog already owns, so they are not re-derived here. The self-exciting feedback structure — events triggering more events of the same kind, subcritical below a threshold and runaway above it — is derived concretely as a reproduction number g=ρ/Δg = \rho/\Delta in liquidation cascades as a trading signal, including the geometric-series total move, the supercritical flash-crash regime, and circuit breakers as one of the three things that bound it. The branching ratio nn below is the point-process analogue of that gg. What is genuinely additive here: nn is estimable in real time from trade timestamps alone, with no liquidation map, no order book depth, and no leverage assumptions. That is the whole reason to bother with the point-process machinery.

The premise that clock time is the wrong sampling axis is the founding argument of beyond time bars, which resolves it by building better bars. This article resolves it differently: by not sampling at all, and modeling the event times directly.

Point Process Fundamentals, Briefly

A point process is a random set of event times, defined by its conditional intensity λ(t)\lambda^*(t) — the instantaneous arrival rate given the full history Ft\mathcal{F}_t:

λ(t)=limΔt0E[N(t,t+Δt)Ft]Δt\lambda^*(t) = \lim_{\Delta t \to 0} \frac{\mathbb{E}[N(t, t + \Delta t) \mid \mathcal{F}_t]}{\Delta t}

The homogeneous Poisson process is the case λ(t)=μ\lambda^*(t) = \mu. The inhomogeneous Poisson process lets λ(t)\lambda(t) follow a deterministic shape (a U-shaped intraday curve, say), but still assumes conditional independence: knowing a trade just happened tells you nothing about whether another is imminent. That assumption is what real order flow violates, and the violation is the entire subject of this article. The asterisk in λ(t)\lambda^*(t) is the whole distinction — it marks the dependence on history.

The Hawkes Process

A univariate Hawkes process has intensity

λ(t)=μ+ti<tϕ(tti)\lambda^*(t) = \mu + \sum_{t_i < t} \phi(t - t_i)

with μ>0\mu > 0 the background intensity (exogenous arrivals) and ϕ()0\phi(\cdot) \geq 0 the excitation kernel. Each event bumps the intensity by ϕ(0)\phi(0), which then decays with the shape of ϕ\phi. A cluster of recent events produces a high intensity, making further events more likely — the process remembers its own history.

The Branching Ratio

n=0ϕ(t)dtn = \int_0^\infty \phi(t) \, dt

nn is the average number of child events triggered by one parent. Stationarity requires n<1n < 1; the stationary mean intensity is λˉ=μ/(1n)\bar{\lambda} = \mu / (1-n), which diverges as n1n \to 1. So nn splits total activity into an exogenous fraction (1n)(1-n) and an endogenous fraction nn: at n=0.7n = 0.7, seventy percent of events are reactions to other events rather than responses to anything outside the market.

This is exactly the subcritical/supercritical split of the cascade multiplier in liquidation cascades, reached from a different direction. The difference in what it costs you to compute: g=ρ/Δg = \rho/\Delta requires a forward map of forced-sell density and live book depth, both of which are estimates layered on assumptions about the leverage distribution. nn requires a list of timestamps.

Filimonov and Sornette (2012) reported nn rising from roughly 0.3 to above 0.7 in E-mini S&P 500 futures between 1998 and 2007. Hardiman, Bercot and Bouchaud (2013) put the same contract near n0.8n \approx 0.8 with a power-law kernel of exponent about 1.15-1.15 at short lags. Both are equity-futures results from over a decade ago, and neither transfers to crypto without measurement. Reproducing them is not the point of this article; checking whether the same regime holds on a 24/7 perpetual-futures tape with different participants and no market-open discontinuity is.

Kernel Choices

Exponential, ϕ(t)=αeβt\phi(t) = \alpha e^{-\beta t}, with n=α/βn = \alpha/\beta. Markovian, so the likelihood has an O(1)O(1)-per-event recursion (below). This is where every practical fit starts.

Power law, ϕ(t)=αcp/(c+t)1+p\phi(t) = \alpha c^p / (c+t)^{1+p}. Reproduces long-memory clustering, but loses the recursion — likelihood evaluation becomes O(N2)O(N^2) or requires truncation.

Sum of exponentials, ϕ(t)=k=1Kαkeβkt\phi(t) = \sum_{k=1}^{K} \alpha_k e^{-\beta_k t}. Approximates power-law decay with KK timescales while keeping the recursion. K=3K = 3 to 55 is usually enough, with βk\beta_k spanning milliseconds to minutes.

Whether crypto trade arrivals decay exponentially or as a power law is an empirical question with a likelihood-ratio answer, and it is measured below rather than cited.

Multivariate Hawkes Processes

For DD event types,

λd(t)=μd+d=1Dtid<tϕdd(ttid)\lambda_d^*(t) = \mu_d + \sum_{d'=1}^{D} \sum_{t_i^{d'} < t} \phi_{dd'}(t - t_i^{d'})

where ϕdd\phi_{dd'} describes how type dd' excites type dd. With exponential kernels the branching matrix is G=[αdd/βdd]G = [\alpha_{dd'}/\beta_{dd'}], and stationarity requires spectral radius ρ(G)<1\rho(G) < 1. The eigenvector of GG associated with the largest eigenvalue identifies the dominant excitation mode — which group of event types tends to fire together.

The interesting instantiation for an order book is D=6D = 6: market buy, market sell, limit buy, limit sell, cancel buy, cancel sell. That matrix has 36 entries and is the part of the Hawkes toolkit this blog does not have anywhere else. Note that one of its predicted entries is already documented empirically without the vocabulary: correlated mass cancellation across consecutive levels — wall pulls — is measured directly in queue position and order book wall analysis. A fitted ϕcancel,cancel\phi_{\text{cancel},\text{cancel}} is the same phenomenon expressed as a kernel, and the two measurements should agree. If they do not, one of them is wrong.

Cross-asset and multi-venue versions are the same machinery with different labels: off-diagonal kernels capture lead-lag and contagion, and Shi, Broussard and Booth (2019) used exactly this on the 30 Dow stocks during the 2010 flash crash, finding asymmetric cross-excitation with identifiable contagion sources.

Calibration

Maximum Likelihood

For event times {t1,,tN}\{t_1, \ldots, t_N\} on [0,T][0, T]:

(θ)=i=1Nlogλ(ti)0Tλ(t)dt\ell(\theta) = \sum_{i=1}^{N} \log \lambda^*(t_i) - \int_0^T \lambda^*(t) \, dt

The first term rewards intensity where events happened; the second penalizes intensity that produced nothing.

For the exponential kernel the recursion

Ri=j<ieβ(titj)=eβ(titi1)Ri1+1R_i = \sum_{j < i} e^{-\beta(t_i - t_j)} = e^{-\beta(t_i - t_{i-1})} \cdot R_{i-1} + 1

gives λ(ti)=μ+αRi\lambda^*(t_i) = \mu + \alpha R_i at O(1)O(1) per event, and the compensator closes:

0Tλ(t)dt=μT+αβi=1N(1eβ(Tti))\int_0^T \lambda^*(t) \, dt = \mu T + \frac{\alpha}{\beta} \sum_{i=1}^{N} \left(1 - e^{-\beta(T - t_i)}\right)

Total cost O(N)O(N), which is what makes million-event fits routine. Optimize with L-BFGS-B under positivity constraints.

Two failure modes worth knowing before you trust an output. The likelihood surface flattens badly as n1n \to 1, so a near-critical fit can report a confident-looking point estimate sitting in a valley that is nearly level for ±0.1\pm 0.1 in nn — always profile the likelihood in nn rather than reading the optimizer's Hessian. And in the multivariate case parameter count grows as O(D2)O(D^2), so past D10D \approx 10 you need group-Lasso on the kernel norms or the matrix is fitting noise.

EM and Non-Parametric Estimation

EM treats the branching structure as latent: each event is either an immigrant from μ\mu or an offspring of some earlier event. The generic E-step/M-step mechanics, the local-optimum caveat, and the multiple-initialization discipline are covered in the Baum-Welch section of regime detection with HMMs and are identical here. The Hawkes-specific part is the E-step quantity itself:

pij=ϕ(titj)λ(ti),pi0=μλ(ti)p_{ij} = \frac{\phi(t_i - t_j)}{\lambda^*(t_i)}, \quad p_{i0} = \frac{\mu}{\lambda^*(t_i)}

pijp_{ij} is a posterior over which event caused which — an interpretable output, not just an optimization intermediate. Summed by event type it gives an attribution of the tape: this fraction of the last hour's sells was triggered by earlier sells, that fraction arrived from outside. It also lets you estimate ϕ\phi non-parametrically as piecewise-constant on a grid, which is how you check the exponential assumption without committing to an alternative. Cost: O(N2)O(N^2) for the full pijp_{ij} matrix, so it does not scale past roughly 10510^5 events without approximation.

Bacry and Muzy's spectral method is the other model-free route — the power spectral density of a stationary Hawkes process factors as C^(ω)=IΦ^(ω)2diag(μ)\hat{C}(\omega) = |I - \hat{\Phi}(\omega)|^{-2} \cdot \text{diag}(\mu), so estimating the covariance density and solving the factorization recovers the kernels with no parametric form assumed.

Fitting Real Crypto Tape

Every number in this section must come from an actual fit on real data. Recovering parameters you injected into a simulator is not evidence of anything except that the optimizer works.

The data: Binance BTC/USDT aggTrade timestamps over a defined window, with the window, symbol, and event count stated explicitly alongside every reported figure. aggTrade aggregates fills at the same price from one taker order into a single record, which is the right unit here — one aggressive order is one event, not one event per counterparty fill.

Univariate Fit

import numpy as np
import pandas as pd
from tick.hawkes import HawkesExpKern

trades = pd.read_parquet("binance_btcusdt_aggtrades.parquet")

t0 = trades["transact_time"].iloc[0]
ts = ((trades["transact_time"] - t0) / 1000.0).to_numpy(dtype=np.float64)
T = ts[-1]

learner = HawkesExpKern(decays=BETA_GRID, penalty="none", verbose=False)
learner.fit([ts])

mu_hat = learner.baseline[0]
alpha_hat = learner.adjacency[0, 0]
n_hat = alpha_hat / BETA_CHOSEN

print(f"events   = {len(ts)}")
print(f"window   = {T/3600:.2f} h")
print(f"mu       = {mu_hat:.4f} events/s")
print(f"n        = {n_hat:.4f}")
print(f"lambda_bar (model) = {mu_hat/(1-n_hat):.4f} events/s")
print(f"lambda_bar (data)  = {len(ts)/T:.4f} events/s")

The last two prints are the first sanity check that costs nothing: if the model's stationary mean intensity μ/(1n)\mu/(1-n) does not land near the empirical event rate, the fit is wrong regardless of what the optimizer reported.

β\beta should not be fixed by hand. Profile the likelihood over a grid of decays and report the profile, because α\alpha and β\beta trade off strongly and n=α/βn = \alpha/\beta can be stable while neither parameter is.

Does the Kernel Actually Decay Exponentially?

The power-law claim in the literature comes from 2013 equity-futures papers. Test it directly: fit an exponential kernel and a power-law kernel to the same tape, compare by log-likelihood on held-out data (not in-sample, since the power law has an extra parameter), and separately look at the empirical intensity decay following large trades.

large = ts[trades["quantity"].to_numpy() > LARGE_TRADE_THRESHOLD]

lags = np.logspace(-3, 2, 60)   # 1 ms .. 100 s
rate = np.empty(len(lags) - 1)
for k in range(len(lags) - 1):
    lo, hi = lags[k], lags[k + 1]
    counts = [
        np.searchsorted(ts, t0_ + hi) - np.searchsorted(ts, t0_ + lo)
        for t0_ in large
    ]
    rate[k] = np.mean(counts) / (hi - lo)

Plotted log-log, an exponential kernel bends; a power law is straight. That plot is a stronger piece of evidence than either likelihood number, because it shows where the misfit is — typically exponentials underfit the tail and overfit the first few milliseconds.

The Branching Matrix

Minimum viable multivariate model: two dimensions, aggressive buy and aggressive sell, separated by is_buyer_maker. If L3 data is available, extend to cancels.

buys  = ts[~trades["is_buyer_maker"].to_numpy()]   # taker bought
sells = ts[ trades["is_buyer_maker"].to_numpy()]   # taker sold

mv = HawkesExpKern(decays=BETA_CHOSEN, penalty="l2", C=C_CV, verbose=False)
mv.fit([buys, sells])

G = mv.adjacency / BETA_CHOSEN          # branching matrix
rho = np.max(np.abs(np.linalg.eigvals(G)))
print("G =\n", G)
print(f"spectral radius = {rho:.4f}")   # must be < 1

The two quantities to publish are the matrix itself and its spectral radius. The asymmetry is the interesting part: whether sell-excites-sell exceeds buy-excites-buy, and whether the cross terms are symmetric, are testable statements about crypto tape that nobody here has measured.

Goodness of Fit: Time Rescaling

The time-rescaling theorem: if the model is correct, the transformed times τi=0tiλ(s)ds\tau_i = \int_0^{t_i} \lambda^*(s)\,ds form a unit-rate Poisson process, so the differences Δτi\Delta\tau_i are Exp(1)\text{Exp}(1).

from scipy.stats import kstest, expon

compensator = np.empty(len(ts))
for i, ti in enumerate(ts):
    compensator[i] = mu_hat * ti + (alpha_hat / BETA_CHOSEN) * np.sum(
        1 - np.exp(-BETA_CHOSEN * (ti - ts[:i]))
    )

tau = np.diff(compensator)
stat, pval = kstest(tau, expon(scale=1.0).cdf)
print(f"KS = {stat:.4f}, p = {pval:.4g}, N = {len(tau)}")

One caution on reading this test: with NN in the hundreds of thousands, the KS test rejects on trivial misspecification. A tiny p-value at N=5×105N = 5 \times 10^5 means almost nothing on its own; the informative output is the QQ plot of Δτ\Delta\tau against Exp(1)\text{Exp}(1) and the KS statistic itself, which is a scale-free effect size. Report both, and report them honestly — if the exponential kernel is rejected on crypto tape, that is a result worth publishing rather than burying, in the same spirit as the honest negative result on robust edges.

Does n Actually Move With Fragility?

The claim that nn is a real-time fragility indicator is cited constantly and tested rarely. The test is straightforward: estimate nn on rolling windows across a calm period and across a known crypto cascade date, and see whether it rises before or only during the event. A quantity that only spikes concurrently with the crash is a description, not a warning.

Stability and Robustness

A fitted nn is not a measurement until you know how much it moves when you change things that should not matter. Four specific traps, in rough order of how much damage they do.

Timestamp resolution manufactures self-excitation. Binance aggTrade timestamps are millisecond-resolution. Trades that were genuinely microseconds apart collapse onto identical millisecond stamps, and a Hawkes likelihood reads coincident events as maximal excitation — ϕ(0)\phi(0) evaluated at exactly zero lag. This biases nn upward, and the bias grows with activity, which means it is worst exactly during the bursts where you most want the number to be trustworthy. Quantify it: count the fraction of events sharing a timestamp with a neighbour, then refit with those events jittered uniformly within their millisecond bin and report how much nn moves. If jittering changes nn by more than the confidence interval, the headline number is measuring the clock, not the market.

Exchange batching. Exchanges do not emit events as they occur; they emit them as their matching and dissemination pipeline flushes. Binance's one-per-second throttle on the liquidation stream is the documented precedent — a stream that looks like clustered arrivals is partly an artifact of the publisher. Any batching in the trade feed imprints a periodicity on the inter-arrival distribution that a Hawkes kernel will happily absorb into α\alpha. Check for it directly: histogram the inter-arrival times and look for spikes at the batching period before fitting anything.

Sensitivity to the assumed decay. n=α/βn = \alpha/\beta depends on β\beta, and β\beta is usually fixed or grid-searched rather than jointly estimated. Report nn as a function of β\beta over the plausible range, not as a point. If the curve is flat, the number is real; if nn tracks β\beta closely, you have chosen your answer.

Estimation window. nn estimated over an hour, a day, and a week will differ, partly because the process is genuinely non-stationary and partly because a longer window mixes regimes, which inflates apparent excitation by conflating between-regime variation with within-regime clustering. Report the window-length sweep. The right way to read a rising nn is against the same window length measured at other times, never against a number from a different window.

The pattern here is the one established in the GPU precision trap: a pipeline that runs cleanly and returns a plausible number is not evidence of a correct number, and the only defense is to perturb the inputs that should not matter and confirm the output does not move.

What This Does and Does Not Buy You

Three connections to microstructure theory, kept short because the blog covers each at length elsewhere.

Price formation. In Kyle (1985), the market maker prices off net order flow mixing informed and noise trading; the impact coefficient λ\lambda and depth 1/λ1/\lambda are laid out with the follow-on literature — including the evidence against Kyle's linearity — in slippage cost models. The Hawkes reading maps μ\mu onto genuinely new information and the self-excited events onto mechanical reaction, making nn a measurable proxy for the noise-driven share of flow.

Volatility clustering. Clustering, persistence, the stationarity condition α+β<1\alpha + \beta < 1 and the long-run variance ω/(1αβ)\omega/(1-\alpha-\beta) — structurally the exact analogue of n<1n < 1 and μ/(1n)\mu/(1-n) — are covered in GARCH volatility forecasting for crypto. The genuinely new claim is Bacry, Delattre, Hoffmann and Muzy (2013): a near-critical Hawkes process generates return series whose volatility autocorrelation decays as a power law, with no explicit volatility model anywhere. Volatility clustering falls out as an emergent property of self-exciting order flow rather than being assumed.

Epps effect. Bacry and Muzy showed a bivariate Hawkes model reproduces the decay of measured correlation at high sampling frequency purely from the finite propagation time of excitation between the two processes — no extra mechanism required.

On execution, the prescription that follows from self-excitation — slow down after a slice, speed up in quiet periods — is already the core of the POV feedback-loop section in TWAP, VWAP and POV execution algorithms, and the critique of naive equal slicing is Almgren-Chriss. What a Hawkes fit adds is not the advice but a number: the fitted kernel half-life ln2/β\ln 2 / \beta says how long the excitation from your own slice takes to decay, which converts "wait a bit" into a specific pause length.

Limitations

No inhibition. The classical model only allows events to increase intensity. Markets contain the opposite: a large limit order absorbing pressure can deter aggressive trading. Hawkes processes with inhibition permit negative kernel values, at the cost of having to enforce λ(t)0\lambda^*(t) \geq 0. Whether this matters for a given fit is visible in the non-parametric kernel estimate — if the piecewise-constant ϕ^\hat\phi dips below zero at some lag, the constrained model is fighting the data.

Non-stationarity. The standard model assumes stationarity, and crypto is 24/7 but not uniform: liquidity, participant mix and event rate all shift across the day and around funding timestamps. A time-varying baseline μ(t)\mu(t) handles this at the cost of more parameters, and the estimation-window sensitivity above is how you find out whether you need it.

Summary

The Hawkes process is worth the machinery for one reason: it collapses the clustering of order flow into a single interpretable number, the branching ratio nn, computable from timestamps alone with no order-book reconstruction and no assumptions about leverage or positioning. That makes it the cheapest available estimate of how endogenous a market currently is — the same question liquidation cascades answers expensively through g=ρ/Δg = \rho/\Delta.

The machinery is straightforward: exponential kernels give an O(N)O(N) likelihood via the RiR_i recursion, EM gives an interpretable posterior over which event caused which, and time rescaling gives a real goodness-of-fit test rather than a plausibility argument. What is not straightforward is trusting the output. Millisecond timestamp rounding biases nn upward precisely during bursts, exchange batching imprints structure the kernel will absorb, and nn moves with both the assumed decay and the estimation window. A branching ratio reported without those four sensitivities is a number, not a measurement.


References and Further Reading

ข้อจำกัดความรับผิดชอบ: ข้อมูลที่ให้ไว้ในบทความนี้มีไว้เพื่อการศึกษาและให้ข้อมูลเท่านั้น และไม่ถือเป็นคำแนะนำทางการเงิน การลงทุน หรือการเทรด การเทรดสกุลเงินดิจิทัลมีความเสี่ยงสูงที่จะขาดทุน

ผู้เขียน

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

ก้าวนำหน้าตลาด

สมัครรับจดหมายข่าวของเราเพื่อรับข้อมูลเชิงลึกการเทรดด้วย AI เฉพาะ การวิเคราะห์ตลาด และการอัปเดตแพลตฟอร์ม

เราเคารพความเป็นส่วนตัวของคุณ ยกเลิกการสมัครได้ทุกเมื่อ