Complete MQL5 guide & code

MQL5 PositionSelect Guide: Netting vs Hedging & Position Properties

Master MQL5 PositionSelect and position inspection. Understand the difference between PositionSelect and PositionSelectByTicket, hedging lowest-ticket behavior, and property access via PositionGetInteger and PositionGetDouble.

What this MQL5 guide covers

PositionSelect(symbol) selects an open position by symbol name for subsequent inspection.

On Hedging accounts with multiple positions on the same symbol, PositionSelect(symbol) selects the position with the lowest ticket number.

For robust multi-position handling in Hedging mode, loop through PositionsTotal() and select each position via PositionGetTicket(index).

Properties of selected positions are retrieved using PositionGetInteger(), PositionGetDouble(), and PositionGetString().

PositionSelect vs PositionSelectByTicket

Before reading volume, open price, or floating profit of a position, that position must be actively selected into the terminal’s internal cache.

MetaTrader 5 provides two primary selection functions: PositionSelect(symbol) and PositionSelectByTicket(ticket).

FunctionParameterReturn TypeBest Used For
PositionSelect(symbol)const string symbolboolNetting accounts (where only one position exists per symbol)
PositionSelectByTicket(ticket)ulong ticketboolHedging accounts (direct access to a known ticket ID)
PositionGetTicket(index)int index (0 to total-1)ulongLooping through all currently open positions sequentially
PositionsTotal()voidintReturns count of all open positions on the account

The Hedging Lowest-Ticket Rule

A critical nuance in the official MQL5 documentation: On Hedging accounts where multiple positions exist for the same symbol, calling PositionSelect(symbol) always selects the position with the lowest ticket number (the oldest position).

If an EA attempts to manage or trail stops on the newest position using PositionSelect(symbol), it will mistakenly modify the oldest position instead. To avoid this, always loop through PositionsTotal() and inspect each ticket explicitly.

  • Netting mode: PositionSelect("EURUSD") works predictably because only 1 position exists.
  • Hedging mode: PositionSelect("EURUSD") locks onto the lowest ticket number.
  • Safe Hedging pattern: Loop PositionsTotal(), retrieve PositionGetTicket(i), and verify PositionGetString(POSITION_SYMBOL).

Reading Position Properties

Once a position is selected, query its properties using the typed getter functions:

Getter FunctionKey Enum IdentifiersReturn Value Description
PositionGetIntegerPOSITION_TICKET, POSITION_TYPE, POSITION_MAGIC, POSITION_TIMEPosition ticket ID, BUY/SELL type, EA magic number, open timestamp
PositionGetDoublePOSITION_VOLUME, POSITION_PRICE_OPEN, POSITION_SL, POSITION_TP, POSITION_PROFITPosition volume in lots, open price, stop loss, take profit, floating profit
PositionGetStringPOSITION_SYMBOL, POSITION_COMMENTFinancial instrument name and custom trade comment

Implementation details & mechanics

Core implementation pattern

Before opening a new position, check if an existing position already exists on the symbol: if(PositionSelect(_Symbol)) { double lots = PositionGetDouble(POSITION_VOLUME); return; }. This prevents duplicate entries on netting accounts or single-position strategies.

Error handling & safety rules

To inspect positions for exit conditions: loop from PositionsTotal() - 1 down to 0, obtain the ticket via PositionGetTicket(i), and read floating profit with PositionGetDouble(POSITION_PROFIT). If profit reaches target or exit conditions fire, pass the ticket to CTrade::PositionClose(ticket).

MQL5 Code Implementation Code

//+------------------------------------------------------------------+
//|                                         PositionSelectGuide.mq5 |
//|                             Copyright 2026, Pineify Guides Series |
//|                                              https://pineify.app |
//+------------------------------------------------------------------+
#property copyright "Pineify Guides Series"
#property link      "https://pineify.app/mql5/positionselect-guide"
#property version   "1.00"
#property script_show_inputs

//--- Input parameters
input ulong InpFilterMagic = 0; // Magic Number to inspect (0 = all)

//+------------------------------------------------------------------+
//| Demonstration: Netting vs Hedging Position Inspection           |
//+------------------------------------------------------------------+
void InspectPositions()
  {
   // 1. Method A: PositionSelect by Symbol (Ideal for Netting accounts)
   Print("--- Method A: PositionSelect(_Symbol) ---");
   if(PositionSelect(_Symbol))
     {
      ulong  ticket = (ulong)PositionGetInteger(POSITION_TICKET);
      double lots   = PositionGetDouble(POSITION_VOLUME);
      double price  = PositionGetDouble(POSITION_PRICE_OPEN);
      double profit = PositionGetDouble(POSITION_PROFIT);
      ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);

      PrintFormat("PositionSelect(%s) Found: Ticket #%I64u | Type: %s | Lots: %.2f | Open: %.5f | Profit: %.2f",
                  _Symbol, ticket, EnumToString(type), lots, price, profit);
      Print("Note: On hedging accounts with multiple positions, PositionSelect selects the lowest ticket.");
     }
   else
     {
      PrintFormat("No open position found for symbol %s using PositionSelect()", _Symbol);
     }

   // 2. Method B: Robust Hedging Loop (Iterates all positions by ticket)
   Print("--- Method B: Full PositionsTotal() Iteration (Hedging Safe) ---");
   int total = PositionsTotal();
   PrintFormat("Total open positions across account: %d", total);

   for(int i = 0; i < total; i++)
     {
      // PositionGetTicket automatically selects the position at index 'i'
      ulong ticket = PositionGetTicket(i);
      if(ticket == 0)
         continue;

      string symbol = PositionGetString(POSITION_SYMBOL);
      ulong  magic  = (ulong)PositionGetInteger(POSITION_MAGIC);

      // Optional magic filter
      if(InpFilterMagic > 0 && magic != InpFilterMagic)
         continue;

      double lots   = PositionGetDouble(POSITION_VOLUME);
      double open   = PositionGetDouble(POSITION_PRICE_OPEN);
      double sl     = PositionGetDouble(POSITION_SL);
      double tp     = PositionGetDouble(POSITION_TP);
      double profit = PositionGetDouble(POSITION_PROFIT);
      string comment= PositionGetString(POSITION_COMMENT);
      ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);

      PrintFormat("Index [%d] -> Ticket #%I64u | %s %s | Vol: %.2f | Open: %.5f | SL: %.5f | TP: %.5f | P/L: $%.2f | Magic: %I64u | Note: '%s'",
                  i, ticket, symbol, EnumToString(type), lots, open, sl, tp, profit, magic, comment);
     }
  }

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   InspectPositions();
  }

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 produces clean, typed MQL5 source code ready to compile in MetaEditor.

Frequently Asked Questions

Related MQL5 pages

Technical references

Risk and testing note

Past performance is not indicative of future results. Backtest statistics are based on historical data and do not guarantee future profits. Trading involves significant risk of loss. This content is for educational purposes only and does not constitute financial advice.