The core of Clawster is a 10-step loop executed each cycle — triggered by cron, heartbeat, or manual command.
Read ### Clawster Config from TOOLS.md. Apply defaults for any missing parameters. See Configuration for all options.
Read aster-api-account-v1 skill, call GET /fapi/v2/balance. Record available balance. If balance is zero or API fails, abort cycle.
Call GET /fapi/v1/positionRisk. Reconcile with memory/clawster-state.json. If positions exist on-chain but not in state, adopt them at MONITORING state.
Read memory/clawster-state.json. If dailyPnL loss exceeds daily_loss_pct of balance → stop trading, log reason, skip to step 10.
If cooldownUntil is set and hasn't expired → skip to step 10. Existing positions continue to be managed.
If dailyTradeCount >= max_daily_trades → skip to step 10.
Read aster-api-market-data-v1 skill. For each configured trading pair, fetch:
- Current price (
GET /fapi/v1/ticker/price) - Klines/candlesticks (
GET /fapi/v1/klines) - Funding rate (
GET /fapi/v1/fundingRate) - Order book depth (
GET /fapi/v1/depth)
If strategy_prompt is set, use it as the decision framework. Otherwise, apply the built-in strategy. Produce one of:
- LONG signal with entry price, SL, TP
- SHORT signal with entry price, SL, TP
- NO_TRADE — no setup found
If a signal was generated:
- Validate against risk rules (position size, max concurrent, drawdown)
- Read
aster-api-trading-v1for order placement - Set leverage (
POST /fapi/v1/leverage) - Place entry order (
POST /fapi/v1/order) - Once filled, place SL and TP orders immediately
- Log trade to
memory/trade-log.jsonl
Write current state to memory/clawster-state.json:
- Open positions and their states
- Daily PnL running total
- Daily trade count
- Consecutive loss counter
- Cooldown timer (if active)
┌────────────┐
│ ANALYZING │ ← Market data evaluation
└─────┬──────┘
│ signal found
▼
┌────────────┐
│ENTRY_SIGNAL│ ← Risk validation
└─────┬──────┘
│ passes risk checks
▼
┌────────────┐
│ORDER_PLACED│ ← Waiting for fill
└─────┬──────┘
│ filled
▼
┌─────────────┐
│POSITION_OPEN│ ← Set SL/TP orders
└─────┬───────┘
│ SL/TP placed
▼
┌────────────┐
│ MONITORING │ ← Track price, adjust stops
└─────┬──────┘
│ exit condition met
▼
┌────────────┐
│EXIT_SIGNAL │ ← Place close order
└─────┬──────┘
│ close order placed
▼
┌────────────┐
│ CLOSING │ ← Waiting for close fill
└─────┬──────┘
│ filled
▼
┌────────────┐
│ CLOSED │ ← Log PnL, update stats
└────────────┘
At any state, if the order is rejected or times out, the position moves to error recovery (see below).
The agent makes decisions based on:
- Market data — price action, volume, indicators derived from klines
- Strategy rules — either the built-in strategy or
strategy_prompt - Current exposure — existing positions, unrealized PnL
- Risk constraints — position limits, daily loss, drawdown
The strategy produces a signal with conviction level. Low conviction signals may be skipped. The agent explains its reasoning in trade logs.
| Order Type | When Used |
|---|---|
| Limit | Default for entries (better fill price) |
| Market | When immediate execution needed, or for emergency closes |
| Stop Market | Stop loss orders |
| Take Profit Market | Take profit orders |
Orders are monitored via GET /fapi/v1/openOrders. If an entry order isn't filled within the expected timeframe, it's canceled and the signal is discarded.
| Scenario | Action |
|---|---|
| Order rejected | Read reason, adjust size/price, retry once. If still rejected, skip. |
| API timeout | Wait 5s, retry up to 3 times. |
| Rate limited | Follow backoff rules from aster-api-errors-v1. |
| Position without SL/TP | Place missing orders immediately on detection. |
| Balance insufficient | Log warning, skip trade, continue monitoring existing positions. |
| Unknown error | Log full details, skip trade, continue loop. |
See Memory & State for how the agent recovers after a restart.