获取测试财务统计数据:TesterStatistics
我们通常根据交易报告来评估 EA 交易的质量,交易报告类似于用测试程序进行交易的测试报告。其包含了大量表征交易风格、稳定性以及盈利能力的变量。除了少数例外情况,所有这些指标均可通过特殊函数 TesterStatistics 用于 MQL 程序。因此,EA 交易开发人员能够分析代码中的单个变量,并根据这些变量构建他们自己的组合优化质量标准。
double TesterStatistics(ENUM_STATISTICS statistic)
TesterStatistics 函数可返回指定统计变量的值,该值是根据测试程序中 EA 交易的单独运行结果计算得出。可以在 OnDeinit 或 OnTester 处理程序中调用函数,这将在后面讨论。
ENUM_STATISTICS 枚举中总结了所有可用的统计变量。其中一些变量具有定性特征,即实数型(通常包括利润总额、提款、比率等),另一些变量具有定量特征,即整数型(例如交易次数)。但是,两组变量都由具有 double 结果的相同函数控制。
下表显示了实数型指标(货币金额和系数)。所有货币金额都以存款货币表示。
标识符 |
说明 |
---|---|
STAT_INITIAL_DEPOSIT |
初始存款 |
STAT_WITHDRAWAL |
从账户中提取的金额 |
STAT_PROFIT |
测试结束时的净利润或亏损,即 STAT_GROSS_PROFIT 和 STAT_GROSS_LOSS 的总和 |
STAT_GROSS_PROFIT |
总利润,即所有盈利交易的总和(大于等于零) |
STAT_GROSS_LOSS |
总亏损,即所有亏损交易的总和(小于或等于零) |
STAT_MAX_PROFITTRADE |
最大利润:所有盈利交易中的最大值(大于等于零) |
STAT_MAX_LOSSTRADE |
最大亏损:所有亏损交易中的最小值(小于或等于零) |
STAT_CONPROFITMAX |
一系列止盈交易的最大总利润(大于等于零) |
STAT_MAX_CONWINS |
最长止盈交易系列的总利润 |
STAT_CONLOSSMAX |
一系列亏损交易的最大总亏损(小于或等于零) |
STAT_MAX_CONLOSSES |
最长亏损交易系列的总亏损 |
STAT_BALANCEMIN |
最小余额值 |
STAT_BALANCE_DD |
最大余额提款 |
STAT_BALANCEDD_PERCENT |
在最大余额提款 (STAT_BALANCE_DD) 时记录的以百分比表示的余额提款 |
STAT_BALANCE_DDREL_PERCENT |
最大余额提取百分比 |
STAT_BALANCE_DD_RELATIVE |
在最大余额提款百分比 (STAT_BALANCE_DDREL_PERCENT) 时记录的以等值货币表示的余额提款 |
STAT_EQUITYMIN |
最小净值 |
STAT_EQUITY_DD |
最大提款金额 |
STAT_EQUITYDD_PERCENT |
在货币中资金的最大提款时 (STAT_EQUITY_DD) 记录的以百分比表示的提款 |
STAT_EQUITY_DDREL_PERCENT |
最大提款百分比 |
STAT_EQUITY_DD_RELATIVE |
最大提款时记录的以百分比表示的提款 (STAT_EQUITY_DDREL_PERCENT) |
STAT_EXPECTED_PAYOFF |
盈利的数学期望(总利润和交易次数的算术平均值) |
STAT_PROFIT_FACTOR |
盈利能力,即 STAT_GROSS_PROFIT/STAT_GROSS_LOSS 的比率(如果 STAT_GROSS_LOSS = 0;盈利能力取值 DBL_MAX) |
STAT_RECOVERY_FACTOR |
恢复系数:STAT_PROFIT/STAT_BALANCE_DD 的比率 |
STAT_SHARPE_RATIO |
夏普比率 |
STAT_MIN_MARGINLEVEL |
达到的最小保证金水平 |
STAT_CUSTOM_ONTESTER |
OnTester 函数返回的自定义优化准则的值 |
下表显示了整数型指标(金额)。
标识符 |
说明 |
---|---|
STAT_DEALS |
已完成的交易次数 |
STAT_TRADES |
交易次数(退出市场的交易) |
STAT_PROFIT_TRADES |
盈利交易 |
STAT_LOSS_TRADES |
亏损交易 |
STAT_SHORT_TRADES |
空头交易 |
STAT_LONG_TRADES |
多头交易 |
STAT_PROFIT_SHORTTRADES |
空头盈利交易 |
STAT_PROFIT_LONGTRADES |
多头盈利交易 |
STAT_PROFITTRADES_AVGCON |
一系列盈利交易的平均长度 |
STAT_LOSSTRADES_AVGCON |
一系列亏损交易的平均长度 |
STAT_CONPROFITMAX_TRADES |
构成 STAT_CONPROFITMAX 的交易次数(盈利交易序列中的最大利润) |
STAT_MAX_CONPROFIT_TRADES |
最长盈利交易系列的交易次数 |
STAT_CONLOSSMAX_TRADES |
构成 STAT_CONLOSSMAX 的交易次数(亏损交易序列中的最大亏损) |
STAT_MAX_CONLOSS_TRADES |
最长亏损交易系列的交易次数 STAT_MAX_CONLOSSES |
我们尝试使用给出的指标来创建我们自己的复杂 EA 交易质量标准。要做到这一点,我们需要某种 MQL 程序的“实验”示例。我们以 EA 交易 MultiMartingale.mq5 为起点,但是我们将对其进行简化:删除多币种、内置错误处理和时间安排。此外,我们将选择一个信号交易策略以及一个单一的计算柱线,即开盘价。这将加快优化速度,并扩大实验领域。
该策略将基于 OsMA 指标确定的超买和超卖条件。叠加在 OsMA 上的 Bollinger 带指标可帮你动态找到波动幅度过大的边界,即交易信号。
当 OsMA 从下向上穿越通道下边界并回到通道内时,我们将开启买入交易。当 OsMA 从上到下以同样的方式越过上边界时,我们则开启卖出交易。为了退出仓位,我们使用了移动平均线,也适用于 OsMA。如果 OsMA 显示反向移动(多头向下或空头向上)并触及 MA,该仓位将被平仓。下面的截图展示了这种策略。
基于 OsMA、BBands 和 MA 指标的交易策略
蓝色竖线对应的是开仓买入时的柱线,因为在前两根柱线上,下方的 Bollinger 带被 OsMA 柱状图从下向上穿过(这个仓位在子窗口内用蓝色空心箭头标出)。红色竖线是反转符号的位置,所以买入交易关闭,卖出交易打开。在子窗口中,在这个位置(或者更确切地说,在前面两根柱线上,空心红色箭头所在的位置),OsMA 柱状图自上而下穿过上 Bollinger 带。最后,绿线表示成交,因为柱状图开始高于红色均线。
我们将 EA 交易命名为 BandOsMA.mq5。一般设置将包括一个魔术编号、一个固定手数和一个以点为单位的止损距离。对于止损,我们将使用前面示例中的 TrailingStop。此处不用止盈。
input group "C O M M O N S E T T I N G S"
|
三组设置可用于这些指标。
input group "O S M A S E T T I N G S"
|
在 MultiMartingale.mq5 EA 交易中,我们没有交易信号,而开仓方向是由用户设定的。此处我们有交易信号,合理做法是将其单独列为一类。首先,我们说明一下抽象接口 TradingSignal。
interface TradingSignal
|
该接口和我们的其他接口 TradingStrategy 一样简单。这样很好。接口和对象越简单,就越有可能执行同样的操作,这是一种很好的编程风格,因为可最大限度地减少错误,并使大型软件项目更容易理解。由于在任何使用 TradingSignal 的程序中都有抽象概念,便可以用一个信号替换另一个信号。我们也可以替换策略。我们的策略现在负责准备和发送订单,并根据市场分析发出启动订单符号。
就我们的情况下而言,我们将 TradingSignal 的具体实现打包到 BandOsMaSignal 类中。当然,我们需要变量来存储 3 个指标的说明符。指标实例分别在构造函数和析构函数中创建和删除。所有参数都将通过输入变量传递。注意,iBands 和 iMA 是基于 hOsMA 处理程序构建的。
class BandOsMaSignal: public TradingSignal
|
当前交易信号的方向放在 direction 变量内:0 - 无信号(未定义情况),+1 - 买入,-1 - 卖出。我们将在 signal 方法中填充这个变量。其代码重复了上面 MQL5 中信号的口头说明。
virtual int signal(void) override
|
可以看到,指标值是为第 1 和第 2 根柱线读取的,因为我们将打开一根柱线,而第 0 根柱线在我们调用 signal 方法时刚刚打开。
实现 TradingStrategy 接口的新类将被命名为 SimpleStrategy。
该类提供了一些新特性,同时还使用了一些以前存在的部分。特别是,其为 PositionState 和 TrailingStop 保留了自动指针,并为 TradingSignal 信号提供了一个新的自动指针。此外,因为我们只在柱线打开时交易,所以我们需要 lastBar 变量,其用于存储最后一个处理柱线的时间。
class SimpleStrategy: public TradingStrategy
|
全局参数被传递给 SimpleStrategy 构造函数。我们还传递一个指向 TradingSignal 对象的指针:在这种情况下,为 BandOsMaSignal,该指针必须通过调用代码来创建。接下来,构造函数试图在现有仓位中找到具有所需 magic 号和符号的仓位,如果成功,则添加一个跟踪止损。如果 EA 交易因为这样或那样的原因而中止运行,并且仓位已经被打开,这将是有用的。
public:
|
trade 方法的实现类似于鞅的示例。但是,我们已经删除了许多乘法,并增加了 signal 方法调用。
virtual bool trade() override
|
辅助方法 openBuy、openSell 等都做了极小的改动,就不一一列举了(完整源代码附后)。
因为在这个 EA 交易中我们总是只有一个策略,与多币种鞅相反,在多币种鞅中每个符号都需要自己的设置,所以我们可以排除策略池,直接管理策略对象。
AutoPtr<TradingStrategy> strategy;
|
我们现在有了一个现成的 EA 交易,可以用来作为研究测试程序的工具。首先,我们创建一个辅助结构体 TesterRecord,用于查询和存储所有统计数据。
struct TesterRecord
|
在这种情况下,只有信息日志输出才需要 feature 字符串型字段。要保存所有指标(例如,为了能够在以后生成你自己的报告),只需要一个适当长度的 double 类型的简单数组。
使用 OnDeinit 处理程序中的结构体,我们可确保 MQL5 API 返回与测试程序报告相同的值。
void OnDeinit(const int)
|
例如,在存款为 10000 且未进行任何优化(使用默认设置)的情况下,在 EURUSD,H1 上运行 EA 交易时,对于 2021 年,我们将获得大约以下值(片段):
[feature] [value]
|
知道了所有这些值,我们可以编写我们自己的公式,用于 EA 交易质量的组合度量指标,同时用于目标优化函数。但是在任何情况下,这个指标的值都需要向测试程序报告。这就是 OnTester 函数的作用。