Skip to main content

Polymarket Trading Agent

Architecture of a Postgres event-bus trading system with probability hard gates, adaptive risk controls, and deterministic worker processing for prediction markets.

5 min read·Intermediate·Concept·Jul 26, 2026
trading systemsevent-driven architecturerisk management

Polymarket Trading Agent

What Was Built

The Polymarket Autonomous Trading Engine is a modular monolith that discovers, validates, and executes prediction-market trades. Phases 0–15 implement a full pipeline from market data ingestion through trade execution, position monitoring, learning analytics, and adaptive parameter tuning. All modules communicate through a Postgres event bus with deterministic worker claiming via FOR UPDATE SKIP LOCKED.

The Problem

Prediction markets have fragmented liquidity, stale quotes, and slow information propagation — but turning structural edges into profit requires more than signal detection. A trading system must enforce probability estimates before execution, capitalize safely under hard risk limits, and recover from worker failures without duplicate orders or lost events.

Why This Problem Is Difficult

  1. Event ordering — market data, signals, and execution events must flow through a consistent pipeline without race conditions.
  2. Probability dependency — trading without a fair-value estimate is speculation, not edge exploitation.
  3. Capital safety — drawdown, exposure, and daily loss limits must be enforced atomically before order submission.
  4. Strategy lifecycle — underperforming strategies must auto-disable without manual intervention.
  5. AI isolation — advisory LLM recommendations must never block or alter execution.

Beginner Mental Model

Think of a factory assembly line where each station reads from a shared conveyor belt (Postgres events). Workers claim one package at a time, process it, and place the result back on the belt. Before the final station (execution), a quality inspector checks that a probability estimate exists and is fresh — no probability, no trade. A separate risk officer caps position sizes and can pull the emergency stop.

Requirements and Constraints

RequirementImplementation
Deterministic processingWorkerLoop: claim → process → complete/fail
Event durabilityPostgres-backed event bus with retry and dead-letter
Probability gatePhase 12.5 hard gate: staleness checks before execution
Risk limits7 hard limits enforced by capital allocation engine
Strategy isolationPlugin surface via BaseStrategy implementations
AI advisory isolationRead-only advisor; failures do not affect execution path
DRY_RUN defaultObserve pipeline before live trading

Architecture Overview

All workers run inside one Python process (modular monolith) and communicate exclusively through the event bus — no direct cross-module calls.

Execution Flow

  1. Market data ingestion — Polymarket client normalizes orderbooks; scanner persists market records and price snapshots.
  2. Market quality filter — liquidity, spread, activity, and depth checks; rejects emit market_filtered_event.
  3. External signals — weather, crypto, RSS, and calendar ingestors produce external_signal_event with source-health telemetry.
  4. Feature engineering — versioned feature_computed_event with spread, momentum, volatility, and optional signal fields.
  5. Probability modeling — Bayesian, Monte Carlo, and domain-specific models emit probability_computed_event.
  6. Probability hard gate — lookup persisted probability; staleness thresholds (5 min arbitrage/informational, 15 min speculative); trigger recomputation if stale.
  7. Edge discovery — spread, liquidity imbalance, information-lag, and microstructure detectors with deduplication.
  8. Edge validation — EV gating, fee/slippage estimation, latency decay, ranking.
  9. Opportunity selection — composite ranking (EV 35%, edge score 25%, confidence 20%, market quality 10%, urgency 10%); top-K filter.
  10. Capital allocation — Kelly sizing, 40/40/20 category budgets, adaptive risk engine with drawdown clamps.
  11. Trade execution — Polymarket CLOB adapter with approval verification before build/sign/submit.
  12. Position monitoring + learning — P&L tracking, strategy metrics, edge decay detection, adaptive tuning (±20% per-cycle caps).

Important Components

ComponentResponsibility
core/event_bus.pyPostgres event publish, claim, complete/fail API
core/worker_runtime.pyDeterministic worker loop lifecycle
modules/probability_engine/Feature builder + probability hard gate
modules/edge_discovery/Edge detectors with event-contract validation
modules/capital/allocator.pyKelly sizing, category budgets, concentration modes
modules/capital/adaptive_risk_engine.pyDynamic effective_risk computation
modules/execution/trade_executor.pyOrder orchestration via CLOB adapter
modules/safety/kill_switch.pyCircuit breaker and daily loss triggers
modules/analytics/ai_advisor.pyRead-only advisory layer (Phase 14)
strategies/base_strategy.pyPlugin interface for concrete strategies

Simplified Implementation Examples

Worker claim pattern (simplified):

# simplified — deterministic claim → process → complete
event = event_bus.claim_next("edge_validation") # uses FOR UPDATE SKIP LOCKED
if event:
result = validator.process(event.payload)
event_bus.complete(event.id, result)

Probability hard gate (simplified):

# simplified — NO PROBABILITY → NO TRADE
prob = repo.get_probability(market_id)
if prob is None or prob.age_seconds > STALENESS_THRESHOLD:
trigger_recomputation(market_id)
raise ProbabilityGateBlocked(market_id)

Adaptive risk sizing (simplified):

# simplified — bounded effective risk
effective_risk = (
base_risk
* strategy_weight
* performance_multiplier
* market_condition_multiplier
* edge_confidence
)
effective_risk = min(effective_risk, HARD_CEILING_0_20)

Reliability and Idempotency

  • State storage: PostgreSQL event bus with versioned schema migrations.
  • Worker claiming: FOR UPDATE SKIP LOCKED prevents double-processing.
  • Retry/dead-letter: Failed events retry with backoff; persistent failures route to dead-letter queue.
  • Strategy auto-disable: strategy_killer disables strategies on configurable win-rate/ROI/drawdown thresholds with cooldown and re-enable.
  • Kill switch: Daily loss and drawdown triggers halt execution immediately.

Failure Modes

FailureBehaviour
Missing probabilityTrade blocked; recomputation triggered
Stale probabilityBlocked per staleness threshold by strategy type
Risk limit exceededAllocation rejected; audit log entry
CLOB approval missingExecution blocked; approval_missing logged
Strategy underperformingAuto-disabled via strategy killer
AI advisor failureIsolated; execution path unaffected
Worker crashUnclaimed events remain; next worker claims them

Trade-offs and Rejected Alternatives

ChoiceWhyRejected alternative
Modular monolithShared Postgres; no network overheadMicroservices per phase
Postgres event busDurable, queryable, transactional claimsRedis/Kafka message queues
Probability hard gateEnforces edge-based trading disciplineTrade on signals without fair value
Kelly + hard ceilingsMathematical sizing with safety boundsFixed position sizes
AI advisor isolationPrevents LLM latency/failures from blocking tradesLLM in execution path
DRY_RUN defaultSafe observation before capital riskLive trading on first deploy

Testing

The repository includes mirrored pytest suites under tests/modules/ and tests/workers/ for every merged module. make quality runs lint, import-boundary checks, and full test suite. Economic validation runs via make validation-run.

Operations and Observability

  • Deployment: Docker Compose on VPS (poly-agent + postgres containers)
  • Log collection: scripts/collect_logs.sh produces PRS (Production Readiness Score)
  • Control: Telegram kill switch and circuit-breaker commands
  • Health: utils/health_check.py and structured JSON logging
  • Default mode: DRY_RUN=true — observe before enabling live execution

Lessons Learned

  1. NO PROBABILITY → NO TRADE — enforcing fair-value estimates before execution separates edge exploitation from speculation.
  2. Event bus as integration layer — module boundaries stay clean when all communication flows through persisted events.
  3. Hard risk limits are architecture contracts — drawdown clamps and exposure caps must be enforced in code, not configuration suggestions.
  4. Isolate advisory AI — LLM recommendations belong in analytics, not the execution critical path.

Sources