Risk engine
The risk engine is one pure function, plan(target, context), in engine/risk.mjs. It takes what the model asked for and the state of the book, and returns the orders that may be sent, the refusals with their reasons, and notes. It makes no network call and reads no setting the model can reach.
Rules and their default values
| Rule | Default | Effect |
|---|---|---|
maxWeight | 35% | One stock never holds more than this share of the book. |
minCash | 10% | The total asked is scaled down until this share stays in USDG. |
minOrderUsd | $5 | No dust orders. |
minDeltaPct | 2% | A change smaller than this share of the book is ignored. |
maxTurnover | 25% | Buys are shrunk so one cycle trades at most this share of the book. Sells are never shrunk. |
maxImpactPct | 0.6% | An order that would move its pool more than this is cut to fit, or refused. |
maxTwapDevPct | 1.0% | A stock whose spot price is more than this far from its 5 minute average is not traded: the pool may be being pushed. |
slippagePct | 1.2% | Minimum output on every swap, so a price that moved reverts the swap. |
cooldownMin | 30 | A stock that just traded is not bought or trimmed again until this has passed. Closing a position is always allowed. |
noBuyWeekend | true | No new buys from Friday 20:00 to Sunday 20:00 ET, nor on NYSE holidays. |
dailyLossPct | 7% | After a day this bad, no new buys until tomorrow. |
drawdownBreaker | 15% | Sell everything, pause, wait for a human. |
How an answer is processed
- Clean. Weights that are not numbers or are negative become zero. Each weight is capped at
maxWeight. If the sum exceeds1 - minCash, all weights are scaled down together. - Compare with the current weights. Differences under
minDeltaPctare dropped. Differences worth less thanminOrderUsdare refused. - Check the price. If spot is more than
maxTwapDevPctaway from the 5 minute average, the stock is skipped. - Check the context. Weekend and daily loss block buys. Cooldown blocks a stock.
- Cap turnover, shrinking buys only.
- Limit buys to the cash that exists, counting the proceeds of the sells in the same cycle.
- Measure impact for each order from the pool depth. Cut the order to fit under
maxImpactPct, or refuse it if what is left is underminOrderUsd.
The order of sells and buys in the output is sells first, so the proceeds exist when the buys are sent.
The breaker
The breaker is checked before the model is consulted. It watches the time-weighted index of the book, which ignores deposits, so a deposit never hides a drawdown and a withdrawal never creates one. When the index is 15% under its high, the engine sells every position in that cycle, writes the reason, and sets the agent to paused. A paused agent never resumes by itself.
Price impact is a first-order estimate
The impact of an order is computed from the pool's current liquidity and price, inside the current tick range. A swap that crosses into a different range would move the price more than estimated. That is why every swap also carries a minimum-output guard: the estimate keeps the orders small, the guard makes a bad fill revert.
Run it yourself
The site's playground imports the same risk.mjs file and runs it in your browser on the live depths. The unit tests call plan with synthetic books and check each rule.