Install
openclaw skills install vincent-trade-managerAutomates stop-loss, take-profit, and trailing stop orders on Polymarket positions by monitoring prices in real-time and executing trades when triggered.
openclaw skills install vincent-trade-managerUse this skill to create automated trading rules (stop-loss, take-profit, trailing stop) for your Polymarket positions. The Trade Manager runs as part of the Vincent backend and automatically executes trades when price conditions are met.
All commands use the @vincentai/cli package.
Trade Manager is a companion to the Polymarket skill:
Architecture:
/api/skills/polymarket/rules/...Before creating rules, verify the monitoring worker is running:
npx @vincentai/cli@latest trade-manager health
# Expected: {"status":"ok","version":"0.1.0"}
npx @vincentai/cli@latest trade-manager status --key-id <KEY_ID>
# Returns: worker status, active rules count, last sync time, circuit breaker state
Automatically sell a position if price drops below a threshold:
npx @vincentai/cli@latest trade-manager create-rule --key-id <KEY_ID> \
--market-id 0x123... --token-id 456789 \
--rule-type STOP_LOSS --trigger-price 0.40
Parameters:
--market-id: The Polymarket condition ID (from market data)--token-id: The outcome token ID you hold (from market data — use the token ID you bought)--rule-type: STOP_LOSS (sells if price <= trigger), TAKE_PROFIT (sells if price >= trigger), or TRAILING_STOP--trigger-price: Price threshold between 0 and 1 (e.g., 0.40 = 40 cents)The CLI automatically passes {"type": "SELL_ALL"} as the action (only supported type in MVP).
Automatically sell a position if price rises above a threshold:
npx @vincentai/cli@latest trade-manager create-rule --key-id <KEY_ID> \
--market-id 0x123... --token-id 456789 \
--rule-type TAKE_PROFIT --trigger-price 0.75
Pro tip: Create both a stop-loss AND take-profit on the same position to bracket your trade.
A trailing stop starts with a stop price, then automatically moves that stop price up as price rises.
npx @vincentai/cli@latest trade-manager create-rule --key-id <KEY_ID> \
--market-id 0x123... --token-id 456789 \
--rule-type TRAILING_STOP --trigger-price 0.45 --trailing-percent 5
Trailing stop behavior:
--trailing-percent is percent points (for example 5 means 5%)candidateStop = currentPrice * (1 - trailingPercent/100)candidateStop is above the current triggerPrice, it updates triggerPricetriggerPrice never moves downcurrentPrice <= triggerPrice# All rules
npx @vincentai/cli@latest trade-manager list-rules --key-id <KEY_ID>
# Only active rules
npx @vincentai/cli@latest trade-manager list-rules --key-id <KEY_ID> --status ACTIVE
# Only triggered rules
npx @vincentai/cli@latest trade-manager list-rules --key-id <KEY_ID> --status TRIGGERED
npx @vincentai/cli@latest trade-manager update-rule --key-id <KEY_ID> --rule-id <RULE_ID> --trigger-price 0.45
npx @vincentai/cli@latest trade-manager delete-rule --key-id <KEY_ID> --rule-id <RULE_ID>
The rule status changes to "CANCELED" and won't trigger anymore.
See what positions the Trade Manager is currently tracking:
npx @vincentai/cli@latest trade-manager positions --key-id <KEY_ID>
Returns cached position data with current prices. This cache updates via WebSocket and periodic polling.
See detailed history of rule evaluations and executions:
# All events (most recent first, default limit=100)
npx @vincentai/cli@latest trade-manager events --key-id <KEY_ID>
# Events for specific rule
npx @vincentai/cli@latest trade-manager events --key-id <KEY_ID> --rule-id <RULE_ID>
# Paginated results
npx @vincentai/cli@latest trade-manager events --key-id <KEY_ID> --rule-id <RULE_ID> --limit 50 --offset 100
Event types:
RULE_CREATED - Rule was createdRULE_TRAILING_UPDATED - Trailing stop moved triggerPrice upwardRULE_EVALUATED - Worker checked the rule against current priceRULE_TRIGGERED - Trigger condition was metACTION_PENDING_APPROVAL - Trade requires human approval, rule pausedACTION_EXECUTED - Trade executed successfullyACTION_FAILED - Trade execution failedRULE_CANCELED - Rule was manually canceledEach event includes a data object with fields relevant to the event type:
currentPrice - Price at time of evaluationtriggerPrice - The rule's trigger thresholdshouldTrigger - Whether the condition was metsource - "websocket" for real-time WebSocket updates, absent for polling-based evaluationsHere's how to use both skills together:
# Search for a market
npx @vincentai/cli@latest polymarket markets --key-id <KEY_ID> --query bitcoin
# Place a bet on "Yes" outcome
npx @vincentai/cli@latest polymarket bet --key-id <KEY_ID> --token-id 123456789 --side BUY --amount 10 --price 0.55
# You bought 18.18 shares at 55 cents
# Protect your position with a 40 cent stop-loss
npx @vincentai/cli@latest trade-manager create-rule --key-id <KEY_ID> \
--market-id 0xabc... --token-id 123456789 \
--rule-type STOP_LOSS --trigger-price 0.40
# Lock in profit if price hits 85 cents
npx @vincentai/cli@latest trade-manager create-rule --key-id <KEY_ID> \
--market-id 0xabc... --token-id 123456789 \
--rule-type TAKE_PROFIT --trigger-price 0.85
# Check status
npx @vincentai/cli@latest trade-manager list-rules --key-id <KEY_ID> --status ACTIVE
# Check recent events
npx @vincentai/cli@latest trade-manager events --key-id <KEY_ID>
ACTIVE to TRIGGERED atomically (prevents double-execution)RULE_TRIGGERED and ACTION_EXECUTED eventsImportant: Executed trades still go through Vincent's policy enforcement. If your trade violates a spending limit or requires approval, the Trade Manager respects those policies.
ACTIVE - Rule is live and being monitoredTRIGGERED - Condition was met, trade executed (or attempted)PENDING_APPROVAL - Trade requires human approval; rule is paused until the approval is granted or deniedCANCELED - Rule was manually canceled before triggeringFAILED - Rule triggered but trade execution failedEXPIRED - (Future feature for time-based expiration)The Trade Manager runs a background worker that:
Circuit Breaker: If the Polymarket API fails 5+ consecutive times, the worker pauses. It resumes after a cooldown period. Check worker status:
npx @vincentai/cli@latest trade-manager status --key-id <KEY_ID>
Look for consecutiveFailures: 0 (healthy) or a circuitBreakerUntil timestamp (paused due to errors).
400 Bad Request - Invalid trigger price: Fix: Use prices between 0.01 and 0.99
400 Bad Request - Missing required field: Fix: Include all required flags (--market-id, --token-id, --rule-type, --trigger-price)
404 Not Found - Rule doesn't exist: Fix: Check the rule ID is correct
Failed rule execution:
The rule status will be FAILED with an errorMessage field explaining what went wrong. Common causes:
Check the event log for details:
npx @vincentai/cli@latest trade-manager events --key-id <KEY_ID> --rule-id <RULE_ID>
SELL_PARTIAL) coming in v2SELL_ALL action (no partial sells yet)When a user says:
--status ACTIVE/api/skills/polymarket/rules/...