如何根据时间确定 MT4 中 K 线的序号(Time 数组的索引值)

MQL4、MQL5 自定义指标中 OnCalculate() 函数的参数会引用传递关于 K 线价格和时间的数组,通常指标都是直接遍历所有数组元素,并不需要单独提取某一根 K 线。

ArrayBsearch() 函数

如果需要寻找特定价格的 K 线序号,可以使用 ArrayBsearch() 函数,比如有一个数组:

int t[] = {1, 2, 3, 4, 5, 6, 7};

如果调用:

ArrayBsearch(t, 4);

会返回 3。( t[3] = 4)

ArrayBsearch() 函数支持六种类型的数组,包括:double、float、long、int、short、char,所以 OnCalculate() 的参数中,open[]、high[]、low[]、close[]、tick_volume[]、volume[]、spread[] 都可以用这个函数查找需要的元素,但 time[] 就不行了。

而我在编写 MT4、MT5 自定义指标时偏偏需要用到这个功能,简单搜索了一下 MQL4 和 MQL5 的文档,没有找到检索 datetime 类型数组的函数,于是自己写了下面一个算法:

MT4、MT5 Time[] 数组查找算法(一)

int i = (int)(Time[0] - dt) / PeriodSeconds();

这里的 dt 是处理过的时间,对应当前图表周期的整数时刻,用数组中第一个元素的时间减去 dt,再除以当前图表对应的周期秒数,就可以得到索引值。

实际应用时发现计算的索引值并不是每次都是正确的,检查了一下意识到 K 线图中的 K 线在时间上并不是连续的,所以不能通过简单的时间相减来计算两根 K 线的间距,只能自己写一个类似 ArrayBsearch() 的函数了。

MT4、MT5 Time[] 数组查找算法(二)

由于 Time[] 数组是按时间排序的,所以当给定一个时间,可以先跟 Time[] 数组的中间元素对比,给定的时间大于数组中间元素,则向左递归查找,小于则向右递归,相等就是找到了。递归比较浪费资源,可以改成循环查找。

MT4、MT5 Time[] 数组查找源码

int datetimeArrayBsearch(const datetime &time[], datetime dt){

  // 时序数组是从右向左的,是倒序,left 为数组最末端。
  int left = ArraySize(time);
  int right = 0;
  int parent =  int(left / 2);

  // 这里可以使用 while 循环,测试时为了避免算法有误出现死循环所以用的 for 循环。
  for(int i = 0; i < 50; i++){
    if(dt < time[parent]){right = parent;}
    else if(dt > time[parent]){left = parent;}
      else if(dt == time[parent]){break;}
    parent = int((left - right) / 2) + right;
  }

  return parent;
}

注:

  1. 参数 dt 也是需要传入一个处理后的时间,不然会匹配不到。或者将时间处理方法并入此函数开头。
  2. 此函数仅为算法示例,即使 dt 是符合当前图表周期的整数时刻,也可能会出现 Time[] 数组不包含 dt 的情况。K 线图在时间上不一定是连续的。

由于每次比较后,待查找的元素总数都是上一次的二分之一,这个算法的效率还是非常高的。


MT4 自定义指标、 MT4 平台、MT5 编程入门、MQL4 函数、MQL5 中文文档。

版权声明:本站所有原创文章,作者保留版权。转载必须包含本声明,不得修改任何内容(包括文章标题),并以超链接的形式注明作者“Bary”和本文原始地址。

发表评论

电子邮件地址不会被公开。 必填项已用*标注