Repaint Inspector
- 实用工具
-
Quoc Dat Quach
Software engineer with 8 years in fintech and mobile, writing MQL4/MQL5 since 2017. I build Expert Advisors, indicators, trade and risk-management panels and utilities for MT4/MT5, and I trade forex and gold on MT5 myself. - 版本: 1.0
Repaint Inspector 通过实际测量来判断一个指标是否重绘,而不是轻信其声明。将它加载到图表上,指定任意自定义指标及其参数列表,它就会在已经收盘的K线上反复读取该指标的缓冲区,统计每一个发生变动的值、每一个新出现的值和每一个消失的值,并记录这些情况在历史中最远仍会发生在多久以前。
这是一个测量工具。在图表上它从不发送任何订单。在策略测试器中,它会在开始时开立并平掉一笔最小交易量的持仓,因为 MQL5 市场的自动测试会检查智能交易系统是否执行了交易操作;这笔交易会在日志中注明,不属于测量的一部分,并且可以通过一个输入参数关闭。它不使用 DLL,不访问网络,除了 MQL5\Files 中它自己的两个 CSV 文件之外,不向磁盘写入任何内容。
为什么需要它:“不重绘”是指标描述中常见的说法,却很难验证。通常的检验方法是看一眼图表,大致记住箭头的位置,重新加载后再看一次。这种检验会漏掉两种让人亏钱的情况。第一种是在图表一直打开的情况下,一根早已收盘的K线上的值发生了变化:箭头移动了几个像素,或者在你的注意力集中在图表右端时被删除。第二种是指标在运行期间表现正常,重新加载后却给出不同的历史,而用户切换时间周期、重启终端或打开新图表时,发生的恰恰就是这种重新加载。这两种情况都可以测量。
测量的定义如下,这部分决定了结果是否有意义:
- K线以其开盘时间来识别,从不以偏移来识别,因此新K线的出现、图表滚动和历史数据补齐都不会被误认为是变化。
- 只比较已收盘的K线,即偏移 1 及以上。仍在形成中的K线按定义就会变化,不能说明任何重绘问题。
- 一根已收盘K线上首次读到的值作为参考值。之后的每次读数都与上一次读数比较,以此计数事件;每当计到一个事件时,再与首次读数比较,以此测量漂移。
- 三类事件分别计数,因为它们的严重程度不同。Changed:一个值变成了另一个值。Appeared:一个空位获得了值,即信号出现在一根已经收盘的K线上。Vanished:一个已发布的值被擦除,这是严重的一类,因为交易者据以操作的信号已不在下一个读取者看到的历史中。
- 核心数值是 MaxShift,即观察到任何事件时的最大偏移。只重画最后一根已收盘K线的指标,与会改写十五根K线的指标,完全不是一回事。
- 每个事件都会写入一个 CSV 文件,内容包括检测时间、K线时间、检测时的偏移、缓冲区、事件类型、旧值和新值、差值、相对首次读数的漂移,以及一个重新加载后标志,因此报告可以重新核算,而不必轻信。第二个文件中每个缓冲区一行,包含所有计数器,运行期间每 15 秒刷新一次。
- 被测指标通过 IndicatorCreate 按解析后的参数列表创建,因此无需编辑或重新编译任何内容即可检查任意自定义指标。解析后的列表会在启动时输出到日志,这样错误的参数列表就会显露出来,而不是悄无声息。
- 可以每 N 分钟释放并重新创建一次句柄,同时有意保留已记录的历史,用来捕捉那种运行期间表现平静、重新加载后却给出不同过去的指标。只有当没有其他程序持有参数相同的同一指标时,终端才会在重新加载时重新计算,因此在这项测试运行期间,请从你的图表上移除该指标。
- 在以下情况下,一次检查会被丢弃并计为跳过,而不作为证据:句柄尚不存在、指标尚未计算完成、已收盘K线数量少于所监测的深度(在第一次可用的检查中,深度本身会被截短为可用的历史长度,并在日志中注明)、某个缓冲区无法复制,或者在读取时间与读取数值之间序列发生了移动。
以下测量使用终端自带的指标,任何人都可以重复。同一终端的四个图表上运行四个副本,XAUUSD M1,1 小时 26 分钟,监测 300 根已收盘K线,每秒检查一次:
- Examples\ZigZag (12,5,3):每个缓冲区 1,315,713 次比较,0 个变动,0 个出现,绘图缓冲区上 17 个消失,MaxShift 为 15,两个计算缓冲区上分别有 3 个和 10 个消失。没有任何值发生移动,因为 ZigZag 的极值就是其所在K线的最高价或最低价,不会漂移;它是被删除,然后在别处重新发布。
- Examples\Custom Moving Average (13,0,2):1,305,513 次比较,没有一个事件。
- Examples\Fractals:25 个事件,全部为 Appeared,没有 Changed,没有 Vanished,全部位于偏移 3。这不是重绘,而是延迟确认,因为分形需要再多两根K线才能画出;以上基于 1,303,713 次比较。结论行仍显示 REPAINTS,因为工具只报告它观察到的情况,把判断留给你:如果事件全部是 Appeared 且位于同一个固定偏移,说明这是一个可用的、延迟已知的指标;如果事件是 Vanished 且分散在不同偏移上,则不是。
- 第四个副本运行同一个 ZigZag,但把 0.0 当作普通值而不是无值:1,308,513 次比较,32 个事件,全部为 Changed,MaxShift 同样为 15,最大绝对差值为 4184.088,也就是黄金价格本身,因为此时每一次删除都表现为一个峰值被 0.0 取代。同样的重绘,只是换了个名字。
上述 ZigZag、移动平均线和 Fractals 三次运行分别进行了 4,387、4,353 和 4,347 次检查。同一工具在策略测试器中可以把一天压缩到几秒钟:同一个 ZigZag 运行一个交易日(XAUUSD M1,1 分钟 OHLC 建模),得到 5,512 次检查、1,651,923 次比较,在当时已收盘的K线上有 342 个值消失、3 个值出现,涉及 343 根不同的K线,MaxShift 为 28。
计数器的独立核验。用 Python 独立重新实现了 Examples\ZigZag,在从终端获取的原始K线上运行,并与事件文件进行对比。实时运行:绘图缓冲区丢失值的 17 根K线中,每一根上的该值在回放中都不存在,并且对全部 17 根K线,工具的最后一次读数都等于回放值。测试器运行:343 根K线有事件,其中 341 根是丢失值的K线;同样的两项核对,没有任何不一致。比较次数也能对上:实时运行期间新开了 87 根 M1 K线,(检查次数减 1) 乘以 300 再减 87,正好重现报告中的每一个比较次数。
输入参数:要检查的指标的 iCustom 路径及其参数(以逗号分隔的列表)、要监测的缓冲区数量(1 到 32)、交易品种和时间周期(如需检查非本图表的品种和周期)、监测的已收盘K线数量(默认 300)、两次检查之间的最小秒数(默认 1,在测试器中为模拟时间)、绝对容差(低于该值的变化将被忽略)、将 0.0 视为无值的开关(适用于箭头和 ZigZag 类缓冲区,默认开启)、句柄重建间隔、可选的 N 分钟后停止、CSV 开关、文件名和行数上限、面板设置(显示或隐藏、角落、位置偏移、字体大小和五种颜色),以及上文所述的策略测试器示例交易开关。每个输入参数在终端中都有各自的注释说明。路径默认有意留空:未填写时,工具会在日志和面板上说明这一点并且不做任何测量,而不是指向一个你的终端上可能并不存在的指标。
局限性,如实说明。本工具无法证明不存在重绘;它只能说明在所测量的时段内没有发现重绘,这也是为什么每个结论旁边都附有比较次数。它按检查间隔采样,因此一个在单个间隔内出现又消失的值可能会被漏掉:在上述一个半小时中就发生过一次,两个启动时间相差 14 秒的 ZigZag 副本对一根K线(03:32,涉及两个缓冲区)的结果不一致,该K线上的值存在的时间不到一个检查间隔,所以一个副本采样到了它,另一个没有。它测量的是指标通过缓冲区发布的内容,因此对于绘制图表对象而不是填充缓冲区的指标,它是看不到的。在策略测试器中,被测指标必须在运行开始前就已存在并已编译:测试器会把 IndicatorCreate 失败视为严重错误并卸载该智能交易系统,工具内部的任何错误处理都无法改变这一点。在实时图表上,同样的错误路径并不致命,工具会保持加载状态并每 30 秒重试一次,因此无需移除它即可更正输入参数。
策略测试器中的示例交易使用该交易品种的最小交易量,发送时不设止损和止盈,并且在发送前会将所需保证金与可用保证金进行核对,因此测试存款较小时只会在日志中留下一行记录,而不会产生被拒绝的订单。它带有自己的幻数,会在之后的某个 tick 上再次平仓,测量的任何计数器、结论或 CSV 行都不受它影响。在 1000 USD 的测试存款上实测:一笔交易,两笔成交,0.06 USD 成本;在相同区间内以 Examples\ZigZag 为被测指标时,每一个重绘计数器都与完全不含交易代码的版本一致,直至 3,404,353 次比较、10 个消失值和 MaxShift 17 都完全相同。
实际限制。K线数乘以缓冲区数不得超过 200,000 个槽位,这是一项内存保护措施;超过时深度会被缩减,并在日志中写入一行。它是一个智能交易系统,因此会占用图表唯一的 EA 位置:每个图表只能运行一个副本,不能放在运行你自己 EA 的图表上,但可以在多个图表上同时运行副本。只请求指标实际拥有的缓冲区,因为不存在的缓冲区会在每次检查中失败,并且在写入五行日志后,这些失败只会计为跳过。使用你自己指定的 CSV 文件名时,该文件在每次启动时都会被覆盖;自动生成的文件名带有启动时间(精确到分钟)。在策略测试器中,文件写入测试代理自己的 MQL5\Files 文件夹,而不是终端的文件夹;而且在测试器中看到的重绘与在实时行情中看到的重绘并不一定是同一回事——当答案很重要时,请在实时行情中运行。最后,本工具并不评价一个指标是否值得用于交易:不重绘的指标仍可能毫无用处,而有些重绘指标是被有意且正确地使用的。
