Taking copy trading offline, and offboarding a leader with a book
The five switches and three destructive actions that each stop a different part of copy trading, which of them leave follower money sitting in the COPY_TRADING wallet, and the order that finishes cleanly.
Every allocation in copy trading is a real transfer. When a follower subscribes,
their money leaves their ECO or SPOT wallet and sits in a COPY_TRADING wallet,
which has no withdrawal path and no transfer path out other than the ones this addon
provides. Turning something off does not move it back.
So the question to hold in your head through this whole page is not "did copying stop" — several switches will do that in seconds. It is "whose money is still in COPY_TRADING, and what will take it out again."
Disabling copy trading, enabling maintenance mode, turning off spot or binary copying, and disabling the Ecosystem extension all stop activity. Not one of them cancels an open copy, releases a wallet hold, deactivates an allocation or moves a balance.
Only three actions move money: a follower's own stop, an admin leader delete with refunds, and the ordinary settlement of a position. Read the whole page before you flip anything on a live install.
The five switches, and exactly what each one stops
All five are decisions you make and then live with; four are on
/admin/copy-trading/settings and the fifth is the Ecosystem extension itself.
copyTradingEnabled — the master switch
Off, it does three things: every user-facing eligibility check refuses with "Copy
trading is currently disabled", and the replication backstop
(processPendingCopyTrades) skips its entire run — including the binary backstop
nested inside it, which is checked after the master gate.
It does not cancel open copies, does not release holds, and does not return capital.
The live spot path (the order hook that fires the moment a leader places an order)
checks copyTradingEnableSpot, not copyTradingEnabled. The live binary path
checks copyTradingEnableBinary. Neither consults the master switch.
So with copyTradingEnabled off, a leader placing an order still has it copied
onto their followers' accounts in real time. What stops is new applications, new
subscriptions, and the database-driven backstop that catches copies the live path
dropped.
If your intent is "stop money moving", the master switch is not the control. The two class switches below are.
copyTradingMaintenanceMode — pause the front door
The gentlest of the five. It refuses with "Copy trading is currently under maintenance" on the same checks the master switch refuses on, and leaves existing subscriptions, open positions, the backstop and live replication completely alone.
Use it for a maintenance window on the surrounding platform. It is not a wind-down step on its own.
copyTradingEnableSpot and copyTradingEnableBinary — the real kill switches
These are the two that actually stop replication, because they are checked on the live path as well as on setup. Turn spot off and the next leader order is not copied to anybody.
The backstop checks the spot switch once per run, before it selects any rows.
With spot off it logs "Spot copy trading is disabled, skipping" and stops — the
pending leader trades stay PENDING, untouched, with no attempt counted against
them. That is deliberate: turning the switch back on resumes from where you were
rather than burning through a backlog and parking it as REPLICATION_FAILED.
Binary is gated twice on purpose. If platform-wide binary trading is off, the binary engine would reject a copied order anyway, so the copy layer refuses up front with a message naming the real reason.
Neither switch touches a position that is already open, and neither returns capital.
Disabling the Ecosystem extension
Turning ecosystem off at /admin/system/extension makes spot copying fail
closed. Every spot path re-checks that the extension is enabled — not merely that
its files resolve — before it writes anything, so replication, reconciliation and
stop-loss monitoring all log "Ecosystem extension not available" and skip. No
copy-trade rows are written for orders that were never placed.
Every follower's allocation is still sitting funded in their COPY_TRADING wallet,
every open spot copy is still open, and the reconciler that would normally tear down
a stale copy is itself disabled — so drift accumulates instead of being cleaned up.
Worse, the follower's own stop route needs the ecosystem wallet service to move the money back, so your customers cannot self-serve their way out while it is off.
Binary copying is unaffected and keeps running. A binary-only deployment can run with Ecosystem disabled indefinitely; a spot deployment cannot.
The three destructive actions
Suspending a leader
Sets the leader to SUSPENDED and pauses every follower behind them in one
statement. Refuses if the leader is not currently ACTIVE. The reason is mandatory
and is carried into the notification the leader reads.
Money is untouched — every allocation stays funded in COPY_TRADING, and it moves
to the dashboard's Stranded band immediately, because the leader can no longer
trade.
resetCopyTradingDailyLimits deliberately skips any follower whose leader is not
ACTIVE, and even for an active leader it only lifts a pause whose latest audit
action is DAILY_LOSS_LIMIT_REACHED from a previous UTC day. A pause caused by a
suspension is logged against the leader, not the follower, so no automatic path
will ever lift it.
Reactivating the leader restores their ability to trade and leaves every one of their
followers paused, indefinitely, with money committed. Each subscription has to be
resumed — by the follower, or by you at /admin/copy-trading/follower.
Before suspending a leader with a large book, decide how you will unwind it.
Deleting a leader — the only bulk refund path
This is the action that returns money, and it is the backbone of a planned wind-down.
It first refuses if that leader has any trade — their own or a follower copy — in
OPEN, PENDING or PARTIALLY_FILLED, with a message naming the count. Positions
must be closed first.
With refundFollowers true (the default), for every non-STOPPED follower and every
active allocation it:
- computes the unused portion —
baseAmount − baseUsedAmountandquoteAmount − quoteUsedAmount; - moves it back to the wallet it came from:
COPY_TRADING → ECOfor a spot allocation,COPY_TRADING → SPOTfor a binary stake budget; - writes a
REFUNDtransaction row per leg withADMIN_LEADER_DELETEDin its metadata; - deactivates the allocation and writes down its recorded amounts to the used portion;
- sets the subscription to
STOPPED.
Then it sets the leader INACTIVE and soft-deletes them. The whole thing runs in one
database transaction, and each transfer carries a stable idempotency key, so
repeating the deletion cannot refund a second time.
With refundFollowers false, subscriptions are stopped and nothing is refunded —
every allocation stays funded in COPY_TRADING, unreachable by the customer. There
is no supported reason to do this on a live install.
Deleting sends no notification. Tell the followers yourself.
Force-stopping one subscription
The Stop button on /admin/copy-trading/follower and on the subscription detail
page. It takes a reason, locks the row, refuses if the subscription is already
STOPPED, sets it to STOPPED, and writes an ADMIN_FORCE_STOP audit row.
It is not the same teardown the follower's own stop runs. It cancels no orders, releases no wallet holds, deactivates no allocation and transfers nothing. The code says so explicitly: "funds remain in individual allocations".
A subscription stopped this way is exactly the case the dashboard's Stranded band
was built to surface — "held against a follower who stopped and whose allocation was
never released". It also sends the follower no notification, because the
FORCE_STOPPED event has no call site.
Use it to stop copying now, during an investigation. It is a containment action, not a closure. The money still has to come out via a leader delete with refunds, or by the follower stopping the subscription themselves.
For comparison, the follower's own stop at POST /api/copy-trading/follower/{id}/stop
does the full teardown: it cancels live copy orders and releases their
COPY_TRADING holds, then refuses outright if any position has actually filled —
telling the customer which symbols and suggesting they pause instead — and only then
transfers every allocation's unused balance back to ECO or SPOT, writes DEALLOCATION
rows, deactivates the allocations and sets the subscription STOPPED.
That refusal is deliberate: a filled position is coins in a wallet, not an order, and nothing in a single request can unwind it. It is also why the customer path is the one that returns money cleanly, and the admin path is not.
Pausing, for completeness
Only works on an ACTIVE subscription, notifies the follower, and writes an
ADMIN_PAUSE audit row. Use it while you are still working out what happened —
pausing leaves the money where it is, which is what you want mid-investigation.
Note that the list screen offers Resume and Stop but no Pause button; the pause endpoint exists and is reachable from the API and the detail page.
A wind-down that finishes
The order matters, because the delete step is blocked by open positions and the positions only close while copying is still functioning.
-
Announce it. Every follower is about to have money returned to a wallet they did not choose, and every leader is about to lose their book. Nothing in this sequence notifies them except the leader-suspension mail.
-
Stop replication — set
copyTradingEnableSpotandcopyTradingEnableBinaryto off on/admin/copy-trading/settings→ Trading. These are the switches the live path actually reads. No new copy is placed from this moment. -
Close the front door — set
copyTradingMaintenanceModeon, orcopyTradingEnabledoff. Either refuses new applications and new subscriptions. Do this second, not first, so you are not fielding "I can't subscribe" while copies are still firing. -
Drain the open positions. Filter
/admin/copy-trading/tradeforOPEN,PARTIALLY_FILLED,CLOSING,PENDINGandPENDING_REPLICATION. LeaveprocessClosedCopyTrades,reconcileCopyTradingOrdersandmonitorCopyTradingStopLevelsrunning — they are what settles and cleans up. Anything stuck inREPLICATION_FAILEDneeds a human before you proceed. -
Delete each leader with
refundFollowerstrue. This is the step that returns the money. It will refuse while any of that leader's trades are still open, which is why step 4 comes first. Use the bulk status endpoint to move a large set toINACTIVEfirst if you want them off the leaderboard immediately — but understand that a bulk status change refunds nothing. -
Sweep the remainder. Any subscription still holding capital behind a leader you have already deleted shows in the Stranded band. Those are follower-side stops that never released; the customer has to run their own stop, or you delete the leader they sat behind if you have not already.
-
Prove it. See below.
How to prove it finished
A falling total is not proof. The dashboard at /admin/copy-trading splits allocated
capital into four bands computed in one server-side pass, and they sum exactly to the
total beside them.
| Band | Must read | Because |
|---|---|---|
| Copying | 0 | Nothing should still be behind an active leader with an active subscription |
| Paused | 0 | Paused money is still committed. A paused subscription is a live claim on funds sitting in COPY_TRADING |
| Leader dormant | 0 | Capital behind an ACTIVE leader who has not traded for 7 days |
| Stranded | 0 | Behind a leader who cannot trade, or held against a follower who stopped and was never released |
Zero in Stranded and zero in Paused is the finish line. A total that has fallen 90% while Stranded holds the rest means the wind-down stopped halfway and somebody's money is sitting in a wallet they cannot reach.
Two further checks worth doing:
capital.currencyin the dashboard response isnullwhenever the open allocations span more than one quote asset. While that is the case, the totals are a correct sum of a column and not an amount in any currency — read the bands as "is it zero", never as "how many dollars".- The at-risk leader table beneath the meter names a reason per leader:
leader-inactive(reinstate or refund),dormant(ask the leader), orunreleased(the teardown did not finish). It is capped at eight rows and reports the true count, so read "showing 8 of 23" literally.
Rate limits and doing it at scale
Every route under /api/admin/copy-trading that changes something is limited to
50 actions per hour, per admin — approve, reject, activate, suspend, delete,
recalculate, bulk status, the leader and subscription edit routes, pause, resume,
force stop, and transaction reversal. Approving, suspending or deleting a backlog by
hand will hit that ceiling, and the 51st action fails with "Too many admin actions.
Please wait."
The read routes carry no limiter at all — the dashboard, analytics, audit, health, and the leader, subscription, trade and transaction lists and detail pages. Refreshing a screen while you work costs you nothing against the ceiling, so watch the capital bands as often as you like.
The bulk endpoint takes leaderIds, a status of ACTIVE, SUSPENDED or
INACTIVE, and a mandatory reason, and counts as one action against the limit.
Its behaviour differs from the single-action routes in ways that matter:
SUSPENDEDpauses every active follower of each leader, exactly as a single suspend does.ACTIVEon aPENDINGleader is refused per row with "Use approve endpoint for pending leaders" — the rest of the batch still processes.- A leader already at the target status is reported as
skipped. - Reactivating from
SUSPENDEDleaves followers paused, same as the single route. - It sends no notifications at all. Not to leaders, not to followers, not to
administrators. It writes
BULK_<STATUS>audit rows and nothing else.
It cannot delete and cannot refund, so it is a way to clear a leaderboard quickly, not a way to return capital.
Related
- Admin console — reading the capital bands and the audit trail
- Settings — every key, and the six that are never enforced
- Notifications — who gets told what, and who does not