MQL5 Magic Number Guide: Filtering, CTrade and Netting Limits
Learn how to set a strategy tag with CTrade::SetExpertMagicNumber and filter positions by symbol and magic. Magic is an application convention, not an ownership lock. This tutorial explains the account-mode limits and provides an EA that logs by default, with an optional single demo-order attempt.
What this MQL5 guide covers
A magic number is an application-assigned trade tag; the platform does not enforce uniqueness between EAs.
SetExpertMagicNumber configures the tag used by subsequent trade requests from that CTrade instance.
Filter both symbol and magic, then act by ticket; on netting accounts this does not isolate separate strategies trading the same symbol.
Stored order/deal properties can be queried after reconnecting; initialize each new CTrade instance with the intended tag.
What is a Magic Number in MetaTrader 5?
MqlTradeRequest.magic and CTrade::SetExpertMagicNumber take ulong. Order, deal, and position properties are accessed through integer-property functions returning long. These are distinct records: do not treat a position magic as a permanent ledger of every contributing strategy.
Magic tags are a convenient filtering convention. Ticket and position identifiers can also support an explicit ledger. On netting accounts, all deals for one symbol affect one combined position, even when their magic tags differ.
| Trade Property | Type | Access Function | Purpose |
|---|---|---|---|
| POSITION_MAGIC | ulong / long | PositionGetInteger(POSITION_MAGIC) | Position tag; not an exclusive ownership guarantee |
| ORDER_MAGIC | ulong / long | OrderGetInteger(ORDER_MAGIC) | Application tag of an active order |
| DEAL_MAGIC | ulong / long | HistoryDealGetInteger(deal, DEAL_MAGIC) | Application tag recorded on a historical deal |
| trade.SetExpertMagicNumber(n) | void | CTrade method | Sets internal magic number for all subsequent CTrade requests |
Configuring Magic Numbers with CTrade and MqlTradeRequest
When using the standard CTrade class, you configure the magic number once inside OnInit() by calling trade.SetExpertMagicNumber(InpMagicNumber).
If you construct low-level MqlTradeRequest structs manually for OrderSend(), assign the value directly to request.magic = InpMagicNumber.
- CTrade assignment: trade.SetExpertMagicNumber(202601);
- MqlTradeRequest assignment: request.magic = 202601;
- Convention: Use distinct magic numbers for each currency pair and timeframe combination.
Multi-EA Filtering Pattern
When writing trailing stops, trade counters, or close-all routines, always filter by both _Symbol and POSITION_MAGIC.
On hedging accounts, symbol-plus-magic filtering helps select separately held positions when tags are unique. On netting accounts, another EA or manual deal on the same symbol changes the shared position. Use separate symbols/accounts or an explicit shared-position coordinator; magic filtering alone cannot prevent interference.
Implementation details & mechanics
Core implementation pattern
Save the example under MQL5/Experts. It sets the trade tag in OnInit and logs matching-position counts. By default it sends no orders. If explicitly enabled on a demo hedging account, it attempts one buy after initialization when the matching count is below the configured maximum. This is a filtering demonstration without a trading signal or stop-loss, not a strategy.
Error handling & safety rules
The close helper selects by symbol and magic and submits by ticket, checking the server result. It is supplied for inspection and is not called by OnTick. No automatic exit or trailing stop is implemented. Partial execution must be reconciled against remaining positions; a successful CTrade Boolean alone does not prove completion.
MQL5 Code Implementation
//+------------------------------------------------------------------+
//| MagicNumberGuide.mq5 |
//| Copyright 2026, Pineify Guides Series |
//| https://pineify.app |
//+------------------------------------------------------------------+
#property copyright "Pineify Guides Series"
#property link "https://pineify.app/mql5/magic-number-guide"
#property version "1.00"
#property strict
#include <Trade/Trade.mqh>
//--- Input parameters
input group "--- EA Identification ---"
input bool InpEnableDemoOrder = false; // Explicit demo-only order example
input ulong InpMagicNumber = 884401; // Unique Magic Number
input double InpLotSize = 0.10; // Lot Size
input int InpMaxPositions = 1; // Max Positions For This EA
//--- Global trade instance
CTrade trade;
bool attempted = false;
int lastCount = -1;
//+------------------------------------------------------------------+
//| Helper: Count open positions belonging to this EA & Symbol |
//+------------------------------------------------------------------+
int CountOpenPositionsByMagic(ulong magic, const string symbol)
{
int count = 0;
int total = PositionsTotal();
for(int i = 0; i < total; i++)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0)
continue;
// Filter by symbol
if(PositionGetString(POSITION_SYMBOL) != symbol)
continue;
// Filter by magic number
if((ulong)PositionGetInteger(POSITION_MAGIC) == magic)
count++;
}
return count;
}
//+------------------------------------------------------------------+
//| Helper: Close only positions belonging to this EA & Symbol |
//+------------------------------------------------------------------+
void CloseAllPositionsForThisEA(ulong magic, const string symbol)
{
int total = PositionsTotal();
// Iterate backwards when closing positions to maintain valid index alignment
for(int i = total - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0)
continue;
if(PositionGetString(POSITION_SYMBOL) == symbol &&
(ulong)PositionGetInteger(POSITION_MAGIC) == magic)
{
bool sent = trade.PositionClose(ticket);
if(sent && trade.ResultRetcode() == TRADE_RETCODE_DONE)
{
PrintFormat("Closed position #%I64u belonging to Magic %I64u", ticket, magic);
}
else
{
PrintFormat("Failed to close position #%I64u: %s",
ticket, trade.ResultRetcodeDescription());
}
}
}
}
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if(InpMagicNumber == 0 || InpLotSize <= 0 || InpMaxPositions <= 0)
return INIT_PARAMETERS_INCORRECT;
if(InpEnableDemoOrder &&
(AccountInfoInteger(ACCOUNT_TRADE_MODE) != ACCOUNT_TRADE_MODE_DEMO ||
AccountInfoInteger(ACCOUNT_MARGIN_MODE) != ACCOUNT_MARGIN_MODE_RETAIL_HEDGING))
return INIT_PARAMETERS_INCORRECT;
trade.SetTypeFillingBySymbol(_Symbol);
trade.SetAsyncMode(false);
// Set magic number for all orders placed through CTrade
trade.SetExpertMagicNumber(InpMagicNumber);
PrintFormat("EA Initialized on %s with Magic Number: %I64u", _Symbol, InpMagicNumber);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Count only this EA's active positions
int myPositions = CountOpenPositionsByMagic(InpMagicNumber, _Symbol);
if(myPositions != lastCount)
{
Print("Matching positions: ", myPositions);
lastCount = myPositions;
}
if(!InpEnableDemoOrder || attempted || myPositions >= InpMaxPositions) return;
attempted = true; // One attempt per initialization, including rejected requests.
bool sent = trade.Buy(InpLotSize, _Symbol, 0.0, 0.0, 0.0, "Pineify Magic Demo");
uint code = trade.ResultRetcode();
if(!sent || (code != TRADE_RETCODE_DONE && code != TRADE_RETCODE_DONE_PARTIAL))
Print("Demo order not completed: ", code, " ", trade.ResultRetcodeDescription());
else Print("Demo order result: ", code, "; inspect actual volume in Positions");
}
Copy this code into MetaEditor, save it in your MQL5 folder (Experts, Scripts, or Include), and compile with F7.
Generate custom MQL5 code with Pineify AI
Describe the trade execution, indicator calculations, risk management, or data processing logic you need. Pineify generates editable MQL5 source code. Review its logic, request a syntax check, and compile and test the final file in MetaEditor.
Frequently Asked Questions
Related MQL5 pages
Technical references
Risk and testing note
These educational examples require independent compilation and testing. A compile pass or an illustrative setting does not establish execution correctness or profitability. Any reported performance must be supported by reproducible data and test settings; past results do not predict future returns. Trading involves significant risk of loss. This content is not financial advice.