- EA 交易的主要事件:OnTick
- 基本原理和概念:订单、交易和仓位
- 交易操作类型
- 订单类型
- 按价格和数量划分的订单执行模式
- 挂单到期日期
- 期货订单的保证金计算方法:OrderCalcMargin
- 估算交易操作的利润:OrderCalcProfit
- MqlTradeRequest 结构体
- MqlTradeCheckResult 结构体
- 请求验证:OrderCheck
- 请求发送结果:MqlTradeResult 结构体
- 发送交易请求:OrderSend 和 OrderSendAsync
- 买入和卖出操作
- 修改仓位的止损和/或止盈水平
- 跟踪止损
- 平仓:全部和部分
- 反向平仓:全部和部分
- 挂单
- 修改挂单
- 删除挂单
- 获取活动订单列表
- 订单特性(现行和历史)
- 用于读取活动订单特性的函数
- 按特性选择订单
- 获取仓位列表
- 仓位特性
- 用于读取仓位特性的函数
- 交易特性
- 从历史中选择订单和交易
- 用于从历史中读取订单特性的函数
- 用于从历史中读取交易特性的函数
- 交易类型
- OnTradeTransaction 事件
- 同步和异步请求
- OnTrade 事件
- 监测交易环境变化
- 创建多交易品种 EA 交易
- EA 交易的优势和局限性
- 在 MQL 向导中创建 EA 交易
用于从历史中读取订单特性的函数
根据特性值的基本类型,按照将可用特性的标识符划分为 3 种枚举,这与将可用属性标识符划分为三个枚举的方式一致: ENUM_ORDER_PROPERTY_INTEGER、 ENUM_ORDER_PROPERTY_DOUBLE 和 ENUM_ORDER_PROPERTY_STRING ,这在前面研究活动订单时的 单独的章节 中讨论过。
在调用这些函数之前,你需要以某种方式 在历史中选择一组合适的订单号。
如果你尝试读取其订单号不在所选历史上下文内的订单或交易的特性,环境可能会生成 WRONG_INTERNAL_PARAMETER (4002) 错误,可以通过 _LastError对其进行分析。
对于每个基础特性类型,有两种函数形式:一种直接返回所请求特性的值,第二种将它写入通过引用传递的参数,并返回成功指示符 (true)或错误 (false)。
对于整数型及其兼容型(datetime 和枚举)特性,有一个专用函数 HistoryOrderGetInteger。
long HistoryOrderGetInteger(ulong ticket, ENUM_ORDER_PROPERTY_INTEGER property)
bool HistoryOrderGetInteger(ulong ticket, ENUM_ORDER_PROPERTY_INTEGER property,
long &value)
该函数允许你通过订单号从所选历史中找出订单 property。
对于实数型特性,分配了 HistoryOrderGetDouble 函数
double HistoryOrderGetDouble(ulong ticket, ENUM_ORDER_PROPERTY_DOUBLE property)
bool HistoryOrderGetDouble(ulong ticket, ENUM_ORDER_PROPERTY_DOUBLE property,
double &value)
最后,可以使用 HistoryOrderGetString 读取字符串型特性。
string HistoryOrderGetString(ulong ticket, ENUM_ORDER_PROPERTY_STRING property)
bool HistoryOrderGetString(ulong ticket, ENUM_ORDER_PROPERTY_STRING property,
string &value)
现在我们可以补充 OrderMonitor 类 (OrderMonitor.mqh) 来处理历史订单。首先,让我们将一个布尔变量添加到 history 类中,我们将根据选择带有传递订单号订单的片段将该变量填充到构造函数中:在活跃订单中 (OrderSelect) 或在历史 (HistoryOrderSelect) 中。
class OrderMonitor: public OrderMonitorInterface
|
我们需要在成功的 if 分支中调用 ResetLastError 函数,以便重置可能由 OrderSelect 函数设置的错误(如果订单在历史中)。
事实上,这个版本的构造函数包含了一个严重的逻辑错误,我们将在几段后返回来研究。
为了读取 get 方法中的特性,我们现在调用不同的内置函数,具体取决于 history 变量的值。
virtuallongget(constENUM_ORDER_PROPERTY_INTEGERproperty)constoverride { returnhistory?HistoryOrderGetInteger(ticket、property) :OrderGetInteger(property); }
virtualdoubleget(constENUM_ORDER_PROPERTY_DOUBLEproperty)constoverride { returnhistory?HistoryOrderGetDouble(ticket、property) :OrderGetDouble(property); }
virtualstringget(constENUM_ORDER_PROPERTY_STRINGproperty)constoverride { returnhistory?HistoryOrderGetString(ticket、property) :OrderGetString(property); } ... |
OrderMonitor 类的主要用途是向其他分析类提供数据。OrderMonitor 对象用于筛选 OrderFilter 类中的活动订单,我们需要一个类似的类来根据历史中的任意条件选择订单:HistoryOrderFilter。
让我们在同一个文件 OrderFilter.mqh 中编写这个类。其使用两个新函数来处理历史:HistoryOrdersTotal 和 HistoryOrderGetTicket。
class HistoryOrderFilter: public TradeFilter<OrderMonitor,
|
这个简单的代码继承自模板类 TradeFilter,其中该类作为模板 OrderMonitor 的第一个参数传递,以读取相应对象的特性(我们看到了一个用于仓位的模拟,很快也会为交易创建一个模拟)。
这就是 OrderMonitor 构造函数的问题所在。正如我们在 从历史中选择订单和交易一节中了解到的,为了分析账户,我们必须首先用一个函数(如 HistorySelect)设置上下文。因此,在源代码 HistoryOrderFilter 中,假设 MQL 程序已经选择了所需的历史片段。但是,OrderMonitor 构造函数的新中间版本可使用 HistoryOrderSelect 调用来检查订单号在历史中是否存在。同时,该函数还可以重置历史订单的先前上下文并选择单个订单。
因此,我们需要一个辅助方法 historyOrderSelectWeak,以一种“软”的方式验证订单号,而不破坏现有的上下文。为此,我们可以简单地检查 ORDER_TICKET 特性是否等于传递的订单号 t:(HistoryOrderGetInteger(t, ORDER_TICKET) == t)。如果已经选择了这样的订单号(可用),则检查成功,并且监视器不需要操作历史。
class OrderMonitor: public OrderMonitorInterface
|
在我们为交易准备了类似的功能后,下一节将考虑对历史应用订单筛选的示例。