Pure-Python multivariate Hawkes process simulation and MLE (exponential kernels), no C++ deps
Project description
phawkes
Pure-Python multivariate Hawkes processes with exponential kernels — simulation, MLE, and systemic-risk metrics. No C++ dependencies.
Why this exists
There is already an excellent Hawkes library: tick from École Polytechnique. We recommend it whenever it works for you.
However, as of Python 3.13, tick 0.8.0.1 builds but its Base metaclass breaks on instantiation of any learner class ('HawkesExpKern' object has no settable attribute 'events'). This is a known incompatibility with CPython 3.13's stricter descriptor protocol. The simulator side of tick still works; only the fitters fail.
phawkes fills the gap with a minimal, tested, pure-numpy + scipy implementation of the exponential-kernel multivariate Hawkes MLE. It is deliberately small — if you need sum-of-exponentials kernels, L1 / trace-norm regularization, EM for semi-parametric kernels, or GPU Riemannian fits, tick on Python ≤ 3.12 is still the better tool.
Install
pip install phawkes
Requires Python ≥ 3.9, numpy ≥ 1.23, scipy ≥ 1.10.
Quickstart
import numpy as np
from phawkes import HawkesExpSim, HawkesExpMLE, branching_ratio
true_mu = np.array([0.3, 0.2])
true_alpha = np.array([[0.2, 0.1], [0.3, 0.15]])
beta = 1.0
# simulate a realization on [0, 4000]
sim = HawkesExpSim(baseline=true_mu, adjacency=true_alpha, decay=beta, seed=7)
events = sim.simulate(end_time=4000.0)
# fit by MLE
learner = HawkesExpMLE(decay=beta).fit(events, end_time=4000.0)
print(learner.baseline_) # ~ true_mu
print(learner.adjacency_) # ~ true_alpha
print(learner.branching_ratio()) # spectral radius of fitted alpha
The math (1-minute version)
A multivariate exponential-kernel Hawkes process with shared decay β has conditional intensity
$$ \lambda_i(t) = \mu_i + \sum_j \sum_{t_j^k < t} \alpha_{ij}, \beta, e^{-\beta (t - t_j^k)} $$
μᵢ ≥ 0is the baseline (background) rate on dimiαᵢⱼ ≥ 0is the branching coefficient from dimjto dimiβ > 0controls how fast past events' excitation decays
Stability (finite expected event count per unit time) requires the spectral radius of α — the branching ratio λ_max(α) — to be strictly less than 1. As it approaches 1, a single shock can cascade through many downstream events; this is the quantitative signature of near-critical contagion in finance and epidemics.
Log-likelihood on the window [0, T]:
$$ \ell = \sum_i \left[\sum_k \log \lambda_i(t_i^k)\right] - \sum_i \int_0^T \lambda_i(t), dt $$
For exponential kernels the integral is closed-form, and the sum of log-intensities admits Ogata's 1981 recursion for O(N) total evaluation. phawkes.HawkesExpMLE implements this, parameterises μ = exp(log_μ) and α = exp(log_α) for strict positivity, optimises by L-BFGS-B with analytic gradients, and optionally ridges log_α.
Per-regime fitting
Pooling Hawkes events across different market regimes creates spurious criticality — the MLE interprets regime shifts as endogenous self-excitation and inflates the branching ratio. fit_per_regime slices event streams by labelled time intervals and fits a separate MLE per label:
from phawkes import RegimeSegment, fit_per_regime
segments = [
RegimeSegment(0.0, 500.0, "calm"),
RegimeSegment(500.0, 700.0, "crisis"),
RegimeSegment(700.0, 1000.0, "calm"),
]
fits = fit_per_regime(events, segments, decay=1.0)
fits["calm"].branching_ratio() # e.g. 0.3
fits["crisis"].branching_ratio() # e.g. 0.85 — near-critical
Roadmap
v0.1 (this release):
- Exponential-kernel multivariate Hawkes MLE with shared decay
- Ogata-thinning simulator
- Per-regime convenience wrapper
- Branching-ratio utility
- Unit-tested against simulator ground truth on 2-dim and 5-dim problems
v0.2+ (planned):
- Sum-of-exponentials kernels (richer temporal structure)
- L1 / trace-norm regularization (Bacry et al. 2020, JMLR)
- Per-edge decay
βᵢⱼ(currently shared) - Cross-validation for choosing
β - Benchmark parity with
tickon Python 3.12
Authors
- Pierre Samson (@darw007d) — idea, use-case, design decisions
- Claude Opus (Anthropic) — implementation and tests
Originally motivated by the OMEGA Swarm hedge-fund project, where regime-stratified Hawkes calibration replaces a heuristic 5% per cycle edge-decay in a live contagion network. The library is deliberately agnostic of that use-case.
Contributing
Issues and PRs welcome. We care about:
- Numerical correctness (every new fitter needs a simulator-recovery test)
- Zero heavy dependencies (no C++, no
tensorflow/torch) - Honest documentation — if something is slow or unstable, say so
Citations
If phawkes contributes to a published result, please cite the foundational references alongside this library:
- Hawkes, A.G. (1971). Spectra of some self-exciting and mutually exciting point processes. Biometrika.
- Ogata, Y. (1981). On Lewis' simulation method for point processes. IEEE Trans. Inform. Theory.
- Laub, P.J., Taimre, T. & Pollett, P.K. (2015). Hawkes Processes. arXiv:1507.02822.
- Bacry, E., Bompaire, M., Gaïffas, S. & Muzy, J.-F. (2020). Sparse and low-rank multivariate Hawkes processes. JMLR.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file phawkes-0.1.0.tar.gz.
File metadata
- Download URL: phawkes-0.1.0.tar.gz
- Upload date:
- Size: 15.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
58ba119d048b4217092cb3f4ebfa4da9fce580ed4b4fc177c2b4fcf3c5662f16
|
|
| MD5 |
2afbf402031e814c6bf6cc5a84b1734e
|
|
| BLAKE2b-256 |
dd7b28532427004d845172d3803156413bccb759f91b62d50a5b25e0310bce5b
|
File details
Details for the file phawkes-0.1.0-py3-none-any.whl.
File metadata
- Download URL: phawkes-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e9585b025a5020bd480075e252d4fc294ef7ab401922a47b25ef29751edb5337
|
|
| MD5 |
03bde24034e5bd2fce72863b9ef8aab5
|
|
| BLAKE2b-256 |
4a5e2b4f5979dc619c05c0e8620fa614ad9bf41524830255b5f355fc69d566ac
|