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). Both can be used on either account mode. A selection copies properties that can later become stale; select again when fresh data is required.
| Function | Parameter | Return Type | Best Used For |
|---|---|---|---|
| PositionSelect(symbol) | const string symbol | bool | Symbol lookup on either account mode; at most one position per symbol in netting |
| PositionSelectByTicket(ticket) | ulong ticket | bool | Known-ticket lookup on either account mode |
| 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 (do not use this as an independent opening-time sort).
Selection alone does not modify anything. If an EA needs a specific position, select its known ticket or inspect all candidates and compare the required properties. Lowest ticket and newest opening time are different selection rules.
- Netting mode: at most one position exists per symbol, but several strategies may contribute to it.
- Hedging mode: PositionSelect("EURUSD") locks onto the lowest ticket number.
- Inspection pattern: loop PositionsTotal(), retrieve PositionGetTicket(i), and check symbol and scope; refresh before acting.
Reading Position Properties
Once a position is selected, query its properties using the typed getter functions. POSITION_PROFIT is floating profit in account currency; swap is a separate property and this is not a complete lifetime P/L ledger. In the script, a zero filter means all magic values, so it cannot filter only magic zero:
| 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
PositionSelect(_Symbol) can be an existing-position guard in one EA, but it is not an atomic lock against other instances or in-flight orders. The script below only prints information: Method A inspects one chart-symbol position; Method B iterates the account and applies an optional magic filter. It sends no trade requests.
Error handling & safety rules
For an execution-enabled EA, reselect the intended ticket immediately before reading or changing it and verify symbol, scope and account mode. Selected properties are a snapshot, not a live lock. A close request needs result handling and refreshed account state; no closing code is included here.
MQL5 Code Implementation
//+------------------------------------------------------------------+
//| 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: Snapshot iteration; indices can change during account updates.
Print("--- Method B: Full PositionsTotal() Iteration (inspection only) ---");
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 %s | Magic: %I64u | Note: '%s'",
i, ticket, symbol, EnumToString(type), lots, open, sl, tp, profit, AccountInfoString(ACCOUNT_CURRENCY), 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 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.