指标所有者的句柄和计数器
在程序中操作指标需要使用句柄进行控制。这与文件描述符的运行机制类似(请参阅 打开和关闭文件章节):通过 File Open函数告知系统文件名和打开模式,之后该描述符将作为访问其他所有文件函数的“通行证”。
指标描述符系统有以下几项用途。
它允许提前向终端告知需要启动的指标和需要计算的时间序列。由于下载初始历史数据及计算指标需要一定时间(至少在第一次请求时需要),同时还需分配资源(内存、图形界面),因此指标创建时间点和就绪时间点并不相同。描述符是这两者之间的桥梁。它是一种指向终端内部对象的链接,该对象存储我们创建指标时设置的特性集合及其当前状态。
当然,为了处理描述符,终端需要维护一个记录所有请求指标及其特性的特定表格。但终端并不提供总表中的实际编号信息:相反,每个程序都会形成自己请求的指标私有列表。该列表中的条目指向总表中的元素,而描述符只是列表中的一个编号。
因此,不同程序中相同的描述符可能对应完全不同的指标。因此,在程序之间传递描述符的值毫无意义。
描述符是终端资源管理系统的一部分,因为它们会尽量避免重复创建具有相同特征的指标实例。换言之,所有内置指标和通过编程方式、手动方式或从 tpl 模板创建的自定义指标都会进行缓存。
在创建新的指标实例之前,终端会检查缓存中是否存在完全相同的指标。检查副本时会应用以下标准:
- 匹配交易品种和周期
- 匹配参数
对于自定义指标,还必须额外匹配以下内容:
- 磁盘路径(作为字符串,但不会规范化为绝对路径形式)
- 指标运行所在的图表(当从 MQL 程序创建指标时,被创建的指标会继承创建它的程序所在的图表)
内置指标会按交易品种进行缓存,因此它们的实例可供分配以在不同图表(相同交易品种/时间范围)上单独使用。
请注意, 无法在同一图表上手动创建两个完全相同的指标。不同的程序实例可以请求同一个指标,此时只会创建该指标的一个副本,并提供给所有发出请求的程序。
对于每个独特的条件组合,终端会维护一个计数器:第一次请求创建某个特定指标后,其计数器值为 1;后续每请求一次,计数器值加 1(不会创建新的指标副本)。当某个指标被释放时,其计数器值减 1。只有当计数器重置时,即所有所有者明确不再使用指标时,指标才会进行卸载。
要注意的是,在同一个 MQL 程序中多次调用相同参数(包括交易品种/时间范围)的指标构建函数,不会导致引用计数器多次递增,计数器只会递增一次。因此,对于每个句柄值,调用一次释放函数 (IndicatorRelease) 即可。所有后续调用都是多余的,且会返回错误,因为已没有可释放的指标。
除在 MQL5 中通过 iCustom 和 IndicatorCreate 创建指标外,还可以获取第三方(已存在)指标的句柄。这可以通过 ChartIndicatorGet函数实现,我们将在 图表一章中学习该函数。需要注意的是,通过这种方式获取句柄也会增加其引用计数,并阻止指标卸载,除非后续释放该句柄。
如果程序创建了从属指标,则当该程序进行卸载时,这些指标的句柄将自动释放(计数器减 1),即使没有调用 IndicatorRelease函数。