2.14 FeeSlippageEstimator
Stamps every approved OrderIntent with an explicit fee + slippage estimate before the order shaper sees it. The estimate is a structured object (maker_fee_bps, taker_fee_bps, expected_slippage_bps, total_cost_usd) that downstream tools and UIs all read instead of guessing.
v3 readiness
A bot is done when all four scores are. What does done mean?
1. Bot Identity
| Layer | Execution Execution |
|---|---|
| Bot class | ExecutionUtility |
| Authority | Annotate |
| Status | PLANNED |
| Readiness | Spec ready |
| Runs before | exec.smart_router, exec.order_shaper |
| Runs after | intel.orderflowanalyzer |
| Applies to | Per OrderIntent |
| Default mode | shadow |
| User-visible | Yes |
| Developer owner | Execution pod |
Operational profile
| Ownership | Execution pod · on-call exec-oncall · #polytraders-exec · escalates to Head of Execution · P2 |
|---|---|
| Latency budget | p50: 4ms · p99: 15ms |
| Modes supported | offshadowadvisoryenforcedquarantine |
| Data freshness | max_market_data_age_ms=2000 · max_orderbook_age_ms=2000 · on stale → Stamp cost_estimate with method='conservative_default'. |
| Human override | no · by — · logs — · time-bound: — · scope: — · single approver |
2. Purpose
Stamps every approved OrderIntent with an explicit fee + slippage estimate before the order shaper sees it. The estimate is a structured object (maker_fee_bps, taker_fee_bps, expected_slippage_bps, total_cost_usd) that downstream tools and UIs all read instead of guessing.
3. Why This Bot Matters
Hidden cost surprises
Without a per-order estimate, post-trade reports are the first place anyone learns the order was unprofitable after fees.
Inconsistent cost models
Each strategy inventing its own cost estimate produces inconsistent reports and dashboards.
Affiliate/builderCode accounting
The builder-fee component on V2 must be visible per order to track attribution correctly.
No worked examples on this bot yet. Worked examples are optional but strongly recommended — they turn an abstract failure mode into something a developer can verify in a fixture.
4. Required Polymarket Inputs
| Input | Source | Required? | Use |
|---|---|---|---|
| Live OrderBookSnapshot | intel.orderflowanalyzer | Yes | Estimate slippage from depth profile. |
| Polymarket fee schedule (maker/taker/builder) | Config | Yes | Current tier fees. |
5. Required Internal Inputs
| Input | Source | Required? | Use |
|---|---|---|---|
| OrderIntent | Strategy bot | Yes | The order to estimate. |
| Market microstructure prior | intel.liquidity_decay_monitor | No | Improves slippage estimate when available. |
6. Parameter Guide
| Parameter | Default | Warning | Hard | What it controls |
|---|---|---|---|---|
| maker_fee_bps | 0 | — | — | Polymarket maker fee in basis points (0 today on V2 binary). |
| taker_fee_bps | 200 | 250 | 400 | Polymarket taker fee in basis points. |
| builder_fee_bps | 0 | — | — | Polytraders builderCode fee in basis points. |
| slippage_safety_factor | 1.5 | 1.0 | 3.0 | Multiplier applied to the linear slippage estimate to account for adverse selection. |
7. Detailed Parameter Instructions
maker_fee_bps
What it means
Polymarket maker fee in basis points (0 today on V2 binary).
Default
{ "maker_fee_bps": 0 }
Why this default matters
Polymarket V2 currently does not charge a maker fee on binary markets.
Threshold logic
| Condition | Action |
|---|---|
| 0 | Default |
Developer check
fee += notional * p.maker_fee_bps/10000;
User-facing English
(Internal.)
taker_fee_bps
What it means
Polymarket taker fee in basis points.
Default
{ "taker_fee_bps": 200 }
Why this default matters
200 bps (2%) is the V2 binary taker default.
Threshold logic
| Condition | Action |
|---|---|
| 200 | Default |
Developer check
fee += notional * p.taker_fee_bps/10000;
User-facing English
(Internal.)
builder_fee_bps
What it means
Polytraders builderCode fee in basis points.
Default
{ "builder_fee_bps": 0 }
Why this default matters
Set by config; defaults to 0 until builderCode is registered.
Threshold logic
| Condition | Action |
|---|---|
| 0 | Until registered |
Developer check
fee += notional * p.builder_fee_bps/10000;
User-facing English
(Internal.)
slippage_safety_factor
What it means
Multiplier applied to the linear slippage estimate to account for adverse selection.
Default
{ "slippage_safety_factor": 1.5 }
Why this default matters
1.5 is the empirical median across Polymarket binary markets.
Threshold logic
| Condition | Action |
|---|---|
| 1.0 | Optimistic |
| 1.5 | Default |
| 2.0+ | Defensive |
Developer check
slip_bps *= p.slippage_safety_factor;
User-facing English
(Internal.)
8. Default Configuration
{
"maker_fee_bps": 0,
"taker_fee_bps": 200,
"builder_fee_bps": 0,
"slippage_safety_factor": 1.5
}9. Implementation Flow
— not yet authored —
10. Reference Implementation
Pseudocode is language-agnostic. FETCH = read input. EMIT = produce output. IF/THEN/ELSE = decision. Translate directly to TypeScript, Python, Go, or Rust.
depth = walk_book(book, intent.side, intent.price, intent.size_usd)
slip_bps = (depth.vwap - book.mid) / book.mid * 10000 * p.slippage_safety_factor
fee_bps = p.taker_fee_bps + p.builder_fee_bps
stamp(intent, cost_estimate={maker:p.maker_fee_bps, taker:p.taker_fee_bps, builder:p.builder_fee_bps, slip:slip_bps, total_bps:fee_bps+slip_bps, total_usd: ...})11. Wire Examples
Input — what arrives on the wire
{
"intent_id": "intent_004",
"market_id": "0xabc",
"size_usd": 500,
"side": "BUY",
"price": 0.62
}
Output — what the bot emits
{
"intent_id": "intent_004",
"cost_estimate": {
"slippage_bps": 35,
"total_cost_bps": 235,
"total_cost_usd": 11.75
},
"vote": "ANNOTATE"
}12. Decision Logic
APPROVE
Compute marketable_depth at intent.price + side. Estimate fill VWAP and slippage_bps. Compute fee_bps from configured schedule. Stamp the OrderIntent and pass it through unchanged otherwise.
RESHAPE_REQUIRED
This bot does not reshape orders.
REJECT
No reject path defined for this bot — it is observe-only.
WARNING_ONLY
No warn-only path defined.
13. Standard Decision Output
This bot returns a RiskVote object. See RiskVote schema.
{
"intent_id": "intent_004",
"cost_estimate": {
"maker_fee_bps": 0,
"taker_fee_bps": 200,
"builder_fee_bps": 0,
"slippage_bps": 35,
"total_cost_bps": 235,
"total_cost_usd": 2.35,
"method": "linear_with_safety_factor"
},
"vote": "ANNOTATE"
}14. Reason Codes
| Code | Severity | Meaning | Action | User-facing message |
|---|---|---|---|---|
EXEC_COST_ESTIMATED | P2 | Exec Cost Estimated | See decision output and developer log for context. | Estimated total cost of this order, including fees and the price impact of moving the market. |
EXEC_COST_FALLBACK | P2 | Exec Cost Fallback | See decision output and developer log for context. | Estimated total cost of this order, including fees and the price impact of moving the market. |
EXEC_COST_FEE_SCHEDULE_STALE | P2 | Exec Cost Fee Schedule Stale | See decision output and developer log for context. | Estimated total cost of this order, including fees and the price impact of moving the market. |
15. Metrics & Logs
Metrics emitted
| Metric | Type | Unit | Labels | Meaning |
|---|---|---|---|---|
estimates_total | counter | event | bot_id | Estimates total. |
estimated_vs_realised_bps_histogram | counter | event | bot_id | Estimated vs realised bps histogram. |
fallback_estimates_total | counter | event | bot_id | Fallback estimates total. |
Dashboards
- 2.14 overview dashboard
16. Developer Reporting
"Per estimate: intent_id, market_id, size_usd, marketable_depth_usd, slippage_bps, fee_bps, total_cost_bps."17. Plain-English Reporting
| Situation | User-facing explanation |
|---|---|
| When this bot acts | Estimated total cost of this order, including fees and the price impact of moving the market. |
18. Failure-Mode Block
| main_failure_mode | Underestimating slippage for orders larger than top-of-book. |
|---|---|
| false_positive_risk | Over-conservative estimate suppresses orders that would have been profitable; mitigation: track realised vs estimated cost and re-tune safety factor weekly. |
| false_negative_risk | Stale fee schedule misses a fee change; mitigation: validate fee schedule against on-chain CTFExchangeV2 storage at startup. |
| safe_fallback | On any failure, stamp cost_estimate.method='conservative_default' with a generous flat estimate. Never strip the field. |
| required_dependencies | — |
19. Failure-Injection Recipes
| Scenario | How to inject | Expected behaviour | Recovery |
|---|---|---|---|
Strip the live book and assert fallback estimate is stamped, not absent | Strip the live book and assert fallback estimate is stamped, not absent. | Bot detects within its latency budget and emits the corresponding reason code. | Remove the injected fault; bot returns to healthy state within one debounce window. |
Inject a fee-schedule mismatch and assert the stale code fires | Inject a fee-schedule mismatch and assert the stale code fires. | Bot detects within its latency budget and emits the corresponding reason code. | Remove the injected fault; bot returns to healthy state within one debounce window. |
20. State & Persistence
Stateless. Reads live book + config; no persistence required.
State stores
| Name | Kind | Key | Value shape | TTL | Durability |
|---|---|---|---|---|---|
fee_slippage_estimator_state | in-memory + fast KV mirror | bot_id | Stateless. Reads live book + config; no persistence required. | 24h | crash-safe via KV mirror |
Cold-start recovery
Cold-start hydrates from fast KV; missing keys default to safe fallback.
On restart
All in-flight decisions are re-evaluated; no bot decision is trusted across restart without re-emit.
21. Concurrency & Idempotency
| Aspect | Specification |
|---|---|
| Execution model | Pure function over (book, intent, fees). Trivially concurrent. |
| Max in-flight | 32 |
| Idempotency key | order_intent_id |
| Replay-safe | True |
| Deduplication | By idempotency_key within a 60s window. |
| Ordering guarantees | Per-market_id FIFO; cross-market unordered. |
| Per-call timeout (ms) | 250 |
| Backpressure strategy | Bounded queue; oldest-dropped with metric increment when full. |
| Locking / mutual exclusion | Per-market_id mutex; no global locks. |
22. Dependencies
Depends on (must run first)
| Bot | Why | Contract |
|---|---|---|
| intel.orderflowanalyzer |
Emits to (downstream consumers)
| Bot | Why | Contract |
|---|---|---|
| exec.smart_router | ||
exec.order_shaper |
Requires (graph.requires)
Required before (graph.required_before)
exec.smart_router exec.order_shaper
| Consumes | OrderIntent OrderBookSnapshot |
|---|---|
| Emits | AnnotatedOrderIntent |
| Blocks orders | no |
23. Security Surfaces
No external surface; reads internal config + live book.
Signing surface
None — bot does not sign or submit.
Mitigations
- Rate-limit per source
- Audit-log every override
- Require role-based authz on admin paths
24. Polymarket V2 Compatibility
| Aspect | Value |
|---|---|
| CLOB version | V2 |
| Collateral asset | pUSD |
| EIP-712 Exchange domain version | 2 |
| Aware of builderCode field | yes |
| Aware of negative-risk markets | yes |
| Multi-chain ready | yes |
| SDK used | Polymarket CLOB V2 SDK |
| Settlement contract | CTFExchangeV2 |
| Notes | Reads V2 fee schedule (maker_fee_bps, taker_fee_bps, builder_fee_bps). |
25. Versioning & Migration
| Field | Value |
|---|---|
| current | 0.1.0 |
| contract_version | 1.0.0 |
| last_breaking_change | none |
| deprecation_window_days | 30 |
26. Acceptance Tests
Unit Tests
| Test | Setup | Expected result |
|---|---|---|
| For an order at top-of-book ≤ depth, slippage estimate is < 5 bps. | Synthetic fixture per template. | Behaviour matches the rule described in the test name. |
| For an order > 2x top-of-book depth, slippage estimate exceeds 50 bps. | Synthetic fixture per template. | Behaviour matches the rule described in the test name. |
Integration Tests
| Test | Expected result |
|---|---|
| End-to-end: estimate vs realised cost on 100 historical orders agrees within ±25%. | End-to-end behaviour matches the spec without manual intervention. |
Property Tests
| Property | Required behaviour |
|---|---|
| Total cost is monotonically non-decreasing in size_usd for a fixed book. | Always true across all generated inputs. |
27. Operational Runbook
If estimated-vs-realised drifts > 25%, re-tune slippage_safety_factor on a weekly cadence.
On-call actions
| Alert | First step | Diagnosis | Mitigation | Escalate to |
|---|---|---|---|---|
2.14_anomaly | Open the bot's reporting page and confirm the alert is real (not a metric hiccup). | Inspect developer log entries for the affected market_id over the last 30 minutes. | Force-clear via Admin UI if the rule is clearly stale; otherwise leave engaged and notify owner. | Execution pod |
Manual overrides
polytraders bot pause 2.14— Disables the bot's enforcement layer; downstream consumers fall back to safe defaults.
Healthcheck
GET /healthz/fee_slippage_estimator → 200 if last successful evaluation < 60s ago.28. Promotion Gates
A bot does not advance to the next readiness state until every gate below is green. Gates are observable from production data — no subjective sign-off.
Promote to Shadow
| Gate | How measured | Threshold |
|---|---|---|
| Stub | deterministic on synthetic books. | Documented threshold met for the full window. |
Promote to Limited live
| Gate | How measured | Threshold |
|---|---|---|
| Shadow | 14 days against historical orders. | Documented threshold met for the full window. |
| Advisory | 7 days; downstream tools may consume. | Documented threshold met for the full window. |
Promote to General live
| Gate | How measured | Threshold |
|---|---|---|
| Enforced | required field on every OrderIntent. | Documented threshold met for the full window. |
29. Developer Checklist
Ready-to-ship score: 27/27 sections complete · 100%
| Requirement | Status |
|---|---|
| Purpose defined | ✓ done |
| Required inputs listed | ✓ done |
| Parameters defined | ✓ done |
| Defaults defined | ✓ done |
| Warning thresholds defined | ✓ done |
| Hard thresholds defined | ✓ done |
| Safe fallback defined | ✓ done |
| Structured output defined | ✓ done |
| Developer log defined | ✓ done |
| Plain-English explanation | ✓ done |
| Unit tests defined | ✓ done |
| Integration tests defined | ✓ done |
| Property tests defined | ✓ done |
| Failure-mode block complete | ✓ done |
| Reference implementation pseudocode | ✓ done |
| Wire examples (input + output) | ✓ done |
| Reason codes listed | ✓ done |
| Metrics & logs defined | ✓ done |
| State & persistence defined | ✓ done |
| Concurrency & idempotency defined | ✓ done |
| Dependencies declared | ✓ done |
| Security surfaces declared | ✓ done |
| Polymarket V2 compatibility declared | ✓ done |
| Version & migration history declared | ✓ done |
| Operational runbook defined | ✓ done |
| Promotion gates defined | ✓ done |
| Failure-injection recipes defined | ✓ done |