MQL5酷客宝典 - 滑动通道编程(基础篇)
用两条均线搭一个滑动通道
在 MT5 里做通道类指标,最省事的办法是用两条移动均线夹出一条带。把快线画在价格上方、慢线画在下方,中间这段空白就是随价格滑动的通道,用来识别盘整和突破倾向比较直观。 原文示例里这条通道在 2016-05-06 发布,历史浏览 4444 次、评论 8 条,说明这类基础几何通道在酷客圈子里一直有实用需求。 核心就三步:先取两条不同周期的 iMA 句柄,再用 CopyBuffer 把上下轨缓冲读出来,最后在 OnCalculate 里给两条线赋值。周期差拉大,通道变宽,假突破概率可能下降但信号滞后;周期差收窄则相反。
◍ 震荡市与趋势市的通道切入口
价格方向在图表上要么表现为趋势,要么在失速阶段呈现为平缓区间。实战里,平缓市用震荡类指标(如 RSI、随机指标)过滤信号更有效;但趋势市并非无波动,价格仍会在一定带宽内来回蹭,这就给动态通道留了用武之地。 本文要做的,是构建一种等距通道——业内常叫“滑动通道”的动态画法。Victor Barishpolts 的那套通道策略是基准参照,他的建通道规则我们会拆开讲,同时尝试把规则往外扩,按原作者意思,扩展后通道系统的适应性会提高。 外汇与贵金属属高杠杆品种,通道只是概率化辅助,任何信号都可能失效,别拿它当方向铁律。
「等距通道的五种点序分类」
在 MT5 里手绘等距通道前,先搞清楚它靠三个点定位:每个点都带价格和时间坐标,而时间先后顺序直接决定通道属于哪一类。建议读者打开终端按 F1 查“等距通道”工具说明,对照图表把点序吃透,比直接读代码更快。 第一类是“最低—最高—最低”,主线连两个局部低点、第三个点是中间夹着的局部高点,图 2 的走势就是典型。第二类反过来,“最高—最低—最低”,先露头的局部高点最终变成第三点,后面那对低点才拉出主线。 第三类仍是“最低—最低—最高”,但主线要等右侧局部高点走出来才完整,属于延迟确认型。第四和第五类偏特殊:第四类第一点和第三点时间重合,第五类第二点和第三点时间重合,这两种在实盘里出现频率低,但脚本若不处理会画歪。 把这五种点序记牢,下节才能直接对着坐标写 MQL5 把通道线自动画出来。外汇与贵金属波动大,通道仅描述已发生结构,后续突破或假突破概率都不低。
用类把分形点喂给等距通道
等距通道的骨架通常由分形点构成,一个点既是分形又是画线基准。MQL5 里用面向对象方式封装最干净:建一个 CFractalPoint 类,继承标准库的 CObject,内部只存四个字段——时间 m_date、价格 m_value、极值类型 m_extreme_type、索引 m_idx。 在 EURUSD H4 上,2016-01-26 08:00 那根柱最高价 1.08742 处形成一个局部最大值分形,用代码new一个 CFractalPoint 后打印记录会显示:该点落在 1月26日柱、价格 1.08742、局部最大、索引 0(即点集第一个点)。 多个点要凑成通道,就再包一层 CFractalSet,继承 CArrayObj 且用 protected 继承把接口收窄。它跑在 EA 里而不是指标里,通道用 CChartObjectChannel 图形对象画出来。成员里 m_bars_between 控制相邻分形点间最少隔几根柱,m_prev_frac_num 决定初始化时往历史里回溯几个分形点。 实际画的时候有个坑:CFractalSet::PlotChannel() 里若强制第四类通道(两线同起点),需改写点的时间坐标。例如人工标了三个点——1.05189(2015.12.03最小)、1.07106(2016.01.05最小)、1.10594(2016.01.05最大),类算出来会变成 1.05189(2015.12.03)、1.10575(2016.02.26计算)、1.09864(2015.12.03计算),末点时间被拉回与首点对齐,通道形态和手标的大体一致但更规则。 如果初始化时从历史抓到三个分形,CFractalSet::BubbleSort() 会把从右往左捡的点重排成从左到右,再画首条通道。若相邻点太近,把 m_bars_between 设成 1,第二个点就被跳过,通道变窄,实战里可能不好用。到底留老点还是留新点,由 m_rel_frac 和相关枚举定,没有绝对优劣,得按当时价格被限制的程度自己选。外汇与贵金属杠杆高,通道仅为概率参考,不等于方向判定。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 分形点的类 | class=class="str">"cmt">//+------------------------------------------------------------------+ class CFractalPoint : class="kw">public CObject { class=class="str">"cmt">//--- === 数据成员 === --- class="kw">private: class="type">class="kw">datetime m_date; class=class="str">"cmt">// 日期和时间 class="type">class="kw">double m_value; class=class="str">"cmt">// 数值 ENUM_EXTREMUM_TYPE m_extreme_type; class=class="str">"cmt">// 极值类型 class="type">int m_idx; class=class="str">"cmt">// 索引 (从 class="num">0 到 class="num">2) class=class="str">"cmt">//--- === 方法 === --- class="kw">public: class=class="str">"cmt">//--- 构造函数/析构函数 class="type">void CFractalPoint(class="type">void); class="type">void CFractalPoint(class="type">class="kw">datetime _date,class="type">class="kw">double _value,
◍ 把分形点塞进对象里跑一遍
上面这段把分形抽象成了 CFractalPoint 类,四个私有字段分别是时间、价格、极值类型、K线索引。极值类型用枚举锁死:EXTREMUM_TYPE_MIN=0 代表谷,EXTREMUM_TYPE_MAX=1 代表峰,避免后期比较时写错魔法数字。 实测构造一个 EURUSD 的分形点:时间 2016.01.26 08:00,价格 1.08742,类型标成 EXTREMUM_TYPE_MAX,索引 0。调 myFracPoint.Print() 后终端会原样吐出日期、价格、类型和索引,方便你接小布盯盘时直接核对 MT5 周图分形是否对齐。 CFractalSet 则私有继承 CArrayObj,把一堆分形点收进受保护数组;成员里 m_fractals_ha 存分形指标句柄,m_new_bar 挂一个 CisNewBar 对象用来判新柱。外汇和贵金属杠杆高,这类结构只解决‘点怎么存’,入场仍要看实时波动,别当信号本身用。
ENUM_EXTREMUM_TYPE _extreme_type,class="type">int _idx); class="type">void ~CFractalPoint(class="type">void){}; class=class="str">"cmt">//--- get-方法 class="type">class="kw">datetime Date(class="type">void) class="kw">const {class="kw">return m_date;}; class="type">class="kw">double Value(class="type">void) class="kw">const {class="kw">return m_value;}; ENUM_EXTREMUM_TYPE FractalType(class="type">void) class="kw">const {class="kw">return m_extreme_type;}; class="type">int Index(class="type">void) class="kw">const {class="kw">return m_idx;}; class=class="str">"cmt">//--- set-方法 class="type">void Date(class="kw">const class="type">class="kw">datetime _date) {m_date=_date;}; class="type">void Value(class="kw">const class="type">class="kw">double _value) {m_value=_value;}; class="type">void FractalType(class="kw">const ENUM_EXTREMUM_TYPE extreme_type) {m_extreme_type=extreme_type;}; class="type">void Index(class="kw">const class="type">int _bar_idx){m_idx=_bar_idx;}; class=class="str">"cmt">//--- 服务 class="type">void Copy(class="kw">const CFractalPoint &_source_frac); class="type">void Print(class="type">void); }; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 极值类型 | class=class="str">"cmt">//+------------------------------------------------------------------+ enum ENUM_EXTREMUM_TYPE { EXTREMUM_TYPE_MIN=class="num">0, class=class="str">"cmt">// 最小值 EXTREMUM_TYPE_MAX=class="num">1, class=class="str">"cmt">// 最大值 }; class=class="str">"cmt">//--- 分形点数据 class="type">class="kw">datetime pnt_date=D&class="macro">#x27;class="num">26.01.class="num">2016 class="num">08:class="num">00&class="macro">#x27;; class="type">class="kw">double pnt_val=class="num">1.08742; ENUM_EXTREMUM_TYPE pnt_type=EXTREMUM_TYPE_MAX; class="type">int pnt_idx=class="num">0; class=class="str">"cmt">//--- 创建分形点 CFractalPoint myFracPoint(pnt_date,pnt_val,pnt_type,pnt_idx); myFracPoint.Print(); class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 分形点集合的类 | class=class="str">"cmt">//+------------------------------------------------------------------+ class CFractalSet : class="kw">protected CArrayObj { class=class="str">"cmt">//--- === 数据成员 === --- class="kw">private: ENUM_SET_TYPE m_set_type; class=class="str">"cmt">// 点集的类型 class="type">int m_fractal_num; class=class="str">"cmt">// 固定的点的数目 class="type">int m_fractals_ha; class=class="str">"cmt">// 分形指标的句柄 CisNewBar m_new_bar; class=class="str">"cmt">// 新柱的对象 };