Senpi Trade — execute a direct trade with the user, one decision at a time
This skill runs the two direct trade paths: a manual one-off position (open / edit / close)
and a mirror of a specific trader. You draw the trade out one question at a time, sanity-check
it, execute it, and confirm the real returned result — never firing a money tool on a guess.
Protection is OPTIONAL — and know exactly what a raw position can carry
A manual position or a raw mirror can run bare, with a static stop/TP, or with a profit-lock
trailing ladder (ratchet_stop_add) — all with no runtime. But be precise about that ladder: it
is profit-lock ONLY. It trails a stop up as the position gains (and never loosens) — it does
NOT place a downside floor. On a raw position you are bare on the losing side until a profit tier
triggers. (The MCP ratchet_stop_add tool silently drops max_loss_pct / retrace_threshold — the
Phase-1 floor is not persisted without a runtime; only the tier ladder sticks.)
So without a runtime, "protection" is one of two things, never a pair you can promise: the profit-lock
ladder (ratchets up as you win) or a static SL (edit_position — fixed, does not ratchet).
A position has one stop order, and once a ratchet is active the engine owns it: ratchet_stop_add
REPLACES a static SL. Name the stop the user gives up, get a yes, then read strategy_get_open_orders
back and report what actually rests. Don't call either one "DSL."
The real, integrated two-phase DSL — a max-loss floor that ratchets up through breakeven into the
profit locks, the engine replacing the stop at each tier — is a runtime feature (exit.dsl_preset);
a managed mirror template has it built in and auto-applies it on every fill. Don't tell a user a
raw position "can't be protected" (it can — profit-lock + a static SL), but don't oversell it as DSL
either. When they want a true two-sided ratcheting stop → managed template.
The protection protocol — reading and changing a stop on a position
Every question about a stop or a ladder ("show my DSL levels", "is it protected", "which is tighter") and
every change to one runs the same six rules. Each one was broken on a live short, and it was the user's own
arithmetic that caught it.
- Read in the same turn, or say you haven't. A claim about a live stop or ladder needs
ratchet_stop_get (the ratchet) and strategy_get_open_orders (what actually rests) in the turn that
makes the claim. Never describe a ladder from memory, from an earlier turn, or from a rule that says one
"should" exist. status: DELETED (or no row) means no ratchet protection: no tier, no floor, no
order — say exactly that; PAUSED means the engine has stopped updating it — what still rests is
whatever strategy_get_open_orders shows.
- Quote, never compute. The floor is
tierFloorPrice. lockRoe is a share of the high-water ROE
(floorRoe = highWaterRoe × lockRoe / 100) — never a share of margin, never an absolute ROE. Dollars
kept at a stop are (entry − stop) × size for a short and (stop − entry) × size for a long, nothing
else. If the engine did not print a number, do not print it either.
- A short's stop sits above the price. Closer to the price is tighter, so for a short a LOWER trigger
is tighter and keeps more; a higher trigger is looser and keeps less. A long is the mirror image. Before
any "tighter / looser / locks more" sentence, work out which trigger the price reaches first.
- Leverage is the exchange's.
strategy_get_clearinghouse_state → leverage.value and .type, never
the strategy's name or a stale ratchet record; say it when they differ. The engine's ROE is on
notional ÷ that leverage, not on the margin actually posted — name the base whenever you quote ROE.
- A change is read → say → yes → act → read back. State what will change and what it replaces (a
ratchet replaces a static SL; a leverage change does not move a stop), get an explicit yes, act, then
read
strategy_get_open_orders and ratchet_stop_get again and quote them. The read-back is the
confirmation; a tool's success: true is not.
- Consent comes from this conversation. A saved instruction ("always add the ratchet", "mandatory on
every position") is neither evidence a ratchet exists nor consent to add one — it is a reminder to ask.
A spoken "no DSL" / "forget about it unless I ask" stands until the user says otherwise, in any later
session. A status check ("did you finish?", "how's it going?", "run a health check") is not a yes, and
a health check never changes protection.
Worked example, a short: entry $80,890, price $77,300, manual stop $77,500, ratchet floor $78,370. The
price reaches $77,500 first, so the manual stop is the tighter one and it keeps (80,890 − 77,500) × size;
the floor keeps less. Adding the ratchet would replace that stop — say so before it happens. The four
regression cases behind these rules, with the expected answers, are in
references/protection-cases.md.
When a managed strategy / template IS the better answer — steer there for the real reasons, which now
explicitly include integrated two-phase DSL (a raw position gets only profit-lock + an uncoordinated
static SL, per above):
- they want it managed for them going forward — DSL auto-attached to every new fill without
you babysitting, budget-relative sizing (and, with Shadow / Jackal, fresh-entry-only — no chasing a runner). A raw mirror
- per-position DSL means you wrap each new fill by hand; a template does all of it automatically.
- they want to mirror more than one trader at once, by signal — a template can position by where the
smart-money cohort leans (the aggregate of many proven traders), not copy one trader's book. A raw
mirror is strictly 1:1; multi-trader, signal-driven copying is only possible with a runtime template.
| The user wants… |
Route to |
Why (real reason) |
| Ongoing, hands-off, protected-on-every-fill |
senpi-strategy-author (custom runtime) |
continuous management + DSL on every fill |
| "Something already built" |
senpi-strategy-discover (100+ templates) |
DSL + risk gates + budget-relative sizing built in |
| To copy / mirror a trader, managed |
senpi-strategy-discover → a named mirror template |
budget-relative sizing, auto-DSL; Shadow/Jackal add fresh-entry-only |
| A genuine one-off, or to mirror one specific trader hands-on |
stay here |
direct execution the user is driving |
The named copy templates — surface them by name for the copy intent.
Direct-mirror (copy specific traders' books): Remora (whale-cohort, or name your whales) · Shadow
(multi-trader fresh-entry, name 2–3) · Oxpecker (elite conviction — their single biggest concentrated
bet) · Raptor (hot-streak — traders winning right now) · Cuckoo (copy-the-copiers — consensus of
top strategies).
Smart-money by signal (position by where the whole cohort leans — many traders at once, not 1:1):
Stingray (ranks the entire smart-money board and rotates long/short by net conviction) · Starling
(buys when a flock of top wallets pile into the same name at once) · Whalehunter (with the smart cohort,
against the crowd) · Phalanx (follows the proven cohort's headcount flow — enters only while conviction is
growing, boosted when the cohort diverges from the 4h crowd, wide stops that let winners run). These are the
answer for "follow the smart money" rather than one specific trader.
Offer the managed option once, then respect a "no." For mirror, the templates fix the exact pains
a raw mirror causes (tiny size, stale entries) — offer one before you reach for a raw strategy_create.
Branch A — Manual position (open / edit / close)
Opening is a FORK — ask which product, never assume
On "go long HYPE 10x" / "buy BTC" / "short NVDA", do not just place it. Ask which:
- (A) A managed strategy — named, supervised, auto-DSL. → hand to senpi-strategy-author. Stop here.
- (B) A one-off position — you place it, protection is your call. → proceed below.
No coin named — "deploy whatever you think is profitable", "trade for me", "be aggressive" — is not a
one-off at all; it is a mandate, and a mandate is a strategy: hand to senpi-strategy-discover.
Never pick the coins yourself and open them here.
NEVER open a manual position into a wallet a deployed runtime is managing. A hand-placed position
in a scanner-managed wallet is reconciled as foreign and flattened within minutes — the order
"succeeds," the position vanishes, the user eats the round-trip. A one-off goes into its own fresh
wallet (strategy_create_custom_strategy creates it) or an existing un-managed wallet.
The interview (one question at a time; pre-fill anything already said)
- Asset & direction — verify the coin against
market_list_instruments (exact casing — kPEPE
not KPEPE; XYZ needs the xyz: prefix). Reject unknowns; do not retry them.
- Size & leverage — you set
marginAmount (USD collateral) + leverage; the engine derives size
(notional = marginAmount × leverage). Min notional $10 (auto-bumped to $12). Look up max_leverage
per asset — never hardcode. Never invent the amount — if unstated, ASK; don't default to the balance.
- Entry — MARKET (immediate, taker) or FEE_OPTIMIZED_LIMIT (maker, cheaper; add
ensureExecutionAsTaker for a guaranteed fill).
- Protection — OPTIONAL, offer all three: (a) none, (b) a static stop/TP (
stopLoss/takeProfit,
percentage XOR price; margin-relative %; one fixed trigger, won't trail), or (c) a profit-lock
ladder via ratchet_stop_add (tiered locks that trail up as you gain — profit-lock only; NO downside
floor without a runtime; it replaces (b) if one exists — say so). Explain the
difference in one line; let them pick.
Then replay the full spec, get an explicit "yes", and place.
Execute & manage
- Open:
strategy_create_custom_strategy (fresh wallet + position [+ static SL/TP]) or create_position
(into an existing un-managed wallet) — and always pass skillName + skillVersion (real params on both;
strategy_create_custom_strategy creates a wallet outside deploy.py, so without them the position is
orphaned / unattributed per CLAUDE.md). Async — poll strategy_list to ACTIVE; report the real returned
status, never assume success.
- Protect (if chosen):
ratchet_stop_add on the open position (asset + tier config; it auto-reads the live position).
- Edit:
edit_position — targetMargin is absolute, not a delta; a direction flip does NOT carry
SL/TP over. Partial close = edit_position with a lower targetMargin.
- Close:
close_position (full only; best-effort cancels resting SL/TP + DSL).
Branch B — Mirror a specific trader
0. Own the PICK — the user usually wants YOU to find the trader
The #1 real ask is "find me someone worth copying," not an address. Delegate the find + vet to the
senpi-trader-research skill — its engine ranks track records and reads each trader's current book;
don't hand-roll discovery_* here. Whether the trader comes back from there or the user pastes an
address, hold it to the same bar before you mirror — 2–3 vetted candidates with
max-drawdown + margin beside win-rate/ROI — never rank by ROI, never ROI alone. Two things the data
will try to fool you on:
- A 100% win rate is a warning, not a credential — it usually means near-zero closed trades or hidden
unrealised drawdown. If it reads 100% for every candidate, the field is broken — don't cite it at
all; judge on max-drawdown + closed-trade count + mirrorability. A "−100% / −93% max drawdown" rated
"solid" is a contradiction — surface it, don't launder it.
- Mirrorability is the go/no-go — check it before you recommend anyone. Pull each candidate's current
positions (
discovery_get_trader_state) and read how far each sits from the trader's entry. That
distance is the slippage gate: a trader whose winners have already run (mark far past entry) is
un-mirrorable right now — the mirror opens nothing (every position slippage-skips), and a flat trader
has nothing to copy. The "best track record" is often the worst mirror today for exactly this reason.
When the book has already moved, lead with a fresh-entry template — Shadow (or Jackal), the ones that wait
for the trader's next open instead of copying the old book — or find a trader entering now. Still show
the full template menu (more choice is better); just label it honestly: Remora / Raptor / Oxpecker / Cuckoo
mirror the cohort's current positions, so they're a valid copy style but not the fresh-entry fix for an
already-run book — don't sell them as such.
If the user pasted an address, still run both checks on it before mirroring.
Steer the product FIRST — the copy questionnaire (lead with capital use)
Before you run a raw mirror, find the right shape. Ask one at a time, pre-fill from the opening ask;
the goal is to land them on raw mirror / a named template / custom — offer as peers, recommend the fit.
- Capital use — ask this first; it is the #1 pain. "Do you want to use most of your capital in a
few concentrated positions, or replicate the trader's exact proportional book?"
- "use most of my funds / a few big orders / not 5% sitting idle" → a budget-relative template
(Shadow / Remora) — they size to your capital and open a few full-size positions, which a
proportional mirror won't (it tracks the trader's proportions). Common answer.
- "exactly proportional to the trader" → raw mirror (below), sized via the multiplier. If the
trader's account dwarfs the budget, match a closer-sized trader or raise the multiplier so
positions clear the $10 floor — a proportional mirror preserves their utilization %, it doesn't
shrink yours.
- Hands-on or hands-off? Drive one trader yourself → raw mirror. Set-and-forget, auto-DSL every
fill → template.
- What shape of copy? → one specific trader (raw) · a whale cohort (Remora) · 2–3 named
traders, fresh entries only (Shadow) · one elite's single biggest conviction bet (Oxpecker) ·
traders hot right now (Raptor) · consensus of the top copy strategies (Cuckoo) · a rule the
templates don't cover (→ senpi-strategy-author).
- Budget — their call; don't advise how much to trade. Just state the trader's minimum to run it
properly (
senpi-trader-research min_mirror_budget.min_budget_usd). If their budget is below it,
say plainly it won't open their full book (below opens_nothing_below_usd, nothing opens) and offer a
closer-sized trader, a higher multiplier, or a budget-relative template. The pre-fund sim confirms it.
- Protection — default follow their exits; offer an added DSL safety-net, especially if the
trader runs without stops.
Route the answer: template → hand to senpi-strategy-discover by name · custom → senpi-strategy-author
· raw mirror of one specific trader → continue below. Offer the managed option once, then respect a "no."
How a mirror actually works — explain it from the single source
When the user needs the mechanics — and many do ("why did it open at a 30% different entry?", "why so
small?", "do I need my own stop?", "spot or perps?", "how much do I need?") — explain from
references/mirror-trading-explained.md, the one source every skill quotes. Always hit: sizing
reality (small budget vs big trader = dust; the multiplier is locked; concentrated-use → a template),
slippage is the entry gate (too tight opens nothing), you mirror their exits (unrealised PnL
doesn't transfer), protection is optional and stacks (default: follow their exits). Never paraphrase a
different version of this anywhere.
Set it up (interview; pre-fill what's given)
Vetted trader → budget → mirrorMultiplier (the size knob; immutable after creation — set it
deliberately) → slippage tolerance (explain it above; set it against where their current positions sit — not a silent 1% that opens nothing) → optional
protection (none / static strategy-level SL/TP on total PnL / per-position DSL).
The hero check — simulate BEFORE funding (a one-shot sizing estimate, not paper trading)
Senpi has no paper-trading mode; the estimate below says what would open right now, and the only live test
is running the mirror at the $10 floor. Never offer to watch a trader on a timer — a cron is a model call per firing.
Run execution_estimate_position_opening at the user's budget × multiplier × slippage before creating
anything. It returns, per position, open / skipped(slippage) / skipped(budget) + minimumBudgetRequired
— i.e. exactly what would open for them and at what size. Show the real $ and %. If little would
open, STOP and offer: (a) more budget, (b) a higher multiplier, (c) a trader closer to their size, or
(d) a fresh-entry template (Shadow). This one check prevents the core failure: funding capital that then
barely trades.
Create + verify — don't fabricate
strategy_create with the agreed params — and always pass skillName + skillVersion (both are real
params on strategy_create and strategy_create_custom_strategy). This skill creates the wallet directly,
outside deploy.py, so without them every mirror it opens is orphaned (unattributed) per CLAUDE.md. Poll
strategy_list to ACTIVE, then read
strategy_get_clearinghouse_state and confirm positions actually opened. If the wallet is idle past a short
window, tell the user and adjust target / budget / multiplier — do not close+recreate (see below).
DSL on the mirror
ratchet_stop_add per opened position adds the profit-lock ladder (no runtime) — but that's
profit-lock only, and it takes over the position's stop order: a static SL (edit_position) is the
other option, not a companion — adding the ratchet replaces it, so say which one the user keeps. The real two-phase DSL (a ratcheting max-loss floor + the locks, integrated) needs
a runtime → a managed template (Shadow / Remora) that auto-applies it on every fill. Don't
hand-wrap 40 fills a day.
Closing — present next steps as a LIST, never a paragraph
Whenever you end a mirror or template flow with options ("set it up / simulate first / compare / point a
template at a specific whale"), render them as a short numbered or bulleted list, one option per line —
never a run-on sentence with 1. 2. buried inline. Bold the action verb; one clear next step per line.
The guardrails — every one earned from real mirror-trading churn
| If you're about to… |
Don't — because |
Do instead |
| Fund a mirror without simulating it |
It can deploy a tiny fraction of the budget — the rest sits idle |
Run execution_estimate_position_opening first (Branch B) |
| Mirror a whale whose account dwarfs the budget |
A small budget on a whale-sized account = dust — positions round below the $10 floor |
Check trader-account ÷ budget up front; if ~100×+, raise the multiplier or pick a closer-sized trader |
Call ratchet_stop_add on a raw position "DSL protection", or say it "can't be protected" |
It's profit-lock only (no downside floor — Phase-1 is dropped); integrated two-phase DSL is runtime-only |
Offer profit-lock + a static SL on a raw position; steer to a managed template for real two-sided DSL |
| Say funds are "stuck" / "lost" / "file a ticket" |
PENDING_FUNDING self-completes; FAILED auto-refunds to the embedded wallet |
Poll transient states with backoff; check the on-chain balance before any alarm |
| Report a trade as placed off an EMPTY tool result, or keep polling for it |
Trade tools run behind the agent's approval gate: a call the user does not approve in time is denied and comes back empty — nothing reached the venue, so there is nothing to poll for |
Say the approval timed out and nothing was placed; offer to re-run it for approval. An errored call is different — it carries its own message: surface the verbatim tool text. Read strategy_list / positions only to confirm what actually exists |
| Fire a fund-movement tool on partial args |
A bridge call with {amount:0.01} errored nan |
Build fund calls from a validated template; never proceed as if funds moved when it errored |
| Rank copy targets by raw ROI |
Surfaced 100%-win / −100%-drawdown / 99.6%-margin wallets as "best" |
Filter on drawdown + margin + closed-trade count + copyability first |
| Recommend a "top" trader without checking their book is mirrorable |
The best track record is often the worst mirror today — the winners already ran, so the mirror opens nothing |
Read current-position distance-from-entry first; if it's run, steer to a fresh-entry template |
| Leave slippage at a silent / too-tight default |
1% on a trader whose positions already moved opens nothing — the mirror sits flat and looks broken |
Set slippage against the trader's current distance-from-entry; warn before funding if nothing would open |
| Close + recreate a mirror to "fix" it not trading |
Each round-trip skims ~$1.50 in fees; funds fragment |
The fix is target / budget / multiplier, not re-create |
| Re-derive state fresh each session and misread it |
User had to repeat "you didn't do what I asked" 3× |
Persist intent + strategy IDs; reconcile intended-vs-actual before replying |
| Say anything about a stop or ladder, or change one, outside the protection protocol |
Every rule in it was broken on a live short — the user caught each one |
The six rules above, in order |
State machine is transient, not terminal — up to a point. CREATE_WALLET → FUND_WALLET /
PENDING_FUNDING are normal in-progress states (bridging can take 30s+); don't read a fresh one as
failure. SERR045 ("requires ACTIVE") on a pending strategy means wait, not broken. FAILED money
is refunded automatically. BUT PENDING_FUNDING past ~15 minutes is a real bridge deadlock (the
Base→strategy-wallet bridge never completed) — the funds are trapped and it will NOT self-heal. Stop
reassuring: tell the user plainly it's stuck, never say "it should resolve shortly," and escalate to get
the funds returned. (Agents have churned users by promising a stuck deposit would clear when it never did.)
Handoff & boundaries
- Finding / vetting the trader →
senpi-trader-research. It ranks records + reads current books and
hands the action (set up the mirror) back to this skill; you own the mechanics — slippage, sizing,
the pre-fund sim, execution.
- Ongoing hands-off management / DSL-on-every-fill / fresh-entry / budget-relative sizing →
senpi-strategy-author (custom) or a template via senpi-strategy-discover (mirror: Remora / Shadow /
Oxpecker / Raptor / Cuckoo). This skill executes the direct trade and can add per-position protection.
- Mirror with custom rules the templates don't cover — a position-count cap ("max 5; if he opens
more, don't mirror"), a per-position % cap ("each ≤ 5% of my capital"), "don't copy his shorts",
"capture his adds", or a conditional exit → a custom mirror runtime via
senpi-strategy-author; the
named templates are the fast path for common shapes, author covers bespoke rules. Note the
mirrorMultiplier is immutable after creation — a user who wants to change size live must redeploy;
there is no in-place edit.
- "How's my mirror doing?" / compare my mirrors / is my trader still active / why didn't it fire →
read
references/mirror-monitoring.md — it composes your mirror's state (senpi-portfolio /
strategy_get_clearinghouse_state) with the OG's current book (senpi-trader-research) and diffs them
(are you still tracking, did the OG go idle, which positions drifted). After you create a mirror, tell
the user they can ask any time.
- Close / withdraw / rebalance a mirror →
senpi-strategy-ops (close a mirror, reclaim funds, top-up,
or shift budget between mirrors). A mirror is a strategy — lifecycle actions live in ops, not here.
- A pasted address (
I want to mirror trade 0x…) is the single most common entry — vet it through
senpi-trader-research (mirrorability + drawdown) before mirroring, even when it's a popular wallet
everyone is asking about. Don't rubber-stamp a hot address.
- Never send USDC to an external address (no tool for it — direct the user to the app), and never
present a strategy wallet as a deposit target.
- Every money amount (
marginAmount, initialBudget, mirrorMultiplier, budgets) is user intent —
if missing, ASK; never copy a number from a doc example or default to the balance.
Red flags — STOP and re-check
- You're about to
strategy_create a mirror without having run the deployability sim.
- You're about to call
ratchet_stop_add on a raw position "DSL protection" — it's profit-lock only (no downside floor without a runtime); offer a static SL and/or a managed template for real two-sided DSL.
- You're about to tell the user funds are "stuck", or to treat an EMPTY tool result as a placed trade — an unapproved (timed-out) call is denied and executes nothing; say so and offer the re-run.
- You're about to open a manual position into a wallet a runtime is managing.
- You're about to close+recreate a mirror that "isn't trading."
- You're about to say anything about a stop or ladder — or change one — without the protection protocol's same-turn read and yes.
- You're quoting a trader's ROI/win-rate with no drawdown beside it.
- You're about to recommend mirroring a trader whose current positions have already run past their entry — the mirror would open nothing.
- You're about to recommend a trader who trades rarely or hasn't traded in weeks (
infrequent_trader / dormant) without warning the user the mirror will sit idle until they trade again — it only fires when they do.
- You're about to promise a mirror "will replicate shortly" or a stuck strategy "should resolve" — verify on-chain first; never predict a sync that hasn't happened.
All of these mean: stop, run the check, correct the framing, or route to the managed path.
1---2name: senpi-trade3description: Execute a DIRECT trade with the user — a one-off manual position (open / edit / close) or mirroring a specific Hyperliquid trader — ONE decision at a time. Use for "go long HYPE 10x", "short BTC", "buy SOL and set a stop", "close my ETH", "copy this wallet", "mirror this whale", "follow this trader", "find me a trader to copy". Both paths can carry protection and it is OPTIONAL: bare, a static stop/TP, or a profit-lock trailing ladder (`ratchet_stop_add`, no runtime) — but that ladder is profit-lock ONLY (no downside floor); the full two-phase DSL (a ratcheting max-loss floor + the profit locks) is runtime-only, so route to a managed mirror template for real two-sided protection. Any question about a stop or a ladder, and any change to one, runs the protection protocol: read it in the same turn, quote the engine's floor (never compute one), say what a change replaces and get a yes, read it back. Steer users to a MANAGED strategy when they want ongoing autonomy — senpi-strategy-author (custom runtime) or a tem4license: Apache-2.05---67# Senpi Trade — execute a direct trade *with* the user, one decision at a time89This skill runs the two **direct** trade paths: a **manual one-off position** (open / edit / close)10and a **mirror** of a specific trader. You draw the trade out one question at a time, sanity-check11it, execute it, and confirm the **real** returned result — never firing a money tool on a guess.1213## Protection is OPTIONAL — and know exactly what a raw position can carry1415> A manual position or a raw mirror can run **bare**, with a **static stop/TP**, or with a **profit-lock16> trailing ladder** (`ratchet_stop_add`) — all with **no runtime.** But be precise about that ladder: it17> is **profit-lock ONLY.** It trails a stop **up as the position gains** (and never loosens) — it does18> **NOT** place a downside floor. On a raw position you are **bare on the losing side until a profit tier19> triggers.** (The MCP `ratchet_stop_add` tool silently drops `max_loss_pct` / `retrace_threshold` — the20> Phase-1 floor is **not persisted** without a runtime; only the tier ladder sticks.)21>22> So without a runtime, "protection" is one of two things, never a pair you can promise: the profit-lock23> ladder (ratchets up as you win) **or** a **static SL** (`edit_position` — fixed, does **not** ratchet).24> **A position has one stop order, and once a ratchet is active the engine owns it: `ratchet_stop_add`25> REPLACES a static SL.** Name the stop the user gives up, get a yes, then read `strategy_get_open_orders`26> back and report what actually rests. Don't call either one "DSL."27>28> **The real, integrated two-phase DSL** — a max-loss floor that ratchets up through breakeven into the29> profit locks, the engine replacing the stop at each tier — is a **runtime** feature (`exit.dsl_preset`);30> a **managed mirror template** has it built in and auto-applies it on every fill. **Don't** tell a user a31> raw position "can't be protected" (it can — profit-lock + a static SL), **but don't oversell it as DSL**32> either. When they want a true two-sided ratcheting stop → managed template.3334## The protection protocol — reading and changing a stop on a position3536Every question about a stop or a ladder ("show my DSL levels", "is it protected", "which is tighter") and37every change to one runs the same six rules. Each one was broken on a live short, and it was the user's own38arithmetic that caught it.39401. **Read in the same turn, or say you haven't.** A claim about a live stop or ladder needs41 `ratchet_stop_get` (the ratchet) and `strategy_get_open_orders` (what actually rests) in the turn that42 makes the claim. Never describe a ladder from memory, from an earlier turn, or from a rule that says one43 "should" exist. `status: DELETED` (or no row) means no ratchet protection: no tier, no floor, no44 order — say exactly that; `PAUSED` means the engine has stopped updating it — what still rests is45 whatever `strategy_get_open_orders` shows.462. **Quote, never compute.** The floor is `tierFloorPrice`. `lockRoe` is a share of the **high-water** ROE47 (`floorRoe = highWaterRoe × lockRoe / 100`) — never a share of margin, never an absolute ROE. Dollars48 kept at a stop are `(entry − stop) × size` for a short and `(stop − entry) × size` for a long, nothing49 else. If the engine did not print a number, do not print it either.503. **A short's stop sits above the price.** Closer to the price is tighter, so for a short a LOWER trigger51 is tighter and keeps more; a higher trigger is looser and keeps less. A long is the mirror image. Before52 any "tighter / looser / locks more" sentence, work out which trigger the price reaches first.534. **Leverage is the exchange's.** `strategy_get_clearinghouse_state` → `leverage.value` and `.type`, never54 the strategy's name or a stale ratchet record; say it when they differ. The engine's ROE is on55 notional ÷ that leverage, not on the margin actually posted — name the base whenever you quote ROE.565. **A change is read → say → yes → act → read back.** State what will change and what it replaces (a57 ratchet replaces a static SL; a leverage change does not move a stop), get an explicit yes, act, then58 read `strategy_get_open_orders` and `ratchet_stop_get` again and quote them. The read-back is the59 confirmation; a tool's `success: true` is not.606. **Consent comes from this conversation.** A saved instruction ("always add the ratchet", "mandatory on61 every position") is neither evidence a ratchet exists nor consent to add one — it is a reminder to ask.62 A spoken "no DSL" / "forget about it unless I ask" stands until the user says otherwise, in any later63 session. A status check ("did you finish?", "how's it going?", "run a health check") is not a yes, and64 a health check never changes protection.6566Worked example, a short: entry $80,890, price $77,300, manual stop $77,500, ratchet floor $78,370. The67price reaches $77,500 first, so the manual stop is the tighter one and it keeps `(80,890 − 77,500) × size`;68the floor keeps less. Adding the ratchet would replace that stop — say so before it happens. The four69regression cases behind these rules, with the expected answers, are in70[`references/protection-cases.md`](references/protection-cases.md).7172**When a managed strategy / template IS the better answer** — steer there for the real reasons, which now73explicitly include **integrated two-phase DSL** (a raw position gets only profit-lock + an uncoordinated74static SL, per above):7576- they want it **managed for them going forward** — DSL auto-attached to **every** new fill without77 you babysitting, **budget-relative sizing** (and, with **Shadow / Jackal**, **fresh-entry-only** — no chasing a runner). A raw mirror78 + per-position DSL means *you* wrap each new fill by hand; a template does all of it automatically.79- they want to **mirror more than one trader at once, by signal** — a template can position by where the80 **smart-money cohort** leans (the aggregate of many proven traders), not copy one trader's book. A raw81 mirror is strictly **1:1**; multi-trader, signal-driven copying is only possible with a runtime template.8283| The user wants… | Route to | Why (real reason) |84|---|---|---|85| Ongoing, hands-off, protected-on-every-fill | **senpi-strategy-author** (custom runtime) | continuous management + DSL on every fill |86| "Something already built" | **senpi-strategy-discover** (100+ templates) | DSL + risk gates + budget-relative sizing built in |87| To **copy / mirror a trader, managed** | **senpi-strategy-discover** → a **named mirror template** | budget-relative sizing, auto-DSL; Shadow/Jackal add fresh-entry-only |88| A genuine one-off, or to mirror **one specific trader hands-on** | **stay here** | direct execution the user is driving |8990**The named copy templates — surface them by name for the copy intent.**91*Direct-mirror* (copy specific traders' books): **Remora** (whale-cohort, or name your whales) · **Shadow**92(multi-trader fresh-entry, name 2–3) · **Oxpecker** (elite conviction — their single biggest concentrated93bet) · **Raptor** (hot-streak — traders winning right now) · **Cuckoo** (copy-the-copiers — consensus of94top strategies).95*Smart-money by signal* (position by where the whole cohort leans — **many traders at once, not 1:1**):96**Stingray** (ranks the entire smart-money board and rotates long/short by net conviction) · **Starling**97(buys when a flock of top wallets pile into the same name at once) · **Whalehunter** (with the smart cohort,98against the crowd) · **Phalanx** (follows the proven cohort's headcount flow — enters only while conviction is99growing, boosted when the cohort diverges from the 4h crowd, wide stops that let winners run). These are the100answer for *"follow the smart money"* rather than one specific trader.101102Offer the managed option **once**, then respect a "no." For mirror, the templates fix the exact pains103a raw mirror causes (tiny size, stale entries) — offer one before you reach for a raw `strategy_create`.104105---106107## Branch A — Manual position (open / edit / close)108109### Opening is a FORK — ask which product, never assume110On "go long HYPE 10x" / "buy BTC" / "short NVDA", do **not** just place it. Ask which:111- **(A) A managed strategy** — named, supervised, auto-DSL. → hand to **senpi-strategy-author**. Stop here.112- **(B) A one-off position** — you place it, protection is your call. → proceed below.113114No coin named — "deploy whatever you think is profitable", "trade for me", "be aggressive" — is not a115one-off at all; it is a **mandate**, and a mandate is a strategy: hand to **senpi-strategy-discover**.116Never pick the coins yourself and open them here.117118> **NEVER open a manual position into a wallet a deployed runtime is managing.** A hand-placed position119> in a scanner-managed wallet is reconciled as *foreign* and **flattened within minutes** — the order120> "succeeds," the position vanishes, the user eats the round-trip. A one-off goes into its own fresh121> wallet (`strategy_create_custom_strategy` creates it) or an existing **un-managed** wallet.122123### The interview (one question at a time; pre-fill anything already said)1241. **Asset & direction** — verify the coin against `market_list_instruments` (exact casing — `kPEPE`125 not `KPEPE`; XYZ needs the `xyz:` prefix). Reject unknowns; do not retry them.1262. **Size & leverage** — you set `marginAmount` (USD collateral) + `leverage`; the engine derives size127 (`notional = marginAmount × leverage`). Min notional $10 (auto-bumped to $12). Look up `max_leverage`128 per asset — never hardcode. **Never invent the amount — if unstated, ASK; don't default to the balance.**1293. **Entry** — MARKET (immediate, taker) or FEE_OPTIMIZED_LIMIT (maker, cheaper; add130 `ensureExecutionAsTaker` for a guaranteed fill).1314. **Protection — OPTIONAL, offer all three:** (a) none, (b) a **static** stop/TP (`stopLoss`/`takeProfit`,132 `percentage` XOR `price`; margin-relative %; one fixed trigger, won't trail), or (c) a **profit-lock133 ladder** via `ratchet_stop_add` (tiered locks that trail up as you gain — **profit-lock only; NO downside134 floor without a runtime**; it replaces (b) if one exists — say so). Explain the135 difference in one line; let them pick.136137Then **replay the full spec, get an explicit "yes"**, and place.138139### Execute & manage140- **Open:** `strategy_create_custom_strategy` (fresh wallet + position [+ static SL/TP]) or `create_position`141 (into an existing un-managed wallet) — and **always pass `skillName` + `skillVersion`** (real params on both;142 `strategy_create_custom_strategy` creates a wallet outside `deploy.py`, so without them the position is143 **orphaned** / unattributed per CLAUDE.md). Async — poll `strategy_list` to ACTIVE; **report the real returned144 status**, never assume success.145- **Protect (if chosen):** `ratchet_stop_add` on the open position (asset + tier config; it auto-reads the live position).146- **Edit:** `edit_position` — `targetMargin` is **absolute, not a delta**; a direction flip does NOT carry147 SL/TP over. Partial close = `edit_position` with a lower `targetMargin`.148- **Close:** `close_position` (full only; best-effort cancels resting SL/TP + DSL).149150---151152## Branch B — Mirror a specific trader153154### 0. Own the PICK — the user usually wants YOU to find the trader155The #1 real ask is "find me someone worth copying," not an address. **Delegate the find + vet to the156`senpi-trader-research` skill** — its engine ranks track records and reads each trader's current book;157don't hand-roll `discovery_*` here. Whether the trader comes back from there or the user pastes an158address, hold it to the same bar before you mirror — 2–3 vetted candidates with159**max-drawdown + margin beside win-rate/ROI — never rank by ROI, never ROI alone.** Two things the data160will try to fool you on:161162- **A 100% win rate is a warning, not a credential** — it usually means near-zero closed trades or hidden163 unrealised drawdown. **If it reads 100% for *every* candidate, the field is broken — don't cite it at164 all;** judge on max-drawdown + closed-trade count + mirrorability. A "−100% / −93% max drawdown" rated165 "solid" is a contradiction — surface it, don't launder it.166- **Mirrorability is the go/no-go — check it before you recommend anyone.** Pull each candidate's *current*167 positions (`discovery_get_trader_state`) and read **how far each sits from the trader's entry.** That168 distance is the slippage gate: a trader whose winners have **already run** (mark far past entry) is169 **un-mirrorable right now — the mirror opens nothing** (every position slippage-skips), and a flat trader170 has nothing to copy. The "best track record" is often the worst mirror *today* for exactly this reason.171 When the book has already moved, **lead with a fresh-entry template — Shadow (or Jackal), the ones that wait172 for the trader's *next* open instead of copying the old book** — or find a trader entering now. Still show173 the full template menu (more choice is better); just label it honestly: Remora / Raptor / Oxpecker / Cuckoo174 mirror the cohort's *current* positions, so they're a valid copy style but **not** the fresh-entry fix for an175 already-run book — don't sell them as such.176177If the user pasted an address, still run **both** checks on it before mirroring.178179### Steer the product FIRST — the copy questionnaire (lead with capital use)180Before you run a raw mirror, find the right **shape**. Ask one at a time, pre-fill from the opening ask;181the goal is to land them on **raw mirror / a named template / custom** — offer as peers, recommend the fit.1821831. **Capital use — ask this first; it is the #1 pain.** *"Do you want to use **most** of your capital in a184 few concentrated positions, or replicate the trader's exact proportional book?"*185 - *"use most of my funds / a few big orders / not 5% sitting idle"* → **a budget-relative template186 (Shadow / Remora)** — they size to *your* capital and open a few full-size positions, which a187 proportional mirror won't (it tracks the trader's proportions). **Common answer.**188 - *"exactly proportional to the trader"* → **raw mirror** (below), sized via the multiplier. If the189 trader's account **dwarfs** the budget, match a closer-sized trader or raise the multiplier so190 positions clear the $10 floor — a proportional mirror preserves *their* utilization %, it doesn't191 shrink yours.1922. **Hands-on or hands-off?** Drive one trader yourself → **raw mirror**. Set-and-forget, auto-DSL every193 fill → **template**.1943. **What shape of copy?** → one specific trader (**raw**) · a whale cohort (**Remora**) · 2–3 named195 traders, fresh entries only (**Shadow**) · one elite's single biggest conviction bet (**Oxpecker**) ·196 traders hot right now (**Raptor**) · consensus of the top copy strategies (**Cuckoo**) · a rule the197 templates don't cover (**→ senpi-strategy-author**).1984. **Budget — their call; don't advise how much to trade.** Just state the trader's **minimum to run it199 properly** (`senpi-trader-research` `min_mirror_budget.min_budget_usd`). If their budget is below it,200 say plainly it won't open their full book (below `opens_nothing_below_usd`, nothing opens) and offer a201 closer-sized trader, a higher multiplier, or a budget-relative template. The pre-fund sim confirms it.2025. **Protection** — default **follow their exits**; offer an added DSL safety-net, especially if the203 trader runs without stops.204205**Route the answer:** template → hand to **senpi-strategy-discover** by name · custom → **senpi-strategy-author**206· raw mirror of one specific trader → continue below. Offer the managed option **once**, then respect a "no."207208### How a mirror actually works — explain it from the single source209When the user needs the mechanics — and many do (*"why did it open at a 30% different entry?"*, *"why so210small?"*, *"do I need my own stop?"*, *"spot or perps?"*, *"how much do I need?"*) — explain from211**`references/mirror-trading-explained.md`**, the one source every skill quotes. Always hit: **sizing212reality** (small budget vs big trader = dust; the multiplier is locked; concentrated-use → a template),213**slippage is the entry gate** (too tight opens nothing), **you mirror their exits** (unrealised PnL214doesn't transfer), **protection is optional and stacks** (default: follow their exits). Never paraphrase a215different version of this anywhere.216217### Set it up (interview; pre-fill what's given)218Vetted trader → **budget** → **`mirrorMultiplier`** (the size knob; **immutable after creation** — set it219deliberately) → **slippage tolerance** (explain it above; **set it against where their current positions sit — not a silent 1% that opens nothing**) → **optional220protection** (none / static strategy-level SL/TP on total PnL / per-position DSL).221222### The hero check — simulate BEFORE funding (a one-shot sizing estimate, not paper trading)223Senpi has no paper-trading mode; the estimate below says what would open *right now*, and the only live test224is running the mirror at the $10 floor. Never offer to watch a trader on a timer — a cron is a model call per firing.225Run `execution_estimate_position_opening` at the user's budget × multiplier × slippage **before** creating226anything. It returns, per position, `open` / `skipped(slippage)` / `skipped(budget)` + `minimumBudgetRequired`227— i.e. **exactly what would open for them and at what size.** Show the real **$ and %**. If little would228open, STOP and offer: (a) more budget, (b) a higher multiplier, (c) a trader closer to their size, or229(d) a fresh-entry template (Shadow). This one check prevents the core failure: funding capital that then230barely trades.231232### Create + verify — don't fabricate233`strategy_create` with the agreed params — and **always pass `skillName` + `skillVersion`** (both are real234params on `strategy_create` *and* `strategy_create_custom_strategy`). This skill creates the wallet directly,235outside `deploy.py`, so without them every mirror it opens is **orphaned** (unattributed) per CLAUDE.md. Poll236`strategy_list` to ACTIVE, then read237`strategy_get_clearinghouse_state` and confirm positions actually opened. If the wallet is idle past a short238window, **tell the user** and adjust target / budget / multiplier — **do not** close+recreate (see below).239240### DSL on the mirror241`ratchet_stop_add` per opened position adds the **profit-lock ladder** (no runtime) — but that's242**profit-lock only**, and it takes over the position's stop order: a **static SL** (`edit_position`) is the243other option, not a companion — adding the ratchet replaces it, so say which one the user keeps. The **real two-phase DSL** (a ratcheting max-loss floor + the locks, integrated) needs244a **runtime** → a managed template (**Shadow / Remora**) that auto-applies it on **every** fill. Don't245hand-wrap 40 fills a day.246247### Closing — present next steps as a LIST, never a paragraph248Whenever you end a mirror or template flow with options ("set it up / simulate first / compare / point a249template at a specific whale"), render them as a short **numbered or bulleted list, one option per line** —250never a run-on sentence with `1.` `2.` buried inline. Bold the action verb; one clear next step per line.251252---253254## The guardrails — every one earned from real mirror-trading churn255256| If you're about to… | Don't — because | Do instead |257|---|---|---|258| Fund a mirror without simulating it | It can deploy a **tiny fraction of the budget** — the rest sits idle | Run `execution_estimate_position_opening` first (Branch B) |259| Mirror a whale whose account dwarfs the budget | A small budget on a whale-sized account = **dust** — positions round below the $10 floor | Check trader-account ÷ budget up front; if ~100×+, raise the multiplier or pick a closer-sized trader |260| Call `ratchet_stop_add` on a raw position "DSL protection", or say it "can't be protected" | It's **profit-lock only** (no downside floor — Phase-1 is dropped); integrated two-phase DSL is runtime-only | Offer profit-lock **+ a static SL** on a raw position; steer to a **managed template** for real two-sided DSL |261| Say funds are "stuck" / "lost" / "file a ticket" | `PENDING_FUNDING` **self-completes**; `FAILED` **auto-refunds** to the embedded wallet | Poll transient states with backoff; check the on-chain balance before any alarm |262| Report a trade as placed off an EMPTY tool result, or keep polling for it | Trade tools run behind the agent's **approval gate**: a call the user does not approve in time is **denied** and comes back empty — nothing reached the venue, so there is nothing to poll for | Say the approval timed out and **nothing was placed**; offer to re-run it for approval. An errored call is different — it carries its own message: surface the **verbatim** tool text. Read `strategy_list` / positions only to confirm what actually exists |263| Fire a fund-movement tool on partial args | A bridge call with `{amount:0.01}` errored `nan` | Build fund calls from a validated template; never proceed as if funds moved when it errored |264| Rank copy targets by raw ROI | Surfaced 100%-win / −100%-drawdown / 99.6%-margin wallets as "best" | Filter on drawdown + margin + closed-trade count + copyability first |265| Recommend a "top" trader without checking their book is mirrorable | The best track record is often the worst mirror *today* — the winners already ran, so the mirror opens **nothing** | Read current-position **distance-from-entry** first; if it's run, steer to a fresh-entry template |266| Leave slippage at a silent / too-tight default | 1% on a trader whose positions already moved opens **nothing** — the mirror sits flat and looks broken | Set slippage against the trader's current distance-from-entry; warn before funding if nothing would open |267| Close + recreate a mirror to "fix" it not trading | Each round-trip skims ~$1.50 in fees; funds fragment | The fix is **target / budget / multiplier**, not re-create |268| Re-derive state fresh each session and misread it | User had to repeat "you didn't do what I asked" 3× | Persist intent + strategy IDs; **reconcile intended-vs-actual** before replying |269| Say anything about a stop or ladder, or change one, outside the protection protocol | Every rule in it was broken on a live short — the user caught each one | The six rules above, in order |270271> **State machine is transient, not terminal — *up to a point*.** `CREATE_WALLET` → `FUND_WALLET` /272> `PENDING_FUNDING` are normal in-progress states (bridging can take 30s+); don't read a fresh one as273> failure. `SERR045` ("requires ACTIVE") on a pending strategy means *wait*, not *broken*. `FAILED` money274> is refunded automatically. **BUT `PENDING_FUNDING` past ~15 minutes is a real bridge deadlock** (the275> Base→strategy-wallet bridge never completed) — the funds are trapped and it will NOT self-heal. Stop276> reassuring: tell the user plainly it's stuck, never say "it should resolve shortly," and escalate to get277> the funds returned. (Agents have churned users by promising a stuck deposit would clear when it never did.)278279---280281## Handoff & boundaries282- **Finding / vetting the trader → `senpi-trader-research`.** It ranks records + reads current books and283 hands the *action* (set up the mirror) back to this skill; you own the mechanics — slippage, sizing,284 the pre-fund sim, execution.285- **Ongoing hands-off management / DSL-on-every-fill / fresh-entry / budget-relative sizing →**286 `senpi-strategy-author` (custom) or a template via `senpi-strategy-discover` (mirror: Remora / Shadow /287 Oxpecker / Raptor / Cuckoo). This skill executes the **direct** trade and can add **per-position** protection.288- **Mirror with *custom rules* the templates don't cover** — a position-count cap ("max 5; if he opens289 more, don't mirror"), a per-position % cap ("each ≤ 5% of my capital"), "don't copy his shorts",290 "capture his adds", or a conditional exit → a **custom mirror runtime** via `senpi-strategy-author`; the291 named templates are the fast path for common shapes, author covers bespoke rules. Note the292 **`mirrorMultiplier` is immutable after creation** — a user who wants to change size live must redeploy;293 there is no in-place edit.294- **"How's my mirror doing?" / compare my mirrors / is my trader still active / why didn't it fire →**295 read **`references/mirror-monitoring.md`** — it composes your mirror's state (`senpi-portfolio` /296 `strategy_get_clearinghouse_state`) with the OG's current book (`senpi-trader-research`) and diffs them297 (are you still tracking, did the OG go idle, which positions drifted). After you create a mirror, tell298 the user they can ask any time.299- **Close / withdraw / rebalance a mirror →** `senpi-strategy-ops` (close a mirror, reclaim funds, top-up,300 or shift budget between mirrors). A mirror **is** a strategy — lifecycle actions live in ops, not here.301- **A pasted address (`I want to mirror trade 0x…`) is the single most common entry** — vet it through302 `senpi-trader-research` (mirrorability + drawdown) **before** mirroring, even when it's a popular wallet303 everyone is asking about. Don't rubber-stamp a hot address.304- **Never** send USDC to an external address (no tool for it — direct the user to the app), and never305 present a strategy wallet as a deposit target.306- Every money amount (`marginAmount`, `initialBudget`, `mirrorMultiplier`, budgets) is **user intent** —307 if missing, ASK; never copy a number from a doc example or default to the balance.308309## Red flags — STOP and re-check310- You're about to `strategy_create` a mirror without having run the deployability sim.311- You're about to call `ratchet_stop_add` on a raw position "DSL protection" — it's **profit-lock only** (no downside floor without a runtime); offer a static SL and/or a managed template for real two-sided DSL.312- You're about to tell the user funds are "stuck", or to treat an EMPTY tool result as a placed trade — an unapproved (timed-out) call is denied and executes nothing; say so and offer the re-run.313- You're about to open a manual position into a wallet a runtime is managing.314- You're about to close+recreate a mirror that "isn't trading."315- You're about to say anything about a stop or ladder — or change one — without the protection protocol's same-turn read and yes.316- You're quoting a trader's ROI/win-rate with no drawdown beside it.317- You're about to recommend mirroring a trader whose current positions have already run past their entry — the mirror would open **nothing**.318- You're about to recommend a trader who trades **rarely or hasn't traded in weeks** (`infrequent_trader` / `dormant`) without warning the user the mirror will sit idle until they trade again — it only fires when they do.319- You're about to promise a mirror "will replicate shortly" or a stuck strategy "should resolve" — verify on-chain first; never predict a sync that hasn't happened.320321All of these mean: stop, run the check, correct the framing, or route to the managed path.