聚类分析(第一部分):精通指标线的斜率(基础篇)
◍ 用斜率给指标线做聚类分层
指标线不是只有方向和数值,它的斜率本身携带了市场节奏信息。把一段时期的斜率按大小聚类,能区分出“横盘微动”“温和趋势”“陡坡冲刺”三种状态,比单纯看金叉死叉早半步。 在 MT5 里取均线斜率很简单:用 iMA 拿到句柄后,读相邻两根柱的 MA 值做差,再除以 Period() 秒数得到单位时间变化率。下面这段代码演示了如何计算并输出当前斜率。 [CODE] int maHandle = iMA(_Symbol, PERIOD_H1, 20, 0, MODE_SMA, PRICE_CLOSE); double ma0, ma1; CopyBuffer(maHandle, 0, 0, 1, ma0); CopyBuffer(maHandle, 0, 1, 1, ma1); double slope = (ma0[0] - ma1[0]) / PeriodSeconds(PERIOD_H1); Print("Slope per sec: ", slope); [/CODE] 逐行看:第一行建 20 周期 H1 均线句柄;二三行声明两个 double 接收当前与上一根值;四五行用 CopyBuffer 分别取 0 号与 1 号偏移的缓冲;第六行用差值除以 H1 的秒数(3600)得到每秒斜率;最后打印。 把 slope 的绝对值分桶:小于 0.00002 视为微动,0.00002–0.0001 为温和,大于 0.0001 大概率是陡坡。外汇与贵金属杠杆高、滑点突兀,这种分层只作概率参考,开 MT5 挂个脚本跑 EURUSD H1 就能验证你的阈值是否过宽。
class="type">int maHandle = iMA(_Symbol, PERIOD_H1, class="num">20, class="num">0, MODE_SMA, PRICE_CLOSE); class="type">class="kw">double ma0, ma1; CopyBuffer(maHandle, class="num">0, class="num">0, class="num">1, ma0); CopyBuffer(maHandle, class="num">0, class="num">1, class="num">1, ma1); class="type">class="kw">double slope = (ma0[class="num">0] - ma1[class="num">0]) / PeriodSeconds(PERIOD_H1); Print("Slope per sec: ", slope);
用聚类看指标斜率的状态
聚类是 AI 里最基础的手段之一:把观测值(常是数值或坐标点)按相似度归到不同的堆里。一旦新点被划入某个已知堆,就能借用该堆的属性来决策。 落到 MT5 上,我们关心的是:技术指标的斜率,能不能被聚类成「横盘」和「趋势」两类状态。斜率接近 0 的观测点聚为一堆,明显偏离 0 的聚为另一堆,这样新一根 K 线的斜率进来,就能直接判它属于哪一类。 实际观测中,同一周期下 RSI(14) 的斜率在 ±0.3 以内时,价格后续 20 根棒走窄幅震荡的概率偏高;超出这个范围则更倾向出现单边段。外汇与贵金属杠杆高,这种划分只作概率参考,不等于方向确认。
「MQL5里如何给聚类分析留接口」
HalfTrend 指标从 MQL4 搬过来时,柱线索引沿用了老习惯:rates_total 为最久远一根,0 号是最新当前柱。OnCalculate 首次调用 prev_calculated 为 0,之后可用它判断已算和未算的柱数,这是写增量计算的逻辑起点。 双色线由 up[] 和 down[] 两个缓冲区实现,同一索引 iB 下只有一个取正值,另一个置 0 不绘制。为了别处能直接复用聚类逻辑,代码只补了最少量的结构,后加行都用注释框起来,完整函数放在附带的 ClusterTrend.mqh。 聚类基础结构里,µ 是均值,σ 是标准差即方差根,描述值围绕均值的离散程度,max/min 为极值,S2 是辅助变量,n 为样本数,ID 作标识。MQL5 多维数组只能动态调第一维,所以把待检数值类型数挂在第一维,第二维固定为分类值数量。 CatCoeff 一维数组有 9 个系数,决定了 cluster 第二维固定大小须大于 5,两条线紧邻排布,原因后面展开。差异检测只看 x[iB]-x[iB+1],并转成 _Point 点数,这样 EURUSD 的 5 位小数和 XAUUSD 的 2 位小数(贵金属杠杆高、滑点风险大)能放一起比。 下面这段是新增的结构定义与系数表,直接贴进 MT5 能编译看内存布局。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| added for cluster analysis | class=class="str">"cmt">//+------------------------------------------------------------------+ .... class=class="str">"cmt">//+------------------------------------------------------------------+ class="kw">struct __IncrStdDev { class="type">class="kw">double µ, class=class="str">"cmt">// average σ, class=class="str">"cmt">// standard deviation max,min, class=class="str">"cmt">// max. and min. values S2; class=class="str">"cmt">// auxiliary variable class="type">uint ID,n; class=class="str">"cmt">// ID and no. of values }; __cluster cluster[][class="num">14]; class="type">class="kw">double CatCoeff[class="num">9] = {class="num">0.0,class="num">0.33,class="num">0.76,class="num">1.32,class="num">2.04,class="num">2.98,class="num">4.21,class="num">5.80,class="num">7.87};
◍ 用聚类给行情状态定阈值
做 EA 的第一道坎,是先搞清楚当前行情是窄幅横盘还是趋势在跑。横盘里贴着均值在通道边界接反抽、赚回中心的差价;趋势里则要在偏离均值的方向追,直到价格从中心反向扯远、出现逆势翻转的苗头。两种打法完全相反,EA 必须拿到一个能区分它们的数字,再配阈值判断此刻算趋势还是震荡。 肉眼看图往往觉得一眼就能分,但视觉感受没法直接写进公式。聚类分析是把数据点归类的数学手段,正好能帮 EA 把行情状态切成几堆。它靠优化来定三件事:聚类个数、各类中心、以及每个样本点只归一个类(尽量不重叠)。 优化目标很直接——把绝大多数数值元组(异常值可除外)塞进某个聚类,同时让类内散布尽量小、类间重叠尽量少、用的聚类数尽量省。但要注意,当样本点和聚类数量一大,这套优化在计算上会非常贵,MT5 里跑大规模聚类别指望实时秒出。
用 O-计数法看聚类算力的真实量级
算法复杂度习惯用 O-计数法表达,O(n) 表示只遍历 n 个元素一次。经典排序里最快常见 O(nlogn)、最慢常见 O(n²),过去算力弱时这是硬指标,现在机器快了,但光学分析这类场景的数据量涨得更猛。 聚类里的 k-means 把 n 个观测值分到 k 个类,靠最小化到类心的欧氏距离,理论成本是 O(n^(dk+1))。放到行情上,GBPUSD 日线在 MQ 模拟账户里有 7265 根柱线,即 n;我们取维度 d=1(各指标相对前值的差),先试 k=9 类,代入公式就是 O(7265^10),约 4.1×10³⁸,普通交易电脑根本跑不动。 但用本文方法实测,GBPUSD D1 的聚类 16 毫秒完成,折合每秒 454063 个值;换 GBPUSD M15 有 556388 根柱线、同样 9 类,耗时 140 毫秒,每秒 3974200 个值。这比 O(n) 还快,原因是 MT5 终端按周期组织数据,计算指标时顺带把算力复用进来了。外汇与贵金属行情高波动、高杠杆,这类实测仅供你在自己终端验证,不代表任何收益可能。
「HalfTrend 的斜率阈值难题」
我选用 MQ 自带的 HalfTrend 作为底层指标,它的水平段行程明显偏长,肉眼能看出横盘与趋势的分野。但问题落在量化上:到底斜率小到什么程度算横盘,大到什么程度算趋势,原文并没有给出可硬编码的明确阈值。 行情斜率的细微变化很难一刀切,EA 若只拿到一个浓缩了整张图信息的数字,而不是人眼看到的那一大片视觉图像,就会在临界区反复误判。作者提到后续用聚类分析解决,但本节先停在指标本身的改造前夜。 外汇与贵金属市场高杠杆、高波动,这类靠斜率区分状态的指标在实盘里可能频繁在横盘与趋势边界抖动,直接拿去开仓信号过滤要谨慎。