Guards & Risk
Guards are pre-execution safety checks that run inside each UTA before orders reach the broker. They enforce risk limits automatically, catching mistakes before they become trades.
How Guards Work
When you push a commit, the guard pipeline:
- Fetches current positions and account info from the broker
- Builds a
GuardContextwith the operation, positions, and account data - Runs each guard sequentially — first rejection wins
- If all guards pass, the operation is dispatched to the broker
- If any guard rejects, the operation fails with a clear reason
tradingPush → Guard Pipeline → Broker
│
├── max-position-size ✓
├── cooldown ✓
└── symbol-whitelist ✗ "DOGE not in whitelist"
→ Operation rejected
Built-in Guards
max-position-size
Prevents any single position from exceeding a percentage of your total equity. Default threshold: 25%.
{
"type": "max-position-size",
"options": { "maxPercentOfEquity": 20 }
}
The guard estimates the projected position value after the order and compares it to net liquidation. If the projected size exceeds the threshold, the order is rejected:
[guard:max-position-size] Position for NVDA would be 32.5% of equity (limit: 20%)
cooldown
Enforces a minimum time between trades on the same symbol, preventing impulsive rapid-fire trading.
{
"type": "cooldown",
"options": { "minutes": 5 }
}
symbol-whitelist
Restricts trading to a predefined list of symbols.
{
"type": "symbol-whitelist",
"options": { "symbols": ["AAPL", "MSFT", "GOOGL", "NVDA", "TSLA"] }
}
Any order for a symbol not in the list is rejected immediately.
Configuring Guards
Guards are configured per-account in data/config/accounts.json:
{
"id": "alpaca-paper",
"type": "alpaca",
"enabled": true,
"guards": [
{ "type": "max-position-size", "options": { "maxPercentOfEquity": 15 } },
{ "type": "cooldown", "options": { "minutes": 10 } },
{ "type": "symbol-whitelist", "options": { "symbols": ["AAPL", "MSFT"] } }
],
"brokerConfig": { ... }
}
Guards are resolved from the registry at account init time. Unknown guard types are skipped with a warning.
Guard Categories
Each broker type declares a guard category:
| Broker | Category |
|---|---|
| CCXT | crypto |
| Alpaca | securities |
| IBKR | securities |
This categorization is available for guard implementations that need to behave differently for crypto vs traditional securities.
Rejection Flow
When a guard rejects an operation during push:
- The operation result is recorded as
rejectedwith the guard name and reason - The commit is still recorded in the git history (with rejection details)
- Alice sees the rejection reason and can adjust her approach
This means rejected trades are part of the audit trail — you can always trace why something was blocked.
Custom Guards
You can create custom guards by implementing the OperationGuard interface and registering them. See Custom Guards for a step-by-step guide.