Polytraders Dev Guide
internal
v3 spine Phase 1 · Shared contracts 9 demo-wired · 0 shadow-ready · 0 production-live · 100 pending · 109 total 15/33 infra tasks the plan status board
HomeBy LayerExecution2.12 PriceBandValidator

2.12 PriceBandValidator

Execution Execution Utility Reshape PLANNED Spec started capital · Direct P5 · Execution rails pending stub

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.

v3 readiness

Docs27/27
donehow scored
Impl0/15
pendinghow scored
Backtest0/4
pendinghow scored
Runtime0/8
pendinghow scored

A bot is done when all four scores are. What does done mean?

1. Bot Identity

LayerExecution  Execution
Bot classExecution Utility
AuthorityReshape
StatusPLANNED
ReadinessSpec started
Runs beforeOrder signing and CLOB V2 submission
Runs afterSmartRouter (ExecutionPlan assembled)
Applies toEvery ExecutionPlan before order signing
Default modeshadow_only
User-visibleyes
Developer ownerPolytraders core — Execution pod

Operational profile

Modes supportedquarantine

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.

4. Required Polymarket Inputs

InputSourceRequired?Use
CLOB V2 top-of-book snapshotclob_publicYesCompute current mid price for band validation.
Market negRisk flaggammaNoApply sum-to-one constraint for negRisk markets.

5. Required Internal Inputs

InputSourceRequired?Use
ExecutionPlan from SmartRouterexec.smart_routerYesValidate plan.price against current mid ± max_offset_from_mid_pct.

6. Parameter Guide

ParameterDefaultWarningHardWhat it controls
max_offset_from_mid_pct101525Maximum 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_breachrejectAction to take on a price band breach: reject (discard order), warn (annotate and proceed), or reshape (snap price to band edge).
warn_only_in_shadowTrueIn 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

ConditionAction
offset_pct <= 10PASS — price within band
10 < offset_pct <= 15WARN — 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

ConditionAction
order_type IN require_band_forBand check mandatory
order_type NOT IN require_band_forBand 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

ConditionAction
action=rejectDiscard ExecutionPlan; emit HARD_REJECT
action=warnAnnotate ExecutionPlan; proceed
action=reshapeSnap 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

ConditionAction
mode=shadow AND warn_only_in_shadow=trueAll breaches → WARN only
mode=live OR warn_only_in_shadow=falseApply 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

  1. Receive ExecutionPlan from SmartRouter.
  2. If mode=shadow and warn_only_in_shadow=true, set effective_action=warn.
  3. If plan.order_type NOT IN require_band_for, skip band check.
  4. Fetch top-of-book snapshot from clob_public; compute mid = (best_bid + best_ask) / 2.
  5. Compute offset_pct = abs(plan.price - mid) / mid * 100.
  6. If offset_pct > max_offset_from_mid_pct: apply action_on_breach (reject/warn/reshape).
  7. If market.neg_risk: check that all leg prices for this market group sum to <= 1.0.
  8. 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 SmartRouterexec.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

CodeSeverityMeaningActionUser-facing message
PRICE_BAND_PASSINFOOrder price within max_offset_from_mid_pct of current mid.Forward ExecutionPlan to signing.
PRICE_BAND_WARNWARNOrder 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_BREACHHARD_REJECTOrder 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_RESHAPEDRESHAPEOrder 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_BREACHHARD_REJECTNegRisk 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

MetricTypeUnitLabelsMeaning
polytraders_exec_pricebandvalidator_decisions_totalcountercountverdictTotal price band decisions by verdict.
polytraders_exec_pricebandvalidator_offset_pcthistogrampctDistribution of order price offsets from mid at evaluation time.
polytraders_exec_pricebandvalidator_breaches_totalcountercountreason_codeTotal price band breaches by reason code.

Alerts

AlertConditionSeverityRunbook
PBVHighBreachRaterate(polytraders_exec_pricebandvalidator_breaches_total[5m]) > 0.05P2#runbook-pbv-breach-rate
PBVNegRiskBreachesrate(polytraders_exec_pricebandvalidator_breaches_total{reason_code='PRICE_BAND_NEGRISK_BREACH'}[5m]) > 0P1#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

SituationUser-facing explanation
Price check passedYour order price was within the expected range for the current market.
Order rejected — price too far from marketYour 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 edgeYour order price was adjusted to be within the safe range for this market.

18. Failure-Mode Block

main_failure_modeTop-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_riskA 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_riskA fat-finger with offset exactly at max_offset_from_mid_pct passes without warning.
safe_fallbackIf clob_public top-of-book is unavailable, reject the order with STALE_MARKET_DATA rather than proceeding without a band check.
required_dependenciesclob_public top-of-book snapshot, ExecutionPlan from SmartRouter

19. Failure-Injection Recipes

ScenarioHow to injectExpected behaviourRecovery
STALE_TOP_OF_BOOKBlock clob_public and let cache TTL expireclob_public restored; next plan triggers fresh fetch
FAT_FINGER_PRICESubmit ExecutionPlan with price=0.06, mid=0.62 (90% offset), action=rejectAutomatic; strategy corrects price
NEGRISK_SUM_BREACHSubmit negRisk ExecutionPlan with leg prices [0.60, 0.55, 0.10] summing to 1.25Automatic; strategy corrects leg prices

20. State & Persistence

Cold-start recovery

Cache empty on restart; first validation per market triggers fresh fetch.

21. Concurrency & Idempotency

AspectSpecification
Execution modelper-plan goroutine
Max in-flight100
Idempotency keytrace_id + market_id + price
Per-call timeout (ms)200
Backpressure strategyshed if > 100 plans queued
Locking / mutual exclusionper-market_id read-lock for cache reads

22. Dependencies

Depends on (must run first)

BotWhyContract
exec.smart_routerSource of ExecutionPlan to validate.PriceBandValidator must run before order signing.

Emits to (downstream consumers)

BotWhyContract
exec.orderlifecyclemanagerPassed-through ExecutionPlan forwarded to signing and lifecycle tracking.Only PASS or RESHAPE plans forwarded; BREACH plans discarded.

External services

ServiceEndpointSLA assumedOn failure
CLOB V2 public APIhttps://clob.polymarket.com99.9% / 200ms p99If top-of-book unavailable, reject order with STALE_MARKET_DATA.
Gamma APIhttps://gamma-api.polymarket.com99.9% / 500ms p99If 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

AspectValue
CLOB versionv2
Collateral assetpUSD
EIP-712 Exchange domain version2
Aware of builderCode fieldno
Aware of negative-risk marketsyes
Multi-chain readyno
SDK usedpy-clob-client-v2
Settlement contractCTFExchangeV2
NotesFor 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

FieldValue
spec2.0.0
implementation0.1.0
schema2
releasedNone
planned_releaseQ4-2026

Migration history

DateFromToReasonAction taken
2026-04-28n/av2-specSpec drafted post-CLOB-V2 cutover; bot not yet implementedDesigned against V2 schema (pUSD, builder codes, V2 EIP-712 domain)

26. Acceptance Tests

Unit Tests

TestSetupExpected result
PASS when order price within 10% of midorder_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=rejectoffset_pct=90.3 > 25; PRICE_BAND_BREACH; order discarded
WARN only in shadow mode regardless of action_on_breachmode=shadow, warn_only_in_shadow=true, offset_pct=30PRICE_BAND_WARN; order not discarded

Integration Tests

TestExpected result
Reshape: price snapped to band edgereshaped_price = mid * (1 - 0.10) = 0.558; PRICE_BAND_RESHAPED
NegRisk sum-to-one check: leg prices sum > 1.0 triggers PRICE_BAND_NEGRISK_BREACHHARD_REJECT if negRisk market and sum_of_leg_prices > 1.0

Property Tests

PropertyRequired behaviour
When action_on_breach=reject and offset > hard, order is never signedAlways 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

AlertFirst stepDiagnosisMitigationEscalate to
PBVHighBreachRateIdentify which strategy is generating breaches; check if max_offset_from_mid_pct is calibrated for current market spread.Strategy pod lead
PBVNegRiskBreachesImmediately 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.

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

GateHow measuredThreshold
Band computation unit tests pass with known fat-finger and negRisk scenariosCI test run100% pass

Promote to Limited live

GateHow measuredThreshold
False-positive breach rate < 0.1% over 48h shadow runCross-reference PRICE_BAND_BREACH events with manual price audit< 0.1% false positives

Promote to General live

GateHow measuredThreshold
No negRisk sum-to-one breach false positives over 7-day limited-livepolytraders_exec_pricebandvalidator_breaches_total{reason_code='PRICE_BAND_NEGRISK_BREACH'}Zero false positives

29. Developer Checklist

Ready-to-ship score: 27/27 sections complete · 100%

RequirementStatus
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