
Profitability is secondary to edge longevity.
Every grid instance must estimate how fast its statistical edge is decaying due to market adaptation, crowding, or volatility regime drift—and self-throttle or terminate accordingly.

Notation (per grid instance g)
Time:
t = discrete update index (e.g., every 1s or every K fills)
i = fill index
Prices:
p_i = fill price of trade i
m_i = midprice at fill time (best_bid + best_ask)/2
m_i(Delta) = midprice Delta seconds after fill (markout horizon)
Side / size:
s_i = +1 for BUY fill, -1 for SELL fill
q_i = filled quantity (base units)
Costs:
fee_i = explicit fee paid (per unit or total)
rebate_i = maker rebate (per unit or total)
impact_i = estimated impact cost (optional)
Horizon set for markout:
H = {Delta1, Delta2, …} e.g. {0.2s, 1s, 5s, 30s}
EWMA parameters:
alpha_x in (0,1) = smoothing factor for metric x
beta in (0,1) = smoothing for variance/uncertainty
gamma in (0,1) = smoothing for decay slope
Baselines:
x_base = long-run baseline for x in “healthy edge” period (rolling training window)
++++++++++++++++(((((((((
Per-fill “EDGE OBSERVATION” y_i (net alpha per unit)
1 Net PnL per unit at horizon Delta
pnl_i(Delta) = s_i * ( m_i(Delta) - p_i ) - fee_i_per_unit + rebate_i_per_unit - impact_i_per_unit
(If fees/rebates are totals, divide by q_i to convert to per unit.)
2 Immediate “spread capture component” (at fill time)
capture_i = s_i * ( m_i - p_i )
3 Markout (adverse selection component)
markout_i(Delta) = s_i * ( m_i(Delta) - m_i )
Relationship: pnl_i(Delta) = capture_i - markout_i(Delta) - fee_i_per_unit + rebate_i_per_unit - impact_i_per_unit
4 Choose a reference horizon for edge estimation
Pick Delta_ref (e.g., 1s or 5s), then: y_i = pnl_i(Delta_ref)
(You can also use a weighted multi-horizon version later.)

Online edge estimator (mean + uncertainty)
You want BOTH:
theta_t = estimated edge level (expected y)
sigma_t^2 = estimated noise/dispersion (uncertainty proxy)
Assume you aggregate fills arriving since last update into one batch statistic:
ybar_t = mean(y_i) over fills in update interval t
n_t = number of fills in interval t
1 EWMA mean (fast, stable)
theta_t = (1 - alpha_theta) theta_{t-1} + alpha_theta ybar_t
2 EWMA variance (for confidence / P(edge>0))
err_t = ybar_t - theta_{t-1} sigma2_t = (1 - beta) sigma2_{t-1} + beta (err_t * err_t)
3 Effective sample size (EWMA “memory length”)
n_eff_theta = (1 + (1 - alpha_theta)) / (1 - (1 - alpha_theta)) = (2 - alpha_theta) / alpha_theta (Approx. rule-of-thumb; higher alpha_theta => shorter memory)
4 Shrinkage-to-prior (reduces false confidence in low fills)
Let prior mean mu0 (often 0) and prior strength n0 (e.g., 20 “virtual fills”).
theta_shrunk_t = (n_eff_theta theta_t + n0 mu0) / (n_eff_theta + n0)
Use theta_shrunk_t as your “official” theta.
5 Edge confidence probability (Gaussian approximation)
z_t = theta_shrunk_t / ( sqrt(sigma2_t) + eps )
P_edge_pos_t = Phi( z_t ) Where Phi(.) is standard normal CDF, eps prevents divide-by-zero.
(If you don’t want Phi, use logistic approx: Phi(z) ~ 1 / (1 + exp(-1.702*z)) )