Before placing an order, predict the price you would actually fill at — and the probability you will get filled at all.
Challenge we are solving
The visible mid is not what you trade at. Tickwise slippage, fee bps, and book depth determine q_exec, the *expected fill price*. Without it you cannot compute net edge.
What this stage does
Given side, size, and the current book, computes q_exec as a size-weighted walk-the-book, plus expected fees, slippage, fill probability, expected time-to-fill, and warnings.
Why this stage exists
The decision gate needs `net_edge = p_hat − q_exec − fees − buffer`. Stage 6 is the only place that can produce q_exec.
Flow
Bookbid/ask ladders
→
WalkΣ price·qty / Σ qty
→
Feesfee_bps · 10⁻⁴
→
P(fill)depth · flow
→
ExecPlanq_exec · slippage · P(fill)
What the backend should expose
execution_policy (limit · IOC · post-only)
side, size, q_exec, slippage_bps
fee_estimate, fill_probability
expected_time_to_fill_ms
book_hash (the book this estimate was computed against)
warnings (book thin · price moved · stale_book)
validity_duration_ms
Maths we expect here
Every formula below is implemented in packages/polytraders-bots/ or packages/polytraders-runner/. Treat the worked example as the unit-test sanity check you should be able to reproduce locally.
1
Walk-the-book expected fill price
\[q\_exec = \frac{\sum_i price_i \cdot qty_i}{\sum_i qty_i}\;\;\text{over the levels needed to fill }size\]
Symbol
Meaning
Units / range
\(price_i\)
Price at level i on the requested side
0..1
\(qty_i\)
Shares consumed at level i
shares
\(size\)
Total order quantity
shares
worked example\[\text{buy }2{,}000\;\text{YES across ladder}\;[0.64{:}1500,\,0.65{:}600] \;\Rightarrow\; q\_exec=\tfrac{0.64{\cdot}1500 + 0.65{\cdot}500}{2000}=0.6425\]
Always computed against the book hash that ingestion last validated — never against a stale snapshot.
2
Slippage from mid
\[slippage = q\_exec - mid\]
Symbol
Meaning
Units / range
\(mid\)
Current mid-price
0..1
\(q_exec\)
Expected fill price from above
0..1
worked example\[mid=0.63,\; q\_exec=0.6425 \;\Rightarrow\; slippage=+0.0125\;\text{(2.0 % of mid)}\]
worked example\[available\_depth=4{,}000,\; size=2{,}000 \;\Rightarrow\; P_{fill}=1-e^{-2}\approx 0.86\]
Heuristic model. The actual fill probability is observed and compared in stage 10; the multiplier on this formula is recalibrated nightly.
5
Expected time-to-fill
\[E[t_{fill}] = \tfrac{size}{\text{avg arrival rate at price level}}\]
Symbol
Meaning
Units / range
\(avg arrival rate\)
Shares per second traded at the target level over the last 60s
shares/s
worked example\[size=2{,}000,\; rate=180\,\text{sh/s} \;\Rightarrow\; E[t_{fill}]\approx 11\,\text{s}\]
How a developer codes this stage
Reference TypeScript implementation lives in packages/polytraders-* at the repository root. Stage owners maintain these files — read them before writing new code.
packages/polytraders-contracts/src/ExecutionPlan.tsStrict typing for q_exec, slippage, P(fill), validity window.