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).
| Function | Parameter | Return Type | Best Used For |
|---|---|---|---|
| PositionSelect(symbol) | const string symbol | bool | Netting accounts (where only one position exists per symbol) |
| PositionSelectByTicket(ticket) | ulong ticket | bool | Hedging accounts (direct access to a known ticket ID) |
| PositionGetTicket(index) | int index (0 to total-1) | ulong | Looping through all currently open positions sequentially |
| PositionsTotal() | void | int | Returns 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 Function | Key Enum Identifiers | Return Value Description |
|---|---|---|
| PositionGetInteger | POSITION_TICKET, POSITION_TYPE, POSITION_MAGIC, POSITION_TIME | Position ticket ID, BUY/SELL type, EA magic number, open timestamp |
| PositionGetDouble | POSITION_VOLUME, POSITION_PRICE_OPEN, POSITION_SL, POSITION_TP, POSITION_PROFIT | Position volume in lots, open price, stop loss, take profit, floating profit |
| PositionGetString | POSITION_SYMBOL, POSITION_COMMENT | Financial 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.