让新闻交易轻松上手(第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 参数就能看任意品种两周点差落在哪一档。
<span class="comment">class=class="str">"cmt">//Enumeration for Spread rating</span> <span class="keyword">enum</span> SpreadRating { SpreadRating_Terrible,<span class="comment">class=class="str">"cmt">//Terrible</span> SpreadRating_Bad,<span class="comment">class=class="str">"cmt">//Bad</span> SpreadRating_Normal,<span class="comment">class=class="str">"cmt">//Normal</span> SpreadRating_Good,<span class="comment">class=class="str">"cmt">//Good</span> SpreadRating_Excellent<span class="comment">class=class="str">"cmt">//Excellent</span> }; <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> 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 |</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>) { <span class="keyword">if</span>(SetSymbolName(SYMBOL))<span class="comment">class=class="str">"cmt">//Set Symbol</span> { <span class="keyword">class="kw">return</span> CSymbol.SpreadFloat(); } <span class="functions">Print</span>(<span class="class="type">class="kw">string">"Unable to retrieve Symbol&class="macro">#x27;s Spread Float"</span>); <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> } SpreadRating 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 |</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>) { <span class="keyword">if</span>(SetSymbolName(SYMBOL))<span class="comment">class=class="str">"cmt">//Set Symbol</span> { <span class="keyword">if</span>(SpreadFloat(SYMBOL))<span class="comment">class=class="str">"cmt">//Check if Symbol has a floating Spread</span> { <span class="comment">class=class="str">"cmt">//Declarations</span> <span class="keyword">vector</span> Spreads; <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>, SpreadUpper=<span class="number">class="num">0</span>,SpreadLower=<span class="number">class="num">0</span>,SpreadAvgUpper=<span class="number">class="num">0</span>, SpreadAvgLower=<span class="number">class="num">0</span>,SpreadMidUpper=<span class="number">class="num">0</span>,SpreadMidLower=<span class="number">class="num">0</span>; <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 的评分函数,就能在日志里直接看每根棒所处的点差档位。
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 等枚举。
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,用这套函数做提醒时须留意滑点风险。
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;