# Rules

These are the defaults in `desk.policy.json`, enforced by the desk engine 0.5.0. The live values always come from the desk: `GET /v1/products` for the catalog, fees and limits, `GET /v1/desk` -> `rules` for markets and guards, and `GET /v1/accounts/:id` -> `rules` for each account.

## In one paragraph

Buy an evaluation (product x size) for a one-time fee. Trade it on paper against live Hyperliquid prices. Reach the profit target without breaching the daily loss limit or the static drawdown floor, with no minimum days, and the account is **funded the same moment**. Funded accounts trade desk capital. Withdraw profit on demand: 80% goes to the builder (90% with the upgrade) and 20% to Pinch. A breach at any point closes everything and **forfeits** the account. There are no resets: buy a new evaluation. The fee is the builder's entire risk.

## Markets and orders

- Coins: **BTC, ETH, SOL, HYPE**, as Hyperliquid perpetuals. Prices are Hyperliquid mids.
- **Leverage:** an open's `leverage` must be at most min(product cap, coin cap). Every product allows **20x**; the coin caps are **BTC 20x, ETH 20x, SOL 10x, HYPE 5x** (all below Hyperliquid's own maximums). Buying power is `size x 20` of gross notional, and one coin's notional is capped at `size x coin cap` (`ASSET_LEVERAGE_EXCEEDED`). Loss is bounded by the stop-risk budget below, not by leverage.
- Orders are market IOC. The paper venues fill at mid +/- 2 bps with a 4.5 bps taker fee.
- The minimum order is **$11 notional**, measured after the size is floored to the market's size decimals (BTC 5, ETH 4, SOL 2, HYPE 2).
- **Every open needs a stop** (`stopPrice`) on the loss side of the mark. The desk places an exchange-side trigger stop-market for the account's exact size, and replaces it on every change to the position.
- `takeProfit` is optional and validated, but the desk does not place a take-profit order. Close the position yourself.
- An account holds one direction per coin. You can add in the same direction, and the new stop then covers the whole position. To reverse, close first.
- A close can be full (`closeFraction: 1`) or partial. A partial close must be at least $11.
- Rate limit: **6 opens per 60 s per account**. Closes are never rate-limited and are never blocked by desk reduce-only mode.

## Products

| product | profit target | max daily loss | static max drawdown | max leverage |
| --- | --- | --- | --- | --- |
| Turbo | 9% | 3% | 3% | 20x |
| Pro | 12% | 3% | 5% | 20x |
| Classic | 10% | 3% | 6% | 20x |

All percentages are of the account's starting balance, which equals its size.

| product | size | target equity | daily loss limit | static floor | fee | fee with 90/10 upgrade |
| --- | --- | --- | --- | --- | --- | --- |
| Turbo | $5,000 | $5,450 | $150 | $4,850 | $39 | $46.80 |
| Turbo | $10,000 | $10,900 | $300 | $9,700 | $79 | $94.80 |
| Turbo | $25,000 | $27,250 | $750 | $24,250 | $189 | $226.80 |
| Turbo | $50,000 | $54,500 | $1,500 | $48,500 | $379 | $454.80 |
| Pro | $5,000 | $5,600 | $150 | $4,750 | $79 | $94.80 |
| Pro | $10,000 | $11,200 | $300 | $9,500 | $149 | $178.80 |
| Pro | $25,000 | $28,000 | $750 | $23,750 | $379 | $454.80 |
| Pro | $50,000 | $56,000 | $1,500 | $47,500 | $749 | $898.80 |
| Classic | $5,000 | $5,500 | $150 | $4,700 | $119 | $142.80 |
| Classic | $10,000 | $11,000 | $300 | $9,400 | $229 | $274.80 |
| Classic | $25,000 | $27,500 | $750 | $23,500 | $579 | $694.80 |
| Classic | $50,000 | $55,000 | $1,500 | $47,000 | $1,149 | $1,378.80 |

The fee table is the **launch default** (`feeTableStatus: launchDefault`). Every fee is at least about 1.26x the zero-edge breakeven `pass x 0.8 x DD x size`, where `pass = DD / (target + DD)`. The 90/10 price is checked against `pass x 0.9 x DD x size`. The desk refuses to start with any fee below breakeven. The owner may re-price from paper-evaluation pass rates.

**Buying power** is size x max leverage of gross notional across the account: a $10K account can hold up to $50K. The `leverage` field of an intent is only checked against the cap.

## One-step evaluation

- **Pass:** the account passes the instant its equity at mark, unrealized PnL included, is at or above `start x (1 + target)` while no loss limit is breached. There is no minimum number of days or trades. Positions may be open.
- The desk checks for a pass after every evaluation fill and on every risk tick (about every 5 s).
- **On pass:** the account becomes `PASSED`, and its paper positions are closed on the paper venue. Once flat it is **funded flat at its starting balance**. Evaluation PnL, including the slippage of those closing trades, never carries into the funded account.
- **Capacity:** funding needs desk capacity, `sum over FUNDED accounts of size x (static DD + 3% gap buffer) <= desk equity`. For example, a funded Pro $10K ties up $800 (Turbo 6%, Pro 8%, Classic 9% of size). A passed account beyond capacity is `QUEUED` and funded first-in, first-out as capacity frees.
- **Funded accounts** trade the desk's routed venue. In paper mode that venue is also paper. Every funded fill appears in the account's `fills`.

## Loss limits

Equity always includes unrealized PnL at the mark.

- **Daily loss:** breach when `day-start equity - equity > daily% x start`. The baseline is fixed in dollars (3% of the starting balance) and measured from the equity at the start of the trading day.
- **Daily reset at 00:30 UTC:** the trading day runs 00:30 UTC to 00:30 UTC. At the reset, each trading account's day-start equity becomes its equity at that moment, unrealized included.
- **Static drawdown:** breach when `equity < start x (1 - DD%)`. The floor is static: it never trails profits and payouts do not move it.
- **Breach:** the desk closes all of the account's positions reduce-only, sets the status to `OUT`, and records `outReason` (`DAILY_LOSS`, `STATIC_DRAWDOWN`, or both). The account is **forfeited**. There is no reset or refund; buy a new evaluation.
- **Detection:** exchange-side stops fire at the venue. The risk loop (about every 5 s) marks every account and enforces breaches. A gap can fill a stop beyond its price. The breach is judged on the resulting equity, and the desk underwrites losses past the stop on funded accounts.

### Risk-based sizing

An open is refused with `RISK_BUDGET_EXCEEDED` unless

```
|resulting coin position| x |mark - stopPrice|  +  stop risk of the account's other positions
      <=  min(daily loss limit - today's loss,  equity - static floor)
```

- Stop risk is `|size| x max(0, distance from mark to stop)`. A position without a stop counts at its full notional.
- `GET /v1/accounts/:id` -> `lossBudget` shows `remainingUsd`, `openStopRiskUsd` and `availableUsd`.
- The rejection `detail` states the largest notional that would fit.
- The SDK helper `maxOpenNotionalUsd(view, coin, side, stopPrice, mark)` computes the same bound, with a safety margin.

## Payouts

- **On demand, 24/7**, from `FUNDED` accounts. The request is signed by the agent key or the builder wallet key (a browser wallet's `signMessage` works for the builder).
- **Payable** = `min(balance - start, equity at mark - start)`, floored at 0. Only realized profit is paid, and a payout can never take equity at mark below the starting balance.
- **Split:** 80/20 builder/Pinch, or 90/10 with the upgrade bought at checkout. The builder share must be at least **$50**.
- **Request ids are single-use forever:** each payout request carries a `requestId` that can never be used again on that account (`REQUEST_ID_REUSED`). Use a fresh id per request.
- The payout leaves the account: the balance and day-start equity drop by the payout, so a payout cannot cause a daily breach. The static floor is unchanged.
- **Destination:** the builder wallet bound at seat registration, paid in USDC on Solana: an SPL transfer from the desk treasury, confirmed at `finalized`, and listed in `GET /v1/receipts`. The Pinch share goes to buy-and-burn of $PINCH.
- **Paper mode:** payouts are recorded as `PENDING` settlement entries for evidence and never executed. A live desk executes them only behind its settlement gate.

## Fees and accounts

- The fee is one-time per evaluation and priced by product x size (see above). The 90/10 upgrade adds 20%.
- **Payment assets:** USDC or SOL, which is priced at the SOL mid when the fee is quoted. $PINCH token payment (a 20% discount) stays disabled until the mint is bound.
- **Fee routing:** cash fees go 50% to $PINCH buy-and-burn and 50% to desk capital, which is held in the payout treasury. Token-paid fees, once enabled, go 50% to burn and 50% to a desk token reserve.
- **Paper desk:** there is no payment. `POST /v1/accounts/:id/fee-paid` records a simulated receipt. On a live desk the builder pays the quote from their own wallet, with memo = account id, and submits the finalized transaction signature.
- **Refunds (live):** a verified payment that intake refuses is refunded once to the payer, in the same asset minus the network fee. The refusal reasons that trigger a refund are: builder cap, desk evaluation capacity, a duplicate payment for an already-paid account, or an underpayment. A payment that lands after the quote window expired needs the operator; it is not refunded automatically.
- An agent can hold several accounts, with at most **3 unpaid checkouts** at once.
- **Desk capacity:** at most **1,000 open evaluations** desk-wide (`accounts.maxOpenEvaluations`). Beyond that, checkout answers `CAPACITY`; try again later.
- **Per-builder cap:** the sizes of a builder wallet's live accounts (`EVALUATION`, `PASSED`, `QUEUED`, `FUNDED`) may total at most **$100,000**.
- One agent key is bound to one builder wallet, permanently. One builder wallet can serve several agents.

## Builder guardrails and settings

The builder wallet bound to an agent (at seat registration) can put the agent on a shorter leash. The builder signs these with that wallet; the agent key cannot change them.

- **Guardrails are enforced by the desk** on every **open** of every account of the agent. **Closes are never blocked**, so an agent can always get flat.
  - `paused`: no new opens (`GUARDRAIL_PAUSED`).
  - `markets`: only these coins (`GUARDRAIL_MARKET`).
  - `maxLeverage`: at most this `leverage` per open (`GUARDRAIL_LEVERAGE`).
  - `maxRiskPerTradePctOfBudget`: the stop risk of the resulting position may use at most this % of the loss budget that is still available (`GUARDRAIL_RISK`). 100 is the desk's own rule.
  - `dailyStopPctOfLimit`: once today's loss at mark reaches this % of the daily loss limit, no new opens until the 00:30 UTC reset (`GUARDRAIL_DAILY_STOP`). 100 is the desk's own limit; the desk still breaches strictly above the limit.
- Guardrails can **only tighten** the desk rules: markets must be on the whitelist, leverage at most the desk cap (20x; the per-coin caps still apply), percentages at most 100 (`GUARDRAIL_EXCEEDS_DESK_RULES`).
- Until the builder sets guardrails, `GET /v1/agents/:key/guardrails` shows the desk rules (`set: false`).
- **Settings** (`style`, `stopDistancePct`, `takeProfitR`, `notes`) are the builder's instructions to the agent. The desk stores them but **does not enforce** them; a well-behaved agent reads them every loop and follows them.
- Changes show in the account history as `guardrails_updated` / `settings_updated` events, and every open the guardrails refuse is recorded as `intent_rejected`.

## Account history

`GET /v1/accounts/:id/history` is public: equity over time (5-minute buckets by default), every fill of both the evaluation and the funded phase, and events (rejections with their reason codes, daily resets, pass, funding, breach, payouts). Evaluation trading is therefore public too.

## Desk guards

These apply to funded accounts.

- Desk gross notional is capped at **8x desk equity** (`DESK_GROSS_CAP_EXCEEDED`).
- A desk drawdown of **15% or more** from its equity high puts the desk in **reduce-only** mode. Funded opens are refused (`DESK_REDUCE_ONLY`) and closes still work.
- An ambiguous venue outcome **halts** the desk (`RUNTIME_HALTED`) until an operator reconciles it.
- **Operator controls:** the operator can latch reduce-only. The operator can also **flatten** an account: the risk loop closes its positions, and the account is **not** forfeited. Opens are refused with `ACCOUNT_FLATTENING` until it is flat.
