80-20 交易策略·综合运用
📊

80-20 交易策略·综合运用

(3/3)· 接前两篇的信号模块与基础机器人,本篇把它跑成 EA 并回测世纪末策略在当下盘面的存活率

案例拆解 第 3/3 篇
很多交易者把 80-20 当成万能日内反转公式,却忽略原著要求昨日波幅超过均值且信号仅存活于当日。直接挂单不验历史分位,容易在震荡市连续吃假突破。

「用终端全局变量锁住每日单次信号」

把书籍里的 80-20 基础 EA 改造成每日只做一次的短线趋势机器人时,最麻烦的不是信号计算,而是「今天已经下过单」这个状态怎么跨重启保留。程序内存里的布尔变量在终端关闭或 EA 被移除图表时就归零,所以必须把最后一次入场日期写进终端层全局变量,而不是局部变量。 我们给用户暴露了两个输入:One_Trade 控制是否启用每日一单,Magic_Number 给每个 EA 实例分配独立 ID,避免不同品种或回测版本互相覆盖全局变量。代码中前缀 SSB 加上品种名、魔幻数字和测试标识,拼成全局变量命名空间。 OnInit 里读取全局变量 Last_Position_Date 和 Last_Pending_Date,用 TimeCurrent() - TimeCurrent() % 86400 算出当日 0 点时间戳做比对。若相等说明今天已处理过信号,gb_Position_Today / gb_Pending_Today 置真,后续信号直接丢弃。这一处比对逻辑是整段改动的命门,少写 % 86400 就会变成每毫秒都比一遍。 挂单成功和持仓新建两段代码里分别补了 GlobalVariableSet,把当日 0 点时间戳写回终端。这样哪怕 MT5 中途崩了,重启后 EA 仍能从全局变量认出「今天已经动过手」,不会在趋势中段重复追单。外汇与贵金属杠杆高,这类重复入场在滑点扩大时可能把回撤翻倍,验证时建议在策略测试器用 2016 年魔幻数字跑一遍 EURUSD 的 M15。

MQL5 / C++
class="kw">input class="type">bool   One_Trade = class="kw">false;      class=class="str">"cmt">// 每日一单
class="kw">input class="type">uint   Magic_Number = class="num">2016;    class=class="str">"cmt">// EA 魔幻数字

class="type">class="kw">string   gs_Prefix; class=class="str">"cmt">// 全局变量的标识符 (超级)
class="type">bool   gb_Position_Today = class="kw">false,   gb_Pending_Today = class="kw">false;

class="type">int OnInit() {
   class=class="str">"cmt">// 创建全局变量名的前缀 (超级):
   gs_Prefix = StringFormat("SSB %s %u %s", _Symbol, Magic_Number, MQLInfoInteger(MQL_TESTER) ? "t " : "");
   class=class="str">"cmt">// 今日机器人是否已开单?
   gb_Position_Today = class="type">int(GlobalVariableGet(gs_Prefix + "Last_Position_Date")) == TimeCurrent() - TimeCurrent() % class="num">86400;
   gb_Pending_Today = class="type">int(GlobalVariableGet(gs_Prefix + "Last_Pending_Date")) == TimeCurrent() - TimeCurrent() % class="num">86400;
}

if (i_Try != -class="num">10) {
   if (Log_Level > LOG_LEVEL_NONE) Print("放置挂单错误");
   if (Log_Level > LOG_LEVEL_ERR)
      PrintFormat("挂单不可放置在 %s 价位。供给价: %s 采购价: %s 停止位: %s",
         DoubleToString(d_Entry_Level, _Digits),
         DoubleToString(go_Tick.bid, _Digits),
         DoubleToString(go_Tick.ask, _Digits),
         DoubleToString(gd_Stop_Level, _Digits));
} else {
   GlobalVariableSet(gs_Prefix + "Last_Pending_Date", TimeCurrent() - TimeCurrent() % class="num">86400);
   gb_Pending_Today = true;
}

if (PositionSelect(_Symbol)) {
   if (PositionGetDouble(POSITION_SL) == class="num">0.) {
      if (!gb_Position_Today) {
         GlobalVariableSet(gs_Prefix + "Last_Position_Date", TimeCurrent() - TimeCurrent() % class="num">86400);
         gb_Position_Today = true;
      }
   }
}

把书里那套形态丢进近五年行情跑一遍

Raschke 和 Connors 原书用的是四位小数报价下的缩进规则,我在 MT5 上拿 EURUSD、USDJPY、XAUUSD 做验证时,把缩进直接放大 10 倍以适配五位小数环境。原文没给尾随参数和止盈算法,我按日线波动挑了组未深度优化的随意比值,先跑裸规则再看加止盈的差别。 EURUSD 取五年历史,原始规则(无止盈)余额曲线和带止盈版本分开跑了;USDJPY 同样五年,因本身波动最猛,两段曲线斜率差异比欧元对更明显;XAUUSD 只用最近 4 年日线,贵金属的高风险属性意味着样本内结果向外推时概率性很强,不能当必然。 每次测试 EA 的全部参数都封在带完整报告的附件里,开 MT5 载入对应 set 文件就能复现这三组余额图,自己改缩进倍数看曲线怎么扭是最直接的验证动作。

◍ 记住这一条就够了

信号模块的编程逻辑底层对应了 80-20 短线系统,但原文作者把原始规则向外扩了一圈:除了改条件,还建议换更贴合系统的交易标的和信号跟踪参数。评论区有人翻出近 6 年回测,单个样本 233 笔交易,结论倾向“单靠原版规则很难盈利”,趋势市相对好用、震荡市吃不到点。 外汇和贵金属自带高杠杆高风险,任何策略在 MT5 里跑完历史测试前都只是“可能有效”。打开你手里的 EA 或指标,先调一下信号检测的阈值,再换两个品种回测,比盲目跟规则实在。

让小布替你跑这套回测
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到昨日波幅分位与边界突破的实时标记,把重复劳动交给小布,你专注决策。

常见问题

原著未指定历史天数,实战中常用 20 至 50 根日线均值做参照,具体需在回测中按品种波动特性调参。
可以,小布盯盘的品种页已内置边界分位与虚假突破标注,省去手动算前日高低 20% 区间的功夫。
这是原著过滤瞬时毛刺的设定,5 次 tick 确认能降低开盘瞬时假突破触发挂单的概率。
回测结果倾向概率性盈利,但外汇贵金属高风险,需结合当下波动率与手续费重验,不可直接照搬。