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 enforces a layered set of capital protection rules that are checked at the validate stage and re-checked independently at the execute stage immediately before any subprocess is launched. No single configuration value alone determines how much capital is at risk — every sized amount must simultaneously pass all active caps. If even one cap cannot support the minimum trade size of MIN_TRADE_USD, the decision becomes HOLD rather than being rounded up to the minimum.

Position sizing

The sizing logic starts from a confidence-interpolated raw size between MIN_TRADE_USD and MAX_TRADE_USD, scales it by the current drawdown multiplier, then takes the minimum across seven independent caps:
confidence_factor = clamp(
    (confidence - MIN_EXECUTION_CONFIDENCE) / (1.0 - MIN_EXECUTION_CONFIDENCE)
)
raw_size = MIN_TRADE_USD + confidence_factor * (MAX_TRADE_USD - MIN_TRADE_USD)
adjusted_raw = raw_size * risk_multiplier

size = min(
    adjusted_raw,
    MAX_TRADE_USD,                                        # configured_max
    working_bankroll * BASE_RISK_PER_TRADE_PCT / 100.0 * risk_multiplier,  # bankroll_risk
    working_bankroll * MAX_POSITION_BANKROLL_PCT / 100.0, # maximum_position
    remaining_daily_risk_usd,                             # remaining_daily_risk
    remaining_daily_notional_usd,                         # remaining_daily_notional
    remaining_open_exposure_usd,                          # remaining_open_exposure
    free_balance_usd,                                     # available_free_balance
)
Reserve capital is excluded from working_bankroll before any cap is computed. The final size is floored to cent precision; if it is below MIN_TRADE_USD after all caps, the decision is set to HOLD.

Key risk defaults

VariableDefaultPurpose
BASE_RISK_PER_TRADE_PCT1Per-trade bankroll risk cap (%)
MAX_DAILY_RISK_PCT8Daily risk budget as % of working bankroll
MAX_DAILY_NOTIONAL_PCT20Daily notional budget as % of working bankroll
MAX_OPEN_EXPOSURE_PCT20Maximum concurrent open exposure as % of working bankroll
MAX_TRADES_PER_DAY6Hard cap on daily execution count
MAX_POSITION_BANKROLL_PCT5Single-position cap as % of working bankroll
MIN_TRADE_USD0.25Minimum order size
MAX_TRADE_USD1.00Maximum order size
MIN_REWARD_RISK_RATIO1.5Planned take-profit / stop-loss ratio required for approval
MIN_EXECUTION_CONFIDENCE0.72Minimum signal confidence required to size and execute

Drawdown modes

The bankroll stage computes the current drawdown percentage as (peak_equity − equity) / peak_equity × 100 and maps it to a risk mode using hysteresis:
ModeMultiplierActivationRecovery
normal1.00DefaultN/A
reduced0.50drawdown_pct >= DRAWDOWN_TRIGGER_PCT (default 10%)Only at or below DRAWDOWN_RECOVERY_PCT (default 5%)
critical0.25drawdown_pct >= 2 × DRAWDOWN_TRIGGER_PCT (default 20%)Steps down to reduced when drawdown falls below 2 × DRAWDOWN_TRIGGER_PCT; returns to normal only at or below DRAWDOWN_RECOVERY_PCT
Recovery is hysteretic. When drawdown falls below the critical threshold (2 × DRAWDOWN_TRIGGER_PCT) but is still above DRAWDOWN_TRIGGER_PCT, the mode steps down from critical to reduced automatically. A complete return to normal requires the drawdown to fall to or below DRAWDOWN_RECOVERY_PCT from either reduced or critical. The multiplier is applied to the confidence-interpolated raw size before all other caps are evaluated. A critical multiplier of 0.25 effectively quarters the maximum trade size allowed by any other limit.

Daily profit reserve

When daily realized profit exceeds DAILY_PROFIT_RESERVE_TRIGGER_PCT (default 5%) of the day-start equity, DAILY_PROFIT_RESERVE_SHARE (default 50%) of the excess profit above that trigger is locked into a reserve. The reserve is excluded from working_bankroll and cannot be used for position sizing. It resets at UTC day rollover.
reserve = max(0.0, day_profit_usd - trigger_usd) * DAILY_PROFIT_RESERVE_SHARE
working_bankroll = max(0.0, equity - reserve)

Double enforcement: validate then execute

All caps are first evaluated at the validate stage using a shadow copy of the risk state. The shadow state is updated as decisions are processed in sequence, so later decisions in the same cycle see the reduced remaining caps from earlier approvals. This prevents the same daily capacity from being allocated to two decisions simultaneously. At the execute stage, a second independent check re-reads fresh files and re-evaluates every gate immediately before the PolyClaw subprocess is launched. A decision that was valid at validate time can still be blocked at execute time if conditions changed between the two stages.

Circuit breaker

The circuit breaker at trade_gate.py provides a manual emergency stop. Setting the environment variable PANIC_STOP=1 or creating the file panic_stop.flag in the runtime directory will halt all execution immediately. Neither can be reset automatically — operator action is required.PANIC_AUTO_THRESHOLD (default 0, disabled) auto-trips the circuit breaker after that many consecutive failed live orders. Set it to a small positive integer (e.g. 3) to add automatic protection against repeated submission failures.

Failed order handling

When a live order fails, PolyClaw Trading applies a cooldown to that market to prevent immediate retry:
  • FAILED_ORDER_COOLDOWN_SEC (default 1800 s = 30 min): After any failed live order, the affected market is blocked from new orders for this duration. Dry-run simulated orders do not trigger the cooldown.
  • Partial fill (partial_failure): A partial_failure status means PolyClaw returned exit code 0 but the output contained CLOB: Failed or CLOB sell failed. The market is added to registry["failed_attempts"], the cooldown is activated, and the pending order is flagged manual_cleanup_required. Do not retry a partial failure until you have manually inspected and cleaned up both outcome tokens in the wallet.
  • Slippage block (blocked_slippage): If the live public price exceeds max_entry_price (derived from MAX_ENTRY_SLIPPAGE_PCT), the order is blocked before the subprocess is called. This is also recorded as a failed attempt and the cooldown applies.
All execution attempts — including dry-run simulations, failures, and slippage blocks — are appended to runtime/executions/YYYYMMDD.json and the human-readable runtime/logs/YYYYMMDD.log.

Planned exits

For each approved decision, the validate stage computes planned stop and take-profit price levels:
stop_price        = max(0.0001, entry_price - STOP_LOSS_ATR_MULTIPLIER * atr14)
take_profit_price = min(0.9999, entry_price + TAKE_PROFIT_ATR_MULTIPLIER * atr14)
The default STOP_LOSS_ATR_MULTIPLIER is 1.5 and TAKE_PROFIT_ATR_MULTIPLIER is 2.5, giving a default planned reward-to-risk ratio of 2.5 / 1.5 ≈ 1.67, which meets the MIN_REWARD_RISK_RATIO of 1.5. These levels are persisted in the decision for later cycles. The engine never claims that native stop or take-profit orders were submitted to any exchange.

Build docs developers (and LLMs) love