> ## Documentation Index
> Fetch the complete documentation index at: https://docs.0xmonaco.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CopyTradingService

> Copy trading: lead trader profiles, follows and the leaderboard

Package: `monaco.api.copy_trading`

Source: `protos/api/copy_trading.proto`

Use `CopyTradingService` to register as a lead trader, browse and follow lead traders, and manage your follows. A follow allocates collateral to a copy account (a cross risk bucket inside your margin account) and mirrors the leader's fills into it as market orders under your own account.

```protobuf theme={null}
service CopyTradingService {
  rpc UpsertLeadTrader(UpsertLeadTraderRequest) returns (UpsertLeadTraderResponse);
  rpc GetMyLeadTrader(GetMyLeadTraderRequest) returns (GetLeadTraderResponse);
  rpc ListMyFollowers(ListMyFollowersRequest) returns (ListMyFollowersResponse);
  rpc ListLeadTraders(ListLeadTradersRequest) returns (ListLeadTradersResponse);
  rpc GetLeadTrader(GetLeadTraderRequest) returns (GetLeadTraderResponse);
  rpc ListLeadTraderClosedTrades(ListLeadTraderClosedTradesRequest) returns (ListLeadTraderClosedTradesResponse);
  rpc ListLeadTraderOpenPositions(ListLeadTraderOpenPositionsRequest) returns (ListLeadTraderOpenPositionsResponse);
  rpc UpsertFollow(UpsertFollowRequest) returns (UpsertFollowResponse);
  rpc StopFollow(StopFollowRequest) returns (StopFollowResponse);
  rpc CloseFollowPositions(CloseFollowPositionsRequest) returns (CloseFollowPositionsResponse);
  rpc CloseAllCopyPositions(CloseAllCopyPositionsRequest) returns (CloseAllCopyPositionsResponse);
  rpc ListMyFollows(ListMyFollowsRequest) returns (ListMyFollowsResponse);
  rpc GetFollow(GetFollowRequest) returns (GetFollowResponse);
  rpc ListFollowLeaderPositions(ListFollowLeaderPositionsRequest) returns (ListFollowLeaderPositionsResponse);
  rpc PreviewFollow(PreviewFollowRequest) returns (PreviewFollowResponse);
  rpc AddFollowPositionMargin(AddFollowPositionMarginRequest) returns (AddFollowPositionMarginResponse);
}
```

## Notes

* `ListLeadTraders`, `GetLeadTrader` and `ListLeadTraderClosedTrades` are public (no auth). Every other RPC requires authentication and is scoped to the session's account.
* A leader is addressed by their custom TraderCode handle. The sequencer allows one lead profile per wallet (a second application's registration from the same wallet is refused with `INVALID_ARGUMENT`), so a handle names one leader; a leader without a custom handle is not publicly addressable and is not listed. Users appear by wallet address and a `display` string (the custom handle when claimed), never an internal id. `GetLeadTrader` returns `NOT_FOUND` for a suspended leader.
* `UpsertLeadTrader` registers you or edits your profile. A registration must meet the platform's eligibility rules (account equity, trading history, closed positions, and a claimed custom TraderCode handle); a refused registration returns `INVALID_ARGUMENT` naming the rule. The profile is replaced as sent: an omitted `bio` or `min_allocation` clears it, an omitted `status` means `ACTIVE`, and an omitted `share_bps` keeps your current share. Each call spends the per-account settings-write rate limit `UpsertFollow` shares (about one write per second, burst 10; `RESOURCE_EXHAUSTED` past it).
* `UpsertFollow` without `follow_id` creates a follow; with it, edits one of your follows. An edit takes the leader from the follow, so it keeps working after the leader releases their handle (`leader` may be empty; a handle naming a different leader is refused). `copy_existing` on a create also copies the leader's open positions into the new copy account; it applies only to a create (`INVALID_ARGUMENT` on an edit), and the follow keeps recording whether it copied at creation. A create and an edit each spend the per-account settings-write rate limit `UpsertLeadTrader` and the self-trade-prevention default share (about one write per second, burst 10; `RESOURCE_EXHAUSTED` past it).
* `PreviewFollow` shows what a follow with those terms would open if it set `copy_existing`, as totals only: `estimated_margin` (what the copies would reserve at placement) and `estimated_fee`, both rounded up to cents, plus `copied_positions`, `skipped_positions` and `truncated`. It names no market, side or reason: the caller does not follow the leader yet. It is read-only and has the same session and terms rules as `UpsertFollow`: `PERMISSION_DENIED` for delegated agent and sub-account sessions, `NOT_FOUND` for an unknown or suspended leader, `INVALID_ARGUMENT` for terms a follow would refuse, and `FAILED_PRECONDITION` while copy trading is off. It spends the order-risk preview budget and the engine's preview lane share. At most 64 positions are sized; `truncated` is set when more matched.
* `StopFollow` stops one of your own follows. It is an exit and is never refused for the state of the account or the platform: a banned or sub-account session can still stop its own follow, and it stays available during an operations block, when registrations and follows do not. Only three things apply: ownership, the refusal of a delegated agent session, and a per-account rate limit of its own (about one stop per second, burst 20; `RESOURCE_EXHAUSTED` past it), which closes and follow edits never spend.
* `CloseFollowPositions` closes every position in one of your follows' copy accounts at market (reduce-only, immediate-or-cancel) and cancels the resting orders and conditional orders (TP/SL) on its copy risk buckets (a TWAP cannot run there), keeping the follow: the leader's next trades keep mirroring. `CloseAllCopyPositions` does it for every live follow of yours, one batch per follow. Not a flatten guarantee: a thin or halted market can leave part of a position open (`positions_not_closed`), and the leader's next trade opens copies again. Both are exits with `StopFollow`'s rules: never gated by copy trading being off or an operations block, no order budget, and only a delegated agent session is refused (`PERMISSION_DENIED`). Both share a per-account rate limit (about one close per second, burst 5; `RESOURCE_EXHAUSTED` past it). Proceeds stay in the copy account. A follow that is not yours is `NOT_FOUND`; a stopped follow or one whose stop is in progress is `ALREADY_EXISTS` (HTTP 409, the gateway's conflict code; `CloseAllCopyPositions` lists stopping follows in `stopping_follow_ids`). A refused close is `INVALID_ARGUMENT` and one that cannot run right now `UNAVAILABLE`; `CloseAllCopyPositions` lists such a follow in `failed_follows` with a fixed reason and closes the others. The response comes once the batch is durably logged (close orders placed, positions still open); fills arrive on the order, position and copy streams.
* `AddFollowPositionMargin` adds margin to one of your copy positions. `AddFollowPositionMarginRequest` carries `follow_id` (the follow's UUID), `trading_pair_id` (the copy position's trading pair UUID) and `amount` (margin to add in quote units, a positive decimal string). It moves `amount` from the follow's copy account into the margin of its isolated copy position on that pair: the position's initial margin requirement rises by exactly `amount` at the current mark (its leverage drops to what that amount buys at this price), the copy account's remaining collateral falls by the same, and your margin account is never touched. It lowers the position's leverage and moves its liquidation price away; it opens no exposure, so it works while copy trading is switched off and on a `CLOSE_ONLY` follow. `AddFollowPositionMarginResponse` returns `follow_id`, `trading_pair_id`, `risk_bucket_id` (the copy position's isolated risk bucket), `position_id`, `position_margin` (the position's stored margin after the add, in entry-price terms: it rises by `amount × entry price ÷ mark`) and `copy_account_available` (what the copy account can still put into this position after the add). There is no margin reduction: a follow exits by being stopped. `PERMISSION_DENIED` for delegated agent and sub-account sessions; `NOT_FOUND` unless the follow is yours; `ALREADY_EXISTS` (the REST 409) while the follow is stopping or once it is stopped; `INVALID_ARGUMENT` with code `COPY_TRADING_REJECTED` in its `google.rpc.ErrorInfo` detail when the add is refused (no isolated copy position on the pair, the copy position is being liquidated or is in bad debt, or more than the copy account can put in); switching copy trading off does not block an add, which opens no exposure; `UNAVAILABLE` when the matching engine is unavailable, and during an operations block (a margin move, unlike `StopFollow`); `RESOURCE_EXHAUSTED` over the per-user movement budget withdrawals and collateral transfers share. It is not idempotent: after a timeout, read the follow before retrying, or the amount may be added twice.
* `ListLeadTraderOpenPositions` is visible only to the leader's current followers (a live follow in the session's application); anyone else gets `PERMISSION_DENIED`. It is addressed by handle, so once a leader releases their handle it answers `NOT_FOUND` even for current followers, who still see the follow through `ListMyFollows` and `GetFollow`, and the leader's positions through `ListFollowLeaderPositions`.
* `ListFollowLeaderPositions` lists the open positions of the leader one of your follows copies, taking the leader from the follow. `NOT_FOUND` unless the follow is yours; `PERMISSION_DENIED` unless it is live (`ACTIVE` or `CLOSE_ONLY`).
* `GetFollowResponse.copy_account_equity` is the copy account's equity at the engine's marks: its collateral plus the unrealized PnL of its positions. It is a balance, not trading PnL, and it is absent when the engine cannot be read.
* Delegated agent sessions and sub-account sessions cannot register or follow (`PERMISSION_DENIED`); a delegated agent session cannot stop a follow either. A follow or profile that is not yours returns `NOT_FOUND`.
* When copy trading is switched off, registrations and new follows return `FAILED_PRECONDITION`.
* Stats (`LeadTraderStats`) come from the leader's account PnL rollups over 7d, 30d, 90d and all-time. `pnl` is trading PnL (realized plus unrealized, net of fees and funding). `roi_pct` divides it by the highest base balance over the window (starting equity plus net deposits), so a withdrawal cannot inflate it; it is absent when that base is not positive. `max_drawdown_pct` is the largest peak-to-trough fall of cumulative PnL over the same base, sampled at the window's rollup interval (1h for 7d, 4h for 30d and 90d, 1d for all-time). `win_rate_pct` counts winning over winning plus losing closes. A risk bucket's cash balance never feeds these figures.
* `LeadTraderFollowSummary.allocated` is the collateral allocated by live follows (AUM as allocated, not marked to market). `aum_equity` is the same AUM marked: the summed equity of the live follows' copy accounts at the engine's marks, absent when it could not be read. `sort=aum` ranks by it, with leaders lacking it last.
* `ListLeadTraders` serves a leaderboard snapshot refreshed about once a minute (`as_of`); it lists `ACTIVE` leaders only, sorted highest first by `sort`, with leaders lacking a value for the metric last.
* Lists use cursor pagination: omit `page_token` for the first page, then send each response's `next_page_token` until it is empty. A token only works with the filters and sort that produced it (`INVALID_ARGUMENT` otherwise). There are no totals. Page size: up to 1000 on your own lists (`ListMyFollows`, `ListMyFollowers`), up to 100 on the public lists.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.