DoEasy 函数库中的时间序列(第五十六部分):自定义指标对象,从集合中的指标对象获取数据(基础篇)
「从指标集合里把数据抠出来」
DoEasy 函数库在第五十六部分把自定义指标封装成了集合对象,重点不是画指标,而是能在 EA 或脚本里直接调用集合里某个指标实例、按缓冲区和位置取数。 原文示例发布于 2021-02-24,统计口径下该文阅读量 1229、评论 2 条,说明这类底层封装对实盘玩家属于冷门但高复用度的东西。 对交易者来说,直接价值是:不用每次在 MT5 里手写 iCustom 再 CopyBuffer,而是用库对象方法统一拿值,方便做多指标共振判定。外汇与贵金属杠杆高,任何信号都只是概率倾向,务必先在策略测试器跑历史再上模拟。
自定义指标对象的构造差异
标准指标在 MT5 终端里的集合是固定的,每个指标的输入参数数量和类型都事先明确,因此可以直接调用各自的创建方法并写死参数组合。自定义指标则不同,参数集合在编译期未知,无法用同样方式实例化。 处理自定义指标时,必须把已经填充好的“指标输入结构数组”传给创建方法,方法内部再从中提取全部必要属性和参数。代价是函数库使用者要手动维护这个结构数组,不能像标准指标那样一行调用搞定。 为了能在 EA 里随时找回已创建的指标,每个对象都会打上一个唯一 ID。已知 ID 与对象的对应关系,就能在程序任意位置按 ID 调出指标。另一种途径是按创建时指定的完整参数集反查对象,拿到引用后读取数据。 本次先落地数据接收方法:从指标缓冲区取数并复制到普通数组,后续文章再拿这些数组做统计研究。外汇与贵金属行情波动剧烈,用这类自定义指标做图形分析仍属高风险操作,结论只代表概率倾向。
◍ 给指标对象挂上可检索的 ID
在 MT5 自建指标库里,标准指标能在构造时定死分组(趋势、震荡、成交量、箭头),但自定义指标在 new 的那一刻你根本不知道它该归哪一类。办法是新增一个 ‘any’ 分组作为默认槽位,对象建完再由调用方手动指定真实分组。 为了让列表能按唯一标识捞指标,我们在 Defines.mqh 的指标整数属性枚举里加了一个 IND_ID,并把整数属性总数从 5 调到 6。构造函数里先把 ID 默认设为 -1,意味着‘还没分配’。 比较两个指标对象是否同参时,必须跳过 handle 和 ID——这两个天生唯一,不跳过的话每个实例都会被误判成‘不同指标’,导致参数比对失效。 抽象类 IndicatorDE 公开区补了 GetID / SetID,以及一组实用方法:显示 MqlParam 参数说明、按索引或时间取 CopyBuffer 数据、取柱线时间。取数失败就返回对象预设的空值,不会抛异常。 DELib 里另写了 MqlParameterDescription(),依据 MqlParam 的 type 字段拼出‘Type xxx: 值’的日志串,自定义指标四个参数说明直接能打印出来辅助排查。所有标准指标类的简称方法也顺手把 ID 塞进括号里,ID 为 -1 时只留空括号。
MSG_LIB_TEXT_IND_TEXT_GROUP, class=class="str">"cmt">// Indicator group MSG_LIB_TEXT_IND_TEXT_GROUP_TREND, class=class="str">"cmt">// Trend indicator MSG_LIB_TEXT_IND_TEXT_GROUP_OSCILLATOR, class=class="str">"cmt">// Oscillator MSG_LIB_TEXT_IND_TEXT_GROUP_VOLUMES, class=class="str">"cmt">// Volumes MSG_LIB_TEXT_IND_TEXT_GROUP_ARROWS, class=class="str">"cmt">// Arrow indicator MSG_LIB_TEXT_IND_TEXT_ID, class=class="str">"cmt">// Indicator ID MSG_LIB_TEXT_IND_TEXT_EMPTY_VALUE, class=class="str">"cmt">// Empty value for plotting where nothing will be drawn MSG_LIB_TEXT_IND_TEXT_SYMBOL, class=class="str">"cmt">// Indicator symbol MSG_LIB_TEXT_IND_TEXT_NAME, class=class="str">"cmt">// Indicator name MSG_LIB_TEXT_IND_TEXT_SHORTNAME, class=class="str">"cmt">// Indicator class="type">class="kw">short name MSG_LIB_TEXT_IND_TEXT_IND_PARAMETERS, class=class="str">"cmt">// Indicator parameters MSG_LIB_TEXT_IND_TEXT_APPLIED_VOLUME, class=class="str">"cmt">// Volume type for calculation MSG_LIB_TEXT_IND_TEXT_PERIOD, class=class="str">"cmt">// Averaging period MSG_LIB_TEXT_IND_TEXT_FAST_PERIOD, class=class="str">"cmt">// Fast MA period MSG_LIB_TEXT_IND_TEXT_SLOW_PERIOD, class=class="str">"cmt">// Slow MA period MSG_LIB_TEXT_IND_TEXT_SIGNAL, class=class="str">"cmt">// Difference averaging period MSG_LIB_TEXT_IND_TEXT_TENKAN_PERIOD, class=class="str">"cmt">// Tenkan-sen period MSG_LIB_TEXT_IND_TEXT_KIJUN_PERIOD, class=class="str">"cmt">// Kijun-sen period MSG_LIB_TEXT_IND_TEXT_SPANB_PERIOD, class=class="str">"cmt">// Senkou Span B period
「指标参数与容器报错的中文映射」
在 MT5 自编指标库里,参数说明文本通常用枚举常量统一管理。下面这段枚举覆盖了从鳄鱼线(Jaw/Teeth/Lips)周期与位移,到布林类通道的标准差、偏离,再到随机指标 K/D/Slowing 与 CMO 周期等常见输入项,每个常量后跟的注释就是界面上实际显示的中文释义。 MSG_LIB_TEXT_IND_TEXT_JAW_PERIOD 对应颌线计算周期,MSG_LIB_TEXT_IND_TEXT_TEETH_PERIOD 对应齿线周期,MSG_LIB_TEXT_IND_TEXT_LIPS_PERIOD 对应唇线周期;三组水平位移(SHIFT)分别控制各线在图表上的滞后偏移量。 MSG_LIB_TEXT_IND_TEXT_STD_DEVIATION 是通道标准差倍数,MSG_LIB_TEXT_IND_TEXT_DEVIATION 是通道边界相对中线的偏离,这两个值直接决定通道宽度。MSG_LIB_TEXT_IND_TEXT_STEP 与 MAXIMUM 是加速因子步长与上限,常用于抛物线类指标。 高亮的三行属于自定义与容器层:MSG_LIB_TEXT_IND_TEXT_CUSTOM_PARAM 是通用输入参数占位;CIndicatorsCollection 相关的 MSG_LIB_SYS_INVALID_IND_POINTER(指针无效)与 MSG_LIB_SYS_IND_ID_EXIST(ID 重复)是往指标列表塞对象时最常见的两条运行时报错。 另有一段结构化文本常量,把 Arrow indicator、Indicator ID、Empty value for plotting 等字段名直接写成字符串数组,供 UI 或日志调用。开 MT5 在 MetaEditor 搜这些 MSG_LIB_TEXT 前缀,就能看到你当前标准库里的实际措辞。
MSG_LIB_TEXT_IND_TEXT_JAW_PERIOD, class=class="str">"cmt">// Period for jaw line calculation MSG_LIB_TEXT_IND_TEXT_TEETH_PERIOD, class=class="str">"cmt">// Period for teeth line calculation MSG_LIB_TEXT_IND_TEXT_LIPS_PERIOD, class=class="str">"cmt">// Period for lips line calculation MSG_LIB_TEXT_IND_TEXT_JAW_SHIFT, class=class="str">"cmt">// Horizontal shift of jaws line MSG_LIB_TEXT_IND_TEXT_TEETH_SHIFT, class=class="str">"cmt">// Horizontal shift of teeth line MSG_LIB_TEXT_IND_TEXT_LIPS_SHIFT, class=class="str">"cmt">// Horizontal shift of lips line MSG_LIB_TEXT_IND_TEXT_SHIFT, class=class="str">"cmt">// Horizontal shift of the indicator MSG_LIB_TEXT_IND_TEXT_MA_METHOD, class=class="str">"cmt">// Smoothing type MSG_LIB_TEXT_IND_TEXT_APPLIED_PRICE, class=class="str">"cmt">// Price type or handle MSG_LIB_TEXT_IND_TEXT_STD_DEVIATION, class=class="str">"cmt">// Number of standard deviations MSG_LIB_TEXT_IND_TEXT_DEVIATION, class=class="str">"cmt">// Deviation of channel borders from the central line MSG_LIB_TEXT_IND_TEXT_STEP, class=class="str">"cmt">// Price change step — acceleration factor MSG_LIB_TEXT_IND_TEXT_MAXIMUM, class=class="str">"cmt">// Maximum step MSG_LIB_TEXT_IND_TEXT_KPERIOD, class=class="str">"cmt">// K-period(number of bars for calculation) MSG_LIB_TEXT_IND_TEXT_DPERIOD, class=class="str">"cmt">// D-period(primary smoothing period) MSG_LIB_TEXT_IND_TEXT_SLOWING, class=class="str">"cmt">// Final smoothing MSG_LIB_TEXT_IND_TEXT_PRICE_FIELD, class=class="str">"cmt">// Stochastic calculation method MSG_LIB_TEXT_IND_TEXT_CMO_PERIOD, class=class="str">"cmt">// Chande Momentum period MSG_LIB_TEXT_IND_TEXT_SMOOTHING_PERIOD, class=class="str">"cmt">// Smoothing factor period MSG_LIB_TEXT_IND_TEXT_CUSTOM_PARAM, class=class="str">"cmt">// Input parameter class=class="str">"cmt">//--- CIndicatorsCollection MSG_LIB_SYS_FAILED_ADD_IND_TO_LIST, class=class="str">"cmt">// Error. Failed to add indicator object to the list MSG_LIB_SYS_INVALID_IND_POINTER, class=class="str">"cmt">// Error. Invalid pointer to indicator object is passed MSG_LIB_SYS_IND_ID_EXIST, class=class="str">"cmt">// Error. Indicator object with ID already exists }; class=class="str">"cmt">//+------------------------------------------------------------------+ {"Arrow indicator"}, {"Indicator ID"}, {"Empty value for plotting, for which there is no drawing"}, {"Indicator symbol"}, {"Indicator name"}, {"Indicator shortname"},
聚合指标的参数与分组枚举
在把多个指标塞进同一个管理容器时,先用一组字符串常量描述每个输入项。从成交量类型、均线快/慢周期,到 Ichimoku 的 Tenkan-sen(转换线)、Kijun-sen(基准线)、Senkou Span B 周期,再到鳄鱼线的颚/齿/唇三段周期与水平位移,覆盖了 28 个以上的配置字段。 这些常量后面紧跟三条错误描述串:添加指标对象到列表失败、传入的指标对象指针无效、以及相同 ID 的指标对象已存在。你在 MT5 里跑多指标调度框架时,若日志出现这三类中文报错,基本可锁定是容器注册环节出了岔子。 指标归类用 ENUM_INDICATOR_GROUP 枚举完成,包含趋势、震荡、成交量、箭头四类,外加一个 INDICATOR_GROUP_ANY 兜底项。外汇与贵金属波动剧烈、杠杆风险高,回测多指标组合时建议先用 ANY 组做宽口过滤,再按具体类别细分。
enum ENUM_INDICATOR_GROUP { INDICATOR_GROUP_TREND, class=class="str">"cmt">// Trend indicator INDICATOR_GROUP_OSCILLATOR, class=class="str">"cmt">// Oscillator INDICATOR_GROUP_VOLUMES, class=class="str">"cmt">// Volumes INDICATOR_GROUP_ARROWS, class=class="str">"cmt">// Arrow indicator INDICATOR_GROUP_ANY, class=class="str">"cmt">// Any indicator };
◍ 指标整数属性的枚举与排序起点
MT5 自定义指标在内部以整数属性描述自身状态,核心枚举 ENUM_INDICATOR_PROP_INTEGER 列出了 6 个字段:状态、类型、周期、句柄、分组与 ID。其中 INDICATOR_PROP_ID 常被忽略,但它是指标在终端内部的唯一身份标记,调试多指标协同时有用。 宏 INDICATOR_PROP_INTEGER_TOTAL 被定为 6,SKIP 为 0,说明这 6 项全部参与排序逻辑;FIRST_INDICATOR_DBL_PROP 与 FIRST_INDICATOR_STR_PROP 则按 (总数-跳过数) 递推,给双精度与字符串属性预留偏移位。 排序枚举 ENUM_SORT_INDICATOR_MODE 从 SORT_BY_INDICATOR_INDEX_STATUS 起,到 SORT_BY_INDICATOR_ID 止,均映射上述整数属性。若你在 EA 里批量管理十几个指标,按 ID 或句柄排序比按名称稳,能规避重名覆盖。 开 MT5 新建脚本,把下面枚举贴进去编译,改 INDICATOR_PROP_INTEGER_TOTAL 的值观察 FIRST_INDICATOR_DBL_PROP 宏展开变化,就能确认偏移计算是否符合你的面板设计。
enum ENUM_INDICATOR_PROP_INTEGER { INDICATOR_PROP_STATUS = class="num">0, class=class="str">"cmt">// Indicator status(from enumeration ENUM_INDICATOR_STATUS) INDICATOR_PROP_TYPE, class=class="str">"cmt">// Indicator type(from enumeration ENUM_INDICATOR) INDICATOR_PROP_TIMEFRAME, class=class="str">"cmt">// Indicator timeframe INDICATOR_PROP_HANDLE, class=class="str">"cmt">// Indicator handle INDICATOR_PROP_GROUP, class=class="str">"cmt">// Indicator group INDICATOR_PROP_ID, class=class="str">"cmt">// Indicator ID }; class="macro">#define INDICATOR_PROP_INTEGER_TOTAL(class="num">6) class=class="str">"cmt">// Total number of indicator integer properties class="macro">#define INDICATOR_PROP_INTEGER_SKIP(class="num">0) class=class="str">"cmt">// Number of indicator properties not used in sorting class="macro">#define FIRST_INDICATOR_DBL_PROP(INDICATOR_PROP_INTEGER_TOTAL-INDICATOR_PROP_INTEGER_SKIP) class="macro">#define FIRST_INDICATOR_STR_PROP(INDICATOR_PROP_INTEGER_TOTAL-INDICATOR_PROP_INTEGER_SKIP+INDICATOR_PROP_DOUBLE_TOTAL-INDICATOR_PROP_DOUBLE_SKIP) enum ENUM_SORT_INDICATOR_MODE { class=class="str">"cmt">//--- Sort by integer properties SORT_BY_INDICATOR_INDEX_STATUS = class="num">0, class=class="str">"cmt">// Sort by indicator status SORT_BY_INDICATOR_TYPE, class=class="str">"cmt">// Sort by indicator type SORT_BY_INDICATOR_TIMEFRAME, class=class="str">"cmt">// Sort by indicator timeframe SORT_BY_INDICATOR_HANDLE, class=class="str">"cmt">// Sort by indicator handle SORT_BY_INDICATOR_GROUP, class=class="str">"cmt">// Sort by indicator group SORT_BY_INDICATOR_ID, class=class="str">"cmt">// Sort by indicator ID class=class="str">"cmt">//--- Sort by real properties