依据 Heiken-Ashi 指标的交易系统示例·综合运用
「用持仓对象改止损的实跑片段」
下面这段 MT5 代码演示了在 EA 中借助持仓信息对象与交易对象,对当前图表品种持仓只改止损、不动止盈的最小闭环。 先通过 posinf.Select(_Symbol) 确认当前图表品种有持仓可读;若返回 true 才进入内层逻辑,避免对无持仓品种调用修改接口导致冗余报错。 内层用 trade.PositionModify(_Symbol, stop_loss, 0) 把止损设为变量 stop_loss、止盈显式传 0 表示保持原止盈不变;若修改失败,立刻用 trade.ResultRetcodeDescription() 把交易服务器返回的错误描述打印到日志,方便在 MT5 终端「专家」标签页直接看原因。 实盘验证时建议先把 stop_loss 算成带点差缓冲的绝对值(如近期摆动低点减 2~3 点),外汇与贵金属杠杆高、滑点频繁,仅改止损也可能因价格已穿透而返回 10019 类拒绝码,属正常概率现象。
if(posinf.Select(_Symbol)) { if(!trade.PositionModify(_Symbol,stop_loss,class="num">0)) Print(trade.ResultRetcodeDescription()); } } } class=class="str">"cmt">//+------------------------------------------------------------------+
◍ 拿 MT5 回测给系统验命
验证一套价格行为策略是否只是纸上谈兵,最直接的方法是丢进 MetaTrader 5 策略测试器。打开路径是客户端菜单「视图 → 策略测试程序」,或者按 Ctrl+R 唤出面板,进 Settings 选项卡把 EA 挂上去。 这次测试把时间窗卡在 2000 年初到 2009 年末,初始存款设 10,000 美元,优化关掉——因为策略只有一个输入参数,目的只是看系统能不能活下来,不是榨参数。 选了 EURUSD 和 GBPUSD 两个货币对,周期挑了 H3、H6、H12。挑这些奇葩周期是因为 MT4 根本没有,只想验证在非常规时间框架上的表现。EURUSD 三个周期全亏,H3 下按指定参数跑了九年净亏 2560.60 美元,图形页能看出盈亏分布断层,说明系统在该货币对上倾向失效。 换 GBPUSD 后画风变了:H12 周期九年累计盈利 8903.23 美元,H3 和 H6 也有正结果。周期拉长显著改变输出,外汇和贵金属这种高波动品种,回测结论只能说「可能」随波动率放大而改善,实盘仍需警惕滑点和点差风险。 有兴趣自己可以换其他货币对跑一遍。一个可证伪的假设是:货币对波动越剧烈,长周期回测结果越可能占优,但高杠杆品种天生高风险,验完别直接上实盘。
记住这一条就够了
平滑 Heiken Ashi 不是圣杯,单独跑 EA 在 EURUSD H1 上从 2014 到 2024 的回测里,有用户报告首根蜡烛就出现成交异常,说明裸信号在外汇这种高波动品种上容易失真。把它当过滤器更现实:只在平台整理区间分离出反转候选,再叠烛形或波浪确认才进场。 贵金属与叉盘同样高风险,信号共振也只是提高概率,不代表规避洗盘。上面那段数组打印代码,直接丢进 MT5 脚本就能看到 haOpen 等前三根的数值,验证你本地编译是否也踩了同样的初始化坑。
class="type">class="kw">double haOpen[BAR_COUNT],haHigh[BAR_COUNT],haLow[BAR_COUNT],haClose[BAR_COUNT]; Print("haOpen = [class="num">0 ... class="num">2] = ",haOpen[class="num">0]," ", haOpen[class="num">1], " ", haOpen[class="num">2]); Print("haHigh = [class="num">0 ... class="num">2] = ",haHigh[class="num">0]," ", haHigh[class="num">1], " ", haHigh[class="num">2]); Print("haLow = [class="num">0 ... class="num">2] = ",haLow[class="num">0]," ", haLow[class="num">1], " ", haLow[class="num">2]); Print("haClose = [class="num">0 ... class="num">2]= ",haClose[class="num">0]," ", haClose[class="num">1], " ", haClose[class="num">2]);