让新闻交易轻松上手(第五部分):执行交易(2)(基础篇)
📘

让新闻交易轻松上手(第五部分):执行交易(2)(基础篇)

第 1/3 篇

「用 iTradeManager 把新闻单自动挂出去」

在 MT5 里做新闻交易,最怕手速跟不上波动。借助 iTradeManager 这类 EA,可以把预设的挂单逻辑直接交给程序,在新闻发布前后按条件自动布单。 EA 启动后会在图表上画出可拖拽的挂单线,并实时显示距离现价点数、预估止损止盈位。你只需在新闻前把线拉到想进场的位置,EA 会在价格触线时发单,省去手动点单的延迟。 根据 2025 年 6 月 26 日发布的该工具说明,其基础版本在 MQL5 社区获得 790 次查看、6 条讨论反馈,属于轻量型新闻执行辅助,不内含预测信号,仅解决「执行」环节。外汇与贵金属新闻市况滑点可能剧烈,实盘前务必在策略测试器用历史数据跑一遍。

先把新闻EA的骨架搭起来

这套系列的第一要务,是写出一个能挂止损单的新闻交易EA,后续几篇才会拿它去实际接新闻事件跑。也就是说,这一节不谈策略盈利,只谈把下单与管理的底层函数做对。 具体要落地的函数有三类:一是止损单的挂单与滑点控制,二是平仓逻辑,三是开仓前的校验——比如当前是否允许下单、点差是否超限。在MT5里这类检查若偷懒,实盘遇到流动性真空会直接吃大亏。 算法交易里,交易管理不是附属品,而是核心模块。开仓、平仓、移动止损、部分获利了结,每一步都直接决定你在外汇或贵金属这种高杠杆品种上能活多久。把这套函数写稳,后面接新闻才有意义。

◍ 新闻市里用止损单的真正理由

做新闻事件交易,止损单不是装饰。重大经济数据或央行公告出来那一瞬,价格常出现急剧跳动,手动盯盘基本赶不上,提前挂单才能吃到突破段。 买入止损挂现价之上,涨穿阈值自动做多;卖出止损挂现价之下,跌穿阈值自动做空。这样无需人守着屏幕,也能在方向确认后进场。 假突破是新闻市的常态。波动初期价格上下乱扫,提前市价进场容易被洗。止损单强制要求价格先破特定点才触发,相当于用价格行为自己过滤了噪音。 高波动期市价单滑点惊人。止损单虽不保证零滑点,但相比数据已大幅推价后再追市价,成交价更贴近你预设的水平。 跨式挂单是最直白的风控:同时挂买卖止损,例如非农交易欧元兑美元,上破触发买、下破触发卖,另一腿立刻撤掉。美元因NFP走强则欧美跌触发卖单,走弱则涨触发买单,任何方向都自动接住。外汇与贵金属新闻行情杠杆高、点差易裂,实盘前请在MT5策略测试器用历史NFP数据验证挂单距离与撤单逻辑。

「给账户加一道订单数闸门」

MQL5 里 CAccountInfo 只给出现成账户字段,余额、净值、可用保证金都能读,但查「当前挂了几种限价/止损单」得自己写。CAccountProperties 公开继承它,只补了一个 numOrders() 方法,专门数挂单和止损类订单,给上层 EA 判断还剩多少下单额度用。 真实场景里,多数经纪商对账户总订单数有硬上限,常见如 200 单(含已开仓与挂单)。若已占 199 单,还想同时下买入止损和卖出止损,EA 调一次 numOrders 就能知道空间不够,两单都不发,避免报错或被拒单。外汇与贵金属杠杆高,订单超限触发的滑点或拒单可能直接放大回撤,这类前置检查不能省。 numOrders 的逻辑不复杂:用 OrdersTotal() 拿总数,从 0 循环到总数减一;OrderGetTicket(i) 取ticket,大于 0 才有效;再用 OrderGetInteger(ORDER_TYPE) 拿类型,switch 里只认六种挂单/止损类型(买限、买停、买停限、卖限、卖停、卖停限),命中就 num++,其他类型走 default 不动,最后返回计数。 下面这段是类定义与函数本体,逐行看: #include <Trade/AccountInfo.mqh> —— 引入标准库账户信息头文件,CAccountInfo 在此定义。 class CAccountProperties: public CAccountInfo —— 公开继承,直接复用父类所有账户接口。 int CAccountProperties::numOrders(void) —— 返回 int,无参。 int num=0; —— 计数器初始化。 for(int i=0; i<OrdersTotal(); i++) —— 遍历全部订单索引。 if(OrderGetTicket(i)>0) —— 校验订单有效性。 switch(int(OrderGetInteger(ORDER_TYPE))) —— 取订单类型整数做分支。 六个 case 分别对应六种挂单类型,各 num++ 后 break;default 空过。 return num; —— 循环结束吐出总数。 把这段代码贴进 MT5 的 include 目录,EA 里实例化后每次下挂单前调一次 numOrders,再和账户上限比一下,就能把超单风险挡在发送之前。

MQL5 / C++
class="macro">#include <Trade/AccountInfo.mqh>
class CAccountProperties: class="kw">public CAccountInfo
class="type">int CAccountProperties::numOrders(class="type">void)
{
   class="type">int num=class="num">0;
   for(class="type">int i=class="num">0; i<OrdersTotal(); i++)
      if(OrderGetTicket(i)>class="num">0)
         class="kw">switch(class="type">int(OrderGetInteger(ORDER_TYPE)))
         {
            case ORDER_TYPE_BUY_LIMIT:
               num++;
               class="kw">break;
            case ORDER_TYPE_BUY_STOP:
               num++;
               class="kw">break;
            case ORDER_TYPE_BUY_STOP_LIMIT:
               num++;
               class="kw">break;
            case ORDER_TYPE_SELL_LIMIT:
               num++;
               class="kw">break;
            case ORDER_TYPE_SELL_STOP:
               num++;
               class="kw">break;
            case ORDER_TYPE_SELL_STOP_LIMIT:
               num++;
               class="kw">break;
            class="kw">default:
               class="kw">break;
         }
   class="kw">return num;
}

订单分类与交易量自动折半的逻辑

想让风控模块真正兜住外汇、贵金属这种高杠杆品种的风险,先得把「开什么单」这件事在代码层讲清楚。这里用了一个枚举 OrderTypeSelection,把订单分成三类:市价单(MarketPositionType)按当前价立刻成交,受事件驱动;双向止损单(StopOrdersType)是条件单,价格触达才同时挂买停和卖停,不受事件影响;单向止损单(StopOrderType)只挂一边,受事件影响。 变量 myOrderSelection 存的就是交易者当下选的类型,它直接决定了后面仓位怎么切。在 NormalizeLotsize 里能看到一条硬规则:只有当 myOrderSelection 等于 StopOrdersType 时,VolumeLimit 取 CSymbol.LotsLimit() 的一半,因为双向止损要同时开两张单,每张只能吃限额的 1/2;其余两类只开单张,限额不折。

MQL5 / C++
class=class="str">"cmt">//-- Enumeration for Order type
enum OrderTypeSelection
  {
   MarketPositionType,class=class="str">"cmt">//MARKET POSITION
   StopOrdersType,class=class="str">"cmt">//STOP ORDERS
   StopOrderType,class=class="str">"cmt">//SINGLE STOP ORDER
   } myOrderSelection;
class="type">void CRiskManagement::NormalizeLotsize(class="type">class="kw">double &Lotsize)
{
    class=class="str">"cmt">// Adjust lot size to match symbol&class="macro">#x27;s step size or minimum size
    if (Lotsize <= class="num">0.0) class="kw">return;
    class="type">class="kw">double VolumeLimit = (myOrderSelection != StopOrdersType) ? CSymbol.LotsLimit() : CSymbol.LotsLimit() / class="num">2;
    class=class="str">"cmt">// Check and adjust if volume exceeds limits
    class=class="str">"cmt">// ...
}
逐行拆一下上面这段:第 2 行 enum 定义三个枚举值,末尾 myOrderSelection 顺手声明了实例变量;NormalizeLotsize 入口先拦掉 Lotsize<=0 的非法值直接 return;关键的 VolumeLimit 三元表达式把「双向止损折半」写成一行,交易者改 myOrderSelection 就能切换限额逻辑,不用动其他地方。 在 MT5 里把这段塞进你自己的 CRiskManagement 类,把 LotsLimit() 换成对应品种返回值,跑一下双向止损场景,会看到单腿最大手数倾向被压到对称单的一半,这是防止双向触发后总敞口超交易所上限的务实做法。

MQL5 / C++
class=class="str">"cmt">//-- Enumeration for Order type
enum OrderTypeSelection
  {
   MarketPositionType,class=class="str">"cmt">//MARKET POSITION
   StopOrdersType,class=class="str">"cmt">//STOP ORDERS
   StopOrderType,class=class="str">"cmt">//SINGLE STOP ORDER
   } myOrderSelection;
class="type">void CRiskManagement::NormalizeLotsize(class="type">class="kw">double &Lotsize)
{
    class=class="str">"cmt">// Adjust lot size to match symbol&class="macro">#x27;s step size or minimum size
    if (Lotsize <= class="num">0.0) class="kw">return;
    class="type">class="kw">double VolumeLimit = (myOrderSelection != StopOrdersType) ? CSymbol.LotsLimit() : CSymbol.LotsLimit() / class="num">2;
    class=class="str">"cmt">// Check and adjust if volume exceeds limits
    class=class="str">"cmt">// ...
}

◍ 用 CSessions 卡掉隔夜持仓的尾巴

外汇和贵金属隔夜时段往往流动性骤降,买卖价差可能比日内正常时段扩大数倍,滑点概率随之抬升。更麻烦的是跳空:经济事件若发生在闭市后,次日开盘价与前收可能差出几十点甚至上百点,止损单被跳过是常有的事。 CSessions 类继承自 CTimeManagement,核心就三件事:判断时段是否已开、是否已结束、取结束时间。实际用法是在结束前 45 分钟(默认 offsetmin=45)就平掉仓位,并给挂单设好到期,别把头寸留过夜。 isSessionStart 里用 SymbolInfoSessionTrade 抓当前品种当日的交易区间,若 dateto 是 00:00 则压到 23:59;再叠小时/分钟偏移,比对服务器时间 TimeTradeServer() 是否落在区间内。isSessionEnd 逻辑类似但盯结束边界,当前时间晚于偏移后的 sessionend 才返 true。SessionEnd 直接吐出调整过的结束 datetime,方便写进订单过期字段。 贵金属和外汇都属于高风险品种,隔夜还可能吃掉期利息,长拿会把盈利仓拖成微亏。把下面类丢进 MT5 跑一遍,改 offsetmin 看平仓触发点怎么挪,比纸上谈参数实在。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                 NewsTrading |
class=class="str">"cmt">//|                                                     Copyright class="num">2024, MetaQuotes Ltd. |
class=class="str">"cmt">//|                                         [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include "Timemanagement.mqh"
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|Sessions Class                                                            |
class=class="str">"cmt">//+------------------------------------------------------------------+
class CSessions:CTimeManagement
  {
class="kw">public:
                      CSessions(class="type">void) {}
                     ~CSessions(class="type">void) {}
  class=class="str">"cmt">//--- Check if trading Session has began
  class="type">bool                isSessionStart(class="type">int offsethour=class="num">0,class="type">int offsetmin=class="num">0);
  class=class="str">"cmt">//--- Check if trading Session has ended
  class="type">bool                isSessionEnd(class="type">int offsethour=class="num">0,class="type">int offsetmin=class="num">45);
  class=class="str">"cmt">//--- Get Session End class="type">class="kw">datetime
  class="type">class="kw">datetime            SessionEnd(class="type">int offsethour=class="num">0,class="type">int offsetmin=class="num">45);
  };

常见问题

用 iTradeManager 把新闻单提前设成挂单模板,到时一键发送,避免手动输入延误和滑点扩大。
止损单能避开发布瞬间流动性真空导致的极端滑点,只在价格真正触发后进场,概率上更可控。
小布可自动识别新闻时段并提示挂单参数与订单数闸门状态,你只需确认执行,重复劳动交给它。
给账户加订单数闸门,超过设定笔数直接拒单,并在代码里按品种分类把交易量自动折半。
用 CSessions 在会话结束前强制平掉或禁开尾巴单,避免隔夜跳空和外币利率风险暴露。