复合多周期多品种指标对象:从库架构理清标准指标封装基础(基础篇)
(1/3)·多数指标封装教程卡在单对象边界,本文先铺好多曲线缓冲区的底层属性
「DoEasy 库里的复合多周期指标怎么搭」
DoEasy 函数库做到第五十一部分,核心是把标准指标从单品种单周期,扩成可同时挂多周期、多品种的组合时间序列。原文示例发布于 2021 年 1 月 18 日,在 MetaTrader 5 环境运行,页面显示浏览量 1676、评论 0,说明这类底层库改造偏冷门但有人盯。 对做价格行为的人,意义在于:你不必再手动开五个窗口比对均线斜率,库直接把跨周期数据并到同一序列里供 EA 调用。外汇和贵金属杠杆高,跨周期信号共振也只是概率倾向,别当确定性用。 这一节只列了概述、库类方法改进、测试、下一步四块骨架,具体类结构留到后面节展开。想验证就开 MT5 把 DoEasy 拖进编辑器,看 TimeSeries 相关头文件是否多出多品种容器。
复合指标缓冲区怎么挂到一条主线上
做多品种、多周期标准指标对象时,最麻烦的不是画线,而是给一条指标主线挂若干“看不见的辅助缓冲区”。以 Ichimoku 为例,除了数据窗口里那几个关键缓冲区,还要额外开两个缓冲区,专门在 Senkou Span A 和 Senkou Span B 两条线之间画双色直方图,且每个直方图的样式和颜色必须复制对应曲线的设置。 这类写法很适合拿函数库改造成你自己的复合自定义指标。后面还会补上 Gator 振荡器——它基于 Alligator,属于威廉指标家族,是标准指标多周期对象的收尾一个。 关键点在于:无论指标多复杂,所有缓冲区都从属于同一个指标对象。所以必须给缓冲区对象加一个“附加指标曲线编号”的属性,用来定位它是为哪条辅助曲线服务的。比如你想让均线在价格交叉、或与其他指标交叉的瞬间做标记,就加一个或多个缓冲对象,在对应时刻往图表上丢箭头或画区域,逻辑就通了。
◍ 给 DoEasy 库补上 Ichimoku 与 Gator 的缓冲区标识
在 DoEasy 函数库的 Data.mqh 与 Defines.mqh 里,先补一批新消息索引和文本,再给指标曲线类型枚举加入 Ichimoku Kinko Hyo 的各条线及辅助曲线。原先同类型曲线共用枚举值,导致显示缓冲区描述时总回落到第一个零值常量(如 INDICATOR_LINE_MODE_MAIN),虽不算 bug 却容易看串。解决办法不是重排处理程序,而是另开一个 0–15 唯一值的 ENUM_INDICATOR_LINE,让每条具体曲线都能被精确定位。 缓冲区对象整数属性从 24 扩到 25,新增 BUFFER_PROP_IND_LINE_MODE 专门存附加曲线编号;排序准则枚举也同步加上该属性,方便按新字段检索。抽象类 Buffer.mqh 的公开段里,IndicatorLineMode() 改为返回整数,并新增返回曲线描述的方法——内部用位移量(例如鳄鱼牙齿线位移 5)加上缓冲区返回的线值(如 1)得到枚举索引 6,对应 INDICATOR_LINE_TEETH,吐出 “LINE_TEETH” 字样。 构造函数里新属性默认 -1 表示无附加曲线;所有衍生类(BufferArrow、BufferLine 等九个文件)都要改写虚拟方法支持此标志。BuffersCollection.mqh 中给标准指标准备数据的方法补了四个指针,因为 Ichimoku 有五个绘制缓冲而原方法只接三个;云图两条线间的阴影,线型与颜色直接复用对应曲线设置。 Gator 振荡器创建时有个坑:它的第二个缓冲区索引是 2 而非常规双缓冲的 1,因为索引 1 挂着颜色缓冲;库里不用原色缓冲,柱线颜色全自动算,用户也可逐根传色覆盖。云图句柄创建时位移输入原样传递,Senkou Span A/B 及辅助直方缓冲的位移要乘当前图表显示柱数,计算缓冲则不乘。辅助直方缓冲设成不在数据窗口显示,仅服务于外观绘制。 下面这段是库内缓冲区相关消息索引的声明片段,注意每个常量后跟的注释就是将来界面或日志里出现的文字: 别把枚举零值当唯一锚点 早期把相同类型曲线都映射到零,显示时必然撞车。独立开 0–15 的区间枚举,再用位移加法定位,比动处理程序代价小得多,MT5 里改完编译即可验证描述是否准确。
class=class="str">"cmt">//--- CBuffer MSG_LIB_TEXT_BUFFER_TEXT_INDEX_BASE, class=class="str">"cmt">// Base data buffer index MSG_LIB_TEXT_BUFFER_TEXT_INDEX_PLOT, class=class="str">"cmt">// Plotted buffer serial number MSG_LIB_TEXT_BUFFER_TEXT_INDEX_COLOR, class=class="str">"cmt">// Color buffer index MSG_LIB_TEXT_BUFFER_TEXT_NUM_DATAS, class=class="str">"cmt">// Number of data buffers MSG_LIB_TEXT_BUFFER_TEXT_INDEX_NEXT_BASE, class=class="str">"cmt">// Index of the array to be assigned as the next indicator buffer MSG_LIB_TEXT_BUFFER_TEXT_INDEX_NEXT_PLOT, class=class="str">"cmt">// Index of the next drawn buffer MSG_LIB_TEXT_BUFFER_TEXT_ID, class=class="str">"cmt">// Indicator buffers ID MSG_LIB_TEXT_BUFFER_TEXT_IND_LINE_MODE, class=class="str">"cmt">// Indicator line
「指标线枚举里的隐藏映射规则」
在 MT5 自定义指标库里,一条缓冲并不只存数据,它同时绑定了所属指标句柄、指标类型、额外线编号以及周期。上面这段枚举定义把常用指标的主线/信号线/通道线统一编了号,比如 INDICATOR_LINE_MODE_MAIN=0、SIGNAL=1,布林带的 UPPER=0、LOWER=1、MIDDLE=2。 有意思的是云图(Ichimoku)被单独扩到了 4 条线:TENKAN_SEN=0、KIJUN_SEN=1、SENKOU_SPANA=2、SENKOU_SPANB=3。如果你写 EA 时硬套三线的取值习惯去读云图缓冲,会直接漏掉 Span B 那一层。 实操上,开 MT5 的 MetaEditor 把这段枚举原样塞进你的指标头文件,调用 iCustom 时用对应宏代替裸数字,后续换周期或加额外线,编译期就能拦住大部分下标错乱。外汇与贵金属杠杆高,这类底层映射写错不会提示爆仓,只在回测里悄悄给你假信号。
enum ENUM_INDICATOR_LINE_MODE { INDICATOR_LINE_MODE_MAIN = class="num">0, class=class="str">"cmt">// Main line INDICATOR_LINE_MODE_SIGNAL = class="num">1, class=class="str">"cmt">// Signal line INDICATOR_LINE_MODE_UPPER = class="num">0, class=class="str">"cmt">// Upper line INDICATOR_LINE_MODE_LOWER = class="num">1, class=class="str">"cmt">// Lower line INDICATOR_LINE_MODE_MIDDLE = class="num">2, class=class="str">"cmt">// Middle line INDICATOR_LINE_MODE_JAWS = class="num">0, class=class="str">"cmt">// Jaws line INDICATOR_LINE_MODE_TEETH = class="num">1, class=class="str">"cmt">// Teeth line INDICATOR_LINE_MODE_LIPS = class="num">2, class=class="str">"cmt">// Lips line INDICATOR_LINE_MODE_DI_PLUS = class="num">1, class=class="str">"cmt">// Line +DI INDICATOR_LINE_MODE_DI_MINUS = class="num">2, class=class="str">"cmt">// Line -DI INDICATOR_LINE_MODE_TENKAN_SEN = class="num">0, class=class="str">"cmt">// Line Tenkan-sen INDICATOR_LINE_MODE_KIJUN_SEN = class="num">1, class=class="str">"cmt">// Line Kijun-sen INDICATOR_LINE_MODE_SENKOU_SPANA = class="num">2, class=class="str">"cmt">// Line Senkou Span A INDICATOR_LINE_MODE_SENKOU_SPANB = class="num">3, class=class="str">"cmt">// Line Senkou Span B }
指标线枚举里的暗号 mapping
MT5 内核用 ENUM_INDICATOR_LINE 把各类指标的绘图线统一编了号,写 EA 或脚本时靠这个枚举去指定取哪条线,而不是靠肉眼数缓冲区下标。 上面这段枚举里能看到 Ichimoku 的完整拆解:TENKAN_SEN、KIJUN_SEN、SENKOU_SPANA、SENKOU_SPANB、CHIKOU_SPAN 各占一个枚举值,鳄鱼指标则拆成 JAWS、TEETH、LIPS 三条。 另有一段独立的线模式常量定义:INDICATOR_LINE_MODE_CHIKOU_SPAN = 4 对应迟行线,INDICATOR_LINE_MODE_ADDITIONAL = 5 留给自定义附加线。开 MT5 在 MetaEditor 里搜 ENUM_INDICATOR_LINE,能直接看到这套枚举全文,复制进自己的指标调用逻辑即可省去硬编码数字。 外汇与贵金属杠杆高、波动剧烈,用枚举取线做信号判断仅降低代码耦合,不预示任何方向,实盘前务必在策略测试器跑历史数据验证。
INDICATOR_LINE_MODE_CHIKOU_SPAN = class="num">4, class=class="str">"cmt">// Line Chikou Span INDICATOR_LINE_MODE_ADDITIONAL = class="num">5, class=class="str">"cmt">// Additional line }; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Enumeration of indicator lines | class=class="str">"cmt">//+------------------------------------------------------------------+ enum ENUM_INDICATOR_LINE { INDICATOR_LINE_MAIN, class=class="str">"cmt">// Main line INDICATOR_LINE_SIGNAL, class=class="str">"cmt">// Signal line INDICATOR_LINE_UPPER, class=class="str">"cmt">// Upper line INDICATOR_LINE_LOWER, class=class="str">"cmt">// Lower line INDICATOR_LINE_MIDDLE, class=class="str">"cmt">// Middle line INDICATOR_LINE_JAWS, class=class="str">"cmt">// Jaws line INDICATOR_LINE_TEETH, class=class="str">"cmt">// Teeth line INDICATOR_LINE_LIPS, class=class="str">"cmt">// Lips line INDICATOR_LINE_DI_PLUS, class=class="str">"cmt">// Line +DI INDICATOR_LINE_DI_MINUS, class=class="str">"cmt">// Line -DI INDICATOR_LINE_TENKAN_SEN, class=class="str">"cmt">// Line Tenkan-sen INDICATOR_LINE_KIJUN_SEN, class=class="str">"cmt">// Line Kijun-sen INDICATOR_LINE_SENKOU_SPANA, class=class="str">"cmt">// Line Senkou Span A INDICATOR_LINE_SENKOU_SPANB, class=class="str">"cmt">// Line Senkou Span B INDICATOR_LINE_CHIKOU_SPAN, class=class="str">"cmt">// Line Chikou Span INDICATOR_LINE_ADDITIONAL, class=class="str">"cmt">// Additional line };
◍ 指标缓冲区的整型属性枚举怎么排
自定义指标在 MT5 里靠缓冲区(buffer)承载每一根 K 线的计算值,而缓冲区自身有一组整型属性需要声明。下面这段枚举把可设置的整型项一次性列清,开 MT5 写指标时直接对照用。 BUFFER_PROP_INDEX_PLOT 从 0 开始标记该缓冲区的绘图序号;BUFFER_PROP_STATUS 与 BUFFER_PROP_TYPE 分别绑定绘制状态与缓冲区类型枚举。BUFFER_PROP_TIMEFRAME 决定缓冲区数据周期,跨周期指标靠它取值。 BUFFER_PROP_DRAW_TYPE 控制画线方式(如 DRAW_LINE、DRAW_ARROW),箭头类还需 BUFFER_PROP_ARROW_CODE 与 BUFFER_PROP_ARROW_SHIFT 定代码和纵向偏移。BUFFER_PROP_LINE_STYLE、BUFFER_PROP_LINE_WIDTH 管线型与粗细,BUFFER_PROP_DRAW_BEGIN 可跳过前 N 根不画。 BUFFER_PROP_SHIFT 按 bar 数沿时间轴平移图形;BUFFER_PROP_COLOR_INDEXES 与 BUFFER_PROP_COLOR 管多色与着色;BUFFER_PROP_INDEX_BASE 和 BUFFER_PROP_INDEX_NEXT_BASE 串起基础缓冲与下一段数组的索引关系。外汇与贵金属波动剧烈,缓冲区参数设错可能让图形严重偏移,实盘前务必在策略测试器核对。
enum ENUM_BUFFER_PROP_INTEGER { BUFFER_PROP_INDEX_PLOT = class="num">0, class=class="str">"cmt">// Plotted buffer serial number BUFFER_PROP_STATUS, class=class="str">"cmt">// Buffer status(by drawing style) (from the ENUM_BUFFER_STATUS enumeration) BUFFER_PROP_TYPE, class=class="str">"cmt">// Buffer type(from the ENUM_BUFFER_TYPE enumeration) BUFFER_PROP_TIMEFRAME, class=class="str">"cmt">// Buffer data period(timeframe) BUFFER_PROP_ACTIVE, class=class="str">"cmt">// Buffer usage flag BUFFER_PROP_DRAW_TYPE, class=class="str">"cmt">// Graphical construction type(from the ENUM_DRAW_TYPE enumeration) BUFFER_PROP_ARROW_CODE, class=class="str">"cmt">// Arrow code for DRAW_ARROW style BUFFER_PROP_ARROW_SHIFT, class=class="str">"cmt">// The vertical shift of the arrows for DRAW_ARROW style BUFFER_PROP_LINE_STYLE, class=class="str">"cmt">// Line style BUFFER_PROP_LINE_WIDTH, class=class="str">"cmt">// Line width BUFFER_PROP_DRAW_BEGIN, class=class="str">"cmt">// The number of initial bars that are not drawn and values in DataWindow BUFFER_PROP_SHOW_DATA, class=class="str">"cmt">// Flag of displaying construction values in DataWindow BUFFER_PROP_SHIFT, class=class="str">"cmt">// Indicator graphical construction shift by time axis in bars BUFFER_PROP_COLOR_INDEXES, class=class="str">"cmt">// Number of colors BUFFER_PROP_COLOR, class=class="str">"cmt">// Drawing class="type">class="kw">color BUFFER_PROP_INDEX_BASE, class=class="str">"cmt">// Base data buffer index BUFFER_PROP_INDEX_NEXT_BASE class=class="str">"cmt">// Index of the array to be assigned as the next indicator buffer };