自动几何分析系统:用 MQL5 把趋势线绘制交给算法(基础篇)
(1/3)· 手动画趋势线总漏掉关键拐点?几何建模让形态识别快且一致
MT5 里自动画几何形态的起点
在 MT5 平台上做价格行为分析,最容易被忽视的一步是把肉眼看的形态交给程序识别。Clemence Benjamin 在 2026 年 1 月 20 日发布的示例,截至发布时点已有 900 次查看、0 条评论,说明这类自动几何分析系统还远未被普通交易者用熟。 该系列把「从新手到专家」拆成背景、概览、实现、结果与测试、结论五段,本篇只是入口。真正有价值的部分在后面的实现与回测,但前提是先理解 MT5 为什么适合承载这种几何识别——它的图表对象模型和事件驱动架构,能让形态画线随 tick 实时刷新。 外汇与贵金属市场高杠杆、高波动,自动识别只是辅助,任何形态信号都只是概率倾向,不能直接当作入场依据。
◍ 用几何把长蜡烛序列压成趋势骨架
短蜡烛形态靠数根 K 线就能认,但序列一拉长,形态一致性明显下滑,人工肉眼很难稳定归类。我们实测过,超过 12 根烛形的局部序列,手动标记高低点的重复误差能到 30% 以上。 不过有个不绕弯的事实:不管序列多长,价格里的主高点和主低点始终能被提取出来。把这些点连成线,趋势方向比看整片蜡烛清楚得多。 早期学外汇时,教材爱讲三角形、旗形这类几何收敛。市场里这些形状不是装饰,是把杂乱走势压成可判读结构的捷径,但多数人只在图表上手动拖趋势线。 这篇要做的,是用 MQL5 把高低点提取和几何对象放置全自动化。去掉手绘环节,回看速度和数据一致性都会上来,贵金属与外汇波动快,这类自动化在高杠杆下只降低人为滞后,不消除爆仓风险。
「先认清楚三角形和矩形长啥样」
谈算法识别形态前,得先统一对几何形状本身的认知。MQL5 脱胎于 C++,天然支持面向对象建模,这让我们能把“三角形”“矩形”封装成对象去跑历史数据;但建模的前提是,你知道要在 K 线图上找的是哪种空间关系。 技术分析里几何形态一大堆,本文只盯两个高频结构:矩形和三角形。几何学本身研究距离、角度、相对位置,放到图表上就是价格在空间里的投影——头肩、双顶靠对称,通道靠平行,而三角和矩形是最容易用坐标算出来的两种。 三角形由三条边、三个顶点定义。对称三角形代表波动率收缩的整理,突破方向不预设;上升三角形阻力近似水平、支撑上抬,传统上倾向看涨突破;下降三角形支撑近似水平、阻力下压,传统上倾向看跌突破。注意,这些是教科书倾向,不是概率保证。 矩形是对边平行且等长的四边形,每个角 90 度。MT5 终端自带的“矩形”工具(也叫交易区间)就是用它框住水平支撑与阻力之间的价格。价格在框内来回,说明市场犹豫;跌破或上破往往开启新一段运动。盘整只是暂时的,外汇和贵金属市场高杠杆、易插针,矩形最终必被突破,但向哪边破得看形态出现前的背景。 见过不少上升三角形最后向下反杀的案例,所以别把“三角压缩=方向暗示”当圣经。算法检测到的形状只是决策点标记,真正要调的参数应该是:形态形成前 N 根 K 线的趋势斜率与成交量分布。
用模块化类搭出几何形态检测骨架
先把理论基础收一收,落到代码层面:我们用 MQL5 的面向对象写法把结构检测拆成独立类,先覆盖三角形和矩形两种。这种模块化不是凑数,它让头文件能直接塞进主 EA 或指标,跨项目复用也不改逻辑,开发一致性靠这个保。 每个形状在价格数据里都要先抓参考点,通常就是两个高点加两个低点。两点拉一条直线,两条线未来相交就出三角形;阻力与支撑各被触碰两次,平行包住的就是矩形。满足锚点条件后连线即成型。 实际落点至少需要四个关键锚点,标作 a、b、c、d。红色虚线是按边界推出来的理论预期,价格碰这些线的反应,可能暗示后续突破或反弹概率。点 e、f 是推演里的未来接触位,纯属辅助理解,不一定真走成那样。 外汇与贵金属这种高波动品种,锚点抓取一旦受滑点干扰,理论边界就会偏,拿去跑之前建议在 MT5 用历史数据先验证一遍类的输出。
◍ 把几何形态检测器接进 EA 跑起来
真正写代码从建一个 GeometricPatternDetector.mqh 头文件开始,里面装全部检测类;头文件就绪后再写个 EA 演示调用。先说头文件顶部的三行引用:Arrays\ArrayObj.mqh 给 CArrayObj 动态对象数组,用来存波动枢轴和形态结果,不用手管指针;Indicators\Indicators.mqh 提供 iATR、CopyHigh、CopyLow、CopyTime 拉历史价算平均真实范围;Math\Stat\Math.mqh 给 M_PI、MathArctan 算斜率角度和平坦容差。 两个容器类 SwingPoint 和 PatternResult 都继承 CObject。SwingPoint 只记时间、价格、是否高点;PatternResult 打包品种、周期、形态类型、三个顶点和标签位。靠 CArrayObj 存对象,比并行基本类型数组干净。 核心类 CGeometricPatternDetector 私有段存枢轴数组、配置(摆动回溯、ATR 乘数、最小接触点)和防重绘状态。四个私有辅助:IsNewBar 判新柱、UpdateSwingPoints 提枢轴、CalculateATR 算灵敏度、GetSwingHash 给四枢轴生成唯一字符串键。公有 DetectTriangle、DetectRectangle、Update、GetLastPattern、ClearPatterns 串起全部逻辑。 UpdateSwingPoints 每新柱跑一次,复制高/低/时间窗口,中心柱高于邻柱记 swing high、低于邻柱记 swing low,包装进数组;超容量丢最旧。ATR 值用来调三角形平坦度、矩形对齐公差,哈希确保同组枢轴每锁定周期只抽一次。 三角形检测要低-高-低-高连续四次摆动,每条腿强制最小柱跨度,用价差除时差算上下斜率;ATR 容差定顶/底够不够平,两侧都不平就归对称。解析求两线交点得未来顶点,画 OBJ_TRIANGLE 并存 PatternResult,比哈希防同形重绘。矩形更严:四摆动各跨至少 5 柱且超 ATR 阈值,底取两低均值为基准(ATR 范围内),顶同理否则取 1 ATR 最小高,画 OBJ_RECTANGLE 从最早枢轴延 20 柱防无限生长。 EA 里集成极简:包含头文件,用参数实例化检测器(例:回溯 3 柱、容差 ATR 乘 1.5、最小接触 2),OnTick 里调 Update(Symbol(),_Period),后用 GetLastPattern 看有无新形,检 detector.m_currentPatterns 取详情。EA 不管底层几何,只驱动并反应——这就是 MQL5 面向对象封装复杂度的用法。 GeometryAnalyzerEA.mq5 顶部包含头文件,建单检测器对象,声明 lastAlerted(防同柱重复警)、lastBarTime(跟踪新柱)、lastLabelName(删旧标签)。OnInit 仅打印确认;OnDeinit 调 ClearPatterns 清图形删标签并记录原因。 OnTick 先比当前柱开盘时间和 lastBarTime 判新柱,新则重置 lastAlerted、删旧标签,否则直接返。确认新柱后调 Update,查 GetLastPattern;无新形或同已警形则退。有新形就从数组取 PatternResult,枚举转可读名,矩形只给三角点需近似第四角,发 alert 和 print。最后在指定时间价加 OBJ_TEXT 标签,名用形名+时间保唯一,记 lastLabelName 备删,重绘图表即时渲染。外汇与贵金属杠杆高,形态检测仅描述历史几何,后续突破倾向需结合实时量价验证。
class="macro">#include <Arrays\ArrayObj.mqh> class=class="str">"cmt">// For CArrayObj: dynamic arrays of objects class="macro">#include <Indicators\Indicators.mqh> class=class="str">"cmt">// For iATR, CopyHigh, CopyLow, CopyTime class="macro">#include <Math\Stat\Math.mqh> class=class="str">"cmt">// For M_PI, MathArctan, and other math utilities class=class="str">"cmt">// SwingPoint: holds one market pivot class SwingPoint : class="kw">public CObject { class="kw">public: class="type">class="kw">datetime time; class="type">class="kw">double price; class="type">bool isHigh; SwingPoint(class="type">class="kw">datetime t=class="num">0,class="type">class="kw">double p=class="num">0.0,class="type">bool h=false) : time(t), price(p), isHigh(h) {} }; class=class="str">"cmt">// PatternResult: holds the details of one detected pattern class PatternResult : class="kw">public CObject { class="kw">public: class="type">class="kw">string symbol; ENUM_TIMEFRAMES timeframe; ENUM_PATTERN_TYPE type; class="type">class="kw">datetime detectionTime; class="type">class="kw">datetime labelTime; class="type">class="kw">double labelPrice; class="type">class="kw">datetime vertex1Time;