🚀 AI One-Click Generation of mql4 Strategy Code

Mql4: Using `StringSplit()` to Parse Custom Data from `OrderComment()`

mql4 | Published on: 2025/12/10
The following content is generated by EasyQuant .

Problem Description

How can I save extra information with my trades, like which strategy opened it, and then read that information back later?

Solution

In MQL4, there is no dedicated "metadata" field for orders. However, you can save extra information using two specific properties of an order:

  1. Magic Number (int): The most robust method. It is a unique integer identifier assigned by the EA. Brokers do not modify this value.
  2. Order Comment (string): A text field. While easier to read, it is unreliable because brokers often overwrite comments (e.g., during partial closes or stop-loss triggers).

The best practice is to use the Magic Number to identify the strategy logic and map that number to a name within your code.

Implementation: Using Magic Numbers to Identify Strategies

The following code demonstrates a robust framework. It defines unique IDs for different strategies, assigns them when opening orders, and includes a helper function to read that ID and return the human-readable strategy name.

//+------------------------------------------------------------------+
//|                                       StrategyIdentifier_Demo.mq4|
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

//--- 1. Define Unique IDs for your strategies
#define STRATEGY_TREND_FOLLOWING 1001
#define STRATEGY_MEAN_REVERSION  1002
#define STRATEGY_SCALPER         1003

//--- Input parameters
input double Lots = 0.1;
input int    StopLoss = 50;
input int    TakeProfit = 100;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   // Example: Open two trades with different Strategy IDs for testing
   // Note: In a real EA, this would happen based on logic in OnTick
   
   if(OrdersTotal() == 0) 
     {
      // Open a Buy using the Trend Strategy ID
      OpenTrade(OP_BUY, STRATEGY_TREND_FOLLOWING);
      
      // Open a Sell using the Mean Reversion Strategy ID
      OpenTrade(OP_SELL, STRATEGY_MEAN_REVERSION);
     }
     
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // Periodically check open orders to see which strategy opened them
   ReportOpenOrders();
  }

//+------------------------------------------------------------------+
//| Helper: Open a trade with a specific Magic Number (Strategy ID)  |
//+------------------------------------------------------------------+
void OpenTrade(int type, int strategyID)
  {
   double price, sl, tp;
   
   if(type == OP_BUY)
     {
      price = Ask;
      sl = (StopLoss > 0) ? price - StopLoss * Point : 0;
      tp = (TakeProfit > 0) ? price + TakeProfit * Point : 0;
     }
   else
     {
      price = Bid;
      sl = (StopLoss > 0) ? price + StopLoss * Point : 0;
      tp = (TakeProfit > 0) ? price - TakeProfit * Point : 0;
     }

   // --- CRITICAL STEP ---
   // The 'strategyID' is passed as the 'magic' parameter (2nd to last)
   int ticket = OrderSend(_Symbol, type, Lots, price, 3, sl, tp, "Trade Comment", strategyID, 0, clrNONE);
   
   if(ticket < 0)
     {
      Print("OrderSend failed with error #", GetLastError());
     }
   else
     {
      Print("Order Opened. Ticket: ", ticket, " | Strategy ID: ", strategyID);
     }
  }

//+------------------------------------------------------------------+
//| Helper: Convert Magic Number ID to String Name                   |
//+------------------------------------------------------------------+
string GetStrategyName(int magicNumber)
  {
   switch(magicNumber)
     {
      case STRATEGY_TREND_FOLLOWING: return("Trend Following");
      case STRATEGY_MEAN_REVERSION:  return("Mean Reversion");
      case STRATEGY_SCALPER:         return("Scalper");
      default:                       return("Unknown/Manual");
     }
  }

//+------------------------------------------------------------------+
//| Logic: Loop through orders and identify their origin             |
//+------------------------------------------------------------------+
void ReportOpenOrders()
  {
   int total = OrdersTotal();
   
   for(int i = 0; i < total; i++)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
         // 1. Get the Magic Number
         int magic = OrderMagicNumber();
         
         // 2. Translate it to a name
         string stratName = GetStrategyName(magic);
         
         // 3. Print the info
         Print("Ticket #", OrderTicket(), 
               " | Symbol: ", OrderSymbol(), 
               " | Magic: ", magic, 
               " | Strategy: ", stratName);
        }
     }
  }
//+------------------------------------------------------------------+

Key Concepts Explained

  1. #define Constants:
    We define readable names for integer IDs (e.g., STRATEGY_TREND_FOLLOWING is 1001). This prevents "magic number" confusion in the code.

  2. OrderSend Parameter:
    The OrderSend function signature is:
    OrderSend(symbol, cmd, volume, price, slippage, sl, tp, comment, magic, expiration, arrow_color)
    We pass our Strategy ID into the 9th parameter (magic).

  3. OrderMagicNumber():
    When looping through orders using OrderSelect, this function retrieves the integer we saved during OrderSend.

  4. GetStrategyName():
    Since the order only stores an integer (1001), we use a switch statement to map that integer back to a human-readable string ("Trend Following") for logging or on-screen display.

Alternative: Using Comments (Not Recommended)

You can pass a string to the 8th parameter of OrderSend (the comment field).

OrderSend(_Symbol, OP_BUY, Lots, Ask, 3, 0, 0, "TrendStrategy", 0, 0, clrNONE);

And read it back using:

string comment = OrderComment();

Why this is dangerous:
If you perform a partial close (e.g., closing 0.5 lots of a 1.0 lot position), the broker/server will automatically change the comment of the remaining position to something like "from #123456". Your original strategy tag ("TrendStrategy") will be deleted, and your code will lose track of the trade. Magic Numbers persist through partial closes.

Q&A: Trade Metadata in MQL4

Q: Can I change the Magic Number of an open trade?
A: No. The Magic Number is assigned when the order is created and cannot be modified via OrderModify. It is immutable for the life of the order.

Q: Can I store more complex data, like the value of an indicator at the time of entry?
A: Not directly in the order. To do this, you must use the Magic Number as a "Key". You would write the complex data to a CSV file or a Global Variable using the Order Ticket or Magic Number as the reference ID, and look it up later.

Q: What happens if I restart the terminal?
A: Magic Numbers are stored on the trade server. If you restart your terminal or move to a different computer, OrderMagicNumber() will still retrieve the correct ID.

Q: How do I handle manual trades?
A: Manual trades usually have a Magic Number of 0. You can handle this in your GetStrategyName function (as shown in the default case in the code above).