通用智能交易系统:交易策略的模式(第一章)(基础篇)
📘

通用智能交易系统:交易策略的模式(第一章)(基础篇)

第 1/2 篇

「把交易逻辑拆成可开关的模式」

在 MT5 里写 EA,最忌把所有开仓和平仓判断揉进一个 OnTick。把「用于开新仓」和「管理已有仓位」两类方法先拆开,后续调参和回测才不会互相污染。 原文给出的结构把策略切成一个个独立交易模式,每个模式只负责一类动作。这样你改突破逻辑时,不会误伤 trailing stop 的判定。 CTradeState 是这类设计里常见的模式开关:用枚举或布尔把当前 EA 处于「观望 / 试单 / 加仓 / 减仓」哪种状态显式存下来。MT5 回测时,你能在日志里直接看到状态跳变,比埋变量直观得多。 外汇与贵金属杠杆高、滑点跳空频繁,状态机再清晰也挡不住极端行情。先把模式开关跑通在 2016 年那版示例的 8556 次浏览逻辑上,再接自己品种不迟。

把交易技术壳和策略脑子拆开

写 EA 时你通常会碰到几类活:盯盘口算入场信号、管已开仓的退出、接交易报错并重试,还有最基础的读行情和持仓。这些事如果全堆进 EA 源码,后面改逻辑就像拆炸弹。 更干净的做法是用面向对象把「技术执行」和「交易想法」切开。技术那层做成公共类,所有策略都能调,圈内一般叫交易引擎。本系列要讲的通用智能交易系统就是这么一组类,它用一套开平仓条件的通用枚举,把数据获取、持仓查询这些脏活全包了,你只填信号。 整套方案太宽,拆成四篇发。本篇只讲第一部分:策略的交易模式,以及怎么用交易模式管初始持仓。按这个模式写 EA,逻辑像填表,调试时一眼能看出哪根线断了。 后面三篇分别覆盖事件模型与多货币对处理、自定义策略开发、以及把多策略塞进一个 ex5 用 XML 生成组合。思路本身不绑我的类库,不用 OOP 也能借鉴。

◍ 双均线系统的开平仓动作拆解

用两条均线搭一个最朴素的趋势跟随框架:短周期线反应快,长周期线反应慢。经典做法是快线穿慢线向上就买,向下就卖。原文给的示例参数是快速 SMA 50、慢速 SMA 120,交叉点用蓝色虚线标出,EA 在交叉瞬间翻转方向。 但要把这套逻辑写进 EA,光说「交叉就反向」不够。快线向上穿越时,若手里有空单先平掉,再检查有没有多单——没有才开多,有就不动。快线向下穿越则镜像处理:平多、查空、无空才开空。表面看是四个动作,其实多头建仓和空头平仓在原始对称策略里是一回事。 别急着把对称动作合并。一旦把买入和卖出拆成不同均线组合,比如多单用 SMA50 上穿 SMA120、空单用 SMA20 下穿 SMA70,信号就不再镜像,发生时刻和市场环境都不同。通用 EA 模型必须保留四个独立规则:BuyInit、SellInit、SupportBuy、SupportSell,分别对应开多、开空、管多、管空。 从工程角度,这四个规则就是未来策略类的四个方法块。所有交易操作被切成独立模块后,代码里不用再到处塞交叉判断,改逻辑只需往对应方法加条件。外汇与贵金属杠杆高,这种模块化只解决可维护性,不暗示任何胜率。

「用函数开关切换EA交易模式」

EA 的下单动作通常需要被约束,最基础的做法是在 MT4 加载 EA 时于属性页里勾选禁多或禁空。但这类内置开关不够灵活,比如想在太平洋时段低流动性行情里让 EA 忽略新信号,就需要更细的调度。 核心思路是把开仓逻辑收拢到固定函数里:不调用 SellInit 就开不了空,不调用 BuyInit 就开不了多。通过组合 BuyInit / SellInit / BuySupport / SellSupport 的启用与忽略,就能拼出买和卖、仅买、仅卖、禁止新开、暂停、停止六类模式。 以「仅买」为例,启用 BuyInit 与 BuySupport,忽略 SellInit,之前开的空单仍由 SellSupport 管到平仓;「暂停」则四个函数全不调用,持仓脱管、不接新信号,常用于休市。外汇与贵金属波动剧烈,这类模式切换只降低无效成交概率,不消除高风险。 下面这段枚举把六种状态直接落到代码层,改一个枚举值即可整体切换 EA 行为,建议开 MT5 新建 ea 把结构体抄进去试。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 确定EA的交易状态。                                                        |
class=class="str">"cmt">//+------------------------------------------------------------------+
enum ENUM_TRADE_STATE
{
   TRADE_BUY_AND_SELL,                 class=class="str">"cmt">// 允许买入和卖出操作
   TRADE_BUY_ONLY,                     class=class="str">"cmt">// 仅允许买入操作不允许卖出。
   TRADE_SELL_ONLY,                    class=class="str">"cmt">// 仅允许卖出操作不允许买入
   TRADE_STOP,                         class=class="str">"cmt">// 不允许执行交易立即平仓所有头寸不接受新的交易信号。
   TRADE_WAIT,                         class=class="str">"cmt">// 对开仓头寸的控制丢失,忽略新的信号。在新闻发布时有用。
   TRADE_NO_NEW_ENTRY                  class=class="str">"cmt">// 忽略入场信号。然而,根据交易逻辑保留持仓。
};

常见问题

把交易技术壳(下单、平仓、风控)和策略脑子(信号判断)拆成独立模块,用函数开关控制当前启用哪种信号,主循环只负责调度。
在信号函数里快线穿越慢线向上返回开多指令,向下穿越返回平多指令;主逻辑收到指令再调用统一下单接口,不把下单写进信号里。
可以。把EA模式开关和信号函数贴给小布,它能逐段指出空仓期、重复开仓或平仓条件冲突等隐患,省去手动逐行查。
技术壳和策略脑子耦合了。下单手数、止损止盈应放在壳层固定读取,策略只输出买卖信号,不碰仓位参数。
几乎不影响。开关只是跳过未启用信号函数,开销可忽略;重点是把信号计算写成独立函数而非堆在主循环里。