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