针对初学者以 MQL5 编写EA 交易的分步指南·综合运用
📘

针对初学者以 MQL5 编写EA 交易的分步指南·综合运用

第 3/3 篇

卖单请求的结构化填充与条件闸门

下卖单前先把 MqlTradeRequest 结构体的关键字段填实:magic 用 EA_Magic 做订单标识,type 设 ORDER_TYPE_SELL,type_filling 用 ORDER_FILLING_FOK 表示要么全成要么不成,deviation 给 100 点作为价格偏移容差。最后一句 OrderSend(mrequest,mresult) 才真正把请求推给服务器。 卖压触发不是单条件,而是四道闸门叠加:Sell_Condition_1 看 maVal[0]<maVal[1]<maVal[2] 的均线空头排列;Sell_Condition_2 要求收盘价低于 maVal[1];Sell_Condition_3 限定 adxVal[0]>Adx_Min 确保趋势强度够;Sell_Condition_4 用 plsDI[0]<minDI[0] 确认负向动向线占优。四者同时为真才倾向开仓。 发送前先查 Sell_opened 标志,若已有卖仓直接 Alert 并返回,避免马丁式加仓。回码判断上,mresult.retcode 为 10009(已下订单)或 10008(请求完成)才认作成功,否则抛 GetLastError 并 ResetLastError 后退出。外汇与贵金属杠杆高,这类 FOK 卖单在滑点放大时可能直接拒单,实盘前务必在 MT5 策略测试器用点差 20~50 点的环境跑一遍。

MQL5 / C++
   mrequest.magic = EA_Magic;                                                                         class=class="str">"cmt">// 订单幻数
   mrequest.type= ORDER_TYPE_SELL;                                                                       class=class="str">"cmt">// 卖出订单
   mrequest.type_filling = ORDER_FILLING_FOK;                                                            class=class="str">"cmt">// 订单执行类型
   mrequest.deviation=class="num">100;                                                                               class=class="str">"cmt">// 当前价格偏移
   class=class="str">"cmt">//--- 发送订单
   OrderSend(mrequest,mresult);
   class="type">bool Sell_Condition_1 = (maVal[class="num">0]<maVal[class="num">1]) && (maVal[class="num">1]<maVal[class="num">2]);
   class="type">bool Sell_Condition_2 = (p_close <maVal[class="num">1]);
   class="type">bool Sell_Condition_3 = (adxVal[class="num">0]>Adx_Min);
class="type">bool Sell_Condition_4 = (plsDI[class="num">0]<minDI[class="num">0]);
class=class="str">"cmt">// 是否有卖出仓位?
      if (Sell_opened)
      {
         Alert("我们已经有了卖出仓位!!!");
         class="kw">return;   class=class="str">"cmt">// 不建新的卖出仓位
      }
      if(mresult.retcode==class="num">10009 || mresult.retcode==class="num">10008) class=class="str">"cmt">//请求完成或者已下订单
       {
         Alert("卖出订单已经成功下单,订单#:",mresult.order,"!!");
       }
      else
       {
         Alert("卖出订单请求无法完成 -错误:",GetLastError());
         ResetLastError();
         class="kw">return;
       }
      }

「在 MT5 里逐行抓虫与回测验证」

EA 写完后先别急着上真仓,MetaEditor 的调试器能帮你把运行逻辑拆开看。按 F5 或点绿色按钮启动调试,编译器通过只代表语法没问题,运行时错误(比如表达式求值偏差)照样会让策略 silently 失效。 断点是调试核心:在代码行左侧灰区双击或按 F9 设断点,调试器跑到该行就暂停,让你用底部 Debug 选项卡的 Expression 区监视 Old_Time、New_Time[0]、IsNewBar、Mybars 等关键变量。按 F11 单步进入函数、F10 跳过、Shift+F11 跳出,逐行确认值是否符合预期。 断点跑完一轮后,去掉所有断点再启调试,让 EA 在无人干预下跑一会,看买卖条件触发时是否真的发单。注意终端必须联网,否则调试因无法交易直接失效。 策略测试器用 Ctrl+R 调出,选 EA、货币对、周期,自定义日期范围,Execution 设 Normal,Optimization 先 Disable。以单核处理器跑完一轮后,Results 选项卡给出摘要:某次 5 天自定义周期测试净余额约 +1450 USD,但这是历史拟合、外汇高风险下不具外推性。 同样在测试器里把 MA 周期 8 改 10、ADX 改 14、止损 30 改 35、切 2 小时图,结果可能变;右键 Results 存 HTML 报告、点 Open Chart 看成交图。换货币对、周期、止盈值自己跑一遍,才知参数敏感点在哪。

◍ 记住这一条就够了

从净额结算到对冲账户,EA 仓位管理的坑不在逻辑而在账户类型。2010 年原文写就时 MT5 外汇账户全是净额结算,PositionSelect(_Symbol) 直接可用;2016 年对冲账户推出后,必须用 PositionGetTicket() 或 PositionSelectByTicket() 才能精准锁定仓位,否则多单空单会混选。 有读者在美元兑加元日线跑完 33000 种组合回测:ADX 介于 29–60、止盈 300–500、止损 30 或 155 时,2019–2025 样本里利润系数 1.77–2.61,但 86% 盈利来自多头、空头全亏,且最长持仓 3440 小时。外汇与贵金属自带高杠杆高风险,这种长周期低频次结果未必能在实时盘面复现。 真要把 first EA 用起来,先按账户类型改仓位选择代码,再开 MT5 策略测试器用局域网多机分摊回测任务。能跑通、能改参数、能看懂报错,比背任何结论都实在。

常见问题

至少填好交易品种、手数、订单类型、价格与滑点容差,并用条件闸门判断持仓与价格波动后再发单,避免裸发请求。
在发单前打印请求结构与返回代码,对照品种最小止损、点差与成交模式,逐行核对价格是否越界或触发了条件闸门。
小布可读取你的策略说明与关键参数,提示卖单闸门遗漏点与回测异常,帮你快速定位不成交的常见坑。
常忽略用市价偏移或挂单距离校验,导致请求被拒;记得在发单前用条件判断卡住无效价格。
先用模拟盘观察滑点与拒单率,确认卖单闸门在极端波动下不误触,再考虑小资金实盘验证,外汇贵金属风险高。