- EA 交易的主要事件:OnTick
- 基本原理和概念:订单、交易和仓位
- 交易操作类型
- 订单类型
- 按价格和数量划分的订单执行模式
- 挂单到期日期
- 期货订单的保证金计算方法:OrderCalcMargin
- 估算交易操作的利润:OrderCalcProfit
- MqlTradeRequest 结构体
- MqlTradeCheckResult 结构体
- 请求验证:OrderCheck
- 请求发送结果:MqlTradeResult 结构体
- 发送交易请求:OrderSend 和 OrderSendAsync
- 买入和卖出操作
- 修改仓位的止损和/或止盈水平
- 跟踪止损
- 平仓:全部和部分
- 反向平仓:全部和部分
- 挂单
- 修改挂单
- 删除挂单
- 获取活动订单列表
- 订单特性(现行和历史)
- 用于读取活动订单特性的函数
- 按特性选择订单
- 获取仓位列表
- 仓位特性
- 用于读取仓位特性的函数
- 交易特性
- 从历史中选择订单和交易
- 用于从历史中读取订单特性的函数
- 用于从历史中读取交易特性的函数
- 交易类型
- OnTradeTransaction 事件
- 同步和异步请求
- OnTrade 事件
- 监测交易环境变化
- 创建多交易品种 EA 交易
- EA 交易的优势和局限性
- 在 MQL 向导中创建 EA 交易
用于读取活动订单特性的函数
对于活动订单和历史订单,可用于获取所有订单特性值的函数集并不相同。本节介绍读取活动订单特性的函数。有关访问历史订单特性的函数,请参见 相关章节。
可以使用 OrderGetInteger 函数读取整数型特性,该函数有两种形式:第一种直接返回特性值,第二种返回成功 (true) 或错误 (false) 的逻辑交易品种,第二种通过引用传递的参数用特性值填充。
long OrderGetInteger(ENUM_ORDER_PROPERTY_INTEGER property)
bool OrderGetInteger(ENUM_ORDER_PROPERTY_INTEGER property, long &value)
这两个函数都允许你获取请求的整数兼容类型的订单特性(datetime、long/ulong 或 listing)。虽然原型提到了long,但从技术角度来看,该值存储为一个 8 字节的单元,可以将其强制转换为兼容的类型,而无需对内部表示进行任何转换,特别是转换为 ulong,用于所有订单号。
一对类似的函数用于实数型 double 的特性。
double OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE property)
bool OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE property, double &value)
最后,字符串型特性可通过一对 OrderGetString 函数获得。
string OrderGetString(ENUM_ORDER_PROPERTY_STRING property)
bool OrderGetString(ENUM_ORDER_PROPERTY_STRING property, string &value)
所有函数的第一个参数都是我们感兴趣的特性标识符。这必须是下列其中一个枚举元素:ENUM_ORDER_PROPERTY_INTEGER、ENUM_ORDER_PROPERTY_DOUBLE 或 ENUM_ORDER_PROPERTY_STRING(在 上一节中讨论过)。
请注意,在调用任何上述函数之前,应首先使用 OrderSelect 或 OrderGetTicket 选择一个订单。
为了读取特定订单的所有特性,我们将开发 OrderMonitor 类(OrderMonitor.mqh),其工作原理与之前考虑的交易品种 (SymbolMonitor.mqh) 和交易账户 (AccountMonitor.mqh) 监视器相同。
本书中讨论的这些类和其他 monitor 类提供了一种统一的方法,通过重载版本的虚拟 get 方法来分析特性。
回顾一下,假设交易和仓位根据三种主要类型的值具有相同的特性分组,并且我们还需要为其实现监视器。在这方面,将通用算法将其分离到一个基础抽象类 MonitorInterface (TradeBaseMonitor.mqh) 中是有意义的。这是一个具有三个参数的模板类,用于为整数型 (I)、实数型 (D) 和字符串型 (S) 特性组指定特定枚举的类型。
#include <MQL5Book/EnumToArray.mqh>
|
由于在交易环境中寻找订单(交易或仓位)可能会因各种原因而失败,该类有一个保留变量 ready,其中派生类必须写入成功初始化的标志,即选择一个对象来读取其特性。
几个纯虚方法声明对相应类型特性的访问。
virtual long get(const I property) const = 0;
|
在前三种方法中,特性类型由模板参数之一指定。在另外三种方法中,类型由方法本身的第二个参数指定:这是必需的,因为最新方法不接受特定枚举的常量,而只接受一个整数作为第一个参数。一方面,这便于标识符的连续编号(三种类型的枚举常量不相交)。另一方面,我们需要另一个来源来确定值类型,因为函数/方法返回的类型不参与选择适当 重载的过程。
这种方法允许你基于调用代码中可用的各种输入来获取特性。接下来,我们将基于 OrderMonitor(以及期货的 DealMonitor 和 PositionMonitor)创建类,以根据一组任意条件选择对象,所有这些方法都将是必需的。
通常,程序需要获得任何特性的字符串表示,例如,用于日志记录。在新的监视器中,这是通过 stringify 方法实现的。显然,它们可通过上面提到的 get 方法调用来获取所请求特性的值。
virtual string stringify(const long v, const I property) const = 0;
|
唯一没有实现的方法是 long类型的 stringify 的第一个版本。这是因为,正如我们在上一节中看到的,整数型特性组实际上包含不同的应用程序类型,包括日期和时间、枚举和整数。因此,只有派生类可以提供其到可理解字符串的转换。这种情况对于所有交易实体都是常见的,不仅是订单,还有交易和仓位,我们将在后面考虑其特性。
当整数型特性包含枚举元素(例如 ENUM_ORDER_TYPE、ORDER_TYPE_FILLING 等)时,应使用 EnumToString 函数将其转换为字符串。这个任务由一个辅助方法 enumstr 来完成。很快我们将看到该方法在特定监视器类中的广泛使用,在几个段落之后从 OrderMonitor 开始。
template<typename E>
|
为了记录特定类型的所有特性,我们创建了 list2log 方法,该方法在循环中使用 stringify 。
template<typename E>
|
最后,为了更容易地记录所有三个组的特性,有一个print 方法,它为每组特性调用 list2log 三次。
virtual void print() const
|
利用一个基础模板类 MonitorInterface,我们可以说明 OrderMonitorInterface,其中为上一节中的订单指定了某些枚举类型,并为订单的整数型特性提供了 stringify 的实现。
class OrderMonitorInterface:
|
以毫秒为单位显示时间的 STR_TIME_MSC 宏定义如下:
#define STR_TIME_MSC(T) (TimeToString((T) / 1000, TIME_DATE | TIME_SECONDS) \
|
现在我们准备介绍用于读取任何订单特性的最终类:OrderMonitor,派生自 OrderMonitorInterface。订单号被传递给构造函数,并在交易环境中使用 OrderSelect 进行选择。
class OrderMonitor: public OrderMonitorInterface
|
监视器的主要工作部分包括读取特性的虚函数的重新定义。此处我们看到了 OrderGetInteger、OrderGetDouble 和 OrderGetString 函数的调用。
virtual long get(const ENUM_ORDER_PROPERTY_INTEGER property) const override
|
该代码片段以简短的形式呈现:用于处理历史中订单的运算符已删除。当我们在接下来的章节中探讨这个方面时,我们将看到 OrderMonitor 的完整代码。
值得注意的是,监视器对象不存储其特性的副本。因此,对 get 方法的访问必须在创建对象以及相应的调用 OrderSelect 之后立即执行。要在以后读取这些特性,需要在 MQL 程序的内部缓存中再次分配该订单,例如,通过调用方法 refresh。
void refresh()
|
我们通过将 OrderMonitor 添加到 EA 交易 MarketOrderSend.mq5 来测试其运行情况。一个名为 MarketOrderSendMonitor.mq5 的新版本通过指令 #include 连接文件 OrderMonitor.mqh,并在 OnTimer 函数体(在订单上成功确认开仓的块)中创建一个监视器对象并调用其 print 方法。
#include <MQL5Book/OrderMonitor.mqh>
|
在日志中,我们可看到包含订单所有特性的新行。
OK Order: #=1287846602
|
第四行开始于 print 方法的输出,其中包括监视器对象 MonitorInterface 的全名以及参数类型(在本例中是三重 ENUM_ORDER_PROPERTY ),然后是特定订单的所有特性。
但是,特性打印并不是监视器所能提供的最有趣操作。根据条件(任意特性值)选择订单的任务在 EA 交易中更受欢迎。使用监视器作为辅助工具,我们可创建一个筛选订单的机制,类似于我们对交易品种 SymbolFilter.mqh 所创建的机制。