将数组分配为缓冲区:SetIndexBuffer
在程序从启动到终止的整个运行周期内,任何 double类型 动态数组 均可充当指标缓冲区。定义这类数组的最常见方式是在全局层面声明。但在某些情况下,将数组设置为类成员,然后创建包含这些数组的全局对象会更加便捷。我们将在实现多货币对指标(请参阅 多货币和多时间范围指标章节的 IndUnityPercent.mq5示例)和增量成交量指标(请参阅 等待数据和管理可见性章节的 IndDeltaVolume.mq5示例)时探讨这种实现方式的示例。
因此,让我们在全局层面声明一个动态数组 buffer(无需指定大小)。
double buffer[]; |
可以通过终端中的特殊函数SetIndexBuffer将其注册为缓冲区。通常,该函数会与其他许多用于配置指标的函数一样,在 OnInit 处理程序中调用,我们将在后续章节中详细讨论。
bool SetIndexBuffer(int index, double buffer[],
ENUM_INDEXBUFFER_TYPE mode = INDICATOR_DATA)
该函数在 index指定的指标缓冲区与buffer 动态数组之间建立关联。index值必须介于 0 和 N-1 之间,其中 N 是由 #property indicator_buffers指令指定的缓冲区数量。
绑定操作完成后,数组尚未准备好处理数据,甚至不会改变其大小,因此初始化和所有计算都应在OnCalculate函数中执行。将动态数组分配为指标缓冲区后,不可再更改其大小。对于指标缓冲区,所有大小调整操作均由终端本身自动完成。
将数组与指标缓冲区关联后,索引方向默认与普通数组一致。必要时,可使用 ArraySetAsSeries 函数进行更改。
SetIndexBuffer函数成功时返回 true,失败时返回 false。
可选mode参数用于告知系统该缓冲区的使用方式。可能的值在 ENUM_INDEXBUFFER_TYPE 枚举中提供。
标识符 |
说明 |
---|---|
INDICATOR_DATA |
要渲染的数据 |
INDICATOR_COLOR_INDEX |
渲染颜色 |
INDICATOR_CALCULATIONS |
中间计算的内部结果 |
默认情况下,指标缓冲区用于绘制数据 (INDICATOR_DATA)。该值除了在图表上显示数组外,还有另一作用:鼠标光标所在柱线对应的每个缓冲区值会显示在Data window中。不过,这种行为可以通过某些指标设置更改(请参阅 图形绘图设置 章节的 PLOT_SHOW_DATA 特性)。本章的大多数示例都采用 INDICATOR_DATA 模式。
如果指标计算需要存储每根柱线的中间结果,可以为它们分配一个辅助性的非显示缓冲区 (INDICATOR_CALCULATIONS)。相较于使用普通数组实现目的,这种方式更加便捷,因为使用普通数组时,程序员必须自行管理数组大小。本章将展示使用 INDICATOR_CALCULATIONS 的两个示例:IndTripleEMA.mq5(请参阅 跳过初始柱线的绘制)和 IndSubChartSimple.mq5(请参阅 多货币和多时间范围指标)。
某些结构允许为每根柱线设置显示颜色。颜色缓冲区 (INDICATOR_COLOR_INDEX) 用于存储颜色信息。颜色由整数类型 color表示,但所有指标缓冲区必须为 double 类型,在这种情况下,缓冲区将存储由开发者设置的特殊调色板中的颜色编号(请参阅 图表逐元素着色 章节以及其示例指标 IndColorWPR.mq5)。
颜色和辅助缓冲区的值不会显示在 Data window中,并且无法使用 CopyBuffer 函数获取这些值(我们将在 MQL5 内置指标与自定义指标使用 章节中详细探讨该函数)。
指标缓冲区在初始化时不会填充任何数值。如果由于某种原因未计算其某些元素(例如,指标设置中存在最大柱线数量限制,或者图形构建本身要求在重要元素之间保留间隔,如锯齿线顶点之间),则应显式将这些位置填充为特殊的“空值”。空值不会显示在图表上,也不会显示在Data Window中。默认情况下,它存在 EMPTY_VALUE (DBL_MAX) 常量,但如有必要,也可替换为其他值,例如 0。这可以通过 PlotIndexSetDouble 函数实现。
基于对 SetIndexBuffer函数的新认识,让我们完善上一节开始的示例IndReplica1.mq5。具体来说,我们需要 OnInit处理程序。
#property indicator_chart_window
|
由于通过指令定义的缓冲区数量为 1,因此为单个缓冲区分配数组时应使用索引 0(即SetIndexBuffer的第一个参数)。第二个函数调用是错误示例,仅用于演示问题:由于索引 1 对应两个已声明的缓冲区,这将产生 BUFFERS_WRONG_INDEX (4602) 错误。
在OnCalculate函数的最开始,让我们再次打印输出数组的大小。此时,数组已根据柱线数量分配完毕。
int OnCalculate(const int rates_total,
|
现在,让我们讨论指标的计算逻辑。如前所述,我们暂不加入复杂公式,仅尝试将data参数传入的时间序列复制到缓冲区。这也反映在指标的命名中。
...
|
现在,该指标可以正常编译,无警告。我们可以在图表上运行该指标,在默认设置下,它应在缓冲区中复制柱线收盘价的值。这基于 OnCalculate的简化形式,我们在 主要指标事件:OnCalculate中探讨过这一方面。
但存在一个特殊现象:Data window中的缓冲区数值显示正确,但图表上却未出现对应线条。这是因为负责显示的是图形结构,而非缓冲区。在当前版本的指标中,我们仅配置了缓冲区。在下一章节中,我们将创建新版本的 IndReplica2.mq5并补充必要的指令。
同时,上述效果可用于创建“隐藏指标”,这类指标不在图表上显示线条,但可被其他 MQL 程序通过编程方式读取。如果需要,开发者甚至可以在 Data windows中隐藏指标缓冲区的显示(请参阅下一节的 PLOT_SHOW_DATA)。
关于如何通过 MQL5 代码管理指标,我们将在 下一章中讨论