Files
polymarket-terminal/.env.example
T
direkturcryptoandClaude Sonnet 4.6 89a7803aa8 feat(oneshot): add auto-redemption via RedeemEngine
When a position's market expires, RedeemEngine automatically polls the
CTF contract and redeems the winning position on-chain — no manual redeem needed.

Flow:
  1. expirePosition() queues the expired position into RedeemEngine
  2. RedeemEngine polls every 30s (ONESHOT_REDEEM_POLL_MS)
  3. Checks Gamma API first, then CTF.payoutDenominator() on-chain
  4. When settled: emits redemption:complete event with final P&L
  5. Orchestrator passes P&L to RiskEngine

DRY_RUN=true: simulates by reading on-chain payouts and logging win/loss
DRY_RUN=false: submits real redeemPositions() tx on Polygon (gasLimit 300k)

Also stores conditionId and negRisk in PositionEngine state so the
expired position has all data needed for redemption without extra lookups.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 14:20:57 +07:00

199 lines
9.4 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ─────────────────────────────────────────────
# WALLET SETUP
# ─────────────────────────────────────────────
# EOA private key — used for SIGNING only, does NOT hold USDC
PRIVATE_KEY=0xYOUR_EOA_PRIVATE_KEY_HERE
# Polymarket Proxy Wallet — the address shown when you click "Deposit" on Polymarket
# This is where you deposit USDC.e, and where trades are funded from
# How to find: Login to polymarket.com → Profile → Deposit → copy the address
PROXY_WALLET_ADDRESS=0xYOUR_PROXY_WALLET_ADDRESS_HERE
# ─────────────────────────────────────────────
# POLYGON RPC
# ─────────────────────────────────────────────
POLYGON_RPC_URL=https://polygon.lava.build
# ─────────────────────────────────────────────
# POLYMARKET API CREDENTIALS (optional)
# Leave blank to auto-derive from your private key
# ─────────────────────────────────────────────
CLOB_API_KEY=
CLOB_API_SECRET=
CLOB_API_PASSPHRASE=
# ─────────────────────────────────────────────
# TRADER TO COPY
# Use the proxy wallet address of the trader (visible on their Polymarket profile)
# ─────────────────────────────────────────────
TRADER_ADDRESS=0xTRADER_PROXY_WALLET_ADDRESS
# ─────────────────────────────────────────────
# TRADE SIZING
# ─────────────────────────────────────────────
# SIZE_MODE:
# "percentage" = SIZE_PERCENT% of MAX_POSITION_SIZE per market entry
# (e.g. MAX_POSITION_SIZE=$10, SIZE_PERCENT=50 → buy $5 per entry)
# "balance" = SIZE_PERCENT% of your current USDC.e balance per entry
# (e.g. balance=$100, SIZE_PERCENT=10 → buy $10 per entry)
# Note: sizing is independent of the trader's individual fill size.
# Limit orders can fill in many small chunks — we always use our own sizing.
SIZE_MODE=balance
SIZE_PERCENT=10
# Minimum trade size in USDC (skip if calculated size is below this)
MIN_TRADE_SIZE=1
# Maximum total position per market in USDC (won't buy more once this is reached)
MAX_POSITION_SIZE=10
# ─────────────────────────────────────────────
# AUTO SELL
# ─────────────────────────────────────────────
AUTO_SELL_ENABLED=true
AUTO_SELL_PROFIT_PERCENT=10
# Sell mode when copying trader's sell
# "market" = sell at market price immediately
# "limit" = place limit order at trader's sell price
SELL_MODE=market
# ─────────────────────────────────────────────
# INTERVALS
# ─────────────────────────────────────────────
# How often (seconds) to check for resolved markets to redeem
REDEEM_INTERVAL=60
# ─────────────────────────────────────────────
# DRY RUN (set true to simulate without real trades)
# ─────────────────────────────────────────────
DRY_RUN=true
# ─────────────────────────────────────────────
# MARKET MAKER (mm.js / npm run mm-sim)
# ─────────────────────────────────────────────
# Comma-separated assets to market-make (same slug format as sniper)
MM_ASSETS=btc
# Market duration: "5m" (5-minute) or "15m" (15-minute)
MM_DURATION=5m
# USDC amount per side (total exposure = 2x this)
MM_TRADE_SIZE=5
# Limit sell price target (e.g. 0.60 = sell at $0.60)
MM_SELL_PRICE=0.60
# Seconds before market close to trigger cut-loss
MM_CUT_LOSS_TIME=60
# Keyword to match market question (case-insensitive)
MM_MARKET_KEYWORD=Bitcoin Up or Down
# Max seconds after market open to enter (0 = at open only)
MM_ENTRY_WINDOW=45
# How often to poll for new markets (seconds)
MM_POLL_INTERVAL=10
# ── Recovery Buy (after cut-loss) ───────────────────────────
# After cut-loss triggers, monitor prices for 10s and market-buy
# the dominant side if criteria are met. Does not affect the main
# MM flow — purely an opt-in add-on.
#
# Enable recovery buy
MM_RECOVERY_BUY=false
# Minimum price the dominant side must be at (and rising/stable) to qualify
MM_RECOVERY_THRESHOLD=0.70
# USDC size for the recovery buy (0 = use MM_TRADE_SIZE)
MM_RECOVERY_SIZE=0
# ─────────────────────────────────────────────
# ORDERBOOK SNIPER (sniper.js / npm run sniper-sim)
# Places tiny GTC BUY orders at a low price on both sides of
# ETH/SOL/XRP 5-minute markets — catches panic dumps near $0.
# ─────────────────────────────────────────────
# Comma-separated assets to snipe
SNIPER_ASSETS=eth,sol,xrp
# Buy price per share (1 cent = $0.01)
SNIPER_PRICE=0.01
# Shares per side — minimum Polymarket order size is 5 shares
# At $0.01/share: 5 shares = $0.05 per side, $0.10 per market
SNIPER_SHARES=5
# ─────────────────────────────────────────────
# ONESHOT ENGINE (oneshot.js / npm run oneshot-sim)
# Dominant Side Hold strategy.
# Enters ONLY the side that the market already prices as the probable
# winner (mid >= ONESHOT_MIN_DOMINANT_MID), then holds the position
# to market expiry for on-chain redemption at $1.00.
# No take-profit sells. No momentum-based exits.
# ALWAYS test with DRY_RUN=true before going live.
# ─────────────────────────────────────────────
# Comma-separated assets to monitor (e.g. btc,eth,sol)
ONESHOT_ASSETS=btc
# Market duration: "5m" (5-minute) or "15m" (15-minute)
ONESHOT_DURATION=5m
# Book poll interval in milliseconds (200500ms recommended)
ONESHOT_POLL_INTERVAL_MS=300
# USDC risk per trade — size = floor(ONESHOT_BASE_RISK_USDC / entryPrice), min 5 shares
ONESHOT_BASE_RISK_USDC=5
# ── Entry filters ──────────────────────────────────────────────────────
# Minimum mid price for the dominant side to qualify as an entry candidate.
# Example: 0.60 means the token must be priced at ≥60% probability of winning.
# Lower = more trades but more uncertain outcomes. Higher = fewer but more confident.
ONESHOT_MIN_DOMINANT_MID=0.60
# Minimum composite score to trigger entry (01).
# Score is based on: mid price strength (45%), order-book imbalance (35%), spread (20%).
ONESHOT_SCORE_THRESHOLD=0.55
# TTE (time-to-expiry) window in seconds for entry.
# Only enter when the market is between TTE_MIN and TTE_MAX seconds from closing.
# Narrowing this window means entering later when direction is clearer.
ONESHOT_TTE_MIN=20
ONESHOT_TTE_MAX=90
# Minimum shares at the best bid AND best ask for the depth hard gate
ONESHOT_MIN_TOP_SIZE=10
# ── Exit settings ──────────────────────────────────────────────────────
# Emergency stop-loss: exit if the token's mid price drops below this absolute level.
# Protects against a complete market reversal (e.g. entered UP at 0.70, price drops to 0.18).
# Set to 0 to disable (pure hold-to-expiry — binary win/loss outcome).
ONESHOT_STOP_LOSS_MID=0.20
# ── Risk settings ──────────────────────────────────────────────────────
# Number of consecutive emergency exits (losses) before entering cooldown
ONESHOT_MAX_CONSEC_LOSSES=2
# Number of market slots to skip during cooldown
ONESHOT_COOLDOWN_ROUNDS=3
# Maximum cumulative daily loss in USDC before halting all trading
ONESHOT_DAILY_LOSS_CAP=20
# Maximum milliseconds to wait for a FOK fill ack (timeout → cancel → IDLE)
ONESHOT_FILL_TIMEOUT_MS=800
# How often (ms) to poll for on-chain redemption after market expiry.
# 5m markets typically settle on-chain within 25 minutes after close.
ONESHOT_REDEEM_POLL_MS=30000
# Enable verbose debug logging (discovery probes, gate results, scoring, heartbeat)
# Can also be enabled with: npm run oneshot-debug
# Or on the command line: ONESHOT_DEBUG=true npm run oneshot
ONESHOT_DEBUG=false