Simulation Framework (Backtest)

Fill Probability

For a limit order at distance \(\delta\) from mid, with base intensity \(\lambda_t\):

\[p_{\text{fill}} = 1 - \exp(-\lambda_t e^{-k\delta} \Delta t)\]

Fill events are independent Bernoulli trials per side per tick.

Implementation: engine::backtest

Terminal Liquidation

At \(t = T\), remaining inventory can be liquidated by crossing the spread:

\[X_T = X_{T^-} + q_T(S_T - \delta_{\text{liq}})\]

The liquidation_half_spread parameter is passed externally (e.g. to run_backtest_with_liquidation). In solver models with TerminalCondition::LiquidationCost, the terminal value function is \(V(T,q) = -|q| \cdot \text{base_spread}\) where \(\text{base_spread} = \frac{1}{\gamma}\ln(1 + \frac{\gamma}{k})\).

Implementation: engine::backtest, solver::models

PnL Decomposition

\[ \begin{aligned} \text{PnL}\_\text{spread} &= \sum_{i=1}^{N_{\text{fills}}} (P_i - S_{t_i}) \\ \text{PnL}\_\text{dir} &= \sum_{t=1}^T q_{t-1}(S_t - S_{t-1}) \end{aligned} \]

PnL_spread uses signed edge: positive when filled passively (bought below mid / sold above mid), negative when filled aggressively (crossed the spread). Terminal liquidation cost is subtracted from PnL_spread.

Implementation: engine::backtest

Sharpe Ratio

The Sharpe ratio [@sharpe1966mutual] is the standard risk-adjusted return metric. For backtest robustness, the Sortino ratio [@sortino1994performance] (penalizing only downside deviation) is also available.

\[\text{SR} = \frac{\bar{R}}{\sigma_R}, \qquad \bar{R} = \frac{1}{K}\sum_{k=1}^K R_k, \qquad \sigma_R = \sqrt{\frac{1}{K}\sum_{k=1}^K (R_k - \bar{R})^2}\]

Hawkes Matcher Parameters

The StochasticMatcher with Hawkes uses the fluid limit for intensity evolution [@hawkes2018hawkes]:

\[\frac{d\lambda_t}{dt} = \beta(\lambda_\infty - \lambda_t) + \alpha\lambda_t\]

Bilateral variant tracks separate \(\lambda_t^b\), \(\lambda_t^a\) with independent self-excitation on fill events.

Implementation: engine::matcher::stochastic