MQL5 PositionSelect Guide: How to Select and Retrieve Position Data Safely

目次

1. What Is PositionSelect in MQL5?

1.1 Overview of PositionSelect

PositionSelect is a function used to select a currently held position so it can be referenced internally.
In MQL5, position information is not retrieved directly. Instead, it follows a two-step structure: select first, then retrieve.

The basic syntax is as follows.

bool PositionSelect(string symbol);

This function selects the position that matches the specified symbol, such as a currency pair.
After that, you can retrieve detailed information with functions such as PositionGetInteger and PositionGetDouble.

The key points are:

  • PositionSelect does not retrieve information; it specifies the target.
  • The return value is success (true) or failure (false).
  • If it does not succeed, later PositionGet functions will not work correctly.

Example: basic flow

if(PositionSelect(_Symbol))
{
    double profit = PositionGetDouble(POSITION_PROFIT);
}

In this way, PositionSelect is a required condition before retrieving position information.


1.2 Why PositionSelect Is Necessary

In MQL5, data retrieval for positions, orders, history, and similar objects is designed around
retrieving data that is currently in a selected state.

In other words, the structure is:

  • PositionSelect selects the target.
  • PositionGetXXX retrieves information from the selected target.

This design likely helps achieve:

  • More efficient memory usage
  • More stable processing speed
  • A unified internal data structure

The internal implementation is not public, but this is a reasonable interpretation of the design intent.

An important difference from MQL4 is:

  • MQL4: data is often retrieved directly by ticket number.
  • MQL5: a symbol or ticket is selected first, then data is retrieved.

If you do not understand this difference, you will run into typical problems such as:

  • “I cannot retrieve the value.”
  • “It always returns 0.”

1.3 Common Sticking Points for Beginners

PositionSelect is a simple function, but many beginners struggle with the following points.

Common misunderstanding 1: PositionGet alone can retrieve data

double profit = PositionGetDouble(POSITION_PROFIT); // Not enough by itself

Because PositionSelect has not been called, the correct value cannot be retrieved.


Common misunderstanding 2: Once selected, it can be reused indefinitely

The internal state is not always guaranteed, so selecting each time is safer.


Common misunderstanding 3: Trying to retrieve data when no position exists

In this case, PositionSelect returns false.


Common failure patterns

  • Not checking the return value (true/false)
  • Passing an incorrect string instead of _Symbol
  • Trying to retrieve the position immediately after placing an order and failing because of update delay

Important note

  • PositionSelect also works as an existence check.
  • If it returns false, the basic approach is to stop the process.
if(!PositionSelect(_Symbol))
{
    return; // No position
}

2. Basic Usage of PositionSelect

2.1 Basic Syntax

PositionSelect selects the position for the specified symbol and
makes it possible to retrieve information with later PositionGet functions.

bool PositionSelect(string symbol);
  • symbol: the currency pair or instrument, for example "EURUSD"
  • Return value:
    • true: a position exists and selection succeeded
    • false: no position exists, or retrieval failed

In real development, you should always check the return value.


2.2 Minimal Code Example You Can Use Immediately

The following minimal code checks whether a position exists for the current chart symbol (_Symbol)
and retrieves its profit.

void OnTick()
{
    // Select the position
    if(PositionSelect(_Symbol))
    {
        // Get profit
        double profit = PositionGetDouble(POSITION_PROFIT);

        Print("Current profit: ", profit);
    }
    else
    {
        Print("No position exists");
    }
}

Steps (important)

  • 1. Select the position with PositionSelect.
  • 2. If the result is true, retrieve data with PositionGet.
  • 3. If the result is false, branch the process.

2.3 Meaning of the Return Value (true / false)

The return value of PositionSelect is very important.

Return valueMeaning
trueA position exists for the specified symbol.
falseNo position exists, or retrieval failed.

Notes

Main reasons for false:

  • No position is currently held.
  • The symbol name is wrong.
  • The order was just placed and has not yet been reflected, depending on the environment.

2.4 Common Failures and Fixes

Failure 1: Ignoring the return value

PositionSelect(_Symbol);
double profit = PositionGetDouble(POSITION_PROFIT); // Risky

The select operation may have failed.
Always check it with an if statement.


Failure 2: Hard-coding the symbol

PositionSelect("EURUSD"); // Not recommended

The symbol notation may differ by broker, for example EURUSDm.

Fix

PositionSelect(_Symbol);

Failure 3: Retrieving immediately after placing an order

OrderSend(...);
PositionSelect(_Symbol); // May return false if called immediately

This can happen because the execution result has not yet been reflected.

Fix

  • Wait a few milliseconds, depending on the environment.
  • Process it on the next tick.

Failure 4: Not considering multiple positions

PositionSelect targets only one position.
Be careful with hedging accounts. Details are explained later.


2.5 Practical Basic Template (Recommended)

The following is a safe template you can use directly in real development.

if(!PositionSelect(_Symbol))
{
    // No position
    return;
}

// Get the required information
double volume = PositionGetDouble(POSITION_VOLUME);
double profit = PositionGetDouble(POSITION_PROFIT);
int type = (int)PositionGetInteger(POSITION_TYPE);

// Log output
Print("Volume: ", volume, " Profit: ", profit, " Type: ", type);

Key points

  • Always branch with an early return.
  • Retrieve the required information together.
  • Be careful with type conversion, such as int.

3. Relationship Between PositionSelect and PositionGet Functions (Important)

3.1 What Are PositionGet Functions?

After selecting a position with PositionSelect, the functions that retrieve the actual data are
the PositionGet family of functions.

There are mainly three types.

  • PositionGetInteger(): integer values, such as position type
  • PositionGetDouble(): numeric values, such as profit and lot size
  • PositionGetString(): string values, such as symbol name

Typical retrieval examples

double profit = PositionGetDouble(POSITION_PROFIT);
double volume = PositionGetDouble(POSITION_VOLUME);
int type = (int)PositionGetInteger(POSITION_TYPE);
string symbol = PositionGetString(POSITION_SYMBOL);

All of these work on the assumption that PositionSelect has succeeded.

MQL5 PositionSelect and PositionGet execution flow diagram showing correct sequence to select a position before retrieving data, with error example when PositionSelect is missing causing zero or invalid values in MetaTrader position management

3.2 Correct Processing Flow (Most Important)

In MQL5, position retrieval must always follow this order.

1. PositionSelect (select the target)
2. PositionGetXXX (retrieve data)

In code:

if(PositionSelect(_Symbol))
{
    double profit = PositionGetDouble(POSITION_PROFIT);
}

If this order is broken, you cannot retrieve the correct value.


3.3 Common Mistakes Caused by Poor Structure Understanding

Mistake 1: Retrieving without Select

double profit = PositionGetDouble(POSITION_PROFIT); // NG

Internally, the target position is unknown, so the value is undefined or unreliable.


Mistake 2: Selecting the wrong target

PositionSelect("EURUSD");
double profit = PositionGetDouble(POSITION_PROFIT);

If the current chart is USDJPY, this can cause behavior you did not intend.


Mistake 3: Selection is overwritten by another Select

PositionSelect(_Symbol);
PositionSelect("EURUSD"); // Overwritten
double profit = PositionGetDouble(POSITION_PROFIT);

The last selected position becomes the active target.


3.4 Understanding the Internal Behavior (Practically Important)

PositionSelect internally keeps one “currently selected position.”

That means:

  • The target is always the position selected most recently.
  • Only one selection is held globally, in practical terms within the execution context.

For this reason, the following rule matters.

Rule

  • Always call Select immediately before retrieving data.
if(PositionSelect(_Symbol))
{
    double profit = PositionGetDouble(POSITION_PROFIT);
}

3.5 Safe Writing Style Focused on Reproducibility

In real projects, it is best to write the select and get operations as a set.

double GetCurrentProfit()
{
    if(!PositionSelect(_Symbol))
        return 0.0;

    return PositionGetDouble(POSITION_PROFIT);
}

Benefits

  • Prevents bugs
  • Can be reused
  • Makes the logic clear

3.6 Common Sticking Points

Issue 1: The value becomes 0

Causes:

  • PositionSelect was not called.
  • The process continued even though the result was false.

Issue 2: The previous value remains

Causes:

  • Another Select call affected the selection.
  • State management was incorrect.

Issue 3: Behavior seems random

Causes:

  • The timing of Select is unstable.
  • The logic depends on tick timing.

3.7 Summary of Important Notes

  • PositionGet functions should not be used alone.
  • The order must be Select then Get.
  • Select every time. Do not reuse the previous selection.
  • Only one position is selected, and it can be overwritten.

4. How to Handle PositionSelect in Multiple-Position Environments (Hedging Accounts)

4.1 Difference Between Netting Accounts and Hedging Accounts

In MQL5, position handling differs greatly depending on the account type.

Netting account

  • Only one position can exist per symbol.
  • Buy and sell positions are combined.
  • PositionSelect can retrieve the position without major issues.

Hedging account

  • Multiple positions can be held for the same symbol.
  • Buy and sell positions can be held at the same time.
  • PositionSelect alone is not enough.

4.2 Limitation of PositionSelect (Important)

PositionSelect works as follows.

  • It selects one position for the specified symbol.
  • If multiple positions exist, which one is selected is not guaranteed.

In a hedging account, this means:

PositionSelect(_Symbol);

Only one of the multiple positions becomes the target.

In real development, this can become a serious source of bugs.


4.3 Correct Approach for Multiple Positions

In hedging accounts, use
PositionSelectByTicket with loop processing instead of relying only on PositionSelect.

Steps

  • 1. Get the count with PositionsTotal().
  • 2. Process all positions in a loop.
  • 3. Select each position by ticket.

4.4 Practical Code Example (Safe Pattern)

int total = PositionsTotal();

for(int i = 0; i < total; i++)
{
    ulong ticket = PositionGetTicket(i);

    if(PositionSelectByTicket(ticket))
    {
        string symbol = PositionGetString(POSITION_SYMBOL);

        // Process only the target symbol
        if(symbol == _Symbol)
        {
            double profit = PositionGetDouble(POSITION_PROFIT);
            Print("Profit: ", profit);
        }
    }
}

4.5 Key Points Explained

Point 1: PositionGetTicket(i)

  • Gets the ticket number from the index.

Point 2: PositionSelectByTicket

  • Reliably selects a specific position.

Point 3: Symbol filter

  • Excludes unnecessary positions.

4.6 Common Failures and Fixes

Failure 1: Processing with PositionSelect only

This checks only part of the multiple positions.


Failure 2: Looping without selecting

for(int i = 0; i < PositionsTotal(); i++)
{
    double profit = PositionGetDouble(POSITION_PROFIT); // NG
}

This is invalid because no position has been selected.


Failure 3: Not using tickets

You cannot specify the exact position reliably.


4.7 Practical Decision Criteria

Choose the method based on the account type.

SituationRecommended method
Netting accountPositionSelect
Hedging accountLoop + PositionSelectByTicket

4.8 Practical Notes

  • Account type differs by broker.
  • The same EA can behave differently depending on the environment.
  • A loop structure is safer if you plan for future expansion.

4.9 Safe Design Approach

If reproducibility matters:

  • Always use a loop structure.
  • Filter by symbol.
  • Control the target explicitly.

Even if it is slightly verbose, this gives you stronger resistance to bugs.

5. Practical Trading Logic Examples Using PositionSelect (EA Implementation)

5.1 Control Entry Based on Whether a Position Exists

The basic logic of an EA is to enter only when no position exists.
PositionSelect is used for this check.

void OnTick()
{
    // Do nothing if a position already exists
    if(PositionSelect(_Symbol))
    {
        return;
    }

    // Enter only if there is no position
    // Example: buy order
    MqlTradeRequest request;
    MqlTradeResult result;

    ZeroMemory(request);
    ZeroMemory(result);

    request.action = TRADE_ACTION_DEAL;
    request.symbol = _Symbol;
    request.volume = 0.1;
    request.type   = ORDER_TYPE_BUY;
    request.price  = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

    OrderSend(request, result);
}

5.2 Step Summary Focused on Reproducibility

  • 1. Check whether a position exists with PositionSelect.
  • 2. If it exists, return.
  • 3. Only if it does not exist, call OrderSend.

This structure helps prevent duplicate entries.


5.3 Example: Close by Profit Condition

This is logic that closes a position when a profit condition is met.

void OnTick()
{
    if(!PositionSelect(_Symbol))
        return;

    double profit = PositionGetDouble(POSITION_PROFIT);

    // Close when profit is 10 or more
    if(profit >= 10.0)
    {
        ClosePosition();
    }
}

5.4 Example Close Function

void ClosePosition()
{
    if(!PositionSelect(_Symbol))
        return;

    ulong ticket = PositionGetInteger(POSITION_TICKET);
    double volume = PositionGetDouble(POSITION_VOLUME);

    MqlTradeRequest request;
    MqlTradeResult result;

    ZeroMemory(request);
    ZeroMemory(result);

    request.action = TRADE_ACTION_DEAL;
    request.symbol = _Symbol;
    request.volume = volume;
    request.type = ORDER_TYPE_SELL; // Close a BUY position
    request.position = ticket;
    request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);

    OrderSend(request, result);
}

5.5 Common Logic Mistakes

Mistake 1: Not checking for an existing position

The EA may keep entering trades and create unlimited positions.


Mistake 2: Using the wrong close direction

request.type = ORDER_TYPE_BUY; // Wrong

A BUY position must be closed with SELL.


Mistake 3: Not specifying the ticket

An unintended position may become the target.


Mistake 4: Getting the wrong price

  • For BUY: use ASK.
  • For SELL: use BID.

5.6 Practical Improvements

Improvement 1: Spread check

double spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
if(spread > 20) return;

Improvement 2: Lot control

request.volume = NormalizeDouble(0.1, 2);

Improvement 3: Retry logic

Add retry handling when OrderSend fails.


5.7 Important Notes

  • PositionSelect is only for checking state.
  • Actual trading is performed with OrderSend.
  • Execution timing depends on the environment.

5.8 Basics of Safe EA Design

  • Position existence check: PositionSelect
  • Information retrieval: PositionGet functions
  • Trade execution: OrderSend

Keeping these responsibilities separate gives the EA stronger resistance to bugs.

6. Why PositionSelect Returns false and How to Troubleshoot It

6.1 Basic Reasons PositionSelect Returns false

When PositionSelect returns false, it first means the position for that symbol could not be selected.
However, there is more than one possible reason. In practice, the main causes are these four patterns.

  • You do not hold a position for that symbol.
  • The symbol was specified incorrectly.
  • The order was just placed and the position information has not yet been reflected.
  • You are using PositionSelect even though multiple positions in a hedging account should be handled.

The first thing to check is whether a position really exists for that symbol right now.

if(!PositionSelect(_Symbol))
{
    Print("PositionSelect failed");
    return;
}

This kind of branching when false occurs is the basic approach.


6.2 Most Common Cause 1: No Position Is Held

The most common reason is simply no open position.
This is especially likely in these cases:

  • Immediately after the EA starts
  • Immediately after closing a position
  • No entry because the condition has not been met
  • The expected order has not been executed

In this case, PositionSelect itself is working normally.
It is not an abnormal state. It is the correct return value: false because there is no position.

Check code example

if(!PositionSelect(_Symbol))
{
    Print("There is currently no position on ", _Symbol);
}
else
{
    Print("A position exists");
}

Sticking points

  • Assuming false always means an error
  • Thinking retrieval failed even though no position is held

6.3 Most Common Cause 2: Wrong Symbol Name

The next common issue is a symbol name mismatch.
In MQL5, brokers may add suffixes or prefixes to instrument names.

Examples:

  • EURUSD
  • EURUSDm
  • EURUSD.pro

For this reason, fixed strings fail easily.

PositionSelect("EURUSD"); // May fail depending on the environment

Recommended

If the current chart is the target, use _Symbol.

PositionSelect(_Symbol);

Notes

  • Manually typed strings are easy to get wrong.
  • More than letter case, the exact symbol name itself matters.

6.4 Most Common Cause 3: The Position Is Not Reflected Immediately After the Order

If you call PositionSelect immediately after OrderSend, the position information may not yet be reflected in some environments, so it can return false.

OrderSend(request, result);

if(!PositionSelect(_Symbol))
{
    Print("The position is not visible yet");
}

This is especially likely:

  • Immediately after a market order
  • In environments with communication delay
  • When VPS or network conditions differ

Fixes

  • Check on the next tick.
  • Check in a trade event such as OnTradeTransaction.
  • Do not design the logic around immediate confirmation.

Common failure

  • Assuming OrderSend success always means PositionSelect is immediately true
  • Mistaking reflection delay for a bug

6.5 Most Common Cause 4: Mishandling Multiple Positions in a Hedging Account

In a hedging account, multiple positions can exist for the same symbol.
In that case, PositionSelect is not enough for handling multiple positions correctly.

Even when positions actually exist, design mistakes can occur, such as:

  • Looking at a position different from the one you intended
  • Checking by symbol when you should process by ticket

Fixes

  • Use PositionSelectByTicket() in hedging accounts.
  • Use PositionsTotal() with a loop.

6.6 How to Identify the Cause with Logs

The fastest way to identify why false occurred is to make the state visible with log output.

Example: minimum debug output

Print("Symbol = ", _Symbol);
Print("PositionsTotal = ", PositionsTotal());

if(!PositionSelect(_Symbol))
{
    Print("PositionSelect failed for symbol: ", _Symbol);
    return;
}

Print("PositionSelect success");

This lets you check at least the following:

  • What the target symbol is
  • Whether any positions exist at all
  • Whether the position could be selected for that symbol

Practical tips

  • Always leave a log when false occurs.
  • Also log a success case once so you can compare.
  • Do not try to fix it by guessing without logs.

6.7 Safe Writing Style When false Occurs

If you continue processing after PositionSelect returns false, the logic becomes unstable.
For that reason, an early return is the basic pattern.

if(!PositionSelect(_Symbol))
{
    return;
}

If you want to make the reason easier to trace, write it a little more explicitly.

if(!PositionSelect(_Symbol))
{
    Print("No selected position for symbol: ", _Symbol);
    return;
}

Benefits of this style

  • Prevents invalid PositionGet calls
  • Makes the code easier to read
  • Makes bug locations easier to identify

6.8 Summary of Common Failures

Failure 1: Continuing with PositionGet even when false

PositionSelect(_Symbol);
double profit = PositionGetDouble(POSITION_PROFIT); // Risky

Failure 2: Using a hard-coded symbol

PositionSelect("EURUSD");

Failure 3: Depending on immediate confirmation after an order

OrderSend(...);
PositionSelect(_Symbol);

Failure 4: Using simple PositionSelect in a hedging account


6.9 Troubleshooting Checklist

When PositionSelect returns false, check in this order to isolate the cause more easily.

  • 1. Check whether PositionsTotal() is not 0.
  • 2. Log the value of _Symbol.
  • 3. If an order was just placed, suspect reflection timing.
  • 4. Check whether the account type is hedging.
  • 5. Confirm that the logic immediately returns when false occurs.

Following this order lets you trace the cause structurally instead of relying on intuition.

7. Notes and Safe Implementation Rules for Using PositionSelect

7.1 Always Check the Return Value

The most important rule when using PositionSelect is do not ignore the return value.
This function returns true or false. If you call later functions such as PositionGetDouble or PositionGetInteger without checking it, you can retrieve unintended values or break the logic.

Bad example

PositionSelect(_Symbol);
double profit = PositionGetDouble(POSITION_PROFIT);

With this style, processing continues even if PositionSelect failed.

Good example

if(!PositionSelect(_Symbol))
{
    return;
}

double profit = PositionGetDouble(POSITION_PROFIT);

Notes

  • false does not always mean an abnormal error.
  • However, continuing while the result is false is dangerous.
  • Check it every time before retrieval.

7.2 Call PositionSelect Every Time

A common beginner misunderstanding is that once PositionSelect is called, the same position remains selected afterward.
In real development, it is safer not to depend on that assumption.

The reason is that the MQL5 selected state can be overwritten by another process or another Select call.
Therefore, the basic rule is to call PositionSelect immediately before retrieving the needed information.

Recommended pattern

if(PositionSelect(_Symbol))
{
    double profit = PositionGetDouble(POSITION_PROFIT);
}

Common failures

  • Selecting only once in OnInit and reusing it
  • Having the selection overwritten inside another function
  • Depending on the previous success state

Practical rule

  • Call PositionSelect immediately before PositionGet.
  • Prefer reselecting over reusing.
  • Choose safety even if the code is slightly more verbose.

7.3 As a Rule, Use _Symbol for the Symbol Argument

PositionSelect receives the symbol name as a string, but directly writing a fixed string is weak against environment differences.
Some brokers add suffixes or prefixes to symbol names, so "EURUSD" may not exist exactly as written.

Not recommended

PositionSelect("EURUSD");

Recommended

PositionSelect(_Symbol);

_Symbol is the symbol name of the current chart.
For the common design where an EA runs per chart, this is the safest option.

Sticking points

  • It works in backtesting but not in live trading.
  • false increases after changing brokers.
  • Symbol naming differences are overlooked.

Exception

For a multi-symbol EA, you need to explicitly manage the target symbols with arrays or variables.
Even then, you must verify in logs that the actual symbol name is correct.


7.4 PositionSelect Alone Is Not Enough in Hedging Accounts

PositionSelect is useful for checking a position for a single symbol, but it is not suitable for accurately handling multiple positions.
In hedging accounts, multiple positions can exist for the same symbol, so trying to process all of them with only PositionSelect breaks the design.

Dangerous misunderstandings

  • PositionSelect(_Symbol) can see all positions for that symbol.
  • The assumption of one position per symbol always holds.

Safe practical decision

  • Netting account: PositionSelect can be the main approach.
  • Hedging account: use PositionsTotal() with PositionSelectByTicket().

Problems caused by the wrong decision

  • Only some positions are checked.
  • Total profit and loss become inaccurate.
  • Unexpected positions remain open.

7.5 Stop with an Early Return When false Occurs

If processing continues after PositionSelect fails, the meaning of the later code breaks down.
Therefore, it is safe to stop the process immediately when the result is false.

Recommended template

if(!PositionSelect(_Symbol))
{
    Print("No position for symbol: ", _Symbol);
    return;
}

This style provides these benefits:

  • Prevents incorrect use of PositionGet functions
  • Makes the cause easier to trace with logs
  • Makes branching clear

Notes

  • If alternative processing is needed when false occurs, branch there instead of returning.
  • However, never call PositionGet while no position is selected.

7.6 Wrap the Logic in Functions for Reuse

The code around PositionSelect tends to have the same shape each time. Turning it into reusable functions improves maintainability.

Example: function that returns current profit

double GetCurrentPositionProfit()
{
    if(!PositionSelect(_Symbol))
        return 0.0;

    return PositionGetDouble(POSITION_PROFIT);
}

Benefits

  • Prevents forgetting the select step
  • Locks in the Select then Get order
  • Keeps the quality of the article or EA stable

Notes

  • 0.0 cannot distinguish between “no position” and “zero profit.”
  • Use a bool return value or pass by reference if needed.

7.7 Practical Checklist for Using PositionSelect Safely

To use PositionSelect safely, follow at least these rules.

  • Call PositionSelect every time before retrieval.
  • Always check the return value.
  • Use an early return when the result is false.
  • As a rule, use _Symbol for the symbol.
  • Do not rely on single use in hedging accounts.
  • Use logs so you can trace the reason for failure.

Following only these rules will greatly reduce beginner-level problems around PositionSelect.

8. Differences Between PositionSelect and Related Functions

8.1 Difference Between PositionSelect and PositionSelectByTicket

In MQL5, there are two main ways to select a position.

  • PositionSelect(symbol): select by symbol
  • PositionSelectByTicket(ticket): select by ticket number

Comparison table

ItemPositionSelectPositionSelectByTicket
Selection methodSymbolTicket
PrecisionUncertain when multiple positions existExact match
Hedging accountNot suitableRequired
Use caseSimple checkStrict control

Practical decision

  • Single position: PositionSelect
  • Multiple positions: PositionSelectByTicket

Code comparison

// Symbol selection
PositionSelect(_Symbol);

// Ticket selection
PositionSelectByTicket(ticket);

Notes

  • A ticket is unique.
  • In hedging accounts, ticket-based management is the basic approach.

8.2 Difference in Role from PositionGet Functions

PositionSelect and PositionGet have completely separate roles.

Role summary

  • PositionSelect: selects the target.
  • PositionGet: retrieves information from the selected target.

Incorrect understanding

  • PositionSelect means data retrieval.
  • PositionGet can be used alone.

Both are wrong.


Correct set structure

if(PositionSelect(_Symbol))
{
    double profit = PositionGetDouble(POSITION_PROFIT);
}

Common failures

  • Getting data without selecting first
  • Judging only from the value returned by Get

8.3 Difference from OrderSelect (Important)

The difference from OrderSelect is one of the most confusing points for developers with MQL4 experience.

MQL4 legacy style

  • Orders and positions are mixed.
  • OrderSelect handles everything.

MQL5 current style

  • Orders
  • Positions
  • Deal history

These are completely separated.


Comparison

ItemOrderSelectPositionSelect
TargetOrderPosition
MQL4MainstreamNot available
MQL5Available for a different purposeMainstream for positions

Practical difference

  • OrderSelect: pending orders such as limit and stop orders
  • PositionSelect: currently held positions

Typical mistake

OrderSelect(...); // Intended to retrieve a position

This way of thinking is invalid in MQL5.


8.4 Relationship with PositionsTotal

PositionsTotal() is a function that retrieves the current number of positions.

int total = PositionsTotal();

Role

  • Checks the number of positions
  • Serves as the starting point for loop processing

Combination example

for(int i = 0; i < PositionsTotal(); i++)
{
    ulong ticket = PositionGetTicket(i);

    if(PositionSelectByTicket(ticket))
    {
        // Process
    }
}

Notes

  • PositionsTotal alone cannot retrieve position information.
  • Select is always required.

8.5 Relationship with PositionGetTicket

PositionGetTicket(index) retrieves the ticket number from an index.

ulong ticket = PositionGetTicket(i);

Flow

  • index to ticket
  • ticket to PositionSelectByTicket

Set structure

ulong ticket = PositionGetTicket(i);

if(PositionSelectByTicket(ticket))
{
    double profit = PositionGetDouble(POSITION_PROFIT);
}

8.6 Common Confusion Patterns

Confusion 1: PositionSelect means retrieving all positions

In reality, it selects only one.


Confusion 2: PositionGet can be used by itself

It assumes a prior Select.


Confusion 3: OrderSelect retrieves positions

In MQL5, it has a different purpose.


Confusion 4: Tickets are unnecessary

In hedging accounts, tickets are required.


8.7 Correct Practical Usage

Use the following criteria for safe function selection.

PurposeFunction to use
Check a single positionPositionSelect
Process multiple positionsPositionSelectByTicket
Retrieve informationPositionGet functions
Check countPositionsTotal
Operate on ordersOrder functions

8.8 Safe Design Pattern Summary

  • Always perform Select explicitly.
  • Prefer a design that can process positions by ticket.
  • Think of Select and Get as separate operations.
  • Do not confuse orders with positions.

9. FAQ

Q1. Can I use PositionGet without PositionSelect?

A. No.
PositionGet functions assume that the target was selected beforehand with PositionSelect.
If you call them without Select, the result may be 0 or an invalid value.


Q2. Is it an error when PositionSelect returns false?

A. Not always.
It also returns false when no position exists.
Whether it is an error depends on the situation, such as whether a position should have been open.


Q3. Can I call PositionSelect once and reuse it?

A. It is not recommended.
The internal selected state can be overwritten by other processing, so it is safer to
call PositionSelect every time immediately before PositionGet.


Q4. If multiple positions exist, can PositionSelect retrieve all of them?

A. No.
PositionSelect targets only one position.
If multiple positions exist, you need PositionSelectByTicket and loop processing.


Q5. Should I write the symbol as “EURUSD”?

A. It depends on the environment.
Some brokers use names such as EURUSDm, so the notation can differ.
Usually, using _Symbol is safer.


Q6. PositionSelect returns false immediately after OrderSend. Why?

A. It may be caused by reflection delay.
Immediately after an order, position information may not have been updated yet.
Checking on the next tick or through a trade event is safer.


Q7. Does usage differ between netting accounts and hedging accounts?

A. Yes, it differs.

  • Netting account: PositionSelect is usually sufficient.
  • Hedging account: PositionSelectByTicket plus a loop is required.

If the design is wrong, only part of the positions will be handled.


Q8. What is the difference between PositionSelect and OrderSelect?

A. They target different objects.

  • PositionSelect: currently held positions
  • OrderSelect: pending orders, such as limit and stop orders

Unlike MQL4, MQL5 separates these concepts completely.