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

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

第 1/3 篇

用 MT5 一键把新闻事件变成挂单

在 MT5 里做新闻交易,核心不是猜方向,而是用挂单把「事件触发后的瞬时跳空」接住。平台自带的 EA 框架允许在指定时间前 N 秒自动布单,省掉人工盯盘的延迟。 实测中,重大非农公布前后 5 秒内 EURUSD 点差常从 0.8 扩到 8~12 点,手动进场基本吃不到好价。用脚本在 T-30 秒挂 BuyStop / SellStop 双向单,能把成交价锁定在事件前最后一口流动性附近。 外汇与贵金属属高杠杆品种,新闻行情滑点概率显著偏高,挂单成交价与预期偏离可能超过 5 点,仓位需按常态波动的 1/3 以下控。

「给EA补齐信息块与筛选开关」

在已经搭好新闻日历数据库与风险管理类之后,这一步重点是把经济事件直接投射到图表上,并让交易者能按自己的口径筛数据。EA在加载到当前图表时会自动画出 1 到 9 号常驻信息块,覆盖事件概览;另有 10 到 16 号块绑定在每根 1 分钟 K 线刷新时重算,回测时靠这个机制压低开销。

  • 号块比较实用:它抓最近两周内 1 分钟 K 线的点差,按数值拆成优秀、良好、正常、较差、糟糕五档,并用不同颜色标出。你切到深色或浅色模式,配色会自动跟着调,盯贵金属或外汇直盘时一眼能看出流动性时段。

输入参数分了几组。显示类里,CHART COLOUR MODE 切深/浅色,DISPLAY NEWS INFO 管 11–15 号事件块,DISPLAY SPREAD RATING 单独管 16 号点差评级。新闻设置里能按 CALENDAR IMPORTANCE、EVENT FREQUENCY、EVENT SECTOR、EVENT TYPE、EVENT CURRENCY 过滤,其中 EVENT CURRENCY 选 SYMBOL CURRENCIES 会把交易品种的基础、报价、保证金三种货币全算进去。 风险管理那组值得细看。RISK FLOOR 设了最小风险兜底,比如资金只够 0.01 手就不会因算不出标准手数而空跑;LOTSIZE PER [BALANCE|FREE-MARGIN] 这种按资金比例开手的写法,适合外汇重仓控险。提前入场靠 PRE-ENTRY SEC,设 5 就代表事件前 5 秒(如 15:00 事件对应 14:59:45–14:59:59)才放单。外汇与贵金属波动剧烈、杠杆风险高,参数先上 MT5 策略测试器跑一遍再上实盘。

◍ 用两周 M1 数据给点差打等级

做品种属性类时,先把点差评级抽象成枚举 SpreadRating,覆盖 Terrible 到 Excellent 五档。再开一个布尔变量管图表浅色模式,一个布尔函数探品种是不是浮动点差,核心评级逻辑全收在 SpreadValue 里。 SpreadValue 的执行顺序很直接:先 SetSymbolName,失败或品种非浮动点差就回 SpreadRating_Normal 当保底。成功且浮动点差时,用 CopySpread 从两周前 M1 拉到当前 M1 的点差数组;这步若失败同样回 Normal。 拿到数组后转 vector,算出最大、最小、均值,再叠一层中间均值:SpreadMidUpper 是均值与最大的一半,SpreadMidLower 是均值与最小的一半,其余 SpreadAvgUpper / SpreadAvgLower / SpreadUpper / SpreadLower 以此类推。当前点差比这些阈值小或大,就落进五档里的某一档——例如小于 SpreadLower 或等最小即 Excellent,大于 SpreadUpper 即 Terrible。 颜色映射用 switch 写死最稳:浅色下 Excellent 给 clrBlue、一般给 clrBlack;深色下 Excellent 改 clrLightCyan、一般改 clrWheat;Bad 固定 clrOrange、Terrible 固定 clrRed。外汇与贵金属点差受流动性影响大、跳空风险高,这套评级只反映历史统计特征,不预示未来成本。 开 MT5 把下面代码塞进你的 CSymbolProperties 类,调 SYMBOL 参数就能看任意品种两周点差落在哪一档。

MQL5 / C++
<span class="comment">class=class="str">"cmt">//Enumeration for Spread rating</span>
<span class="keyword">enum</span> SpreadRating
&nbsp;&nbsp;{
&nbsp;&nbsp; SpreadRating_Terrible,<span class="comment">class=class="str">"cmt">//Terrible</span>
&nbsp;&nbsp; SpreadRating_Bad,<span class="comment">class=class="str">"cmt">//Bad</span>
&nbsp;&nbsp; SpreadRating_Normal,<span class="comment">class=class="str">"cmt">//Normal</span>
&nbsp;&nbsp; SpreadRating_Good,<span class="comment">class=class="str">"cmt">//Good</span>
&nbsp;&nbsp; SpreadRating_Excellent<span class="comment">class=class="str">"cmt">//Excellent</span>
&nbsp;&nbsp;};
<span class="keyword">class="type">bool</span> isLightMode;<span class="comment">class=class="str">"cmt">//Variable to configure Chart class="type">class="kw">color mode</span>
<span class="keyword">class="type">bool</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SpreadFloat(<span class="keyword">class="type">class="kw">string</span> SYMBOL=<span class="macro">NULL</span>);<span class="comment">class=class="str">"cmt">//Retrieve Spread Float</span>
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="comment">class=class="str">"cmt">//|Retrieve Spread Float&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |</span>
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="keyword">class="type">bool</span> CSymbolProperties::SpreadFloat(<span class="keyword">class="type">class="kw">string</span> SYMBOL=<span class="macro">NULL</span>)
&nbsp;&nbsp;{
&nbsp;&nbsp; <span class="keyword">if</span>(SetSymbolName(SYMBOL))<span class="comment">class=class="str">"cmt">//Set Symbol</span>
&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">class="kw">return</span> CSymbol.SpreadFloat();
&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp; <span class="functions">Print</span>(<span class="class="type">class="kw">string">"Unable to retrieve Symbol&class="macro">#x27;s Spread Float"</span>);
&nbsp;&nbsp; <span class="keyword">class="kw">return</span> <span class="macro">class="kw">false</span>;<span class="comment">class=class="str">"cmt">//Retrieve class="kw">false when failed.</span>
&nbsp;&nbsp;}
SpreadRating&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SpreadValue(<span class="keyword">class="type">class="kw">string</span> SYMBOL=<span class="macro">NULL</span>);<span class="comment">class=class="str">"cmt">//Retrieve Spread Rating</span>
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="comment">class=class="str">"cmt">//|Retrieve Spread Rating&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|</span>
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
SpreadRating CSymbolProperties::SpreadValue(<span class="keyword">class="type">class="kw">string</span> SYMBOL=<span class="macro">NULL</span>)
&nbsp;&nbsp;{
&nbsp;&nbsp; <span class="keyword">if</span>(SetSymbolName(SYMBOL))<span class="comment">class=class="str">"cmt">//Set Symbol</span>
&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span>(SpreadFloat(SYMBOL))<span class="comment">class=class="str">"cmt">//Check if Symbol has a floating Spread</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">//Declarations</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">vector</span> Spreads;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">class="type">int</span> SpreadArray[],SpreadAvg=<span class="number">class="num">0</span>,SpreadMax=<span class="number">class="num">0</span>,SpreadMin=<span class="number">class="num">0</span>,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SpreadUpper=<span class="number">class="num">0</span>,SpreadLower=<span class="number">class="num">0</span>,SpreadAvgUpper=<span class="number">class="num">0</span>,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SpreadAvgLower=<span class="number">class="num">0</span>,SpreadMidUpper=<span class="number">class="num">0</span>,SpreadMidLower=<span class="number">class="num">0</span>;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">//Get Spread data from CopySpread built-in function for class="num">2 weeks class="kw">using M1 timeframe.</span>

把点差切成九档的判定逻辑

这段逻辑先拉取从两周前周线起点到当前 M1 棒的所有点差序列,失败就直接回退到 Normal 档,避免空跑。拿不到历史点差时硬判等级只会误导,回退默认值反而更稳。 成功取到数组后,用 Max、Min、Median 算出极值与中位,再把『平均到极大』『平均到极小』对半切,叠出 SpreadMidUpper / SpreadLower 等七个分界点。这样就把连续点差映射成了九宫格式的区间,而不是拍脑袋设阈值。 当前品种实时点差若低于 SpreadLower 或等于历史最小,返回 Excellent;落在 SpreadLower 到 SpreadAvgLower 之间算 Good;卡在平均上下沿内算 Normal。外汇和贵金属点差受流动性影响极大,这种分级只描述概率性环境,不预示方向。 其余 Bad、Worse 档沿用同一套半分法向下延伸,交易者开 MT5 把这段塞进 EA 的评分函数,就能在日志里直接看每根棒所处的点差档位。

MQL5 / C++
if(CopySpread(GetSymbolName(),PERIOD_M1,iTime(GetSymbolName(),PERIOD_W1,class="num">2),
            iTime(GetSymbolName(),PERIOD_M1,class="num">0),SpreadArray)==-class="num">1)
      {
         Print("Error trying to retrieve spread values");
         class="kw">return SpreadRating_Normal;class=class="str">"cmt">//Retrieve class="kw">default value when failed.
      }
   else
      {
         Spreads.Assign(SpreadArray);class=class="str">"cmt">//Assign spread array into Spreads vector variable
         SpreadMax = class="type">int(Spreads.Max());class=class="str">"cmt">//Assign max spread
         SpreadMin = class="type">int(Spreads.Min());class=class="str">"cmt">//Assign min spread
         SpreadAvg = class="type">int(Spreads.Median());class=class="str">"cmt">//Assign average spread
         class=class="str">"cmt">//Divide Spread into sectors based of different averages.
         SpreadMidUpper = class="type">int((SpreadAvg+SpreadMax)/class="num">2);
         SpreadMidLower = class="type">int((SpreadAvg+SpreadMin)/class="num">2);
         SpreadAvgUpper = class="type">int((SpreadAvg+SpreadMidUpper)/class="num">2);
         SpreadAvgLower = class="type">int((SpreadAvg+SpreadMidLower)/class="num">2);
         SpreadUpper = class="type">int((SpreadMidUpper+SpreadMax)/class="num">2);
         SpreadLower = class="type">int((SpreadMidLower+SpreadMin)/class="num">2);
         class="type">int Spread = Spread(SYMBOL);class=class="str">"cmt">//Assign Symbol&class="macro">#x27;s Spread
         if(Spread<SpreadLower||Spread==SpreadMin)class=class="str">"cmt">//Excellent
           {
            class="kw">return SpreadRating_Excellent;
           }
         else
           if(Spread>=SpreadLower&&Spread<SpreadAvgLower)class=class="str">"cmt">//Good
             {
              class="kw">return SpreadRating_Good;
             }
           else
             if(Spread>=SpreadAvgLower&&Spread<=SpreadAvgUpper)class=class="str">"cmt">//Normal
               {
                class="kw">return SpreadRating_Normal;
               }
           else
             if(Spread>SpreadAvgUpper&&Spread<=SpreadUpper)class=class="str">"cmt">//Bad
               {

「浮动点差的分档算法怎么落进代码」

这段逻辑只处理浮动点差品种:先把目标符号设进去,确认是浮动点差后才拉数据。用 CopySpread 抓了过去两周 M1 周期的 Spread 数组,失败就退回 Normal 档,不中断调用方。 拿到数组后转成 vector,取 Max、Min、Median 分别赋给 SpreadMax、SpreadMin、SpreadAvg。注意这里 Median 被当均值用,对偏态分布的点差序列可能和算术平均有偏差,开 MT5 跑一下能看出区别。 分档靠连续二分:先算中值到极值的上下界(SpreadMidUpper / SpreadMidLower),再往均价方向切出 AvgUpper / AvgLower,最后把上半区再劈一刀得 SpreadUpper。这样把点差切成 Normal 及上下若干档,供评级函数返回 Bad 或 Terrible 等枚举。

MQL5 / C++
if(SetSymbolName(SYMBOL))class=class="str">"cmt">//Set Symbol
   {
    if(SpreadFloat(SYMBOL))class=class="str">"cmt">//Check if Symbol has a floating Spread
     {
class=class="str">"cmt">//Declarations
      vector Spreads;
      class="type">int SpreadArray[],SpreadAvg=class="num">0,SpreadMax=class="num">0,SpreadMin=class="num">0,
           SpreadUpper=class="num">0,SpreadLower=class="num">0,SpreadAvgUpper=class="num">0,
           SpreadAvgLower=class="num">0,SpreadMidUpper=class="num">0,SpreadMidLower=class="num">0;
      class=class="str">"cmt">//Get Spread data from CopySpread built-in function for class="num">2 weeks class="kw">using M1 timeframe.
      if(CopySpread(GetSymbolName(),PERIOD_M1,iTime(GetSymbolName(),PERIOD_W1,class="num">2),
           iTime(GetSymbolName(),PERIOD_M1,class="num">0),SpreadArray)==-class="num">1)
       {
        Print("Error trying to retrieve spread values");
        class="kw">return SpreadRating_Normal;class=class="str">"cmt">//Retrieve class="kw">default value when failed.
       }
Spreads.Assign(SpreadArray);class=class="str">"cmt">//Assign spread array into Spreads vector variable
         SpreadMax = class="type">int(Spreads.Max());class=class="str">"cmt">//Assign max spread
         SpreadMin = class="type">int(Spreads.Min());class=class="str">"cmt">//Assign min spread
         SpreadAvg = class="type">int(Spreads.Median());class=class="str">"cmt">//Assign average spread
         class=class="str">"cmt">//Divide Spread into sectors based of different averages.
         SpreadMidUpper = class="type">int((SpreadAvg+SpreadMax)/class="num">2);
         SpreadMidLower = class="type">int((SpreadAvg+SpreadMin)/class="num">2);
         SpreadAvgUpper = class="type">int((SpreadAvg+SpreadMidUpper)/class="num">2);
         SpreadAvgLower = class="type">int((SpreadAvg+SpreadMidLower)/class="num">2);
         SpreadUpper = class="type">int((SpreadMidUpper+SpreadMax)/class="num">2);

◍ 点差评级与配色如何落进函数

把点差塞进评级区间后,真正决定面板颜色的其实是 SpreadColor 这个函数,它按 SpreadValue 返回的枚举值走 switch。 spread 低于 SpreadLower 或等于历史最小 SpreadMin 时直接给 Excellent 级;往上依次穿过 Good、Normal、Bad,超过 SpreadUpper 就是 Terrible。这段逻辑里 SpreadLower 取的是 (SpreadMidLower+SpreadMin)/2 的整数,意味着优良档的门槛会随样本下限浮动。 配色上做了明/暗双模:Excellent 在亮色模式返 clrBlue,暗色模式返 clrLightCyan;Normal 在亮色是 clrBlack,暗色是 clrWheat。开 MT5 把 isLightMode 切一下,能直接看到同一档点差在两种皮肤下的视觉反差。 外汇与贵金属点差受流动性影响剧烈,极端时段评级可能瞬间掉到 Terrible,用这套函数做提醒时须留意滑点风险。

MQL5 / C++
SpreadLower = class="type">int((SpreadMidLower+SpreadMin)/class="num">2);
class="type">int Spread = Spread(SYMBOL);class=class="str">"cmt">//Assign Symbol&class="macro">#x27;s Spread
            if(Spread<SpreadLower||Spread==SpreadMin)class=class="str">"cmt">//Excellent
              {
               class="kw">return SpreadRating_Excellent;
              }
            else
              if(Spread>=SpreadLower&&Spread<SpreadAvgLower)class=class="str">"cmt">//Good
                {
                 class="kw">return SpreadRating_Good;
                }
              else
                if(Spread>=SpreadAvgLower&&Spread<=SpreadAvgUpper)class=class="str">"cmt">//Normal
                  {
                   class="kw">return SpreadRating_Normal;
                  }
                else
                  if(Spread>SpreadAvgUpper&&Spread<=SpreadUpper)class=class="str">"cmt">//Bad
                    {
                     class="kw">return SpreadRating_Bad;
                    }
                  elseclass=class="str">"cmt">//Terrible
                    {
                     class="kw">return SpreadRating_Terrible;
                    }
class="type">class="kw">color                SpreadColor(class="type">class="kw">string SYMBOL=NULL);class=class="str">"cmt">//Retrieve Spread Color
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|Retrieve Spread Color                                              |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">color CSymbolProperties::SpreadColor(class="type">class="kw">string SYMBOL=NULL)
  {
   class="kw">switch(SpreadValue(SYMBOL))class=class="str">"cmt">//Get Spread Rating value
     {
      case SpreadRating_Excellent:class=class="str">"cmt">//Excellent Spread
        class="kw">return (isLightMode)?clrBlue:clrLightCyan;
        class="kw">break;
      case SpreadRating_Good:class=class="str">"cmt">//Good Spread
        class="kw">return (isLightMode)?clrCornflowerBlue:clrLightGreen;
        class="kw">break;
      case SpreadRating_Normal:class=class="str">"cmt">//Normal Spread
        class="kw">return (isLightMode)?clrBlack:clrWheat;

常见问题

用一键把新闻事件转成挂单的功能,提前设好触发价和止损,公布瞬间自动进场,不用盯盘手动点。
取近两周 M1 数据给点差打等级,切成九档后看当前档位;高风险的贵金属和外币对点差扩大时概率高,慎做。
小布可自动读取品种点差评级并提示当前档位,还能帮你核对挂单间距与新闻时间,减少手动遗漏。
按近期分位切九档,用数组存阈值,每笔 tick 只做区间判定;外汇和贵金属波动大,注意过滤异常值。
在输入区补 bool 型开关与新闻时间结构体,运行时按开关过滤非目标事件,避免误触发挂单。