简介
嵌在 Meta Trader 4 客户端的策略测试程序是 Expert Advisor 内实现的交易策略的优秀检验/质量评估工具。但当前,(在我看来)它有两个缺陷。第一,它不使用交易品种的真实价格变动历史和基于一分钟柱形图对价格变动建模。第二,它没有考虑经纪人重新报价非常频繁的现象,尤其是在交易额较少或交易额非常大以及在“交易清淡”的低流动性市场上。在潜在的重新报价条件下,若不检查 EA 会导致“圣杯”出现,在“峰值”、上升趋势和非市场报价下交易。已经多次解释和证明,这种策略在真实帐户上难以有效,但不幸的是,通常很难意识到你的 Expert Advisors 是否在“峰值”操作。在具有交易的历史图表上,有时可能看到测试程序在上升趋势开仓交易,但并非每次都如此。也很难预测这是否会在此时削弱重新报价策略或仅仅降低获利能力。本文中,我将描述自己的问题解决方法。
假设和定义
重新报价是经纪人对你发送至交易服务器订单的响应。经纪人的响应告知该价格(你试图开仓交易的价格)已不再是实际价格。这通常发生在低流动性或波动的市场上,在交易终端处理你的交易请求时,价格可能大幅变动。当试图在畅销和非市场报价开仓时重新报价也非常频繁。
我们现在假设 Expert Advisor 仅开仓和平仓像 OP_SELL 和 OP_BUY 这样的订单。这不会改变实质,但简化了某些函数。
策略测试程序的重新报价建模
现在用开仓和平仓订单时提前设定的概率模拟重新报价。首先,我们输入设定人工重新报价发生概率的特殊外部变量。根据我的调查/监测,在低流动性货币对畅销时重新报价的概率接近 90%——因此在 Expert Advisor 分析中采用该值。
extern int RQF_TEST = 90;
由于我们要使用 MathRand 函数返回一个任意值,最好初始化伪随机数序列。为此,将在开始运行 Expert Advisor 时执行 MathSrand 函数。更多关于随机值产生和该函数目的的详细信息,可以学习关于 MQL 语言的参考书籍。需要说明的是,如果不使用 MathSrand,尽管存在 MathRand 函数的数字“随机性”,我们运行策略总会得到相同的结果。一般来讲,这并不适合我们:
int start()
{
MathSrand(TimeCurrent());
然后,我们应编写自己的函数 OrderSend 和 OrderClose。将其命名为 MyOrderSend 和 MyOrderClose:
int MyOrderSend(int req_prob, string symbol, int cmd, double volume, double price,
int slippage, double stoploss, double takeprofit,
string comment="", int magic=0, datetime expiration=0,
color arrow_color=CLR_NONE)
{
if(IsTesting() && (MathRand() % 100) < req_prob && (cmd == OP_SELL || cmd == OP_BUY))
return (-1);
return(OrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit,
comment, magic, expiration, arrow_color));
}
bool MyOrderClose(int req_prob, int ticket, double lots, double price, int slippage,
color Color=CLR_NONE)
{
if(IsTesting() && (MathRand() % 100) < req_prob)
return (false);
return (OrderClose(ticket, lots, price, slippage, Color));
}
现在应该将 EA 内的所有 OrderSend 和 OrderClose 函数替换成 MyOrderSend 和 MyOrderClose,同时表明在外部变量 RQF_TEST 之前输入的内容作为第一个参数。以下是来自我自己的 EA 示例。
OrderClose -> MyOrderClose:
if(MyOrderClose(RQF_TEST, ticket, amount, Bid, 0, Blue))
{
Print("Skalpel: Order #" + ticket + " closed! (BUY, " + Bid + ")");
}
else
{
Print("Skalpel: Error while closing order #" + ticket + " (BUY)!");
}
OrderSend -> MyOrderSend:
ticket = MyOrderSend(RQF_TEST, Symbol(), OP_BUY, amount, Ask, 0,
Bid-StopLoss*Point, Bid+TakeProfit*Point,
NULL, EXPERT_MAGIC, 0, Blue);
if(ticket > 0)
Print("Skalpel: Order #" + ticket + " opened! (BUY)");
else
Print("Skalpel: Error while placing order.");
总结和结果分析
首先,应该解释 RQF_TEST 变量的值。它设定了 100 次交易的重新报价数量,相应地取值从 0(没有重新报价)到 100(绝对不可能开仓或平仓订单)。如果在某实例中 RQF_TEST 等于 90,说明 100 次开仓或平仓交易尝试中约有 90 次最终失败,即模拟重新报价。
实际上,在各种 RQF_TEST 值得到的结果显示了你的策略对重新报价和测试程序和经纪人之间价格变动流差异的稳定性。
如果在 RQF_TEST 增长时结果恶化,有必要检查该策略的适宜性,因为对重新报价的敏感度意味着你在剧烈短暂的井喷行情中或不良情绪下交易。关于使用这种智能交易系统的后果已经说了很多。
例如,考虑各种 RQF_TEST 值下在井喷行情时的 EA 经典平衡图表。该 Expert Advisor 取自文章“我的第一个圣杯”(),并为了可视化稍微进行了转换。所有限制类型的订单均由常见市场订单实现,收集参数后,图表显示了重新报价最为显著时的参数恶化。
无重新报价(RQF_TEST = 0):
100 次中有 90 次出现重新报价(RQF_TEST = 90):
显然,这种情形非常糟糕。尤其在测试的 EURCHF 是流动极低的货币对,即使在清淡的市场上重新报价也很频繁,更不用说火热的货币对了。因此,尽管在没有重新报价时图表很漂亮,但使用 EA 的适宜性正在消失。
评价和补充
实际上,发现这种由于重新报价而从获利变为不获利的智能交易系统相当困难。长时间以来,我一直在寻找这种质量下降能清楚的反映在平衡图上的 Expert Advisor。通常,当图表表面上相同时(常量),重新报价(即使在 50% 的水平)会削减交易数量和利润。对此有简单的解释:如果经纪人不允许你在 100 次交易中有 90 次重新报价的“风险”下开仓,那么在剩下的 10% 情况下你会收获一些利润,直到你可以使用 EA。对这种情形的描述请见文章“我的第一个圣杯”。但即使我们假设经纪人不会妨碍(这种情况极少),10 倍的利润减少(当重新报价达到 90% 的水平时正是这个数字 - 智能交易系统只是从 100 中“忽略”了 90 的“风险”)吃掉了所有的“圣杯”优势 - 获利能力不如银行存款。