神经网络变得轻松(第十九部分):使用 MQL5 的关联规则(基础篇)
📘

神经网络变得轻松(第十九部分):使用 MQL5 的关联规则(基础篇)

第 1/3 篇

用关联规则给行情建网络

关联规则在零售交易里常被当成超市「啤酒配尿布」的玩笑,但在 MQL5 里它可以直接用来挖 K 线之间的共现关系。核心思路是:把每段行情切成离散状态(涨/跌/震荡),再统计哪些状态组合出现频率显著高于随机。 在 MT5 中跑这套分析不需要外接 Python,直接用 MQL5 的数组和文件读写就能完成频繁项集计数。一个实用门槛是:样本窗口低于 200 根Bar时,支持度估计会剧烈抖动,建议先在 EURUSD 的 H1 上用 500 根以上历史验证。 外汇与贵金属杠杆高、滑点突变频繁,关联规则挖出的只是「历史共现概率」,下一根Bar是否重复完全不保证。把它当过滤器而非信号源,才不容易在非农夜被反噬。

「FP-Growth 怎么嵌进 MT5 交易逻辑」

把关联规则挖掘搬进交易系统,核心不是跑出一堆频繁项集,而是让历史 K 线里的共现结构变成可执行的过滤条件。比如某品种在美盘开盘后 30 根 M5 棒里,出现「上影大于实体 2 倍」且「后续 3 根不破前高」的组合频率超过 0.18,就可以作为反抽失效的预警输入。 FP-Growth 相比 Apriori 省掉了候选集爆炸这一步,它用一棵前缀树压缩事务库。在 MQL5 里先把每根 bar 的局部形态编码成符号事务,再喂给树结构做条件模式基抽取,这一步直接决定后面规则的可信度。 实盘前必须用 MT5 的帧测试器跑至少 6 个月 tick 数据,观察不同 minSupport 下的规则衰减。外汇与贵金属杠杆高、滑点突变频繁,任何从历史共现推导出的偏好都只是概率倾向,不能直接当入场指令。

◍ 从 Apriori 到 FP-Growth 的提速逻辑

关联规则挖掘属于无监督学习,上一节已铺垫了 Apriori 与 FP-Growth 两种解法。Apriori 的硬伤在于反复扫描数据库:每判定一个频繁项候选集的支持度,就要全表过一遍,I/O 开销随候选规模膨胀。 FP-Growth 把整库压缩进内存里的 FP 树,后续挖掘只在这棵树上做,不再回数据库。由于内存随机访问远快于磁盘全表迭代,实际跑下来建树后单轮挖掘耗时会显著低于 Apriori 的多趟扫描。 在 MT5 里若想验证这个差异,可直接用历史 tick 或分钟 bar 做频繁形态提取,小样本下两者差距不明显,但当商品数过 50、记录过 10 万行时,FP-Growth 的优势会直接体现在策略回测的等待时间上。外汇与贵金属数据波动大、噪点多,这类挖掘结果仅作概率参考,实盘高风险。

把关联规则接进交易决策链

关联规则挖掘的本质,是在历史数据里找二元特征之间稳定的共生依赖,不关心特征是指标、跨周期数值还是不同品种。每个特征在算法眼里都是独立维度,这让它能把多指标组合形态也当成一条规则来评。 我们可以往训练样本里塞一个目标特征,比如「未来 N 根 K 线收阳」,让算法只返回那些导向该目标的稳定规则。这样无监督的关联挖掘就和监督思路接上了,产出的不再是孤立形态,而是带倾向性的触发条件。 外汇与贵金属市场高杠杆、跳空频繁,这类规则只代表历史概率倾向,实盘前务必在 MT5 用叉盘或多周期数据复算一遍稳定性。

「2. FP-Growth 算法实现」

为了实现上一篇文章中研究的 FP-Growth 算法,我们要记住其构造是基于决策树的。 MQL5 标准库拥有构建二叉树的 CTree 类。 不幸的是,二叉树选项对我们来说并不完全方便,因为一棵 FP 树的一个节点的分支数可以超过 2 个(二元实现中的最大可用分支数)。 因此,在构建算法本身之前,我们先创建 CMyTreeNode 类来实现拥有多个分支的树节点。

  • 1. 树的节点类实现

该类将从动态对象数组 CArrayObj 的标准 MQL5 类派生而来。 这个类之所以被选为父类,是因为它拥有与创建和维护动态对象数组相关的所需功能,在我们的例子中,分支节点其实就是动态对象数组。 此外,为了实现算法所需的功能,类中已加入了三个新变量: m_cParent — 指向上一个父节点对象的指针。 对应树根,它将为空 m_iIndex — 源数据库中特征的索引;用于识别特征 m_dSupport — 接收特征支持度值的变量 在类构造函数中,设置变量的初始值,并清除动态数组。 将类析构函数保留为空。 为了操控隐藏的类变量,我们将创建一些方法,这些方法将在 FP-Growth 算法的创建过程中用到。 我还会提供方法目的解释及其用途。 为了计算置信水平,我们创建 GetConfidence 方法。 在其中,我们首先检查指向前置节点的指针,如果它有效,则将当前节点支持度除以父节点支持度。 注意,FP 树构建算法的组织方式是,任何节点的支持度都不能大于父节点的支持度。 因此,方法操作的结果将始终为正值,并且不会大于 1。 由于树节点是基于现有业务添加的,所以我们没有除零检查。 因此,如果一个节点在树中,那么它的特征在数据库中至少出现过一次,且它的支持度最低。 此外,我们添加了一个创建新分支节点的 AddNode 方法。 在方法参数中,我们传递训练样本源数据库中的特征 ID,和节点的支持度。 该方法返回指向所创建对象的指针。 在方法实体中,我们创建树节点的新实例,并立即检查操作结果。 如果发生错误,则返回无效的对象指针。 接下来,我们指定所创建节点的 ID,并将指向当前对象的指针传递给它,作为父对象。 将新对象添加到当前节点的动态数组中,并检查操作结果。 如果往数组中添加对象时出错,则删除所创建对象,并退出方法,同时返回无效指针。 在方法结束时,将参数中指定的支持度保存到新对象当中,然后退出该方法。 一旦我们创建了一个新对象,我们应该能够删除它。 父类中已存在依据动态数组中的索引删除对象的方法。 为了扩展功能,我们创建 DeleteNode 方法,并按功能 ID 删除节点。 该方法接收要删除的功能 ID,并返回操作的布尔结果。 在方法实体中,实现循环以在当前节点的动态数组中查找匹配指定 ID 的节点。 循环将迭代遍历从 0 到 m_data_total 变量值范围内的元素。 该变量包含动态数组的活动元素数量,并由父类管控。 在方法实体中,从动态数组中提取下一个元素,并验证指针。 通过调用父类的 Delete 方法(含有指向欲删除元素的索引),可以立即删除含有无效指针的元素。 注意, Delete 方法返回操作的布尔结果。 如果成功地从动态数组中删除了一个元素,则减少循环迭代的计数器,并移动到下一个数组。 我们只减少循环迭代计数器,而不更改 m_data_total 变量值。 这是因为它的值在 Delete 父类的方法中已经更改。 如果在从动态数组中删除无效元素时发生错误,只需移动到数组的下一个元素即可。 我们不会终止方法时返回 false 结果,因为方法任务不是从无效

常见问题

先把历史K线里的指标状态(如均线多头、RSI超卖)离散化成事件,再用关联规则挖频繁共现组合,就能看出哪些信号组合后倾向出现某类行情。
FP-Growth 只扫两遍数据且免候选集生成,样本几万条时通常比 Apriori 快一个数量级,实盘周更频次下资源占用可控。
可以,小布能按你选的品种和指标自动离散化并跑关联挖掘,把高频共现规则直接列在品种页,省去手敲代码。
不能直下,规则只代表历史共现概率;应接进决策链做二次过滤,外汇贵金属波动大,须带止损并小仓验证。
用现成脚本把指标转成事件标签后导出,再丢进关联分析工具看输出;重点调最小支持度和置信度两个参数找可用组合。