将输出组合到主窗口和辅助窗口
让我们回到在主窗口和子窗口中显示同一指标图形的问题,因为我们在开发示例UseDemoAllSimple.mq5时遇到了该问题。我原本认为,独立窗口不适合在主图表上可视化,而主窗口指标又没有额外窗口。有几种替代方案:
- 为独立窗口实现一个父指标,在其中显示图表,并在主窗口中使用它来显示 图形对象类型的数据。该方案存在缺陷,因为从对象读取数据的方式和从时间序列读取不同,且许多对象会消耗额外的资源。
- 为主窗口开发自定义虚拟面板(类),并在正确缩放的情况下,在其中显示本应在子窗口显示的时间序列数据。
- 使用多个指标(至少一个用于主窗口,一个用于子窗口),并通过共享内存(需调用 DLL)、 资源 或 数据库在指标间交换数据。
- 在主窗口和子窗口的指标中复用计算逻辑(使用公共源代码)。
我们将介绍一种超出单个 MQL 程序限制的解决方案:需要一个具备indicator_separate_window特性的额外指标。实际上我们已经有了,因为已经通过请求句柄创建了其计算部分。我们只需以某种方式将其显示在独立子窗口中即可。
在新版(完整版)的 UseDemoAll.mq5中,我们将分析通过相应的IndicatorType 枚举元素所请求创建的指标的元数据。回想一下,除其他因素外,每种内置指标的工作窗口类型也在其中进行了编码。当某个指标需要独立窗口时,我们将通过特殊的 MQL5 函数创建一个独立窗口,这些函数我们稍后会详细学习。
目前无法获取自定义指标的工作窗口信息。因此,我们添加一个输入变量 IndicatorCustomSubwindow,允许用户声明需要一个子窗口。
input bool IndicatorCustomSubwindow = false; // Custom Indicator Subwindow |
在 OnInit中,我们将隐藏用于子窗口的缓冲区。
int OnInit()
|
完成该设置后,还需要调用一些函数,这些函数不仅适用于指标操作,也适用于图表操作。我们将在相应章节中详细学习这些函数,而 上一节已对它们进行了介绍性概述。
其中,ChartIndicatorAdd函数允许将句柄指定的指标添加到窗口中,不仅可添加到主要部分,还能添加到子窗口。关于图表标识符和窗口编号,我们将在 图表章节中讨论,目前只需知道在下次调用 ChartIndicatorAdd函数时,会将指定 handle 的指标添加到当前图表的新建子窗口中。
inthandle = ...// get indicator handle, iCustom or IndicatorCreate
|
了解这一可能性后,我们可以考虑调用 ChartIndicatorAdd,并向其传递一个已创建的从属指标的句柄。
我们需要的第二个函数是ChartIndicatorName。该函数通过指标句柄返回其简称。该名称对应指标代码中设置的 INDICATOR_SHORTNAME 特性,可能与文件名不同。该名称是必需的,用于清理自身的操作,即在删除或重新配置父指标后,移除辅助指标及其子窗口。
string subTitle = "";
|
在 OnDeinit处理程序中,我们使用保存的 subTitle 调用另一个函数ChartIndicatorDelete(后续会详细讲解)。该函数通过最后一个参数指定的指标名称,从图表中移除对应指标。
void OnDeinit(const int)
|
这里假设图表中仅运行我们这一个指标,且仅存在一个实例。在更通用的场景中,应分析所有子窗口以确保正确删除,但这需要用到 图表章节将介绍的更多函数,因此目前我们暂时采用简化版本。
现在,如果我们运行UseDemoAll并从列表中选择带星号标记的指标(即需要子窗口的指标),例如 RSI 指标,就能看到预期效果:RSI 在独立窗口中。
RSI 在由 UseDemoAll 指标创建的子窗口中