Exits that stay inside a price bound
Sell rules that land when the market moves fast without accepting any price. Every order states its slippage; a reverted sale widens only up to a ceiling you set.
Status
rout-next/src/domain/capabilities.ts:44-45 · rout-automation-ui@61469bfUnlimited slippage gets a sale through, at whatever price the curve has moved to by then. Rout has no such setting. Every buy names order.slippage_bps, between 1 and 10000. Every sale names a start_bps and a max_bps.
How a sale's tolerance moves
| Attempt | Tolerance |
|---|---|
| First | start_bps |
| After a revert | Doubled, capped at max_bps |
start_bps == max_bps | Never widens |
start_bps must be at least 1 and at most max_bps; max_bps at most 10000 (BadExit otherwise). Source: sniper-definition.d.ts:1975-1986.
Two exits from one example
The first rule (then: one condition, then the next) sells everything when the price has gained at least 200% (20000 bps) within 150 slots and the developer then sells at least 1 SOL within 30 slots. It is built at 15%, may widen to 50%, and pays its own 0.01 SOL tip to land ahead of others leaving. The second sells when at least two of its warning signs hold.
{
"proceeds": "native",
"rules": [
{
"name": "pumped-and-the-dev-is-out",
"firing": "once",
"when": {
"then": [
{
"gain": {
"at_least_bps": 20000,
"window_slots": 150
}
},
{
"dev_sold": {
"venues": "any",
"executed_quote": {
"mint": "So11111111111111111111111111111111111111112",
"range": {
"at_least": 1000000000,
"at_most": null
}
},
"share_of_dev_holding_bps": null,
"window_slots": 30
}
}
]
},
"sell": {
"amount": "all",
"slippage": {
"start_bps": 1500,
"max_bps": 5000
},
"tip_lamports": 10000000
}
},
{
"name": "two-red-flags",
"firing": "once",
"when": {
"at_least": {
"count": 2,
"of": [
{
"creator_claimed_fees": {
"venues": "any",
"window_slots": 300
}
},
{
"wallet_sell": {
"wallets": [
"FnU15cRgfeCtJXUQyN4TbGHEjTnTHHSynMRLUKxzLaJQ",
"9m2JeFfBcu7u3DTz3DZCuwprwL5cB5HKzyw6eXtzYMYk"
],
"floor": {
"mint": "So11111111111111111111111111111111111111112",
"raw": 2000000000
},
"window_slots": 600
}
},
{
"liquidity": {
"quote_mint": "So11111111111111111111111111111111111111112",
"bounds_raw": {
"at_least": null,
"at_most": 10000000000
},
"window_slots": 150
}
}
]
}
},
"sell": {
"amount": {
"of_held_bps": 5000
},
"slippage": {
"start_bps": 1000,
"max_bps": 4000
}
}
},
{
"name": "exactly-one-of-two-tops",
"firing": "once",
"when": {
"exactly": {
"count": 1,
"of": [
{
"drawdown_from_peak": {
"at_least_bps": 2000,
"window_slots": 150
}
},
{
"market_cap": {
"bounds_usd_micros": {
"at_least": 2000000000000,
"at_most": null
},
"window_slots": 150
}
}
]
}
},
"sell": {
"amount": {
"of_entry_bps": 3000
},
"slippage": {
"start_bps": 800,
"max_bps": 3000
}
}
},
{
"name": "quiet-unless-a-whale-sold",
"firing": "once",
"when": {
"all": [
{
"held_for": {
"slots": 4500
}
},
{
"at_most": {
"count": 0,
"of": [
{
"wallet_sold": {
"wallets": [
"496xjaVmVpuDDv7WcJAKb1JCcS1AVr8DsX54eGS77MFt"
],
"size": {
"mint": "So11111111111111111111111111111111111111112",
"range": {
"at_least": 1,
"at_most": null
}
},
"window_slots": 4500
}
}
]
}
},
{
"not": {
"price": {
"quote_mint": "So11111111111111111111111111111111111111112",
"quote_raw_per_whole_token": {
"at_least": 100,
"at_most": null
},
"window_slots": 150
}
}
}
]
},
"sell": {
"amount": "initials",
"slippage": {
"start_bps": 500,
"max_bps": 2000
}
}
},
{
"name": "buy-signals-sell-too",
"firing": "once",
"when": {
"any": [
{
"bonded": {
"venues": "any",
"window_slots": 10
}
},
{
"tradable": {
"venues": {
"one_of": [
"pump-swap"
]
},
"window_slots": 10
}
},
{
"dev_bought": {
"venues": "any",
"executed_quote": {
"mint": "So11111111111111111111111111111111111111112",
"range": {
"at_least": 5000000000,
"at_most": null
}
},
"window_slots": 10
}
},
{
"creator_fees_distributed": {
"venues": {
"one_of": [
"pump-fun"
]
},
"recipients": [
"FnU15cRgfeCtJXUQyN4TbGHEjTnTHHSynMRLUKxzLaJQ"
],
"total": {
"mint": "So11111111111111111111111111111111111111112",
"range": {
"at_least": 0,
"at_most": null
}
},
"window_slots": 10
}
},
{
"wallet_bought": {
"wallets": [
"FnU15cRgfeCtJXUQyN4TbGHEjTnTHHSynMRLUKxzLaJQ"
],
"size": {
"mint": "So11111111111111111111111111111111111111112",
"range": {
"at_least": null,
"at_most": 10000000
}
},
"window_slots": 10
}
},
{
"wallet_buy": {
"wallets": [
"9m2JeFfBcu7u3DTz3DZCuwprwL5cB5HKzyw6eXtzYMYk"
],
"floor": {
"mint": "So11111111111111111111111111111111111111112",
"raw": 10000000000
},
"window_slots": 300
}
},
{
"wallet_quorum": {
"wallets": [
"FnU15cRgfeCtJXUQyN4TbGHEjTnTHHSynMRLUKxzLaJQ",
"9m2JeFfBcu7u3DTz3DZCuwprwL5cB5HKzyw6eXtzYMYk"
],
"quorum": 2,
"size": {
"mint": "So11111111111111111111111111111111111111112",
"range": {
"at_least": 1000000000,
"at_most": null
}
},
"window_slots": 150
}
},
{
"mint_venue_creation": {
"venues": "any",
"seen": "executed",
"launch": null,
"window_slots": 10
}
}
]
},
"sell": {
"amount": {
"of_held_bps": 1000
},
"slippage": {
"start_bps": 500,
"max_bps": 2000
}
}
},
{
"name": "either-stop",
"firing": {
"repeat": {
"limit": {
"up_to": 2
},
"cooldown_seconds": 60
}
},
"when": {
"any": [
{
"loss": {
"at_least_bps": 3000,
"window_slots": 150
}
},
{
"graduated": {
"venues": "any",
"step": "curve_completed",
"window_slots": 10
}
}
]
},
"sell": {
"amount": {
"of_entry_bps": 2500
},
"slippage": {
"start_bps": 1500,
"max_bps": 5000
}
}
}
]
}Limits that stop the bleeding
| Limit | What it does |
|---|---|
max_spend_per_day_raw | The most buys may spend in any 24 hours. A buy that didn't land counts nothing. |
max_open_positions | Coins held or being bought at once. A coin bought from several wallets is one. |
max_open_cost_raw | The most open positions may have cost. |
stop_after_loss_raw | Stop buying once realised losses over 24 hours reach this. Buys resume when the window rolls past, or an operator resumes. |
All are in the order's quote, in base units; null means no limit, and 0 is refused. Source: d.ts:1547-1567.
{
"quote": "native",
"max_spend_per_day_raw": 1200000000,
"max_open_positions": 1,
"max_open_cost_raw": 400000000,
"stop_after_loss_raw": 400000000
}How it will be measured
Protocol B reports exits landed within the window and the implementation shortfall: how far the realised price fell below the curve price at the trigger slot, in basis points. The shortfall needs one shared curve-price definition with the engine (E9) before it can be computed.
Resend without buying twice
When a batch half-fails, the usual advice is to stop and reconcile by hand, because a blind resend can execute twice. Durable nonces make a resend safe by construction.
Bundle data contracts
What a published run contains, how /benchmarks finds and reads it, and the exact data contract behind each chart. Wiring real data means publishing bundles in this format; no page code changes.