1. Bot Identity
| Layer | Execution Execution |
|---|
| Bot class | Execution Utility |
|---|
| Authority | Reshape |
|---|
| Status | PLANNED |
|---|
| Readiness | Spec started |
|---|
| Runs before | Order signing and CLOB V2 submission |
|---|
| Runs after | SmartRouter (ExecutionPlan assembled) |
|---|
| Applies to | Every ExecutionPlan before order signing |
|---|
| Default mode | shadow_only |
|---|
| User-visible | yes |
|---|
| Developer owner | Polytraders core — Execution pod |
|---|
Operational profile
| Modes supported | quarantine |
|---|
2. Purpose
PriceBandValidator is a fat-finger and decimal-shift catcher. It rejects or warns on any order priced outside a sanity band relative to the current top-of-book mid, preventing obviously erroneous prices from reaching the CLOB V2 signing step.
3. Why This Bot Matters
Fat-finger price not caught
An order priced at 0.06 instead of 0.60 submits at a tenfold mispricing, immediately filling against informed counterparties at a large loss.
Decimal shift not detected
A misconfigured strategy submitting pUSD amounts as probabilities (e.g. 45.0 instead of 0.45) creates orders orders of magnitude outside market range.
NegRisk sum-to-one constraint not checked
Orders across a negRisk market group that sum to above 1.0 in probability are fundamentally mis-priced and represent an arb against the strategy.
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.
6. Parameter Guide
| Parameter | Default | Warning | Hard | What it controls |
|---|
| max_offset_from_mid_pct | 10 | 15 | 25 | Maximum allowed percentage offset of the order price from the current top-of-book mid. Orders outside this band are rejected or warned. |
| require_band_for | ['GTC', 'GTD'] | — | — | Order types for which the price band check is mandatory. FOK orders may be exempt if strategy explicitly opts out. |
| action_on_breach | reject | — | — | Action to take on a price band breach: reject (discard order), warn (annotate and proceed), or reshape (snap price to band edge). |
| warn_only_in_shadow | True | — | — | In shadow mode, treat all breaches as WARN rather than HARD_REJECT, regardless of action_on_breach, to allow band calibration without blocking orders. |
7. Detailed Parameter Instructions
max_offset_from_mid_pct
What it means
Maximum allowed percentage offset of the order price from the current top-of-book mid. Orders outside this band are rejected or warned.
Default
{ "max_offset_from_mid_pct": 10 }
Why this default matters
10% offset allows normal spread and intentional aggressive pricing while catching decimal shifts and fat-finger errors.
Threshold logic
| Condition | Action |
|---|
| offset_pct <= 10 | PASS — price within band |
| 10 < offset_pct <= 15 | WARN — PRICE_BAND_WARN; proceed |
| offset_pct > 25 (hard) | HARD_REJECT — PRICE_BAND_BREACH; discard order |
Developer check
if abs(price - mid) / mid * 100 > params.max_offset_from_mid_pct: emit(PRICE_BAND_BREACH)
User-facing English
Your order price was checked against current market conditions before submission.
require_band_for
What it means
Order types for which the price band check is mandatory. FOK orders may be exempt if strategy explicitly opts out.
Default
{ "require_band_for": ["GTC", "GTD"] }
Why this default matters
GTC and GTD orders rest in the book and may fill far from intent if mispriced; FOK orders self-cancel if unfilled so the risk is lower.
Threshold logic
| Condition | Action |
|---|
| order_type IN require_band_for | Band check mandatory |
| order_type NOT IN require_band_for | Band check optional (WARN only in shadow mode) |
Developer check
if plan.order_type in params.require_band_for: validateBand(plan.price, mid)
User-facing English
Price checks are applied to all resting orders.
action_on_breach
What it means
Action to take on a price band breach: reject (discard order), warn (annotate and proceed), or reshape (snap price to band edge).
Default
{ "action_on_breach": "reject" }
Why this default matters
Reject is the safest default for production; warn is useful in shadow mode to build confidence in the band calibration.
Threshold logic
| Condition | Action |
|---|
| action=reject | Discard ExecutionPlan; emit HARD_REJECT |
| action=warn | Annotate ExecutionPlan; proceed |
| action=reshape | Snap price to band edge; emit RESHAPE |
Developer check
if breach and params.action_on_breach == 'reject': discard(plan)
User-facing English
A price check failed. Your order was not submitted.
warn_only_in_shadow
What it means
In shadow mode, treat all breaches as WARN rather than HARD_REJECT, regardless of action_on_breach, to allow band calibration without blocking orders.
Default
{ "warn_only_in_shadow": true }
Why this default matters
Shadow-mode data is needed to tune max_offset_from_mid_pct before going live; blocking orders in shadow prevents this.
Threshold logic
| Condition | Action |
|---|
| mode=shadow AND warn_only_in_shadow=true | All breaches → WARN only |
| mode=live OR warn_only_in_shadow=false | Apply action_on_breach normally |
Developer check
if isInShadow() and params.warn_only_in_shadow: action = 'warn'
User-facing English
— not yet authored —
8. Default Configuration
{
"bot_id": "exec.pricebandvalidator",
"version": "0.1.0",
"mode": "shadow_only",
"defaults": {
"max_offset_from_mid_pct": 10,
"require_band_for": [
"GTC",
"GTD"
],
"action_on_breach": "reject",
"warn_only_in_shadow": true
},
"locked": {
"max_offset_from_mid_pct": {
"max": 25
}
}
}
9. Implementation Flow
- Receive ExecutionPlan from SmartRouter.
- If mode=shadow and warn_only_in_shadow=true, set effective_action=warn.
- If plan.order_type NOT IN require_band_for, skip band check.
- Fetch top-of-book snapshot from clob_public; compute mid = (best_bid + best_ask) / 2.
- Compute offset_pct = abs(plan.price - mid) / mid * 100.
- If offset_pct > max_offset_from_mid_pct: apply action_on_breach (reject/warn/reshape).
- If market.neg_risk: check that all leg prices for this market group sum to <= 1.0.
- Emit ExecutionReport with verdict, offset_pct, mid_used, and reason_code.
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.
FUNCTION validatePriceBand(plan):
// Determine effective action
action = params.action_on_breach
IF isInShadow() AND params.warn_only_in_shadow:
action = 'warn'
// Skip check for non-required order types
IF plan.order_type NOT IN params.require_band_for:
EMIT ExecutionReport(PRICE_BAND_PASS)
RETURN plan
// Fetch top-of-book mid
book = FETCH clob_public.GET('/book?market=' + plan.market_id)
IF book IS NULL:
DISCARD plan; reason=STALE_MARKET_DATA
RETURN
mid = (book.best_bid + book.best_ask) / 2
// Compute offset
offsetPct = abs(plan.price - mid) / mid * 100
// NegRisk sum-to-one check
IF plan.neg_risk:
market = FETCH gamma.getMarket(plan.market_id)
legPrices = [plan.price] + [p FOR p IN market.other_leg_prices]
IF sum(legPrices) > 1.0:
DISCARD plan; reason=PRICE_BAND_NEGRISK_BREACH
RETURN
// Band check
IF offsetPct > params.max_offset_from_mid_pct:
IF action == 'reject':
DISCARD plan; reason=PRICE_BAND_BREACH
RETURN
ELIF action == 'reshape':
snapDirection = 1 IF plan.price > mid ELSE -1
plan.price = mid * (1 + snapDirection * params.max_offset_from_mid_pct / 100)
EMIT ExecutionReport(PRICE_BAND_RESHAPED)
ELIF action == 'warn':
EMIT ExecutionReport(PRICE_BAND_WARN)
ELSE:
EMIT ExecutionReport(PRICE_BAND_PASS)
RETURN plan
SDK calls used
clob_public.GET('/book?market=' + plan.market_id)gamma.getMarket(plan.market_id)
Complexity: O(L) where L = number of negRisk outcome legs (typically 2–4)
11. Wire Examples
Input — what arrives on the wire
ExecutionPlan from SmartRouter — exec.smart_router
{
"market_id": "0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b",
"price": 0.68,
"size_usd": 300,
"order_type": "GTC",
"side": "BUY",
"neg_risk": false,
"collateral": "pUSD"
}
Output — what the bot emits
ExecutionReport — PRICE_BAND_PASS
{
"report_id": "rep_7a8b9c0d1e2f3a4b",
"bot_id": "exec.pricebandvalidator",
"order_price": 0.68,
"mid_price": 0.62,
"offset_pct": 9.7,
"verdict": "PRICE_BAND_PASS",
"collateral": "pUSD",
"evaluated_at_ms": 1746770500000
}
12. Decision Logic
APPROVE
offset_pct within max_offset_from_mid_pct; PRICE_BAND_PASS emitted.
RESHAPE_REQUIRED
action_on_breach=reshape: price snapped to band edge (mid ± max_offset pct); PRICE_BAND_RESHAPED emitted.
REJECT
action_on_breach=reject and offset_pct > hard threshold; PRICE_BAND_BREACH emitted; order discarded.
WARNING_ONLY
action_on_breach=warn or mode=shadow; PRICE_BAND_WARN emitted; plan proceeds unchanged.
13. Standard Decision Output
This bot returns a ExecutionReport object. See ExecutionReport schema.
{
"report_id": "rep_7a8b9c0d1e2f3a4b",
"trace_id": "trc_6f7a8b9c0d1e2f3a",
"bot_id": "exec.pricebandvalidator",
"market_id": "0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b",
"order_price": 0.68,
"mid_price": 0.62,
"offset_pct": 9.7,
"verdict": "PRICE_BAND_PASS",
"collateral": "pUSD",
"evaluated_at_ms": 1746770500000
}
14. Reason Codes
| Code | Severity | Meaning | Action | User-facing message |
|---|
PRICE_BAND_PASS | INFO | Order price within max_offset_from_mid_pct of current mid. | Forward ExecutionPlan to signing. | |
PRICE_BAND_WARN | WARN | Order price between warning and hard threshold; or shadow mode warn-only. | Annotate ExecutionPlan; proceed. | Your order price is close to the edge of the normal range. |
PRICE_BAND_BREACH | HARD_REJECT | Order price exceeds max_offset_from_mid_pct and action_on_breach=reject. | Discard ExecutionPlan; emit no order. | Your order price was too far from the current market price and was rejected. |
PRICE_BAND_RESHAPED | RESHAPE | Order price snapped to band edge; action_on_breach=reshape. | Update plan.price to band edge; forward to signing. | Your order price was adjusted to stay within the valid range. |
PRICE_BAND_NEGRISK_BREACH | HARD_REJECT | NegRisk market: sum of outcome leg prices > 1.0. | Discard ExecutionPlan. | Your order prices across this market's outcomes exceeded the valid total. |
15. Metrics & Logs
Metrics emitted
| Metric | Type | Unit | Labels | Meaning |
|---|
polytraders_exec_pricebandvalidator_decisions_total | counter | count | verdict | Total price band decisions by verdict. |
polytraders_exec_pricebandvalidator_offset_pct | histogram | pct | | Distribution of order price offsets from mid at evaluation time. |
polytraders_exec_pricebandvalidator_breaches_total | counter | count | reason_code | Total price band breaches by reason code. |
Alerts
| Alert | Condition | Severity | Runbook |
|---|
PBVHighBreachRate | rate(polytraders_exec_pricebandvalidator_breaches_total[5m]) > 0.05 | P2 | #runbook-pbv-breach-rate |
PBVNegRiskBreaches | rate(polytraders_exec_pricebandvalidator_breaches_total{reason_code='PRICE_BAND_NEGRISK_BREACH'}[5m]) > 0 | P1 | #runbook-pbv-negrisk |
16. Developer Reporting
{
"order_price": 0.68,
"mid_price": 0.62,
"offset_pct": 9.7,
"max_offset_from_mid_pct": 10,
"verdict": "PRICE_BAND_PASS",
"action_on_breach": "reject",
"mode": "shadow_only",
"warn_only_in_shadow": true
}
17. Plain-English Reporting
| Situation | User-facing explanation |
|---|
| Price check passed | Your order price was within the expected range for the current market. |
| Order rejected — price too far from market | Your order price was significantly different from the current market price and was rejected to protect you from a likely error. |
| Order price snapped to band edge | Your order price was adjusted to be within the safe range for this market. |
18. Failure-Mode Block
| main_failure_mode | Top-of-book snapshot is stale, causing mid to be calculated from a stale price that doesn't reflect the current market, producing false positive band breaches or false negatives. |
|---|
| false_positive_risk | A legitimate aggressive price on a wide-spread market triggers PRICE_BAND_BREACH because max_offset_from_mid_pct is calibrated for liquid markets. |
|---|
| false_negative_risk | A fat-finger with offset exactly at max_offset_from_mid_pct passes without warning. |
|---|
| safe_fallback | If clob_public top-of-book is unavailable, reject the order with STALE_MARKET_DATA rather than proceeding without a band check. |
|---|
| required_dependencies | clob_public top-of-book snapshot, ExecutionPlan from SmartRouter |
|---|
19. Failure-Injection Recipes
| Scenario | How to inject | Expected behaviour | Recovery |
|---|
STALE_TOP_OF_BOOK | Block clob_public and let cache TTL expire | | clob_public restored; next plan triggers fresh fetch |
FAT_FINGER_PRICE | Submit ExecutionPlan with price=0.06, mid=0.62 (90% offset), action=reject | | Automatic; strategy corrects price |
NEGRISK_SUM_BREACH | Submit negRisk ExecutionPlan with leg prices [0.60, 0.55, 0.10] summing to 1.25 | | Automatic; strategy corrects leg prices |
20. State & Persistence
Cold-start recovery
Cache empty on restart; first validation per market triggers fresh fetch.
21. Concurrency & Idempotency
| Aspect | Specification |
|---|
| Execution model | per-plan goroutine |
| Max in-flight | 100 |
| Idempotency key | trace_id + market_id + price |
| Per-call timeout (ms) | 200 |
| Backpressure strategy | shed if > 100 plans queued |
| Locking / mutual exclusion | per-market_id read-lock for cache reads |
22. Dependencies
Depends on (must run first)
| Bot | Why | Contract |
|---|
| exec.smart_router | Source of ExecutionPlan to validate. | PriceBandValidator must run before order signing. |
Emits to (downstream consumers)
| Bot | Why | Contract |
|---|
| exec.orderlifecyclemanager | Passed-through ExecutionPlan forwarded to signing and lifecycle tracking. | Only PASS or RESHAPE plans forwarded; BREACH plans discarded. |
External services
| Service | Endpoint | SLA assumed | On failure |
|---|
| CLOB V2 public API | https://clob.polymarket.com | 99.9% / 200ms p99 | If top-of-book unavailable, reject order with STALE_MARKET_DATA. |
| Gamma API | https://gamma-api.polymarket.com | 99.9% / 500ms p99 | If negRisk flag unavailable, skip sum-to-one check and emit WARN. |
23. Security Surfaces
Abuse vectors considered
- Poisoning the top-of-book cache to make a mispriced order appear within band
- Submitting orders with prices just within the hard threshold to avoid detection
Mitigations
- Top-of-book fetched directly from clob_public per evaluation; cache TTL limits staleness to 60s
- Warning threshold at 50% of hard threshold provides early detection before hard limit is reached
24. Polymarket V2 Compatibility
| Aspect | Value |
|---|
| CLOB version | v2 |
| Collateral asset | pUSD |
| EIP-712 Exchange domain version | 2 |
| Aware of builderCode field | no |
| Aware of negative-risk markets | yes |
| Multi-chain ready | no |
| SDK used | py-clob-client-v2 |
| Settlement contract | CTFExchangeV2 |
| Notes | For negRisk markets, PriceBandValidator enforces the sum-to-one constraint across all outcome legs in addition to the per-order price band check. NegRisk flag read from Gamma API. |
API surfaces declared
clob_publicgammainternal
Networks supported
polygon
25. Versioning & Migration
| Field | Value |
|---|
| spec | 2.0.0 |
| implementation | 0.1.0 |
| schema | 2 |
| released | None |
| planned_release | Q4-2026 |
Migration history
| Date | From | To | Reason | Action taken |
|---|
| 2026-04-28 | n/a | v2-spec | Spec drafted post-CLOB-V2 cutover; bot not yet implemented | Designed against V2 schema (pUSD, builder codes, V2 EIP-712 domain) |
26. Acceptance Tests
Unit Tests
| Test | Setup | Expected result |
|---|
| PASS when order price within 10% of mid | order_price=0.68, mid=0.62, max_offset=10% | offset_pct=9.7 < 10; PRICE_BAND_PASS |
| REJECT when offset > hard threshold (25%) | order_price=0.06, mid=0.62, action=reject | offset_pct=90.3 > 25; PRICE_BAND_BREACH; order discarded |
| WARN only in shadow mode regardless of action_on_breach | mode=shadow, warn_only_in_shadow=true, offset_pct=30 | PRICE_BAND_WARN; order not discarded |
Integration Tests
| Test | Expected result |
|---|
| Reshape: price snapped to band edge | reshaped_price = mid * (1 - 0.10) = 0.558; PRICE_BAND_RESHAPED |
| NegRisk sum-to-one check: leg prices sum > 1.0 triggers PRICE_BAND_NEGRISK_BREACH | HARD_REJECT if negRisk market and sum_of_leg_prices > 1.0 |
Property Tests
| Property | Required behaviour |
|---|
| When action_on_breach=reject and offset > hard, order is never signed | Always true |
| Reshaped price always within [mid*(1-max_offset/100), mid*(1+max_offset/100)] | Always true |
27. Operational Runbook
PriceBandValidator breaches indicate either strategy mispricing bugs or stale top-of-book data. NegRisk breaches require immediate strategy review.
On-call actions
| Alert | First step | Diagnosis | Mitigation | Escalate to |
|---|
PBVHighBreachRate | Identify which strategy is generating breaches; check if max_offset_from_mid_pct is calibrated for current market spread. | | | Strategy pod lead |
PBVNegRiskBreaches | Immediately pause the strategy generating negRisk breaches; review leg price calculation logic. | | | Exec pod lead + Strategy pod lead |
Manual overrides
polytraders bot set-param exec.pricebandvalidator --param max_offset_from_mid_pct --value 20 — Wide-spread market requires temporary band widening; requires Exec pod lead approval.
Healthcheck
GET /internal/health/pricebandvalidator -> 200 if clob_public reachable, top-of-book cache fresh (< 60s), breach_rate < 0.01/min. Red: clob_public unreachable (STALE_MARKET_DATA rejecting all orders), negrisk_breach_rate > 0.
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 |