Path signatures in Julia
I am excited to share ChenSignatures.jl, a Julia package for computing path signatures and log-signatures.
What are signatures? The signature of a path X : [0,T] \to \mathbb{R}^d is the sequence of iterated integrals:
S(X)_m = \left(1, \int_0^T dX_{t_1}, \int_0^T \int_0^{t_2} dX_{t_1} \otimes dX_{t_2}, \ldots, \int_0^T \int_0^{t_m} \cdots \int_0^{t_2} dX_{t_1} \otimes \cdots \otimes dX_{t_m}\right)
The k-th level is a tensor S^k(X) \in (\mathbb{R}^d)^{\otimes k} with components:
S^k(X)^{i_1 \ldots i_k} = \int_{0 < t_1 < \cdots < t_k < T} dX^{i_1}_{t_1} \cdots dX^{i_k}_{t_k}
This object uniquely characterizes the path up to tree-like equivalence and has applications in machine learning (time series classification, generative models) and mathematical finance (rough path pricing, expected signatures).
I got interested in signatures while working on derivatives pricing, where they provide a natural way to encode path-dependent payoffs. When I looked for Julia implementations, I found the ecosystem lacking β so I decided to build one.
Why another implementation?
Juliaβs ecosystem lacked an actively maintained option β PathSignatures.jl has been dormant for 5 years. ChenSignatures.jl aims to fill this gap with:
- Native Julia implementation with attention to performance (SIMD, StaticArrays)
- AD support via Enzyme and ForwardDiff
- Python interop through the chen-signatures wrapper
Benchmarks
Comparison against iisignature and pysiglib on signature computation:
| Config (N, d, m) | iisignature | pysiglib | ChenSignatures.jl | chen-signatures (Python wrapper) |
|---|---|---|---|---|
| (200, 2, 4) | 0.04 ms | 0.12 ms | 0.013 ms | 0.07 ms |
| (1000, 2, 6) | 0.62 ms | 0.26 ms | 0.19 ms | 0.31 ms |
| (200, 10, 4) | 6.2 ms | 0.93 ms | 0.57 ms | 0.73 ms |
| (1000, 10, 4) | 32 ms | 3.2 ms | 2.1 ms | 3.1 ms |
| (1000, 10, 6) | 8.1 s | 1.0 s | 0.83 s | 0.94 s |
N = path length, d = dimension, m = truncation depth.
Methodology: Each configuration was run twice with 5 repeats per measurement on the same machine. Times shown are conservative (slower of the two runs). Full results and scripts available at github.com/aleCombi/sig-benchmarks.
Quick start
using ChenSignatures, StaticArrays
# Path as vector of SVectors (recommended for performance)
path = [SVector(sin(t), cos(t)) for t in 0:0.01:1]
sig = signature(path, 4) # Truncation depth 4
logsig = logsignature(path, 4)
Current status
- Dense signatures and log-signatures (flattened vector representation): optimized and tested
- Cross-validated against iisignature
- AD support via Enzyme and ForwardDiff: tested on Julia 1.10 LTS
- AD on Julia 1.12: experimental (Enzyme ecosystem still stabilizing)
- Sparse tensors: experimental
- Known issue: log-signature memory blowup at high depths in Python wrapper β investigating
Contributions
I am not accepting PRs at the moment (I have too many new features and ideas to test), but issues and discussions are welcome!
Links: Documentation Β· GitHub Β· Benchmarks