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 was designed so that the safest possible action is also the default action. Every entry point — Python, Docker, shell script, and the native macOS Swift runner — starts in dry-run mode. A real order cannot be placed by accident; it requires a sequence of deliberate, explicit operator choices. This page explains each layer of protection and what you must do to go live intentionally.

The system-wide default: LIVE_TRADING=0

The EngineConfig class reads LIVE_TRADING from the environment and accepts only the exact string "1" as live mode. Any other value — including "true", "yes", "on", or an empty string — is treated as "0" (dry-run). Malformed values (anything other than "0" or "1") raise a ConfigError and prevent startup.
# From config.py — the only accepted values are "0" and "1"
def _flag(env, name, default="0") -> bool:
    raw = _raw(env, name, default)
    if raw not in {"0", "1"}:
        raise ConfigError(f"{name} must be exactly 0 or 1")
    return raw == "1"
The value is set in .env.local (which is gitignored). The .env.example template ships with LIVE_TRADING=0. Secrets and live-mode flags never appear in tracked files.

The dry-run command always resets live mode

The run_pipeline.py script’s dry-run command forcibly sets LIVE_TRADING to "0" in the process environment before building the config, even if the inherited environment or .env.local has LIVE_TRADING=1. There is no flag or argument that overrides this reset.
# This command is always safe — it can never place a live order
uv run python run_pipeline.py dry-run --fixture tests/fixtures/btc_market.json
The macOS Swift runner’s dry-run command applies the same guarantee at the process level: it pins both LIVE_TRADING and ALLOW_REDEEM to "0" before launching any Python subprocess, even if the inherited shell environment or .env.local says otherwise.
# Swift runner — dry-run is the default; pins LIVE_TRADING and ALLOW_REDEEM to 0
.build/release/polyclaw-mac run

Dry-run executions are fully auditable

Dry-run mode is not silent. Every simulated execution is recorded in runtime/executions/YYYYMMDD.json with "mode": "dry-run" and "status": "simulated". The daily ledger has exactly the same schema as a live execution record. You can run hundreds of dry-run cycles and inspect the complete audit trail before ever enabling live mode.
{
  "timestamp": "2026-01-01T12:00:00Z",
  "mode": "dry-run",
  "status": "simulated",
  "market_id": "...",
  "side": "YES",
  "amount_usd": 0.75,
  "return_code": 0
}
A human-readable summary is also appended to runtime/logs/YYYYMMDD.log for every attempt.

Offline fixtures are forbidden in live mode

The --fixture flag is accepted only by the fetch, cycle, and loop commands. Passing it to any other individual stage raises a ConfigError immediately. Additionally, if LIVE_TRADING=1 is active, the fetch stage itself blocks fixture-based runs at startup with ConfigError: offline fixtures are forbidden when LIVE_TRADING=1. This prevents a scenario where a stale test fixture provides the market data for a live trade.

ALLOW_REDEEM requires explicit opt-in

Automatic redemption of resolved market positions is disabled by default (ALLOW_REDEEM=0). Even if you enable live trading, PolyClaw Trading will not automatically redeem winning positions until you also set ALLOW_REDEEM=1 in .env.local. The two flags are independent; you can trade live without automatic redemption.

Live mode requirements

A real order is only possible when every one of the following conditions is met simultaneously. The execute stage checks them in sequence and blocks immediately if any fails.
  1. LIVE_TRADING=1 is set in .env.local (the exact string "1", nothing else).
  2. The pipeline was started via run live --confirm-live (Swift runner) or with LIVE_TRADING=1 explicitly set — not via dry-run.
  3. A fresh approved decision exists in runtime/decisions.json (not older than MAX_DECISION_AGE_SEC).
  4. The live public price preflight succeeds: the CLOB API returns a finite price in (0, 1) that does not exceed max_entry_price (MAX_ENTRY_SLIPPAGE_PCT).
  5. All risk gates pass: confidence ≥ 0.72, candle quality above threshold, compatible pattern present, semantic mapping confident, no duplicate decision ID, no existing position or pending order in the same market, no active failed-order cooldown, daily caps not exhausted.
  6. The manual PolyClaw wallet approval step has been completed (funded wallet, rotated API keys).
Offline fixtures are forbidden. Any of these checks failing blocks execution without modifying any live state.

Going live: prerequisites checklist

1

Fund the wallet conservatively

Transfer only the amount you are prepared to lose entirely. With MAX_TRADE_USD=1.00 and MAX_TRADES_PER_DAY=6, the theoretical maximum daily notional at default settings is $6.00. Start with a small balance and observe dry-run behavior for multiple days first.
2

Complete the PolyClaw wallet approval step

PolyClaw requires a one-time manual wallet approval before it will accept order submissions. Complete this step and verify it with a manual test trade at the minimum size before enabling automation.
3

Rotate and store API keys

Place your Polymarket API key, private key, and any proxy credentials in .env.local only. Never commit them, log them, or pass them as command-line arguments. The secret scanner CI test (tests/test_secret_scanner.py) fails the build if secret-like patterns appear in tracked files.
4

Run the audit set

uv run python run_pipeline.py audit
This runs the full built-in unittest suite covering deterministic boundaries, risk rules, and execution safety. It requires no network access and no secrets.
5

Run multiple dry-run cycles

uv run python run_pipeline.py loop --max-cycles 5
Review runtime/executions/YYYYMMDD.json and runtime/decisions.json to confirm the engine is selecting the markets and sizes you expect.
6

Set LIVE_TRADING=1 in .env.local

Edit .env.local and change LIVE_TRADING=0 to LIVE_TRADING=1. Optionally set ALLOW_REDEEM=1 if you want automatic redemption of resolved positions.
7

Start with the explicit live entry point

Swift runner (macOS):
.build/release/polyclaw-mac run live --confirm-live
Python runner:
# LIVE_TRADING must already be set to "1" in .env.local
uv run python run_pipeline.py cycle
Every execution — including failures — is recorded in runtime/executions/. Review the ledger after every session.

Secret hygiene by design

The following safeguards prevent secrets from leaking into the codebase or logs:
  • .env.local is gitignored. All secrets live there and only there.
  • tests/test_secret_scanner.py fails the CI build if any tracked file contains patterns that look like API keys, private keys, bearer tokens, or wallet mnemonics. This test runs on every push and pull request.
  • Subprocess output is redacted before being written to disk. The redact() function in execution.py applies five passes of regex substitution covering Authorization headers, OpenAI/GitHub/Google AI tokens, 64-character hex keys, Telegram bot tokens, wallet seed phrases, generic key-value secret patterns, and basic-auth credentials embedded in URLs. All matches are replaced with ***REDACTED***.
  • openclaw_patch.py takes a timestamped backup before modifying the OpenClaw home config at ~/.openclaw/openclaw.json, so no live credentials are silently overwritten.

Build docs developers (and LLMs) love