Skip to content

Repository files navigation

Description

OBQS is a fast, research-grade Order-Book Queue Simulator that estimates time-to-fill (TTF) for passive limit orders using a birth-death queue with rates μ (down events) and λₐ (up arrivals). It includes interchangeable Python / Numba / C engines, a validation harness (Erlang check, KM/QQ/KS diagnostics), and visuals like an E[TTF] heatmap over (μ, λₐ). It can be used to size passive orders, estimate fill probabilities by a deadline, and study queue-drift regimes—clean, reproducible, and ready to extend to real data.

Model

Let $X_t \in \mathbb{Z}_{\ge 0}$ denote the queue depth ahead of a passive order. $X_t$ is a continuous-time birth–death chain with absorbing state $0$

$$ k \xrightarrow[\text{rate } \mu]{\text{down (exec/cancel ahead)}} k-1,\qquad k \xrightarrow[\text{rate } \lambda_a]{\text{up (arrival at price)}} k+1 \quad (k\ge1) $$

Time-to-fill is the hitting time $\tau = \inf{t\ge0 \mid X_t=0}$ with $X_0=k_0$. Generator $Q$ for $k\ge1$ satisfies $Q_{k,k-1}=\mu$, $Q_{k,k+1}=\lambda_a$, $Q_{k,k}=-(\mu+\lambda_a)$ and $Q_{0,0}=0$.

Benchmarks

Pure-death case $\lambda_a=0$ gives $\tau \sim \mathrm{Erlang}(k_0,\mu)$ $\mathbb{E}[\tau]=k_0/\mu$ and $\mathrm{Var}(\tau)=k_0/\mu^2$ Drifted case with $\mu>\lambda_a$ yields $\mathbb{E}[\tau]=k_0/(\mu-\lambda_a)$ If $\mu \le \lambda_a$ then $\mathbb{E}[\tau]=\infty$

Estimands

For a horizon $T>0$ define the fill probability $p(T)=\mathbb{P}(\tau \le T)$ with Monte Carlo estimate

$$ \widehat{p}(T)=\frac{1}{n}\sum_{i=1}^n \mathbf{1}{\tau_i\le T},\qquad \mathrm{SE}\approx \sqrt{\widehat{p}(T)\bigl(1-\widehat{p}(T)\bigr)/n} $$

Distribution diagnostics use Kaplan–Meier survival $\widehat{S}(t)$, a QQ comparison, and the KS statistic $D=\sup_t |\widehat{F}_n(t)-F^\star(t)|$.

Simulation

The engine evolves two independent exponential clocks per path, a down clock with rate $\mu$ and an up clock with rate $\lambda_a$. At each step it advances time to the next clock event, if the down clock rings first it updates the state to $k!\leftarrow!k-1$, otherwise to $k!\leftarrow!k+1$. The loop ends when $k=0$ and the path records $\tau$, or when accumulated time exceeds $T$ and the path is censored (reported as $\infty$ in the raw output). Work per path scales with the number of events until $\min(\tau, T)$ and grows near the critical line $\mu \approx \lambda_a$.

Implementation

Engines share one API and include Python for reference, Numba with JIT, and a C extension using the NumPy buffer interface and deterministic per-path seeding. Outputs are vectors of TTF values with $\infty$ for unfilled paths and helper summaries reporting mean, median, p05, p95, and $P(\text{fill} \le T)$.

Validation

Erlang moments are checked at $\lambda_a=0$. Monotonicity is verified so that increasing $\mu$ decreases $\mathbb{E}[\tau]$ and increasing $\lambda_a$ increases $\mathbb{E}[\tau]$. KM, QQ, and KS provide distribution-level agreement against a reference.

Visualization

A heatmap of $\mathbb{E}[\tau]$ over $(\mu,\lambda_a)$ highlights queue-drift regimes and the transition from fast to rare fills.

Purpose

Provide a precise and reproducible baseline for time-to-fill modeling, enabling estimation of $p(T)$ and $\mathbb{E}[\tau]$ under $(k_0,\mu,\lambda_a)$ with diagnostics that guide extensions such as price-move hazards, state-dependent intensities, and Hawkes-style clustering.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages