Guide to configuring and operating the NTL CopyTrader system for replicating trades from a master MetaTrader 5 account to one or more slave accounts in real time. Covers both deployment options (integrated into EAsiTrader and standalone), all settings, sizing modes, and troubleshooting. For general EA configuration, see the EAsiTrader User Guide.
CopyTrader allows you to replicate trades from one MetaTrader 5 account (the master) to one or more other accounts (the slaves) in real time. The master detects trade events as they happen and publishes them to the NTL API, which enriches the data and broadcasts it to all connected slaves via a persistent WebSocket connection.
Master MT5 ──HTTP POST──> NTL API ──WebSocket──> Slave MT5 (1)
──WebSocket──> Slave MT5 (2)
──WebSocket──> Slave MT5 (n)
The entire process typically completes within 1-2 seconds of the master trade executing.
There are two ways to run the master:
Integrated Master — built into EAsiTrader. Activated simply by providing a Master API Key in the EAsiTrader inputs. No separate EA is needed. Publishes events for any trade that EAsiTrader manages. This is the recommended option when EAsiTrader is your trading EA.
Standalone Master — a separate EA (CopyTraderMaster.ex5) that monitors all trade activity on the account regardless of source. Useful when the master account uses a different EA, manual trading, or a combination. Includes a symbol watchlist filter.
Both master options publish the same event format and are interchangeable from the slave's perspective.
https://www.northentradinglabs.com (Tools > Options > Expert Advisors > Allow WebRequest for listed URL)CopyTraderMaster.ex5 placed in MQL5\Experts\CopyTrader\CopyTraderWs.dll placed in MQL5\Libraries\CopyTraderSlave.ex5 placed in MQL5\Experts\CopyTrader\Master and slave API keys are paired through your NTL account at northentradinglabs.com. One master key can broadcast to multiple slave keys simultaneously. Each slave account needs its own unique key linked to the master.
To obtain keys:
Master API Key fieldDebug Logging to true to verify events are publishinghttps://www.northentradinglabs.com in Tools > Options > Expert AdvisorsNote: The integrated master only publishes trades managed by EAsiTrader. It does not detect trades opened by other EAs or manual trading on the same account. If you need to copy trades from any source, use the standalone master.
CopyTraderMaster.ex5 in MQL5\Experts\CopyTrader\Master API Key inputSymbol Watchlist to restrict which symbols are publishedhttps://www.northentradinglabs.comNote: The standalone master uses
OnTradeTransactionto detect all trade activity on the account, regardless of which EA or manual action created the trade. It will publish events for every position open, modify, and close.
CopyTraderSlave.ex5 in MQL5\Experts\CopyTrader\CopyTraderWs.dll in MQL5\Libraries\Both files are distributed together in the CopyTrader package.
The slave EA requires DLL imports for its WebSocket connection. Enable them in one of two ways:
Globally: Tools > Options > Expert Advisors > check "Allow DLL imports"
Per-chart: When attaching the EA, check "Allow DLL imports" in the Common tab of the EA properties dialog.
Note: MetaTrader will show a security warning when enabling DLL imports. This is expected — the
CopyTraderWs.dllis an NTL-provided library that handles the WebSocket connection to the NTL API.
CopyTraderSlave from the Navigator panel onto the chartThe Experts tab should display a "WebSocket connected" message within a few seconds. If you see errors, check the Troubleshooting section.
Note: Verify your account uses hedging mode before attaching the slave. The EA will print "CopyTraderSlave: hedging account required" and refuse to start on netting accounts. Contact your broker or open a new demo account with hedging mode if needed.
These settings appear in the Copy Trade Master group within EAsiTrader's inputs.
InpCopyTraderMasterKey · Default: ""
Your NTL CopyTrader master API key. Paste the key obtained from your NTL account dashboard. When this field is empty, CopyTrader publishing is completely disabled and no events are sent — there is no performance overhead.
InpCopyTraderDebug · Default: false
Logs each published event to the Experts tab showing the sequence number, event type, symbol, ticket, and volume. Enable temporarily to verify events are being detected and queued correctly. Disable in production to reduce log noise.
These settings appear in the input dialog when attaching CopyTraderMaster.ex5.
InpCopyMasterKey · Default: ""
Your NTL CopyTrader master API key. Required — the EA will not initialise without a valid key.
InpCopySymbols · Default: ""
Comma-separated list of symbols to monitor (e.g. EURUSD,GBPUSD,XAUUSD). Only trades on these symbols will be published. When empty, all symbols on the account are monitored without restriction.
InpCopyDebug · Default: false
Logs each published event to the Experts tab showing the sequence number, event type, symbol, ticket, and volume. Enable temporarily to verify events are being detected and queued correctly.
All settings appear in the input dialog when attaching CopyTraderSlave.ex5.
InpCopySlaveKey · Default: ""
Your NTL CopyTrader slave API key, linked to the master account you wish to copy. The slave uses this key to authenticate with the NTL WebSocket. Required — the EA will not initialise without it.
InpSizingMode · Default: 2 (Risk-Based)
Determines how the slave calculates position size for each replicated trade. See Sizing Modes for detailed formulas and worked examples.
InpFixedLots · Default: 0.01
The constant lot size used for every replicated trade when Sizing Mode is set to Fixed (0). Must be greater than or equal to the broker's minimum lot size for the instrument.
InpLotMultiplier · Default: 1.0
Multiplier applied to the master's trade volume when Sizing Mode is Lot Multiplier (3). A value of 0.5 trades half the master's size; 2.0 trades double. Set to 1.0 to mirror the master's exact lot size.
InpRiskPercent · Default: 1.0
Maximum risk per trade as a percentage of account balance when Sizing Mode is Risk-Based (2). The slave calculates lot size such that hitting the stop loss would lose approximately this percentage of the current balance.
InpMaxSlippage · Default: 20
Maximum price deviation in points allowed when executing orders. If the market moves more than this amount between the quote and execution, the order may be rejected by the broker. Trades that fail due to slippage are logged to the skip file. Increase this value if you experience frequent rejections on volatile instruments.
InpSymbolSuffix · Default: ""
If your broker appends a suffix to symbol names (e.g. EURUSD.a, EURUSDm, EURUSD.raw), enter that suffix here (e.g. .a, m, .raw). The slave strips this suffix to match the normalised symbol names from the API, then re-appends it when placing orders locally. Leave empty if your broker uses standard symbol names without suffixes.
InpSymbolAliases · Default: ""
Comma-separated list of symbol name overrides in the format CANONICAL=LOCAL. Use this when a symbol has a completely different name on the slave broker — not just a suffix difference. The left side is the normalised name from the API; the right side is your broker's local name.
Example: NAS100=USTEC,US30=DJ30 — if the master trades NAS100, the slave will look for USTEC on its broker.
The NTL API also maintains a server-side alias table for common cross-broker mappings (e.g. NAS100/USTEC, XAUUSD/GOLD). Slave-side aliases override the server-side table when both define a mapping for the same symbol.
InpMaxEventAgeSec · Default: 10
Maximum age in seconds for an open-trade event. If the slave receives an open event older than this threshold (due to reconnection, network delay, or event replay), the trade is skipped rather than executed at a potentially unfavourable price. Set to 0 to disable the age check and execute all events regardless of age.
This setting only applies to open events. Modify, partial close, and close events are always executed regardless of age, since those protect existing positions.
InpMaxDeviationPct · Default: 0.1
Maximum allowed price deviation (as a percentage) between the master's fill price and the slave's current market price when opening a trade. If the current ask/bid has moved more than this percentage from the master's entry price, the trade is skipped.
Example: Master fills a buy at 1.08500. With InpMaxDeviationPct = 0.1, the slave will skip the trade if the current ask is above 1.08608 or below 1.08392 (±0.1%).
Set to 0 to disable the deviation check. This setting only applies to open events.
InpCopyDebug · Default: false
Logs all received WebSocket events and trade execution details to the Experts tab. Shows sequence numbers, event types, symbol resolution, sizing calculations, and order results. Enable when diagnosing replication issues. Disable in production to reduce log noise.
Note: Even with Debug Logging disabled, the slave always logs trade confirmations (
CopyTrader OPEN,CopyTrader CLOSE,CopyTrader MODIFY,CopyTrader PARTIAL), skip events (CopyTrader SKIP), sequence gap warnings, and a periodic health summary every 5 minutes. These are operational logs that help you verify the system is working without the verbosity of full debug mode.
The sizing mode determines how the slave translates the master's trade volume into its own position size. Each mode suits different use cases depending on account size, risk tolerance, and strategy.
Every trade uses the same constant lot size regardless of the master's volume or account size.
Formula:
volume = InpFixedLots
When to use: When you want complete control over position size and don't want it to vary based on the master's behaviour. Suitable for small accounts where you always want to trade the minimum lot, or accounts where you want a predictable fixed exposure.
Example: With InpFixedLots = 0.05, every replicated trade opens at 0.05 lots whether the master traded 0.01 or 5.0 lots.
Scales the master's lot size by the ratio of slave balance to master balance. Larger slave accounts take proportionally larger positions.
Formula:
volume = masterVolume × (slaveBalance / masterBalance)
When to use: When you want the slave to maintain the same relative risk as the master. If the slave has half the balance, it trades half the volume.
Example: Master balance is $50,000 and trades 1.0 lot on EURUSD. Slave balance is $10,000. The slave trades 1.0 × (10000 / 50000) = 0.2 lots.
Note: If master balance information is not available from the API, this mode falls back to using Fixed Lot Size.
Calculates lot size based on the stop loss distance and a risk percentage of the slave's account balance. This is the default and recommended mode because it normalises risk regardless of the instrument or stop loss placement.
Formula:
volume = (slaveBalance × riskPercent / 100) / (slDistancePoints × tickValue)
Where:
slaveBalance is the current account balanceriskPercent is the Risk % Per Trade settingslDistancePoints is the stop loss distance in points (provided by the API from the master's SL)tickValue is the local broker's tick value for the instrumentWhen to use: When you want consistent risk per trade regardless of instrument volatility or the master's position sizing. This is the best mode for accounts of any size because it automatically adjusts volume to match your risk tolerance.
Worked example:
| Value | Amount |
|---|---|
| Slave balance | $10,000 |
| Risk % | 1.0% |
| Risk amount | $100 |
| SL distance | 500 points |
| Tick value (EURUSD) | $1.00 |
| Calculated volume | $100 / (500 × $1.00) = 0.2 lots |
Note: If the master trade has no stop loss set, Risk-Based mode cannot calculate volume from SL distance. In this case it falls back to Proportional mode. See Fallback Behaviour.
Directly multiplies the master's lot size by a fixed factor. Simple and predictable.
Formula:
volume = masterVolume × InpLotMultiplier
When to use: When you want a direct relationship to the master's volume. A multiplier of 1.0 mirrors exactly. Use 0.5 to trade half the master's size, 2.0 to trade double, etc.
Example: Master trades 0.5 lots with multiplier set to 0.4. Slave trades 0.5 × 0.4 = 0.2 lots.
When a sizing mode cannot calculate volume due to missing data, it falls back through this chain:
Risk-Based ──(no SL on master)──> Proportional ──(no master balance)──> Fixed
InpFixedLots)InpFixedLots value directlyIn all modes, the final volume is:
The complete lifecycle of a copied trade:
The system tracks four event types:
| Type | ID | Description |
|---|---|---|
| Opened | 1 | A new position was opened on the master |
| Modified | 2 | The SL or TP of an existing position was changed |
| Partial Close | 3 | Part of a position was closed (volume reduced) |
| Closed | 4 | A position was fully closed |
Each event carries the master ticket number, symbol, order type (buy/sell), volume, price, SL, and TP. The slave uses the master ticket to map events to the correct local position via its ticket map.
Symbols often differ between brokers — sometimes just a suffix (EURUSD vs EURUSD.a), sometimes a completely different name (NAS100 vs USTEC). The system handles this at two levels:
USTEC.a).a, .b, .c, m, ., -ECN) to produce a base name (e.g. USTEC)USTEC → NAS100)When an event arrives, the slave resolves the normalised symbol to a local broker name using a three-tier lookup:
InpSymbolAliases contains a mapping for the normalised name (e.g. NAS100=USTEC), the alias target is used directlyThis means the slave can resolve symbols automatically even if they are not pre-loaded in MarketWatch. The lazy resolve runs only once per new symbol — subsequent lookups use the cached result.
Example — suffix only: Master broker uses EURUSD, slave broker uses EURUSD.a. With InpSymbolSuffix = .a, the slave maps EURUSD to EURUSD.a.
Example — different name: Master broker uses NAS100, slave broker calls it USTEC. Set InpSymbolAliases = NAS100=USTEC. The slave maps NAS100 directly to USTEC.
Example — server alias: Master broker uses GOLD.a. The API strips .a → GOLD, then the alias table maps GOLD → XAUUSD. The slave receives XAUUSD as the normalised name and resolves it normally.
Note: If a symbol cannot be resolved through any of the three tiers, the trade is skipped and logged to the skip file with reason "symbol not available".
Every event published by the master receives a unique, monotonically increasing sequence number. This provides:
Files\CopyTrader\master_seq.csv and restored on EA restart, so numbers never repeat or resetThe slave tracks the last received sequence number and automatically detects gaps. If a sequence number jumps (e.g. from 5 to 8), the slave immediately logs a warning: CopyTrader WARNING: sequence gap detected (expected 6, got 8) — 2 event(s) missed. This warning is always-on regardless of the Debug Logging setting.
The master sends a heartbeat to the API every 60 seconds containing:
This allows the API to detect when a master has disconnected (no heartbeat for an extended period) and notify connected slaves accordingly.
The slave maintains a persistent WebSocket connection to wss://www.northentradinglabs.com/ws/copy via the CopyTraderWs.dll.
Connection lifecycle:
WsConnect() with the API endpoint and slave keyEvents that arrive at the API while the slave is briefly disconnected are buffered server-side and delivered when the connection re-establishes.
Persistence files created by the system:
| File | Purpose |
|---|---|
Files\CopyTrader\master_seq.csv |
Last published sequence number (master side) |
Files\CopyTrader\slave_tickets.csv |
Master ticket to slave ticket mappings |
Files\CopyTrader\slave_skipped.csv |
Log of all skipped trades with timestamps and reasons |
The ticket map is loaded on slave startup, allowing it to correctly handle modify and close events for positions that were opened in a previous session.
Symptoms: Slave is connected but receives no events when trades open on the master.
Checks:
CopyTrader: seq=5 type=Opened symbol=EURUSD ticket=12345 volume=0.10 in the Experts tabhttps://www.northentradinglabs.com in Tools > Options > Expert Advisors401 or 403 = invalid or expired API key500 = server error (temporary, will retry automatically)Timeout = network issue or firewall blocking the connectionSymptoms: Master is publishing (confirmed via debug logs) but the slave shows no activity.
Checks:
CopyTraderWs.dll exists in MQL5\Libraries\Symptoms: Some trades from the master are not replicated on the slave.
Check Files\CopyTrader\slave_skipped.csv for the reason. Common causes:
| Reason | Solution |
|---|---|
| Symbol not available | Check the Symbol Suffix and Symbol Aliases settings. If the symbol exists on the slave broker under a different name, add an alias override. The slave searches the full broker list automatically, but completely different names require an explicit alias. |
| Event too old (Xs) | The open event was older than the Max Event Age threshold. This is a safety feature — the trade was skipped to avoid entering at an unfavourable price. If this happens frequently, check network latency or increase the threshold. |
| Price deviation X% exceeds limit | The market price moved more than the Max Price Deviation % between the master's entry and the slave's execution attempt. If this occurs on volatile instruments, consider increasing the threshold. |
| Market closed | The trade arrived outside market hours for that symbol on the slave broker |
| Volume below minimum lot | The calculated volume is smaller than the broker's minimum lot — increase Risk %, use a larger Fixed Lot Size, or increase the Lot Multiplier |
| OrderSend failed | Check the trade server return code in the log — common causes include insufficient margin, too many open orders, or trading disabled on the symbol |
| Close/modify/partial close: no local ticket | The slave has no record of the master position — likely because the open event was skipped (symbol unavailable, too old, or price deviation) |
| Close/modify: position already gone | The position was manually closed or otherwise removed on the slave before the event arrived |
Symptoms: Slave trades at a different lot size than expected.
This is expected behaviour in Risk-Based and Proportional modes — the slave calculates its own volume based on local account conditions. Specific causes:
To check the calculation, enable Debug Logging on the slave. The log shows the sizing mode, inputs, and calculated volume for each trade.
| File | Location | Contents |
|---|---|---|
| Master sequence log | Files\CopyTrader\master_seq.csv |
Single value: the last published sequence number |
| Slave ticket map | Files\CopyTrader\slave_tickets.csv |
CSV mapping master tickets to slave tickets, loaded on restart |
| Slave skip log | Files\CopyTrader\slave_skipped.csv |
Timestamped log of every trade that was not replicated, with the reason |
| Experts tab | Terminal window | Real-time status messages, errors, and debug output (when enabled) |
Note: The
Files\CopyTrader\directory is created automatically the first time CopyTrader runs. If you need to reset the slave's state completely (e.g. after switching master keys), delete the files in this directory and restart the EA.
Rev: 11.05.2026 Add symbol aliases, lazy resolve, staleness protections, and debugging improvements