- 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 properties of active orders
The sets of functions that can be used to get the values of all order properties differ for active and historical orders. This section describes the functions for reading the properties of active orders. For the functions for accessing the properties of orders in the history, see the relevant section.
Integer properties can be read using the OrderGetInteger function, which has two forms: the first one returns directly the value of the property, the second one returns a logical sign of success (true) or error (false), and the second parameter passed by reference is filled with the value of the property.
long OrderGetInteger(ENUM_ORDER_PROPERTY_INTEGER property)
bool OrderGetInteger(ENUM_ORDER_PROPERTY_INTEGER property, long &value)
Both functions allow you to get the requested order property of an integer-compatible type (datetime, long/ulong or listing). Although the prototype mentions long, from a technical point of view, the value is stored as an 8-byte cell, which can be cast to compatible types without any conversion of the internal representation, in particular, to ulong, which is used for all tickets.
A similar pair of functions is intended for properties of real type double.
double OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE property)
bool OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE property, double &value)
Finally, string properties are available through a pair of OrderGetString functions.
string OrderGetString(ENUM_ORDER_PROPERTY_STRING property)
bool OrderGetString(ENUM_ORDER_PROPERTY_STRING property, string &value)
As their first parameter, all functions take the identifier of the property we are interested in. This must be an element of one of the enumerations ENUM_ORDER_PROPERTY_INTEGER, ENUM_ORDER_PROPERTY_DOUBLE, or ENUM_ORDER_PROPERTY_STRING discussed in the previous section.
Please note before calling any of the previous functions, you should first select an order using OrderSelect or OrderGetTicket.
To read all the properties of a specific order, we will develop the OrderMonitor class (OrderMonitor.mqh) which operates on the same principle as the previously considered symbol (SymbolMonitor.mqh) and trading account (AccountMonitor.mqh) monitors.
These and other monitor classes discussed in the book offer a unified way to analyze properties through overloaded versions of virtual get methods.
Looking a little ahead, let's say that deals and positions have the same grouping of properties according to the three main types of values, and we also need to implement monitors for them. In this regard, it makes sense to separate the general algorithm into a base abstract class MonitorInterface (TradeBaseMonitor.mqh). This is a template class with three parameters intended to specify the types of specific enumerations, for integer (I), real (D), and string (S) property groups.
#include <MQL5Book/EnumToArray.mqh>
|
Due to the fact that finding an order (deal or position) in the trading environment may fail for various reasons, the class has a reserved variable ready in which derived classes will have to write a sign of successful initialization, that is, the choice of an object to read its properties.
Several purely virtual methods declare access to properties of the corresponding types.
virtual long get(const I property) const = 0;
|
In the first three methods, the property type is specified by one of the template parameters. In further three methods, the type is specified by the second parameter of the method itself: this is required because the last methods take not the constants of a particular enumeration but simply an integer as the first parameter. On the one hand, this is convenient for the continuous numbering of identifiers (the enumeration constants of the three types do not intersect). On the other hand, we need another source for determining the type of value since the type returned by the function/method does not participate in the process of choosing the appropriate overload.
This approach allows you to get properties based on various inputs available in the calling code. Next, we will create classes based on OrderMonitor (as well as future DealMonitor and PositionMonitor) to select objects according to a set of arbitrary conditions, and there all these methods will be in demand.
Quite often, programs need to get a string representation of any properties, for example, for logging. In the new monitors, this is implemented by the stringify methods. Obviously, they get the values of the requested properties through get method calls mentioned above.
virtual string stringify(const long v, const I property) const = 0;
|
The only method that has not received implementation is the first version of stringify for type long. This is due to the fact that the group of integer properties, as we saw in the previous section, actually contain different application types, including date and time, enumerations, and integers. Therefore, only derived classes can provide their conversion to understandable strings. This situation is common for all trading entities, not only orders but also deals and positions the properties of which we will consider later.
When an integer property contains an enumeration element (for example, ENUM_ORDER_TYPE, ORDER_TYPE_FILLING, etc.), you should use the EnumToString function to convert it to a string. This task is fulfilled by a helper method enumstr. Soon we will see its widespread use in specific monitor classes, starting with OrderMonitor after a couple of paragraphs.
template<typename E>
|
To log all properties of a particular type, we have created the list2log method which uses stringify in a loop.
template<typename E>
|
Finally, to make it easier to log the properties of all three groups, there is a method print which calls list2log three times for each group of properties.
virtual void print() const
|
Having at our disposal a base template class MonitorInterface, we describe OrderMonitorInterface, where we specify certain enumeration types for orders from the previous section and provide an implementation of stringify for integer properties of orders.
class OrderMonitorInterface:
|
The STR_TIME_MSC macro for displaying time in milliseconds is defined as follows:
#define STR_TIME_MSC(T) (TimeToString((T) / 1000, TIME_DATE | TIME_SECONDS) \
|
Now we are ready to describe the final class for reading the properties of any order: OrderMonitor derived from OrderMonitorInterface. The order ticket is passed to the constructor, and it is selected in the trading environment using OrderSelect.
class OrderMonitor: public OrderMonitorInterface
|
The main working part of the monitor consists of redefinitions of virtual functions for reading properties. Here we see the OrderGetInteger, OrderGetDouble, and OrderGetString function calls.
virtual long get(const ENUM_ORDER_PROPERTY_INTEGER property) const override
|
This code fragment is presented in a short form: operators for working with orders in the history have been removed from it. we will see the full code of OrderMonitor later when we explore this aspect in the following sections.
It is important to note that the monitor object does not store copies of its properties. Therefore, access to get methods must be carried out immediately after the creation of the object and, accordingly, the call OrderSelect. To read the properties at a later period, you will need to allocate the order again in the internal cache of the MQL program, for example, by calling the method refresh.
void refresh()
|
Let's test the work of OrderMonitor by adding it to the Expert Advisor MarketOrderSend.mq5. A new version named MarketOrderSendMonitor.mq5 connects the file OrderMonitor.mqh by the directive #include, and in the body of the function OnTimer (in the block of successful confirmation of opening a position on an order) creates a monitor object and calls its print method.
#include <MQL5Book/OrderMonitor.mqh>
|
In the log, we should see new lines containing all the properties of the order.
OK Order: #=1287846602
|
The fourth line starts the output from the print method which includes the full name of the monitor object MonitorInterface together with parameter types (in this case, the triple ENUM_ORDER_PROPERTY) and then all the properties of a particular order.
However, property printing is not the most interesting action a monitor can provide. The task of selecting orders by conditions (values of arbitrary properties) is much more in demand among Experts Advisors. Using the monitor as an auxiliary tool, we will create a mechanism for filtering orders similar to what we have done for symbols: SymbolFilter.mqh.