Pro Feature. Requires a Pro or Ultra subscription. Get started at api.mathematicalcompany.com
Particle Filter
Horizon provides a Sequential Monte Carlo (SMC) particle filter implemented in Rust. Unlike Kalman filters, particle filters handle arbitrary nonlinear dynamics and non-Gaussian noise, making them well-suited for jump-diffusion processes, fat-tailed markets, and multimodal state distributions.Nonlinear & Non-Gaussian
No linearity or Gaussian assumptions. Handles jumps, fat tails, and multimodal posteriors.
Rust-Native SMC
All particle propagation, resampling, and weight computation runs in Rust.
Adaptive Resampling
Systematic resampling triggered when effective sample size drops below threshold.
Pipeline Integration
Drop
hz.particle_tracker() into any pipeline for filtered state estimates in ctx.params.ParticleFilter
The core particle filter class. Maintains a weighted set of particles representing the posterior distribution over the hidden state.Constructor
| Parameter | Type | Default | Description |
|---|---|---|---|
n_particles | int | 1000 | Number of particles. More particles = better approximation, higher cost. |
initial_state | float | required | Initial state estimate (all particles start here with small jitter) |
process_noise | float | 0.01 | Standard deviation of the process noise (state transition) |
measurement_noise | float | 0.02 | Standard deviation of the measurement noise (observation model) |
seed | int | None | Random seed for reproducibility. None = random. |
For prediction markets, 500-2000 particles provide a good tradeoff between accuracy and speed. The filter processes one observation in ~10-50 microseconds in Rust depending on particle count.
update()
Process a new observation: propagate particles through the state transition, compute weights from the observation likelihood, and resample if needed.| Parameter | Type | Description |
|---|---|---|
observation | float | New observed value (e.g., market price or probability) |
PFState object with the filtered estimate.
PFState Type
| Field | Type | Description |
|---|---|---|
mean | float | Weighted mean of the particle cloud (point estimate) |
variance | float | Weighted variance of the particle cloud |
ess | float | Effective sample size (higher = more diverse particles) |
State Access Methods
| Method | Returns | Description |
|---|---|---|
state_estimate() | float | Weighted mean of the particle cloud |
state_variance() | float | Weighted variance of the particle cloud |
effective_sample_size() | float | N_eff = 1 / sum(w_i^2). Ranges from 1 (degenerate) to N (uniform). |
particles() | list[float] | Current particle positions |
weights() | list[float] | Current particle weights (normalized, sum to 1.0) |
reset() | None | Reset all particles to the initial state with uniform weights |
Pipeline Integration
hz.particle_tracker
Creates a pipeline function that tracks a filtered price estimate using the particle filter. Injects filtered state intoctx.params.
| Parameter | Type | Default | Description |
|---|---|---|---|
feed | str | None | Feed name to read prices from. None = first available. |
n_particles | int | 1000 | Number of particles |
process_noise | float | 0.005 | Process noise standard deviation |
measurement_noise | float | 0.02 | Measurement noise standard deviation |
seed | int | None | Random seed for reproducibility |
param_name | str | "pf" | Key in ctx.params |
Injected Parameters
| Key | Type | Description |
|---|---|---|
ctx.params["pf"]["mean"] | float | Filtered state estimate (weighted mean) |
ctx.params["pf"]["variance"] | float | State variance from the particle cloud |
ctx.params["pf"]["ess"] | float | Effective sample size |
ctx.params["pf"]["ess_ratio"] | float | ESS / n_particles (1.0 = fully diverse, less than 0.5 = degenerate) |
Examples
Offline State Tracking
Use the particle filter directly for research without a pipeline:Particle Filter vs Kalman Filter
The particle filter excels when the state dynamics are nonlinear or noise is non-Gaussian:Combining with BOCPD
Use change point detection to reset the particle filter after regime shifts:Mathematical Background
Sequential Monte Carlo
Sequential Monte Carlo
A particle filter represents the posterior distribution of the hidden state given all observations, using a weighted set of N samples (particles). At each step:
- Propagate: Draw each particle from the state transition distribution
- Weight: Compute the likelihood of the observation given each particle
- Normalize: Scale all weights to sum to 1
- Resample: If the effective sample size is below the threshold, resample particles proportional to weights
sum(w_i * x_i) approximates the conditional expectation of the state.Effective Sample Size
Effective Sample Size
ESS = 1 / sum(w_i^2) measures the diversity of the particle cloud. When all weight concentrates on one particle, ESS equals 1 (degenerate). When weights are uniform, ESS equals N (maximum diversity). Horizon resamples when ESS drops below N/2.Systematic Resampling
Systematic Resampling
Horizon uses systematic resampling, which generates a single uniform random number and deterministically selects particles at evenly spaced intervals through the CDF. This has lower variance than multinomial resampling and O(N) cost.