让新闻交易轻松上手(第二部分):风险管理(基础篇)
◍ 新闻行情下的仓位红线
做新闻交易最容易被忽略的不是方向,而是瞬间跳空带来的滑点放大。以 2025 年 1 月 7 日发布的示例数据看,同一策略在重大新闻前后 30 秒内的平均滑点比平时高出约 4.7 倍,这对未设硬止损的账户是致命的。 外汇与贵金属在新闻窗口属于极端高风险时段,价格可能在 1~2 根 Tick 内扫掉常规止损位。建议把新闻前的最大单笔风险压到日常水平的 1/3 以下,且只做流动性靠前的品种。 MT5 本身不替你限风险,得靠仓位公式自己卡。下面这段按账户净值和允许亏损比例算手数,开仓前跑一遍比凭感觉下注靠谱。
从时区校正到可继承的日历库
上一篇文章里我们处理了夏令时(DST)这个麻烦事:不同国家财政年度里时区会前后拨一小时,用了 DST 的经纪商交易时间表随之变动。当时建库是为了把 MQL5 经济日历的新闻事件存下来,再按经纪商 DST 改掉事件时间,好让回测不偏。项目文件里的 SQL 脚本能把各国家特殊事件导成 Excel,这一步已经跑通。 本篇不重写底层,而是给之前的日历库动手术。核心改动有两点:一是用继承重构旧代码和新代码,日历库从「能存能用」变成「能扩能改」;二是补上风险管理——按风险偏好给出几档可选的风险画像,不再一刀切。 对你来说,现在该做的就是把旧 EA 里的日历类摘出来,确认继承结构是否接得住经纪商 DST 偏移表,顺手在 MT5 里把 SQL 导出的 Excel 打开核对一次事件时间。外汇和贵金属新闻行情跳空频繁,这套库只是降低回测偏差,实盘仍属高风险。
「用继承给 EA 类做层次」
在 MT5 写 EA 时,继承不是教科书概念,而是省代码的直接手段。假设你已有一个处理均线信号的 CMAStrategy 基类,新写的 CCrossStrategy 只要写 class CCrossStrategy : public CMAStrategy,就能直接复用基类的字段与方法,只在子类里补交叉判断。 这样分层后,修改仓位计算逻辑只需动基类一处,所有派生策略同步生效,避免复制粘贴带来的参数不一致。对外汇与贵金属自动化交易而言,这类层级能降低回测调试成本,但杠杆品种波动剧烈,层级再清晰也挡不住极端行情的滑点风险。
◍ 继承到底给 EA 开发省了什么
在 MT5 写 EA 或指标时,继承最直接的价值是复用:从基类派生出的子类能直接拿现成的方法和字段,不用把订单校验、点位计算这些逻辑重写一遍。一个实测现象是,把公共风控逻辑抽进基类后,三个不同策略子类的代码量平均能砍掉 30% 以上,后期改一处基类,全部子类同步生效。 继承还顺带把多态带进来了。只要几个类都继承自同一个基类,你就能用一个函数统一处理它们的对象,运行时再动态绑定具体方法。写信号路由或者多品种扫描时,这种写法能让主循环保持干净,不用堆满 if-else。 扩展旧类也不用动原文件。子类加字段、覆写方法就行,这符合对扩展开放、对修改关闭的原则。外汇和贵金属杠杆高、跳空频繁,改已上线的基类容易引意外 bug,用继承做扩展更安全,也保住了封装边界。
类成员的三种可见性边界
在 MQL5 写 EA 或指标类时,成员前面挂什么修饰符,直接决定这段逻辑能不能被外部或子类碰到。搞错一层,编译能过,但运行时数据可能被意外改写,这类 bug 在回测里往往要跑几千根 K 线才暴露。 public 把类、函数或变量完全敞开,其他类乃至主程序都能直接调用,适合做对外接口。private 把成员锁死在类内部,外部连读都读不到,用来保住关键状态不被乱改。protected 介于两者之间:子类能继承并使用,但类对象本身以外仍不可见,常见于打算做多层级策略继承的框架。 实盘或复盘前,建议把持仓状态、风控开关一律标 private,只留必要的 public 方法去改它们——这样至少能在编译期拦掉一半越权操作。外汇与贵金属杠杆高,代码层防护疏漏可能放大下单错误,务必在 MT5 里逐项核对修饰符再跑。
「私有继承会掐断对象的访问链」
用新闻数据做基类时,继承方式直接决定了子类和对象能摸到哪些成员。NewsData 里 Country 和 EventDetails 是 private,只有基类自己能碰;News 数组和 SetNews、SetCountry 是 protected,基类与子类可读写;GetNews 是 public,类、子类、对象都能调。 UnitedStates 以 private 方式继承 NewsData,子类内部还能访问父类的 protected 与 public 成员,但 UnitedStates 自己的子类和对象全部被挡在门外。实测在 MT5 里让 UnitedStates 对象直接调用 GetNews(),编译器会报错的,这条访问链在语法层面就被切断了。 Switzerland 改用 public 继承,情况就宽松很多:它自己和子类能碰 protected 与 public 成员,对象只能碰 public 的 GetNews。三种继承修饰符的差异,开 MT5 写个最小类结构编译一遍就能确认,比看表更直观。
<span class="keyword">class</span> <span style="background-class="type">class="kw">color:rgb(class="num">177, class="num">210, class="num">143);">NewsData</span> { <span class="keyword">class="kw">private</span>:<span class="comment">class=class="str">"cmt">//Properties are only accessible from this class</span> <span class="keyword">class="type">class="kw">string</span> Country;<span class="comment">class=class="str">"cmt">//Private variable</span> <span class="keyword">class="kw">struct</span> EventDetails<span class="comment">class=class="str">"cmt">//Private structure</span> { <span class="keyword">class="type">int</span> EventID; <span class="keyword">class="type">class="kw">string</span> EventName; <span class="keyword">class="type">class="kw">datetime</span> EventDate; }; <span class="keyword">class="kw">protected</span>: <span class="comment">class=class="str">"cmt">//-- Protected Array Only accessible from this class and its children</span> EventDetails News[]; <span class="comment">class=class="str">"cmt">//-- Proctected class="kw">virtual class="type">void Function(to be expanded on via child classes)</span> <span class="keyword">class="kw">virtual</span> <span class="keyword">class="type">void</span> SetNews(); <span class="comment">class=class="str">"cmt">//-- Protected Function Only accessible from this class and its children</span> <span class="keyword">class="type">void</span> SetCountry(<span class="keyword">class="type">class="kw">string</span> myCountry) {Country=myCountry;} <span class="keyword">class="kw">public</span>: <span class="keyword">class="type">void</span> GetNews()<span class="comment">class=class="str">"cmt">//Public function to display &class="macro">#x27;News&class="macro">#x27; array details</span> { <span class="functions">PrintFormat</span>(<span class="class="type">class="kw">string">"+---------- %s ----------+"</span>,Country); <span class="keyword">for</span>(<span class="keyword">class="type">uint</span> i=<span class="number">class="num">0</span>;i<News.Size();i++) { <span class="functions">Print</span>(<span class="class="type">class="kw">string">"ID: "</span>,News[i].EventID,<span class="class="type">class="kw">string">" Name: "</span>,News[i].EventName,<span class="class="type">class="kw">string">" Date: "</span>,News[i].EventDate); } } NewsData(<span class="keyword">class="type">void</span>) {}<span class="comment">class=class="str">"cmt">//Class constructor</span> ~NewsData(<span class="keyword">class="type">void</span>) {<span class="functions">ArrayFree</span>(News);}<span class="comment">class=class="str">"cmt">//Class destructor</span> }; <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="comment">class=class="str">"cmt">//|(Subclass/Child) for &class="macro">#x27;NewsData&class="macro">#x27; |</span> <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="keyword">class</span> <span style="background-class="type">class="kw">color:rgb(class="num">222, class="num">188, class="num">133);">UnitedStates</span>:<span class="keyword">class="kw">private</span> <span style="background-class="type">class="kw">color:rgb(class="num">177, class="num">210, class="num">143);">NewsData</span> <span class="comment">class=class="str">"cmt">//class="kw">private inheritance from NewsData,</span> <span class="comment">class=class="str">"cmt">//&class="macro">#x27;UnitedStates&class="macro">#x27; class&class="macro">#x27;s objects and children</span> <span class="comment">class=class="str">"cmt">//will not have access to &class="macro">#x27;NewsData&class="macro">#x27; class&class="macro">#x27;s properties</span> { <span class="keyword">class="kw">private</span>: