# CT Exit-Calibration Spec — proposal (2026-05-30)

**Status: HYPOTHESIS — SIM-first. Do NOT deploy blind.** This translates the
measured exit behaviour of the winning copy-trade wallets into concrete CT
`.env` values. Every number is a starting point to validate in the SIM harness
(and a funded canary) before it touches a live host.

Evidence: `research/dune/dash_data/q-exit-recon.json` (query 7615350) +
`q-mirror-exit.json` (7615365). Method + findings: run-log Phase 5/5b.

---

## 1. What the winners actually do (measured, 7d)

| Behaviour | Measured | CT today |
|---|---|---|
| Trailing stop **arm point** | **from buy (t0)** — give-back present even on non-pumpers (gb_lowpk ≈ gb_highpk) | only **after +5% TP** |
| Trail width (give-back from peak) | **~20–35%** tail-farmers · ~8–12% mid · ~2–7% flippers | **5–8%** |
| Stop-loss tolerance | **wide, −15 to −30%** (p25 exit ROI) | −3.5 to −9% |
| Hold / time backstop | **5–60s** typical (flip 1–13s; trail 20–60s; swing 100–300s) | **600–1200s** |
| Exit vs leader | **independent — sell BEFORE the leader** (mirror ≈ chance) | n/a |

**Conclusion:** CT's exit is armed too late, trails too tight, stops too tight,
and times out 10–100× too slow. Net effect today: CT dumps a runner at ~+5–12%
while the alpha captures +30–40%, and holds far past the move's life.

## 2. The CT mechanics (how to express it)

CT's exit (`src/grpc_monitor/mod.rs`): when price crosses `TAKE_PROFIT_PERCENT`
it arms `ttp_price = pool_price·(1 − TSL_PERCENT/100)`, ratcheting up with each
new peak; it sells `reason=trailing_stop_loss` when `pool_price < ttp_price`.
Below the TP threshold, only the hard `STOP_LOSS_PERCENT` and
`AUTOSELL_LIFETIME` apply.

- **Arm from buy** ⇒ set `TAKE_PROFIT_PERCENT ≈ 0–1` (the trail arms on the
  first uptick instead of waiting for +5%).
- **Trail width** ⇒ `TSL_PERCENT` = the measured give-back.
- **Drawdown tolerance** ⇒ `STOP_LOSS_PERCENT` = the measured loss-exit band.
- **Move life** ⇒ `AUTOSELL_LIFETIME` = ~1.5× the leader's p75 hold.
- Per-leader differences ⇒ `PER_WALLET_EXIT` (S2 — already built;
  `docs/ops/impl/S2-per-wallet-exit.md`).

## 3. Two exit modes

| Mode | TP (arm) | TSL (trail) | SL | Autosell | Fits leaders whose tokens… |
|---|---|---|---|---|---|
| **FLIP** | 0 | **7%** | 12% | **20s** | move & die fast (hold ≤13s, small give-back) |
| **TRAIL** | 0 | **25%** | 20% | **120s** | run +30–70% then fade (let it run) |
| **SWING** | 0 | 12% | 20% | **300s** | slower multi-minute climbers |

**Global default** for un-mapped leaders = a middle TRAIL: `TP=0 / TSL=15 /
SL=18 / AUTOSELL=120`.

## 4. Proposed `PER_WALLET_EXIT` starter map (COPY alphas)

Each value derived from that leader's own exit fingerprint (`tsl` ≈ median
give-back; `sl` ≈ |p25 exit ROI| trimmed; `autosell` ≈ 1.5× p75 hold). Wire via
the S2 `PER_WALLET_EXIT` format. **Confidence scales with `n`** — low-n rows are
provisional until a wider window confirms.

| Leader | Mode | tp | tsl | sl | autosell | basis (n · peakROI · giveback · p75hold) |
|---|---|---|---|---|---|---|
| `64hP97Bwr5PubotcTeGgfhkFrGiLVVxT2kVo9M9b4AEz` | FLIP | 0 | 8 | 14 | 35 | n4622 · +8% · 7% · 24s |
| `SQHK48QT8SY1vYN44iXji7wQ6CJek8AjfX6mBp47TZq` | TRAIL-lite | 0 | 11 | 18 | 90 | n3845 · +8% · 11% · 64s |
| `DbEh3Yah8wPtRNpcxtixHMP8Kw1H2wvfv9D1DLVH2zKH` | SWING | 0 | 10 | 20 | 300 | n2823 · +11% · 8% · 238s |
| `FYTVwP5hgCUiB14eYYTPtZpBCBL4tqbYFbRkjmRwbNto` | SWING | 0 | 12 | 20 | 300 | n2832 · +13% · 12% · 251s |
| `HK3J9zTFz3qBTNtcja3v9cZmSRfGEM3upXwK6GBuKHrT` | TRAIL-lite | 0 | 12 | 16 | 180 | n1699 · +12% · 10% · 135s |
| `9fpUmh3Tv3UCdeHLyq3o4QhkTBu5XAbEiKP9FtGaSndb` | FLIP | 0 | 10 | 15 | 30 | n184 · +12% · 11% · 9s |
| `4vw54BmAogeRV3vPKWyFet5yf8DTLcREzdSzx4rw9Ud9` | TRAIL | 0 | 30 | 20 | 130 | n610 · +33% · 32% · 87s |
| `4BdKaxN8G6ka4GYtQQWk4G4dZRUTX2vQH9GcXdBREFUk` | TRAIL-wide | 0 | 35 | 25 | 300 | n64 · +74% · 50% · 202s ⚠low-n |
| `BA36AnwpTfKeqNhExVUFFbzUAQTyKYvJrEokKJqVCTPi` | FLIP | 0 | 8 | 12 | 30 | n117 · +14% · 7% · 20s |
| `2fg5QD1eD7rzNNCsvnhmXFm5hqNgwTTG8p7kQ6f3rx6f` | TRAIL | 0 | 24 | 18 | 100 | n38 · +42% · 24% · 67s ⚠low-n |
| `FxN3VZ4BosL5urG2yoeQ156JSdmavm9K5fdLxjkPmaMR` | TRAIL | 0 | 28 | 16 | 40 | n26 · +39% · 28% · 24s ⚠low-n |
| `88vxK7b6uNnTmwWs9u39BzFbaipASZPLyDGFrmXC2UQW` | TRAIL-wide | 0 | 30 | 20 | 600 | n52 · +25% · 36% · 602s ⚠low-n |

(7NAd2EpY, 88vxK, FxN3, 2fg5 are low-n on the 7d window — re-measure on 30d
before trusting; that's a cheap re-run.)

## 5. Risks / why SIM-first (do not skip)
- **Wider SL + wider trail = bigger per-trade variance.** The winners survive
  this because of selectivity + the tail; at our size and with our drag the
  distribution may not clear break-even — that is exactly RV-15 / the SIM's job.
- **Arm-from-buy + wide trail** gives back more on every winner; only pays if
  enough tokens reach the high peak. SIM the give-back vs tail-capture tradeoff.
- **Short autosell** risks cutting a slow climber; per-leader SWING mode
  mitigates. Validate the autosell distribution against per-leader hold.
- **These are leader-token-behaviour proxies, not our realized fills** — our
  latency + slippage shift the entry, which shifts the whole exit geometry.

## 6. Validation plan (gates before any deploy)
1. **SIM** (`src/bin/sim.rs`): replay copies of each leader at our slot-delay,
   apply each mode's SL/TP/TSL/autosell, net of the fee model → per-mode net ROI
   + give-back/tail decomposition. KILL any mode that's net-negative.
2. **FRA canary**, single host, FLIP+TRAIL on 2 leaders, watch the per-reason
   exit mix (needs the KPI instrumentation — Phase 4 of the plan / Snipping port).
3. Only then fleet-wide, per-leader `PER_WALLET_EXIT`.

## 7. Maps to existing work
- **S2** (per-wallet exit) — the delivery mechanism; already built.
- **D-1** (recursive ladder) — the TRAIL-wide leaders (4Bd/88vxK) want a
  first-rung-⅓ ladder, not a single trail; this spec's `PARTIAL_SELL_*` is where
  D-1 plugs in.
- **SIM / RV-15** — the gate. **D-8a** (selection filter) is the other half:
  these exits only print on a screened token set, not copy-everything.
- **Exit KPI instrumentation** (port from Snipping `csv_writers` + per-reason
  KPI) — needed to measure which mode fires in the canary.
