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.2 AntiToxicFill

2.2 AntiToxicFill

Execution Execution Utility Reshape BETA Limited live capital · Direct P5 · Execution rails pending stub

AntiToxicFill detects toxic order-flow patterns on the target market immediately before order submission and reshapes or cancels the ExecutionPlan to avoid being adversely selected. It monitors three primary toxicity signals: one-sided sweeps through more than three book levels in the last 5 seconds, a cancel-storm on the opposite side, and realised post-fill drift over a rolling window. If an adverse news event is detected within ±30 seconds of a planned fill, the bot enters a cooldown. Depending on signal severity, AntiToxicFill either widens the limit price by requote_widen_bps, reduces the order size by downsize_factor, or cancels the order outright. It cannot alter the trade direction, market, or outcome leg.

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
StatusBETA
ReadinessLimited live
Runs beforeOrder signing and CLOB V2 submission
Runs afterSmartRouter (ExecutionPlan assembled) and ObservationReport ingestion
Applies toEvery pending ExecutionPlan where toxic-flow signals or adverse RiskVotes are present on the target market
Default modelimited_live
User-visibleAdvanced details only
Developer ownerPolytraders core — Execution pod

Operational profile

Modes supportedquarantine

2. Purpose

AntiToxicFill detects toxic order-flow patterns on the target market immediately before order submission and reshapes or cancels the ExecutionPlan to avoid being adversely selected. It monitors three primary toxicity signals: one-sided sweeps through more than three book levels in the last 5 seconds, a cancel-storm on the opposite side, and realised post-fill drift over a rolling window. If an adverse news event is detected within ±30 seconds of a planned fill, the bot enters a cooldown. Depending on signal severity, AntiToxicFill either widens the limit price by requote_widen_bps, reduces the order size by downsize_factor, or cancels the order outright. It cannot alter the trade direction, market, or outcome leg.

3. Why This Bot Matters

  • Toxic sweep not detected before submission

    The system fills against an informed counterparty that has just swept the book on privileged news, resulting in immediate adverse mark-to-market on the filled position.

  • Cancel-storm ignored on opposite side

    Mass cancellations on the opposite side of the book signal that the market is repricing. Submitting a resting order into this environment leads to a fill at a price that is immediately stale.

  • Post-fill drift not tracked across rolling window

    Systematic adverse drift after fills indicates chronic toxic flow on the market. Without reshaping, the strategy will continue to be adversely selected until cumulative losses exceed risk limits.

  • News-window cooldown not applied

    News events arriving within ±30 seconds of a fill represent the highest toxicity risk. Filling in this window without a cooldown leads to significant slippage on information-driven price moves.

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 order book — top 10 levels both sidesclob_publicYesDetect one-sided sweeps (>3 levels consumed in 5s) and cancel-storms on the opposite side.
Recent trade tape (last 100 fills on market)ws_marketYesCompute realised post-fill drift over the rolling drift_window_s.
Market metadata (tick size, neg-risk flag)clob_publicYesTick-align the widened requote price after applying requote_widen_bps.

5. Required Internal Inputs

InputSourceRequired?Use
ObservationReport — toxic-flow signalsinternal bus (polytraders.reports.execution)YesReceive structured toxic-flow observations: sweep_detected, cancel_storm_detected, drift_bps, news_event_at_ms.
RiskVote — adverse risk signal from guardrail pipelinerisk guardrail pipelineYesIf any RiskVote carries RESHAPE with a toxicity reason, apply downsize_factor to the order size.
KillSwitch active flagKillSwitchYesAbort order and emit no ExecutionReport if KillSwitch is active.
NewsIngest adverse-event feedinternal NewsIngest serviceNoDetect news events within ±news_window_s of the planned fill; enter cooldown_s pause if hit.

6. Parameter Guide

ParameterDefaultWarningHardWhat it controls
cooldown_s3060120Number of seconds to pause order submission after a toxic-flow event or news hit is detected. During cooldown, all ExecutionPlans for the affected market are held; no orders are submitted.
requote_widen_bps2040100Number of basis points to widen the limit price on a RESHAPE action. For a BUY order the price is lowered by requote_widen_bps; for a SELL order the price is raised, creating a more protective limit.
downsize_factor0.50.250.1Multiplier (0 to 1) applied to the order size when a RESHAPE is triggered by a RiskVote or strong toxic signal. A factor of 0.5 halves the order; 0.1 reduces it to 10% of original.
news_window_s304560Symmetric window in seconds around the planned fill time within which an adverse news event triggers a cooldown. Events within [fill_time - news_window_s, fill_time + news_window_s] are treated as contemporaneous with the fill.

7. Detailed Parameter Instructions

cooldown_s

What it means

Number of seconds to pause order submission after a toxic-flow event or news hit is detected. During cooldown, all ExecutionPlans for the affected market are held; no orders are submitted.

Default

{ "cooldown_s": 30 }

Why this default matters

A 30-second cooldown is long enough to let informed order flow resolve and the book to reprice, while short enough to avoid excessive missed opportunity cost on liquid markets.

Threshold logic

ConditionAction
No toxic signal detectedNo cooldown — proceed to submission
Single signal (sweep OR cancel-storm OR drift) detectedEnter cooldown_s pause (default 30s)
Multiple signals or news hit detectedExtend to warning threshold (60s)
cooldown_s > 120 (hard)Reject config change — PARAMETER_CHANGE_REQUIRES_APPROVAL

Developer check

if cooldown_s > params.hard: raise ConfigError('PARAMETER_CHANGE_REQUIRES_APPROVAL')

User-facing English

Trading on this market was briefly paused because unusual activity was detected that could affect your fill price.

requote_widen_bps

What it means

Number of basis points to widen the limit price on a RESHAPE action. For a BUY order the price is lowered by requote_widen_bps; for a SELL order the price is raised, creating a more protective limit.

Default

{ "requote_widen_bps": 20 }

Why this default matters

A 20 bps widen provides protection against short-lived adverse flow while still leaving the order competitive. More than 40 bps risks missing the trade entirely.

Threshold logic

ConditionAction
No sweep, cancel-storm, or drift detectedNo widen — original price used
Mild signal: drift_bps < 30 or single cancel-stormWiden by requote_widen_bps (default 20 bps)
Strong signal: drift_bps >= 30 or sweep detectedWiden by warning threshold (40 bps)
requote_widen_bps > 100 (hard)Reject config — PARAMETER_CHANGE_REQUIRES_APPROVAL

Developer check

widenedPrice = BUY ? price * (1 - requote_widen_bps/10000) : price * (1 + requote_widen_bps/10000)

User-facing English

Your order price was adjusted slightly to protect against unfavourable market conditions detected just before submission.

downsize_factor

What it means

Multiplier (0 to 1) applied to the order size when a RESHAPE is triggered by a RiskVote or strong toxic signal. A factor of 0.5 halves the order; 0.1 reduces it to 10% of original.

Default

{ "downsize_factor": 0.5 }

Why this default matters

Halving the order on a toxic signal reduces adverse-selection exposure while still allowing partial participation. Factors below 0.25 leave very small residual orders that incur proportionally higher fees.

Threshold logic

ConditionAction
No adverse RiskVote and no strong signalNo resize — original size used
Adverse RiskVote RESHAPE or strong single signalApply downsize_factor (default 0.5)
Multiple signals or news hitApply warning-level factor (0.25)
downsize_factor < 0.1 (hard floor)Clamp to 0.1 — ANTITOXICFILL_SIZE_FLOOR_APPLIED

Developer check

finalSize = max(originalSize * downsize_factor, originalSize * 0.1)

User-facing English

The size of your order was reduced because market conditions suggested a lower-risk position size was appropriate.

news_window_s

What it means

Symmetric window in seconds around the planned fill time within which an adverse news event triggers a cooldown. Events within [fill_time - news_window_s, fill_time + news_window_s] are treated as contemporaneous with the fill.

Default

{ "news_window_s": 30 }

Why this default matters

A ±30-second window covers the typical latency between a news event and its full impact on the Polymarket CLOB order book, without being so wide that routine pre-trade news suppresses all activity.

Threshold logic

ConditionAction
No news event within ±news_window_sNo cooldown triggered by news
News event within ±news_window_sEnter cooldown_s pause — ANTITOXICFILL_NEWS_COOLDOWN
news_window_s > 60 (hard)Reject config — PARAMETER_CHANGE_REQUIRES_APPROVAL

Developer check

newsHit = any(abs(event.ts_ms - fill_planned_ms) <= news_window_s * 1000 for event in news_feed)

User-facing English

A news event was detected close to your planned trade time, so the trade was briefly paused for safety.

8. Default Configuration

{
  "bot_id": "exec.antitoxicfill",
  "version": "2.0.0",
  "mode": "limited_live",
  "defaults": {
    "cooldown_s": 30,
    "requote_widen_bps": 20,
    "downsize_factor": 0.5,
    "news_window_s": 30
  },
  "locked": {
    "cooldown_s": {
      "max": 120
    },
    "requote_widen_bps": {
      "max": 100
    },
    "news_window_s": {
      "max": 60
    }
  }
}

9. Implementation Flow

  1. Receive ExecutionPlan from SmartRouter; load associated ObservationReport and RiskVote from the internal bus.
  2. Check KillSwitch active flag; if active, discard the ExecutionPlan and emit no ExecutionReport.
  3. Check whether the market is in cooldown (cooldown state keyed by market_id in Redis); if in cooldown, hold the plan and re-evaluate after cooldown expires.
  4. Fetch CLOB V2 top-10 book snapshot from clob_public; subscribe to ws_market trade tape for the target market.
  5. Evaluate sweep signal: count book levels consumed on one side in the last 5 seconds using the ws_market trade tape. If > 3 levels consumed, set sweep_detected = true.
  6. Evaluate cancel-storm signal: count cancel events on the opposite side in the last 5 seconds from the ws_market feed. If cancel_count_5s > cancel_storm_threshold (default 10), set cancel_storm_detected = true.
  7. Evaluate post-fill drift: compute mean realised drift in bps over the last drift_window_s seconds using the recent fill tape. If drift_bps > drift_threshold_bps, set drift_detected = true.
  8. Check NewsIngest feed: if any adverse event timestamp falls within ±news_window_s of the planned fill, set news_hit = true.
  9. Determine action: if news_hit or (sweep_detected AND cancel_storm_detected): enter cooldown, cancel order, emit ANTITOXICFILL_NEWS_COOLDOWN or ANTITOXICFILL_SWEEP_CANCEL_STORM. If single signal or adverse RiskVote: apply downsize_factor and requote_widen_bps, emit RESHAPE. If no signals: approve and pass ExecutionPlan through unchanged.
  10. On RESHAPE: compute widenedPrice (tick-aligned, using buildOrderTypedData metadata), apply downsize_factor to size, construct updated ExecutionPlan, forward to signing.
  11. Emit ExecutionReport to polytraders.reports.execution (partition by trace_id, WAL-then-retry, retention 7y) with verdict, reason_code, original and reshaped parameters, and all signal flags.

10. Reference Implementation

On each ExecutionPlan received from SmartRouter, AntiToxicFill evaluates three toxic-flow signals (sweep, cancel-storm, post-fill drift) and a news-event check, then either passes the plan unchanged, reshapes it (widen price, reduce size), or cancels it and enters a market-level cooldown. Emits ExecutionReport to polytraders.reports.execution.

Pseudocode is language-agnostic. FETCH = read input. EMIT = produce output. Translate to TS/Python/Go/Rust.

FUNCTION evaluatePlan(plan, observationReport, riskVotes):
  // --- 0. KillSwitch gate ---
  ks = FETCH internal.killswitch.status
  IF ks.active:
    EMIT ExecutionReport(plan, HARD_REJECT, KILL_SWITCH_ACTIVE)
    RETURN

  // --- 1. Cooldown check ---
  cooldownKey = 'cooldown:' + plan.market_id
  IF FETCH redis.GET(cooldownKey) IS NOT NULL:
    EMIT ExecutionReport(plan, HOLD, ANTITOXICFILL_COOLDOWN_ACTIVE)
    RETURN  // Re-evaluate after TTL

  // --- 2. Fetch market book + trade tape ---
  book = FETCH clob_public.GET('/book?market=' + plan.market_id + '&depth=10')
  tape = FETCH ws_market.recent_fills(plan.market_id, last_n=100)
  IF book IS NULL OR tape IS NULL:
    // Safe fallback: apply conservative defaults
    widenBps = params.requote_widen_bps * 2  // 40 bps default fallback
    finalSize = plan.size_usd * params.downsize_factor
    EMIT ExecutionReport(plan, RESHAPE, ANTITOXICFILL_FEED_UNAVAILABLE,
                         reshaped_price=widenPrice(plan, widenBps),
                         reshaped_size=finalSize)
    RETURN

  // --- 3. Evaluate sweep signal ---
  // Count levels consumed on plan.side in last 5 seconds
  recentTrades = [t FOR t IN tape IF now_ms() - t.ts_ms <= 5000
                  AND t.aggressor_side == plan.side]
  levelsConsumed = COUNT DISTINCT price levels in recentTrades
  sweepDetected = (levelsConsumed > 3)

  // --- 4. Evaluate cancel-storm signal ---
  // Count cancels on opposite side in last 5 seconds
  oppSide = 'SELL' IF plan.side == 'BUY' ELSE 'BUY'
  recentCancels = FETCH ws_market.recent_cancels(plan.market_id, side=oppSide, window_ms=5000)
  cancelStormDetected = (COUNT(recentCancels) > 10)

  // --- 5. Evaluate post-fill drift ---
  driftBps = computeRollingDrift(tape, window_s=params.drift_window_s)  // mean bps drift post-fill
  driftDetected = (driftBps > params.drift_threshold_bps)  // default: 30 bps

  // --- 6. Check news feed ---
  newsEvents = FETCH internal.newsingest.recent(plan.market_id)
  newsHit = ANY(abs(e.ts_ms - plan.planned_fill_ms) <= params.news_window_s * 1000
                FOR e IN newsEvents)

  // --- 7. Check adverse RiskVote ---
  adverseVote = ANY(v.verdict == 'RESHAPE' AND 'toxicity' IN v.tags FOR v IN riskVotes)

  // --- 8. Determine action ---
  IF newsHit OR (sweepDetected AND cancelStormDetected):
    // Hard cancel + cooldown
    reason = ANTITOXICFILL_NEWS_COOLDOWN IF newsHit ELSE ANTITOXICFILL_SWEEP_CANCEL_STORM
    redis.SET(cooldownKey, 1, EX=params.cooldown_s)
    EMIT ExecutionReport(plan, HARD_REJECT, reason)
    RETURN

  IF sweepDetected OR cancelStormDetected OR driftDetected OR adverseVote:
    // Reshape: widen price + downsize
    signalStrength = COUNT([sweepDetected, cancelStormDetected, driftDetected, adverseVote])
    widenBps = params.requote_widen_bps IF signalStrength == 1 ELSE params.requote_widen_bps_warning
    newPrice = widenPrice(plan, widenBps)          // BUY: lower; SELL: raise
    newPrice = tickAlign(newPrice, book.tick_size)  // snap to valid tick
    newSize = max(plan.size_usd * params.downsize_factor,
                  plan.size_usd * 0.1)             // clamp to hard floor
    reshapedPlan = plan WITH price=newPrice, size_usd=newSize
    EMIT ExecutionReport(reshapedPlan, RESHAPE, ANTITOXICFILL_RESHAPE,
                         widen_bps_applied=widenBps,
                         downsize_factor_applied=params.downsize_factor)
    FORWARD reshapedPlan TO signing
    RETURN

  // --- 9. Pass through ---
  EMIT ExecutionReport(plan, PASS, ANTITOXICFILL_PASS)
  FORWARD plan TO signing

Helpers used

HelperSignaturePurpose
widenPricewidenPrice(plan: ExecutionPlan, widenBps: int) -> floatReturns a more protective limit price: BUY orders get a lower price (plan.price * (1 - widenBps/10000)); SELL orders get a higher price.
tickAligntickAlign(price: float, tickSize: float) -> floatRounds price to the nearest valid tick using floor for BUY and ceil for SELL to maintain the protective direction.
computeRollingDriftcomputeRollingDrift(tape: List[Fill], window_s: int) -> floatComputes mean realised post-fill drift in basis points over a rolling window from the trade tape.
fetchClobPublicfetchClobPublic(path: str) -> JSONUnauthenticated GET against https://clob.polymarket.com; returns parsed JSON or null on error.

SDK calls used

  • clob_public.GET('/book?market=' + plan.market_id + '&depth=10')
  • ws_market.subscribe('last_trade_price', plan.market_id)
  • ws_market.subscribe('book', plan.market_id)
  • redis.GET('cooldown:' + plan.market_id)
  • redis.SET('cooldown:' + plan.market_id, 1, EX=cooldown_s)

Complexity: O(1) per ExecutionPlan evaluation; O(F) for rolling drift scan where F = recent fill count (capped at 100)

11. Wire Examples

Input — what arrives on the wire

ExecutionPlan + ObservationReport with sweep signalexec.smart_router + internal bus

{
  "intent_id": "int_3c4d5e6f7a8b9c0d",
  "trace_id": "trc_9f8e7d6c5b4a3f2e",
  "market_id": "0x3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e",
  "side": "BUY",
  "outcome": "YES",
  "price": 0.62,
  "size_usd": 400,
  "order_type": "GTC",
  "planned_fill_ms": 1746769800000,
  "observation_report": {
    "sweep_detected": true,
    "sweep_levels_consumed": 4,
    "cancel_storm_detected": false,
    "cancel_count_5s": 3,
    "drift_bps": 8,
    "news_hit": false
  },
  "risk_votes": [
    {
      "bot_id": "risk.portfolio_guard",
      "verdict": "PASS"
    }
  ]
}

Output — what the bot emits

ExecutionReport — RESHAPE (sweep detected, price widened, size halved)

{
  "report_id": "rep_a1b2c3d4e5f6a7b8",
  "trace_id": "trc_9f8e7d6c5b4a3f2e",
  "bot_id": "exec.antitoxicfill",
  "market_id": "0x3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e",
  "side": "BUY",
  "outcome": "YES",
  "verdict": "RESHAPE",
  "reason_code": "ANTITOXICFILL_RESHAPE",
  "original_price": 0.62,
  "reshaped_price": 0.61,
  "original_size_usd": 400,
  "reshaped_size_usd": 200,
  "widen_bps_applied": 20,
  "downsize_factor_applied": 0.5,
  "collateral": "pUSD",
  "eip712_domain_version": "2",
  "signals": {
    "sweep_detected": true,
    "cancel_storm_detected": false,
    "drift_detected": false,
    "news_hit": false,
    "drift_bps": 8
  },
  "evaluated_at_ms": 1746769800000
}

ExecutionReport — HARD_REJECT (news hit + cooldown applied)

{
  "report_id": "rep_b2c3d4e5f6a7b8c9",
  "trace_id": "trc_1a2b3c4d5e6f7a8b",
  "bot_id": "exec.antitoxicfill",
  "market_id": "0x3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e",
  "side": "SELL",
  "outcome": "NO",
  "verdict": "HARD_REJECT",
  "reason_code": "ANTITOXICFILL_NEWS_COOLDOWN",
  "original_price": 0.41,
  "reshaped_price": null,
  "original_size_usd": 300,
  "reshaped_size_usd": null,
  "collateral": "pUSD",
  "cooldown_s_applied": 30,
  "signals": {
    "sweep_detected": false,
    "cancel_storm_detected": false,
    "drift_detected": false,
    "news_hit": true,
    "news_event_delta_ms": -18000
  },
  "evaluated_at_ms": 1746769850000
}

12. Decision Logic

APPROVE

No toxic signals detected, no adverse RiskVote, no news hit, and market is not in cooldown. ExecutionPlan passes through unmodified. Emit ANTITOXICFILL_PASS.

RESHAPE_REQUIRED

One or more toxic signals (sweep, cancel-storm, or drift) detected, or an adverse RiskVote with toxicity reason received. Apply downsize_factor to size and widen price by requote_widen_bps. Emit ANTITOXICFILL_RESHAPE.

REJECT

News event detected within ±news_window_s, or simultaneous sweep and cancel-storm signals, or KillSwitch active. Enter cooldown_s pause on the market, cancel the ExecutionPlan, emit no order. Emit ANTITOXICFILL_NEWS_COOLDOWN or ANTITOXICFILL_SWEEP_CANCEL_STORM.

WARNING_ONLY

Post-fill drift is in the warning band (above warning threshold but below action threshold). WARN annotation attached to the ExecutionReport; plan proceeds unchanged.

13. Standard Decision Output

This bot returns a ExecutionReport object. See ExecutionReport schema.

{
  "report_id": "rep_a1b2c3d4e5f6a7b8",
  "trace_id": "trc_9f8e7d6c5b4a3f2e",
  "bot_id": "exec.antitoxicfill",
  "market_id": "0x3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e",
  "side": "BUY",
  "outcome": "YES",
  "verdict": "RESHAPE",
  "reason_code": "ANTITOXICFILL_RESHAPE",
  "original_price": 0.62,
  "reshaped_price": 0.608,
  "original_size_usd": 400,
  "reshaped_size_usd": 200,
  "widen_bps_applied": 20,
  "downsize_factor_applied": 0.5,
  "signals": {
    "sweep_detected": true,
    "cancel_storm_detected": false,
    "drift_detected": false,
    "news_hit": false,
    "drift_bps": 8
  },
  "collateral": "pUSD",
  "eip712_domain_version": "2",
  "evaluated_at_ms": 1746769800000
}

14. Reason Codes

CodeSeverityMeaningActionUser-facing message
ANTITOXICFILL_PASSINFONo toxic-flow signals detected; ExecutionPlan passes through unchanged.Forward ExecutionPlan to signing without modification.
ANTITOXICFILL_RESHAPERESHAPEOne or more toxic-flow signals (sweep, cancel-storm, or drift) or an adverse RiskVote detected. Price widened by requote_widen_bps and size reduced by downsize_factor.Apply widen and downsize to ExecutionPlan; forward reshaped plan to signing.Your order was adjusted to protect against unusual market activity detected before submission.
ANTITOXICFILL_NEWS_COOLDOWNHARD_REJECTAn adverse news event was detected within ±news_window_s of the planned fill. Order cancelled; market enters cooldown.Cancel ExecutionPlan; apply cooldown_s to market_id in Redis; emit no order.Trading on this market was briefly paused because a news event was detected near your planned trade time.
ANTITOXICFILL_SWEEP_CANCEL_STORMHARD_REJECTSimultaneous one-sided sweep (>3 levels) and cancel-storm on the opposite side detected. Highest toxicity combination; order cancelled and market enters cooldown.Cancel ExecutionPlan; apply cooldown_s to market_id; emit no order.Significant one-sided activity was detected on this market. Your order was cancelled to avoid adverse fills.
ANTITOXICFILL_COOLDOWN_ACTIVEEXPLAINThis market is currently in a toxicity cooldown from a prior event. New ExecutionPlans are held until the cooldown expires.Hold ExecutionPlan; re-evaluate after cooldown TTL expires.Your order is waiting for unusual market activity to settle before it is submitted.
ANTITOXICFILL_SIZE_FLOOR_APPLIEDWARNdownsize_factor computation would have produced a size below the hard floor (10% of original). Size clamped to 10% of original.Set reshaped_size_usd = original_size_usd * 0.1; log warning.
ANTITOXICFILL_FEED_UNAVAILABLEWARNws_market or clob_public feed unavailable; conservative fallback defaults applied (widen 40 bps, downsize 0.5).Apply fallback reshape parameters; do not block order entirely.
KILL_SWITCH_ACTIVEHARD_REJECTGlobal kill switch is active; no orders may proceed.Discard ExecutionPlan; emit no order.Trading is currently paused.
MARKET_CLOSEDHARD_REJECTTarget market is closed or resolved; ExecutionPlan is invalid.Discard ExecutionPlan; log and emit no order.The market for this order is no longer active.

15. Metrics & Logs

Metrics emitted

MetricTypeUnitLabelsMeaning
polytraders_exec_antitoxicfill_decisions_totalcountercountverdict, reason_codeTotal ExecutionReport records emitted per verdict (PASS/RESHAPE/HARD_REJECT) and reason code.
polytraders_exec_antitoxicfill_cooldowns_activegaugecountNumber of markets currently in a toxicity cooldown. Rising count indicates sustained toxic-flow environment.
polytraders_exec_antitoxicfill_drift_bpshistogrambpsmarket_idDistribution of realised post-fill drift in basis points across evaluated ExecutionPlans.
polytraders_exec_antitoxicfill_sweep_levelshistogramcountmarket_idDistribution of sweep depth (levels consumed in 5s) at evaluation time; >3 triggers RESHAPE or HARD_REJECT.
polytraders_exec_antitoxicfill_eval_latency_mshistogrammsWall-clock latency from ExecutionPlan receipt to ExecutionReport emit.
polytraders_exec_antitoxicfill_reshape_widen_bpshistogrambpsDistribution of price-widen bps actually applied on RESHAPE decisions.

Alerts

AlertConditionSeverityRunbook
AntiToxicFillHighRejectRaterate(polytraders_exec_antitoxicfill_decisions_total{verdict='HARD_REJECT'}[5m]) / rate(polytraders_exec_antitoxicfill_decisions_total[5m]) > 0.3page#runbook-antitoxicfill-high-reject-rate
AntiToxicFillCooldownsSpikingpolytraders_exec_antitoxicfill_cooldowns_active > 5warn#runbook-antitoxicfill-cooldowns-spiking
AntiToxicFillHighDrifthistogram_quantile(0.95, rate(polytraders_exec_antitoxicfill_drift_bps_bucket[5m])) > 30warn#runbook-antitoxicfill-high-drift
AntiToxicFillEvalLatencyHighhistogram_quantile(0.99, rate(polytraders_exec_antitoxicfill_eval_latency_ms_bucket[5m])) > 150warn#runbook-antitoxicfill-latency

Dashboards

  • Grafana — Execution / AntiToxicFill
  • Grafana — Order quality / toxic-flow signals and cooldown history

16. Developer Reporting

{
  "report_id": "rep_a1b2c3d4e5f6a7b8",
  "trace_id": "trc_9f8e7d6c5b4a3f2e",
  "bot_id": "exec.antitoxicfill",
  "market_id": "0x3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e",
  "sweep_levels_consumed": 4,
  "sweep_detected": true,
  "cancel_storm_count_5s": 3,
  "cancel_storm_detected": false,
  "drift_bps": 8,
  "drift_detected": false,
  "news_hit": false,
  "adverse_risk_vote": false,
  "cooldown_active": false,
  "verdict": "RESHAPE",
  "reason_code": "ANTITOXICFILL_RESHAPE",
  "original_price": 0.62,
  "reshaped_price": 0.608,
  "original_size_usd": 400,
  "reshaped_size_usd": 200,
  "requote_widen_bps": 20,
  "downsize_factor": 0.5,
  "tick_size": 0.01,
  "tick_aligned_reshaped_price": 0.61,
  "evaluated_at_ms": 1746769800000
}

17. Plain-English Reporting

SituationUser-facing explanation
Order price widened before submissionUnusual activity was detected on this market just before your order was submitted. The price was adjusted slightly to protect you from filling at a disadvantageous price.
Order size reduced before submissionMarket conditions suggested an elevated risk of adverse fills. The order size was reduced to limit potential losses.
Order paused — news event nearbyA news event was detected close to the time of your planned trade. Trading was briefly paused to let the market adjust before your order was considered again.
Order cancelled — toxic flow detectedSignificant one-sided activity and widespread order cancellations were detected simultaneously. The order was cancelled to protect you from being adversely selected.

18. Failure-Mode Block

main_failure_modeFailing to detect a sweep because the ws_market feed is lagged or the CLOB book snapshot is stale, allowing a toxic order to be submitted without price widening or size reduction.
false_positive_riskTriggering a cooldown on a momentary one-sided sweep that immediately reverses (e.g. large benign taker), causing missed opportunity cost. Over-sensitive cancel-storm detection may also fire on normal book refresh activity.
false_negative_riskMissing a toxic news event because the NewsIngest feed has a latency spike, or because news_window_s is configured too tightly, leading to a fill against an informed counterparty.
safe_fallbackIf ws_market feed or clob_public book snapshot is unavailable, apply conservative defaults: downsize_factor=0.5 and requote_widen_bps=40. If NewsIngest is unavailable, proceed without news check but log ANTITOXICFILL_NEWS_FEED_UNAVAILABLE. If KillSwitch status cannot be read, halt submission.
required_dependenciesws_market trade tape for target market, clob_public top-10 book snapshot, ObservationReport from internal bus, RiskVote from guardrail pipeline, KillSwitch active flag, NewsIngest adverse-event feed (optional — graceful degradation if absent)

19. Failure-Injection Recipes

ScenarioHow to injectExpected behaviourRecovery
WS_MARKET_FEED_STALEDisconnect ws_market subscription; leave last_seen > 10sFeed reconnects; bot reverts to live signal evaluation on next ExecutionPlan
NEWS_HIT_COOLDOWNInject a NewsIngest event with ts_ms = now_ms() - 15000 (15s ago) for the target market; news_window_s=30After 30s, cooldown key expires; next ExecutionPlan evaluated without cooldown
SWEEP_AND_CANCEL_STORM_SIMULTANEOUSInject mock ws_market tape with 5 levels consumed in 2s on BUY side + 15 cancel events on SELL side in 5sAutomatic after cooldown_s expires
KILL_SWITCH_ONSet killswitch.active=trueReturns to normal on manual KillSwitch reset
REDIS_COOLDOWN_STORE_DOWNKill Redis connection during active cooldown periodRedis reconnects; cooldown state re-read; normal evaluation resumes
ADVERSE_RISK_VOTE_DOWNSIZEInject RiskVote with verdict=RESHAPE and tags=['toxicity'] from mock portfolio_guardAutomatic; next plan evaluated fresh

20. State & Persistence

Cold-start recovery

On restart, cooldown entries are re-read from Redis. Any market with an active cooldown key continues in cooldown. Drift cache is rebuilt from ws_market fill replay on reconnect; first evaluation after restart may use conservative fallback if cache is empty.

21. Concurrency & Idempotency

AspectSpecification
Execution modelsingle-threaded event loop
Max in-flight50
Idempotency keytrace_id
Per-call timeout (ms)150
Backpressure strategyExcess ExecutionPlans queued in memory ring buffer (max 50); oldest entry dropped if ring is full and WARN emitted
Locking / mutual exclusionRedis SETNX per market_id for cooldown write to prevent double-trigger during burst

22. Dependencies

Depends on (must run first)

BotWhyContract
exec.smart_routerProvides the ExecutionPlan that AntiToxicFill evaluates and potentially reshapes.AntiToxicFill must not alter side, market_id, or outcome leg from the original ExecutionPlan.
risk.kill_switchKillSwitch active flag is checked before any evaluation; active flag aborts all processing.No ExecutionReport is emitted while KillSwitch is active.
risk.portfolio_guardAdverse RiskVotes from PortfolioGuard with toxicity tags trigger downsize_factor application.If RiskVote verdict is RESHAPE with toxicity reason, AntiToxicFill applies downsize_factor.

Emits to (downstream consumers)

BotWhyContract
gov.fill_quality_analyzerExecutionReport emitted to polytraders.reports.execution, partitioned by trace_id.

Sibling bots (same OrderIntent)

BotWhyContract
exec.queue_wardenQueueWarden manages resting order lifecycle post-submission; AntiToxicFill acts pre-submission. Both consume toxic-flow signals but at different lifecycle stages.

External services

ServiceEndpointSLA assumedOn failure
Polymarket CLOB V2 (public)https://clob.polymarket.com99.9% / 200ms p99
Polymarket WebSocket — market feedwss://ws-subscriptions-clob.polymarket.com/ws/marketbest-effort
Internal NewsIngest serviceinternal://newsingest99% / 100ms p99 (internal SLA)

23. Security Surfaces

Abuse vectors considered

  • Injecting a fabricated ObservationReport with sweep_detected=false to suppress reshaping and allow toxic-fill through at full size
  • Flooding the cooldown Redis key with artificial expiry updates to prevent cooldown from being applied
  • Replay of stale ObservationReport to trigger a false cooldown on a non-toxic market, causing missed trading opportunities

Mitigations

  • ObservationReport messages are HMAC-signed by the emitting bot; AntiToxicFill validates the signature before processing
  • Redis cooldown keys use SETNX with TTL; they cannot be extended by external writers without Redis ACL access
  • ObservationReport freshness check: reports older than 10 seconds are discarded with STALE_DATA reason code
  • ws_market trade tape is fetched directly from Polymarket WebSocket — not from an internal cache that could be tampered with

24. Polymarket V2 Compatibility

AspectValue
CLOB versionv2
Collateral assetpUSD
EIP-712 Exchange domain version2
Aware of builderCode fieldno
Aware of negative-risk marketsno
Multi-chain readyno
SDK usedpy-clob-client-v2
Settlement contractCTFExchangeV2
NotesAntiToxicFill reshapes ExecutionPlans before order signing; it does not sign orders itself. All size and price amounts are denominated in pUSD. The widened price is tick-aligned using the V2 market metadata fetched from clob_public.

API surfaces declared

clob_publicws_marketinternal

Networks supported

polygon

25. Versioning & Migration

FieldValue
spec2.0.0
implementation2.0.0
schema2
released2026-04-28

Migration history

DateFromToReasonAction taken
2026-04-28v1v2CLOB V2 cutoverSwitched to py-clob-client-v2. Collateral denomination updated from USDC.e to pUSD in all ExecutionReport fields. Removed feeRateBps references from order-reshape logic (fees are now operator-set at match time by CTFExchangeV2). EIP-712 Exchange domain version updated from '1' to '2'. ObservationReport and RiskVote bus topics updated to V2 schema. Cooldown state store key updated to include bot_version=v2 prefix to avoid stale V1 entries.

26. Acceptance Tests

Unit Tests

TestSetupExpected result
PASS when no signals detectedsweep_detected=false, cancel_storm_detected=false, drift_bps=5, news_hit=false, killswitch=falseExecutionReport.verdict=PASS, no price or size change
RESHAPE when sweep detected: price widened and size halvedsweep_levels=4, sweep_detected=true, cancel_storm_detected=false, original_price=0.62, original_size_usd=400, requote_widen_bps=20, downsize_factor=0.5reshaped_price=0.608 (tick-aligned to 0.61), reshaped_size_usd=200, reason_code=ANTITOXICFILL_RESHAPE
CANCEL and cooldown when sweep + cancel-storm both detectedsweep_detected=true, cancel_storm_detected=true, news_hit=falseNo order submitted; cooldown_s=30 applied on market_id; reason_code=ANTITOXICFILL_SWEEP_CANCEL_STORM
CANCEL and cooldown on news hit within news_window_snews_event_ts_ms = fill_planned_ms - 20000, news_window_s=30news_hit=true; order cancelled; cooldown applied; reason_code=ANTITOXICFILL_NEWS_COOLDOWN
HARD_REJECT when KillSwitch activekillswitch.active=trueNo ExecutionReport emitted; reason_code=KILL_SWITCH_ACTIVE
RESHAPE on adverse RiskVote with toxicity reasonrisk_vote.verdict=RESHAPE, risk_vote.reason=ANTITOXICFILL_ADVERSE_FLOW, downsize_factor=0.5reshaped_size_usd = original_size_usd * 0.5; reason_code=ANTITOXICFILL_RESHAPE

Integration Tests

TestExpected result
End-to-end: ObservationReport sweep signal → RESHAPE → reshaped ExecutionPlan forwarded to signingReshaped order has tick-aligned widened price and halved size; ExecutionReport emitted to polytraders.reports.execution
News hit: NewsIngest event → cooldown applied → order held → re-evaluated after cooldown_s expiresOrder not submitted during cooldown; after cooldown expires and no further signals, order proceeds as PASS
Cooldown state survives bot restart (Redis TTL)After restart, market cooldown entry read from Redis; order still held until TTL expires

Property Tests

PropertyRequired behaviour
AntiToxicFill never alters the trade side, market_id, or outcome legAlways true — only price, size, and submission timing are modified
Reshaped size is always >= original_size_usd * downsize_factor_hard_floor (0.1)Always true — downsize_factor is clamped to 0.1 minimum
No order is submitted to CLOB V2 while a market is in cooldownAlways true — cooldown state checked before every ExecutionPlan evaluation

27. Operational Runbook

AntiToxicFill incidents fall into two categories: sustained cooldowns causing trading pauses on multiple markets simultaneously (possible false-positive storm or genuine market crisis), and feed unavailability causing conservative fallback reshaping that may be overly restrictive.

On-call actions

AlertFirst stepDiagnosisMitigationEscalate to
AntiToxicFillHighRejectRateCheck reason_code breakdown in Grafana. If ANTITOXICFILL_NEWS_COOLDOWN dominates, check NewsIngest feed for false positives. If ANTITOXICFILL_SWEEP_CANCEL_STORM dominates, check Polymarket market conditions.Sustained HARD_REJECT > 30% indicates either a genuine market-wide toxic event, a false-positive signal loop, or a NewsIngest misconfiguration.If false positives: temporarily increase cooldown_s to reduce churn, or pause NewsIngest integration. If genuine event: let cooldowns run and alert Strategy pod.Exec pod lead + Strategy pod if reject rate sustained > 5 minutes
AntiToxicFillCooldownsSpikingList active cooldown keys in Redis: redis-cli KEYS 'cooldown:*'. Cross-reference with Polymarket market status page.More than 5 simultaneous market cooldowns suggests either a broad market event or a systematic false-positive in the sweep detector.If false positives: run polytraders bot flush-cooldowns exec.antitoxicfill --market <id>. If genuine: let cooldowns expire naturally.Strategy pod lead for trading-pause decision
AntiToxicFillHighDriftCheck drift_bps histogram in Grafana. High drift p95 > 30 bps indicates systematic adverse selection on active markets.Chronic high drift may indicate the drift_threshold_bps parameter needs tuning, or that specific markets are structurally toxic.Lower drift_threshold_bps for affected markets. Consider blacklisting chronically toxic markets.Strategy pod lead for market selection review
AntiToxicFillEvalLatencyHighCheck p99 eval latency. If > 150ms, check ws_market feed latency and Redis response times.High latency means toxic signals arrive too late relative to order submission, reducing the effectiveness of reshaping.Check ws_market WebSocket connection health. Reduce max_in_flight if backpressure is the cause.Infra on-call if latency sustained > 300ms

Manual overrides

Healthcheck

GET /internal/health/antitoxicfill → 200 if ws_market feed connected and last message < 5s ago, Redis cooldown store reachable, NewsIngest feed responding, eval latency p99 < 150ms, cooldowns_active <= 3. RED if ws_market feed disconnected or stale > 10s, Redis unreachable, eval latency p99 > 300ms, or cooldowns_active > 10.

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
All 6 acceptance_tests.unit cases passCI test run100% pass
Side, market_id, and outcome invariants verified in property testsProperty-based test: 1000 random ExecutionPlans, none with side/market_id/outcome alteredZero violations

Promote to Limited live

GateHow measuredThreshold
False-positive cooldown rate < 5% in 48h shadow runCompare cooldown triggers against post-event market price data; count cases where market price did not move adverselyFalse-positive rate < 5%
p99 eval latency < 150ms over 24hpolytraders_exec_antitoxicfill_eval_latency_ms histogramp99 < 150ms

Promote to General live

GateHow measuredThreshold
7-day limited-live: mean post-fill drift on RESHAPE decisions < 10 bpsAudit log comparing pre-reshape and post-fill prices on all RESHAPE decisionsMean drift < 10 bps
Zero false-positive HARD_REJECT cancellations on news events that did not materialiseNews event log vs. post-event price change; HARD_REJECT valid only if price moved > 20 bps within 60s< 2% false-positive HARD_REJECT rate

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