Build a trade copier
Copy trades from one account to many, with idempotency keys so a retry never fills twice, and handle the ones that can't be confirmed.
Copiers fail in two ways: copying a trade twice, or silently not copying it. Here’s how to avoid both.
Copy only into accounts whose owners have authorised it. Copying into someone else’s account is banned by our acceptable use policy and by most prop firms.
Listen to the source
Subscribe to the source account’s stream and act on position changes:
if (f.type === "positionUpdated" && isNew(f.position)) fanOut(f.position);
if (f.type === "positionRemoved") closeCopies(f.positionId);
Fan out with deterministic keys
Derive the idempotency key from the source position and the follower. A crashed and restarted worker then produces the same key and can’t double-copy.
import requests
def copy_open(follower, src):
return requests.post(
f"{TW}/users/current/accounts/{follower}/trade",
headers={
"auth-token": KEY,
"Idempotency-Key": f"open-{src['id']}-{follower}",
"X-Actor": "copier",
"X-Reason": f"copy of {src['id']}",
},
json={
"actionType": "ORDER_TYPE_BUY" if src["type"] == "POSITION_TYPE_BUY" else "ORDER_TYPE_SELL",
"symbol": map_symbol(follower, src["symbol"]),
"volume": size_for(follower, src),
"clientId": f"cp_{src['id']}",
},
timeout=30,
).json()
clientId is stored with the order, so you can find each copy later by the source id.
Symbols differ per broker
EURUSD on one broker is EURUSDm or EURUSD.r on another. Build a map per follower from
GET …/symbols, and check symbols/{symbol}/specification for minVolume and volumeStep before
sizing. Cent accounts need very different volumes.
Many followers in one call
POST /v1/orders sends up to 20 legs across accounts in one idempotent request and returns a
status per leg.
Handle “unknown”
If a leg comes back unknown, don’t send a new order. Retry with the same key, or look for the
clientId in the follower’s positions. See Idempotency.
Skip followers you can’t reach
Check health before copying. If a follower is disconnected, record the missed copy and decide
deliberately (catch up at market, or skip) when it comes back, rather than letting requests time
out.