Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/deniszidbaev-cmyk/polyclaw-trading/llms.txt

Use this file to discover all available pages before exploring further.

PolyClaw Trading is built as a strictly sequential, fail-closed pipeline. Each of the eight named stages — fetch, candles, analyze, signal, bankroll, validate, execute, and report — is independently executable via polyclaw-engine <stage>. Stages share no memory and hold no network connections between them; the only interface between any two stages is a versioned JSON file written to the runtime/ directory. If any stage produces invalid, stale, or malformed output, the pipeline stops and no partial state crosses the boundary.

Pipeline overview

fetch → candles → analyze → signal → bankroll → validate → execute → report
Every file produced by a stage uses this envelope schema:
{
  "schema_version": 1,
  "stage": "signal",
  "generated_at": "2026-01-01T12:00:00Z",
  "data": {}
}
The stage field identifies who wrote the file. Downstream stages assert the expected stage value before reading data; a mismatch is a hard failure.

Atomic writes and freshness

All stage outputs are written atomically: the engine writes to a unique temporary sibling file, calls fsync, then promotes it with os.replace. A partial write never becomes the canonical file. Every read also enforces a freshness deadline. The engine rejects files older than:
Freshness constantDefault
MAX_DECISION_AGE_SEC600 s
MAX_MARKET_AGE_SEC600 s
MAX_CANDLE_AGE_SEC1200 s
MAX_BANKROLL_AGE_SEC600 s
Invalid JSON, duplicate keys, wrong schema version, wrong stage label, missing required fields, non-finite numbers, bad price bounds, bad OHLC geometry, unsupported timeframes, and non-monotonic timestamps all fail closed — they are never silently repaired.

Stage descriptions

1

fetch

Discovers active Bitcoin binary markets via the Polymarket Gamma API (GET /markets/keyset with keyset pagination), joins YES/NO outcome tokens by label, validates question semantics, enforces liquidity and volume floors, and fetches YES-token price history from the CLOB API. Output: runtime/markets.json. Supports an --fixture flag for offline dry-run verification.
2

candles

Builds UTC-aligned 5m and 15m pseudo-OHLC candles from 1-minute-fidelity YES-token price samples. Validates OHLC geometry, enforces minimum candle counts (MIN_CANDLES_5M, MIN_CANDLES_15M), and computes candle quality scores. Output: runtime/candles.json.
3

analyze

Computes EMA(8), EMA(21), RSI(14), ATR(14), sample-density POC, realized volatility, and deterministic candle patterns for both timeframes. Classifies market and candle quality. Output: runtime/market_analysis.json.
4

signal

Applies the seven-component confidence scoring formula to produce a YES, NO, or HOLD signal for each candidate market. Executes penalty deductions. Markets below the MIN_EXECUTION_CONFIDENCE threshold of 0.72 become HOLD. Outputs: runtime/decisions.json (all decisions) and runtime/manual_review.json (HOLD cases with blocking reasons).
5

bankroll

Reads the trade registry (runtime/trade_registry.json) to recompute equity, reserve, open exposure, drawdown percentage, and daily usage. Determines the current risk_mode (normal, reduced, or critical). Outputs: runtime/bankroll_state.json and runtime/risk_state.json.
6

validate

Reads decisions.json, bankroll_state.json, risk_state.json, and trade_registry.json and sizes each approved signal against all active capital caps. Re-checks confidence, candle quality, semantics, expiry, duplicates, cooldowns, and every risk limit using a shadow copy of the risk state to prevent double-counting. Updates decisions.json (stamped validate) and manual_review.json.
7

execute

Re-reads fresh bankroll, risk, registry, expiry, semantic, pattern, quality, and cooldown state immediately before any subprocess launch. In dry-run mode (LIVE_TRADING=0), records a simulated attempt without invoking PolyClaw. In live mode, fetches a current public price for slippage pre-flight, then invokes the PolyClaw CLI as a subprocess without a shell. All attempts — dry-run or live — are appended to runtime/executions/YYYYMMDD.json. Updates runtime/trade_registry.json.
8

report

Produces a terminal summary and runtime/ snapshot reflecting the final state of every stage output. No external network calls are made at this stage.

Two orchestration patterns

The pipeline supports two distinct orchestration patterns:
The cycle command runs all eight stages once in sequence. The loop command repeats cycle on a configurable interval (LOOP_INTERVAL_SEC, default 300 s). This path is fully deterministic and does not depend on an LLM response.
# Run one complete cycle
uv run python -m polyclaw_engine cycle

# Run up to 2 cycles, then exit
uv run python -m polyclaw_engine loop --max-cycles 2

# Run indefinitely
uv run python -m polyclaw_engine loop
run_pipeline.py also exposes a trade-cycle mode that runs the same stages minus report (stages 1–7), and an analysis-cycle mode that runs only the first four stages (fetch, candles, analyze, signal) without bankroll, validation, or execution.

Running individual stages

Every stage is independently executable for debugging and development:
uv run python -m polyclaw_engine fetch
uv run python -m polyclaw_engine candles
uv run python -m polyclaw_engine analyze
uv run python -m polyclaw_engine signal
uv run python -m polyclaw_engine bankroll
uv run python -m polyclaw_engine validate
uv run python -m polyclaw_engine execute
uv run python -m polyclaw_engine report
The --fixture flag is accepted by fetch, cycle, and loop to load an offline market fixture instead of contacting Polymarket. It is rejected by all other individual stages to prevent accidentally seeding analysis from a test file.
Running uv run python -m polyclaw_engine audit does not run the pipeline. It executes the built-in unittest audit set, which covers deterministic boundaries, contracts, risk, and execution safety — no secrets or network access required.

What happens when a stage fails

The orchestrator is designed so that a failed stage always stops the pipeline. There is no retry, no fallback path, and no continuation from malformed or stale upstream state. The loop is sequential so execution never races analysis. The error is printed to stderr with the exception class name and message; the exit code is 2.
[blocked] ContractError: market_analysis is stale (age=1350s > max=1200s)

Build docs developers (and LLMs) love