- Expert Advisors main event: OnTick
- Basic principles and concepts: order, deal, and position
- Types of trading operations
- Order types
- Order execution modes by price and volume
- Pending order expiration dates
- Margin calculation for a future order: OrderCalcMargin
- Estimating the profit of a trading operation: OrderCalcProfit
- MqlTradeRequest structure
- MqlTradeCheckResult structure
- Request validation: OrderCheck
- Request sending result: MqlTradeResult structure
- Sending a trade request: OrderSend and OrderSendAsync
- Buying and selling operations
- Modying Stop Loss and/or Take Profit levels of a position
- Trailing stop
- Closing a position: full and partial
- Closing opposite positions: fill and partial
- Placing a pending order
- Modifying a pending order
- Deleting a pending order
- Getting a list of active orders
- Order properties (active and historical)
- Functions for reading properties of active orders
- Selecting orders by properties
- Getting the list of positions
- Position properties
- Functions for reading position properties
- Deal properties
- Selecting orders and deals from history
- Functions for reading order properties from history
- Functions for reading deal properties from history
- Types of trading transactions
- OnTradeTransaction event
- Synchronous and asynchronous requests
- OnTrade event
- Monitoring trading environment changes
- Creating multi-symbol Expert Advisors
- Limitations and benefits of Expert Advisors
- Creating Expert Advisors in the MQL Wizard
Functions for reading position properties
An MQL program can get position properties using several PositionGet functions depending on the type of properties. In all functions, the specific property being requested is defined in the first parameter, which takes the ID of one of the ENUM_POSITION_PROPERTY enumerations discussed in the previous section.
For each type of property, there is a short and long form of the function: the first returns the value of the property directly, and the second writes it into the second parameter, passed by reference.
Integer properties and properties of compatible types (datetime, enumerations) can be obtained by the PositionGetInteger function.
long PositionGetInteger(ENUM_POSITION_PROPERTY_INTEGER property)
bool PositionGetInteger(ENUM_POSITION_PROPERTY_INTEGER property, long &value)
If it fails, the function returns 0 or false.
The PositionGetDouble function is used to obtain real properties.
double PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE property)
bool PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE property, double &value)
Finally, the string properties are returned by the PositionGetString function.
string PositionGetString(ENUM_POSITION_PROPERTY_STRING property)
bool PositionGetString(ENUM_POSITION_PROPERTY_STRING property, string &value)
In case of failure, the first form of the function returns an empty string.
To read position properties, we already have a ready abstract interface MonitorInterface (TradeBaseMonitor.mqh) which we used to write an order monitor. Now it will be easy to implement a similar monitor for positions. The result is attached in the file PositionMonitor.mqh.
The PositionMonitorInterface class is inherited from MonitorInterface with assignment to the template types I, D, and S of the considered ENUM_POSITION_PROPERTY enumerations, and overrides a couple of stringify methods taking into account the specifics of position properties.
class PositionMonitorInterface:
|
The specific monitor class, ready to view positions, is next in the inheritance chain and is based on PositionGet functions. Selecting a position by ticket is done in the constructor.
class PositionMonitor: public PositionMonitorInterface
|
A simple script will allow you to log all the characteristics of the first position (if at least one is available).
void OnStart()
|
In the log, we should get something like this.
MonitorInterface<ENUM_POSITION_PROPERTY_INTEGER, »
|
If there are no open positions at the moment, we will see an error message.
Error: PositionSelectByTicket(0) failed: TRADE_POSITION_NOT_FOUND |
However, the monitor is useful not only and not so much by outputting properties to the log. Based on PositionMonitor, we create a class for selecting positions by conditions, similar to what we did for orders (OrderFilter). The ultimate goal is to improve our grid Expert Advisor.
Thanks to OOP, creating a new filter class is almost effortless. Below is the complete source code (file PositionFilter.mqh).
class PositionFilter: public TradeFilter<PositionMonitor,
|
Now we can write such a script for receiving specific profit on positions with the given magic number, for example.
input ulong Magic;
|
In this case, we had to call the select method twice, because the types of properties we are interested in are different: real profit and lot, but the string name of the instrument. In one of the sections at the beginning of the chapter, when we were developing the filter class for symbols, we described the concept of tuples. In MQL5, we can implement it as structure templates with fields of arbitrary types. Such tuples would come in very handy for finalizing the hierarchy of filter classes since then it would be possible to describe the select method that fills an array of tuples with fields of any type.
The tuples are described in the file Tuples.mqh. All structures in it have a name TupleN<T1,...>, where N is a number from 2 to 8, and it corresponds to the number of template parameters (Ti types). For example, Tuple2:
template<typename T1,typename T2>
|
In the class TradeFilter (TradeFilter.mqh) let's add a version of the function select with tuples.
template<typename T,typename I,typename D,typename S>
|
An array of tuples can optionally be sorted by the first field _1, so you can additionally study the sortTuple helper method.
With tuples, you can query a filter object for properties of three different types in one select call.
Below there are positions with some Magic number displayed, sorted by profit; for each a symbol and a ticket are additionally obtained.
input ulong Magic;
|
Of course, the parameter types in the description of the array of tuples (in this case, Tuple3<double,string,ulong>) must match the requested property enumeration types (POSITION_PROFIT, POSITION_SYMBOL, POSITION_TICKET).
Now we can slightly simplify the grid Expert Advisor (meaning not just a shorter, but also a more understandable code). The new version is called PendingOrderGrid2.mq5. The changes will affect all functions related to position management.
The GetMyPositions function populates the types4tickets array of tuples passed by reference. In each Tuple2 tuple, it is supposed to store the type and ticket of the position. In this particular case, we could manage just with a two-dimensional array ulong instead of tuples because both properties are of the same base type. However, we use tuples to demonstrate how to work with them in the calling code.
#include <MQL5Book/Tuples.mqh>
|
Note that the last, third parameter of the select method equals true, which instructs to sort the array by the first field, i.e., the type of positions. Thus, we will have purchases at the beginning, and sales at the end. This will be required for the counter closure.
The reincarnation of the CompactPositions method is as follows.
uint CompactPositions(const bool cleanup = false)
|
The CloseAllPositions function is almost the same:
uint CloseAllPositions(const Tuple2<ulong,ulong> &types4tickets[],
|
You can compare the work of Expert Advisors PendingOrderGrid1.mq5 and PendingOrderGrid2.mq5 in the tester.
The reports will be slightly different, because if there are several positions, they are closed in opposite combinations, due to which the closing of other, unpaired positions takes place with respect to their individual spreads.