第十六章 访问时间序列和指标数据

这些函数用于处理 时间序列 和 指标。时间序列 与通常的数据数组不同,——时间序列 的元素索引是反向排序的——意即从数组的 末尾 开始索引编号(从最近的数据到最早的数据)。为了复制 时间序列 的值和指标数据,建议只使用动态数组,因为复制函数旨在分配接收值的数组所需的大小。

这个规则有一个重要的例外:如果 时间序列 和 指标 值需要经常复制,例如在Expert Advisor中每次调用OnTick() 或 在指标中每次调用OnCalculate()时,在这种情况下,应该使用静态分配的数组更好,因为动态数组的内存分配操作需要额外的时间,这在测试和优化期间会有效果。

在使用访问 时间序列 和 指标 值的函数时,应考虑索引方向。 在“数组,缓冲区和时间序列”部分中,对 索引方向 进行了介绍。

指标 和 时间序列 数据的访问应用不考虑要求数据是否准备完好(也就是所谓的 异步访问),这对于自定义指标的计算来说非常重要,因此,如果没有数据,函数 Copy...() 类型会立即返回错误值。然而,当形成EA交易和脚本的访问时,接收数据的尝试会短暂停歇,只是为时序列要求的指标计算值的下载提供必要的时间。

无论所请求的数据是否准备就绪(即所谓的异步访问),都可以访问 指标 和 时间序列数据。 这对于 自定义指标 的计算非常重要,所以如果没有数据,Copy ...() 类型的函数会立即返回错误。但是,从(原英文版有拼写错误form 应该为 from )EA程序 和 脚本进行访问时,需要稍稍暂停一些接收数据的尝试,以便为下载所需的 时间序列 或计算指标值提供一些必要的时间。

avatar

组织数据访问 部分描述了在MetaTrader 5客户端中接收,存储和请求价格数据的细节。 访问历史报价数据,可以从数组的末尾开始执行。物理上,最新的数据总是写在数组的末尾,但是数组末尾的索引编号总是为 0。时间序列 数组中的0索引表示当前K线柱的数据,即对应于此时间框架内未完成的时间阶段的K线柱。

时间框架即是一个时间段,在其中形成的K线柱。在MT5中有21个预定义的标准时间框架。

函数 功能
SeriesInfoInteger 返回有关历史数据状态的信息
Bars 返回指定 交易品种 和 时间周期 的历史数据的的K线柱数量
BarsCalculated 返回指标缓冲区中计算数据的数量 或 (数据尚未计算)出错时返回 -1
IndicatorCreate 返回由MqlParam类型参数数组创建的指定 技术指标 的句柄
IndicatorParameters 基于指定的句柄,返回指标的 输入参数 的数量,以及参数的值和类型
IndicatorRelease 如果没有其他人使用,移除指标句柄并释放该指标的计算模块。
CopyBuffer 从指定指标获得特定缓冲区数据到数组中。
CopyRates 将指定 交易品种 的比率结构的历史数据和周期放在数组中
CopyTime 将指定 交易品种 的K线柱开盘时间的历史数据和周期放在数组中
CopyOpen 将指定 交易品种 的K线柱开盘价格的历史数据和周期放在数组中
CopyHigh 将指定 交易品种 的K线柱最高价的历史数据和周期放在数组中
CopyLow 将指定 交易品种 的K线柱最低价的历史数据和周期放在数组中
CopyClose 将指定 交易品种 的K线柱收盘价的历史数据和周期放在数组中
CopyTickVolume 指定 交易品种 的报价数量的历史数据和周期放在数组中
CopyRealVolume 指定 交易品种 的交易量的历史数据和周期放在数组中
CopySpread 指定 交易品种 的点差历史数据和周期放在数组中
CopyTicks 在MqlTick格式中获取到的报价数据写入到 ticks_array 数组中。
CopyTicksRange 指定日期范围以MqlTick格式接收的报价数据写入到ticks_array数组中

尽管通过使用ArraySetAsSeries()函数可以在数组中设置对 时间序列 中元素的访问权限,但应该记住数组元素在物理上是以同一顺序存储的 —— 只是索引方向不同。为了演示这个事实,我们来举个例子:

   datetime TimeAsSeries[]; 
//--- 如访问 时间序列 一样设置数组访问 
   ArraySetAsSeries(TimeAsSeries,true); 
   ResetLastError(); 
   int copied=CopyTime(NULL,0,0,10,TimeAsSeries); 
   if(copied<=0) 
     { 
      Print("The copy operation of the open time values for last 10 bars has failed"); 
      return; 
     } 
   Print("TimeCurrent =",TimeCurrent()); 
   Print("ArraySize(Time) =",ArraySize(TimeAsSeries)); 
   int size=ArraySize(TimeAsSeries); 
   for(int i=0;i<size;i++)
     { 
      Print("TimeAsSeries["+i+"] =",TimeAsSeries[i]); 
     } 
  
   datetime ArrayNotSeries[]; 
   ArraySetAsSeries(ArrayNotSeries,false); 
   ResetLastError(); 
   copied=CopyTime(NULL,0,0,10,ArrayNotSeries); 
   if(copied<=0) 
     { 
      Print("The copy operation of the open time values for last 10 bars has failed"); 
      return; 
     }    
   size=ArraySize(ArrayNotSeries); 
   for(int i=size-1;i>=0;i--) 
     { 
      Print("ArrayNotSeries["+i+"] =",ArrayNotSeries[i]); 
     }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

因此,我们将得到这样的输出:

TimeCurrent = 2009.06.11 14:16:23 
ArraySize(Time) = 10 
TimeAsSeries[0] = 2009.06.11 14:00:00 
TimeAsSeries[1] = 2009.06.11 13:00:00 
TimeAsSeries[2] = 2009.06.11 12:00:00 
TimeAsSeries[3] = 2009.06.11 11:00:00 
TimeAsSeries[4] = 2009.06.11 10:00:00 
TimeAsSeries[5] = 2009.06.11 09:00:00 
TimeAsSeries[6] = 2009.06.11 08:00:00 
TimeAsSeries[7] = 2009.06.11 07:00:00 
TimeAsSeries[8] = 2009.06.11 06:00:00 
TimeAsSeries[9] = 2009.06.11 05:00:00 
  
ArrayNotSeries[9] = 2009.06.11 14:00:00 
ArrayNotSeries[8] = 2009.06.11 13:00:00 
ArrayNotSeries[7] = 2009.06.11 12:00:00 
ArrayNotSeries[6] = 2009.06.11 11:00:00 
ArrayNotSeries[5] = 2009.06.11 10:00:00 
ArrayNotSeries[4] = 2009.06.11 09:00:00 
ArrayNotSeries[3] = 2009.06.11 08:00:00 
ArrayNotSeries[2] = 2009.06.11 07:00:00 
ArrayNotSeries[1] = 2009.06.11 06:00:00 
ArrayNotSeries[0] = 2009.06.11 05:00:00
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

从结果中可以看到,时间序列 数组增加的索引,索引减少的时间值,也就是说,从当前移到过去,对于普通数组ArrayNotSeries来说,结果是不同的——一旦索引增加,从过去移动到当前。

正如我们从输出中看到的那样,随着 时间序列 数组索引编号的递增,对应的时间值是递减,即我们从现在移到过去。对于 通用数组 ArrayNotSeries,结果是不同的 —— 随着索引编号的递增,我们从过去移到现在。

相关参考

数组动态 , ArrayGetAsSeries , ArraySetAsSeries , 数据系列

# 16.1 数组、缓冲器 和 时间序列 中索引编号的方向

所有 数组 和 指标缓冲区 的默认索引编号方向都是从左至右的,第一元素的索引等于0,因此,数组 或 指标缓冲区的第一元素默认从最左边的0开始,而最后一个元素在最右边。

指标缓冲区是 双精度类型 动态数组,由客户端进行管理,因此它总是对应于被指标计算的K线柱的数量。一个普通的双精度类型动态数组可以使用 SetIndexBuffer() 函数分派绑定到一个指标缓冲区。指标缓冲区不需要使用函数ArrayResize()来设置它们的大小——这将由终端的执行系统完成。

时间序列 是颠倒搜索的数组,例如,时间序列的第一个元素在最右边,最后一个元素在最左边。时间序列是用来存储历史价格数据并包括时间信息,我们可以看见时间序列最右边是最新的数据,而最左边是最旧的数据。

因此,索引编号为0的 时间序列 数组元素包含关于一个 交易品种 的最新报价的信息。如果 时间序列 包含 日线图表的数据,那么当前尚未完成的K线数据位于索引0的位置,而索引1的位置包含了昨天的报价数据。

改变索引方向

函数ArraySetAsSeries()允许改变访问动态数组元素的方法;存储在计算机内存中的数据的物理顺序并没有改变。这个函数只是简单地改变了处理数组元素的方法,所以当使用函数ArrayCopy()将一个数组复制到另一个数组时,接收方数组的内容不依赖于源数组中的索引方向。

对于静态分布的数组,不能更改索引的方向。即使将 静态数组 作为参数传递给ArraySetAsSeries()函数,尝试更改该函数内的索引方向也不会产生任何效果。

对于指标缓冲区来说,像普通数组一样,索引方向向后设置(像时序列),例如,关于指标缓冲区的零位置代表类似指标缓冲区的的最后值,也相当于指标最新字节的值。因此,指标的实际字节位置并未改变。

指标缓冲区,像普通数组一样索引方向也可以设置为向后的(如 时间序列),也就是说,在指标缓冲区中的索引 0 的位置对应的是指示缓冲区的最后一个报价的值,而这将对应于最新的K线柱上的指标的值。不过,指标K线柱的物理位置将保持不变。

指标接收价格数据

每个自定义指标都必须包含OnCalculate() 函数,用来计算在指标缓冲区中所需的价格数据,之后传递给指标。通过使用函数ArrayGetAsSeries(),可以找到这些传递数组中的索引方向。

传递给函数的数组反映价格数据,即这些数组具有 时间序列 的标帜,函数ArrayIsSeries()在检查这些数组时将返回true。但是,在任何情况下,索引方向都应该由函数ArrayGetAsSeries()来检查。

为了不依赖于默认值,ArraySetAsSeries()应该无条件地调用您要处理的数组,并设置所需的方向。

接收价格数据和指标值

在EA交易,指标和脚本中的所有默认检索方向都是从左至右。如果需要,在任何mql5程序中,您都可以请求任何 交易品种 和 时间框架上的 时间序列值,以及在任何 交易品种 和 时间框架上计算的指标值。

EA交易,指标和脚本中所有数组的默认索引方向是从左到右的。

使用Copy...() 函数完成这些操作:
• CopyBuffer – 复制指标缓冲区到双精度类型数组;
• CopyRates – 复制价格记录到结构 MqlRates类型数组;
• CopyTime – 复制时间值到 日期时间 类型数组;
• CopyOpen – 复制K线柱的开盘价到双精度类型数组;
• CopyHigh – 复制K线柱的最高价到双精度类型数组;
• CopyLow – 复制K线柱最低价到双精度类型数组;
• CopyClose – 复制K线柱收盘价到双精度类型数组;
• CopyTickVolume – 复制跳价的数量到长整型数组;
• CopyRealVolume – 复制成交量到长整型数组;
• CopySpread – 复制点差到整型数组;

所有这些函数都以相同方式工作,考虑到CopyBuffer()在示例中包含的原理,暗示在需求数据的索引方向是时序列,0索引位置存储当前未完成字节的数据。为了房屋这些数据,需要复制必要的数据成交量容器数组,例如,数组 buffer。

所有这些函数都以类似的方式工作。让我们考虑一下CopyBuffer()的例子中的数据获取机制。 这意味着所请求数据的索引方向是 时间序列 的索引方向,索引为0(零)的位置存储当前尚未完成的K线柱的数据。为了访问这些数据,我们需要将必要的数据量复制到接收数组中,例如,进入数组缓冲区。

开始复制时,我们需要指定源数组中的起始位置,从中开始将数据复制到接收数组。如果成功,指定数量的元素将从源数组(从本例中的指标缓冲区)复制到接收数组中。与接收数组中设置的索引值无关,复制总是按照上图所示执行。

如果预计价格数据将在具有大量迭代的循环中处理,建议您使用IsStopped()函数检查强制程序终止的事实:

int copied=CopyBuffer(ma_handle,// 指标处理 
                      0,        // 指标缓冲区标引 
                      0,        // 复制的开始位置 
                      number,   // 复制值的数量  
                      Buffer    // 接收值的数组 
                      ); 
if(copied<0) return; 
int k=0; 
while(k < copied && !IsStopped()) 
  { 
   //--- 获得k标引的值 
   double value=Buffer[k]; 
   // ...  
   // 使用值 
   k++; 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

示例:

input int per=10; // 指数周期 
int ma_handle;    // 指标处理 
//+------------------------------------------------------------------+ 
//| EA初始化函数                                                     | 
//+------------------------------------------------------------------+ 
int OnInit() 
  { 
//--- 
   ma_handle=iMA(_Symbol,0,per,0,MODE_EMA,PRICE_CLOSE); 
//--- 
   return(INIT_SUCCEEDED); 
  } 
//+------------------------------------------------------------------+ 
//| EA跳价处理函数                                                     | 
//+------------------------------------------------------------------+ 
void OnTick() 
  { 
//--- 
   double ema[10]; 
   int copied=CopyBuffer(ma_handle,// 指标处理 
                         0,        // 指标缓冲区指数 
                         0,        // 复制的初始位置 
                         10,       // 用于复制的值数 
                         ema       // 接收数组的值 
                         ); 
   if(copied<0) return; 
// .... 深层代码 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

相关参考
组织数据存储

# 16.2 组织数据存储

在本节中,讨论有关获取,存储和请求价格数据(时间序列)的问题。

从交易服务器中获得数据

在MT5客户端的价格数据执行之前,必须先收到然后经过处理,为了接收数据,要确定MT5交易服务器已经确定连接,数据根据终端要求以微小字节形式接收。

在MT5终端中提供报价数据之前,必须先接收并处理它们。要接收数据,必须建立与MT5交易服务器的连接。应终端的请求,来自服务器数据以1分钟K线柱的形式打包接收。

服务器数据的关联结构并不取决于请求的发起方式 - 无论用户是在图表导航中操作 或 以MQL5语言的程序方式发起请求。

储存媒介数据

从服务器接收到的数据将自动解包并保存为HCC中间格式。每个 交易品种 的数据写入一个单独的文件夹:
terminal_directory \ bases \ server_name \ history \ symbol_name。
例如,从MetaQuotes-Demo服务器收到的EURUSD数据将存储在
terminal_directory \ bases \ MetaQuotes-Demo \ history \ EURUSD \

数据被写入扩展名为.hcc的文件中。每个文件存储一年的一分钟(M1)图表的K线柱数据。例如,EURUSD文件夹中名为2009.hcc的文件包含2009年 欧元兑美元 的1分钟(M1)图表的K线。这些文件用于准备所有时间范围的价格数据,它们不适用于直接访问。

在媒介数据外获得必要的时间架构

媒介HCC文件作为 源数据 类型使用,它在HC格式中以建立价格数据的要求来使用的,HC格式的数据是为了快速访问而最大限度地准备的时间序列,它们根据图表或MQL5程序的要求来构建,数据的成交量不能超过 “图表中最多柱数””最大图表数据量”(MT5)(工具-->选项(设定)--图表 标签中)的最大值,数据存储在hc扩展名的文件中以供进一步使用。

为了节省资源,只有在必要时才将时间范围内的数据存储并保存在RAM(内存)中。如果不需要长时间调用,它们将从RAM(内存)中释放并保存到文件中。对于每个时间框架,都准备好数据,无论是否有其它时间框架的现成数据。所有时间框架的形成和访问数据规则都是相同的。即,尽管存储在HCC中的单位数据是一分钟(M1),但HCC数据的可用性并不意味着M1时间框架上的数据与HC在相同数量上的可用性相同。

从服务器接收新数据会调用所有时间框架内HC格式的旧价格数据自动更新。它还导致重新计算所有指标,这些指标隐含地将它们用作计算的输入数据。

参数“图表中最多柱数””最大图表数据量”(MT5)

“图表中最多柱数””最大图表数据量”(MT5)常量限制图表,指标和mql5程序可用的HC格式K线柱数,对于所有可用的时间框架和服务器来说是有效的,首先是为了节约电脑资源。

当设置此参数为较大数值时,应该记住,如果可以使用较小的时间框架的深度历史价格数据,则用于存储 时间序列 和 指标缓冲区 的内存可能变为数百兆字节,并且达到客户端程序的RAM(内存)限制( MS Windows的32位应用程序上限是2Gb)。

在客户端重启之后,“图表中最多柱数””最大图表数据量”(MT5)的改变开始生效,更改此参数既不会自动提交服务器以获取其他数据,也不会形成额外的 时间序列 K线柱。从服务器请求额外的价格数据,并在考虑到新限制的情况下更新时间序列,以防图表滚动到没有数据的区域 或 由mql5程序请求时数据。

从服务器请求的数据量对应于此时间框架所需的K线柱数,并考虑了“图表中最多柱数””最大图表数据量”(MT5)参数。此参数设置的限制并不严格,并且在某些情况下,某个时间范围内的可用K线柱数量可能会比当前参数值稍多一些。

数据有效性

HCC格式的数据 或 甚至使用HC格式准备的数据,并不表示在图表中显示 或 用于MQL5程序时,这些数据绝对可用。

当从mql5程序访问价格数据或指标值时,应该记住它们在特定时刻或从某个时刻开始的可用性不能得到保证。这与以下事实有关:为了节省资源,mql5程序所需的完整数据副本不存储在MetaTrader 5中; 只给出对终端数据库的直接访问。

所有时间框架的价格历史记录均由HCC格式的常用数据构建而成,并且任何服务器数据更新都会导致所有时间框架范围内的数据更新以及重新计算指标。由于这种访问数据可能会被关闭,即使这些数据刚刚可用。

终端数据和服务器数据的同步性

由于mql5程序可以从任何 交易品种 和 时间框架 中调用数据,所以在终端中可能还没有形成必要 时间序列 的数据,或者 必要的价格数据与交易服务器不同步。在这种情况下,很难预测延迟时间。

使用“不做任何操作(do-nothing)”循环的算法不是最好的解决方案。在这种情况下唯一的例外是脚本,因为它们没有任何其它的算法选择,因为没有事件处理。对于自定义指标这样的算法,以及任何其他“不做任何操作(do-nothing)”循环,强烈建议不要这样做,因为它们会导致终止所有指标的计算 以及 对交易品种价格数据操作失败。

对于EA交易和指标,最好使用事件处理模型。如果在处理OnTick() 或 OnCalculate()事件期间,所需 时间序列 的数据接收失败,您应该退出事件处理程序,并依靠下次调用处理程序时的访问可用性。

脚本添加历史的范例

让我们考虑一个脚本示例,该脚本执行请求以从交易服务器接收所选交易品种的历史记录。 该脚本用于在选定交易品种的图表中运行; 时间范围并不重要,因为如上所述,价格数据是从交易服务器接收的一分钟(M1)数据,从中构建了任何预定义的时间序列。

将有关数据接收的所有操作写入一个单独的函数
CheckLoadHistory(symbol, timeframe, start_date):

int CheckLoadHistory(string symbol,ENUM_TIMEFRAMES period,datetime start_date) 
  { 
  }
1
2
3

CheckLoadHistory()函数被设计为通用函数,可以从任何程序(EA交易程序、脚本或指标)调用;因此,它需要三个输入参数:交易品种名称、周期和开始日期,来表明你所需的价格历史开始运行。

在请求缺失的历史数据之前,将必要的检查插入函数代码。首先,我们要确保交易品种名称和周期值是正确的:

if(symbol==NULL || symbol=="") symbol=Symbol();
   if(period==PERIOD_CURRENT)     period=Period();
1
2

然后,让我们确保该 交易品种 在 市场报价 窗口中可见。即,当向交易服务器发送请求时,交易品种 的历史数据是可用的。如果 市场报价 中没有这个 交易品种 ,可以使用函数SymbolSelect()添加它。

   if(!SymbolInfoInteger(symbol,SYMBOL_SELECT))
     {
      if(GetLastError()==ERR_MARKET_UNKNOWN_SYMBOL) return(-1);
      SymbolSelect(symbol,true);
     }
1
2
3
4
5

现在我们应该会收到指定起始日期、周期的货币对的可用的历史数据。也许,传递给CheckLoadHistory()的输入参数 start_date 的值已经有可用的历史数据,这样就不需要向交易服务器发送请求。为了获得当前交易品种周期的第一个日期,可以使用SeriesInfoInteger()函数和SERIES_FIRSTDATE修饰符。

   SeriesInfoInteger(symbol,period,SERIES_FIRSTDATE,first_date);
   if(first_date > 0 && first_date <= start_date) return(1);
1
2

下一个重要的检查是检查调用函数的程序的类型。注意,不要与指标同时发送 时间序列 的更新请求。在与指标相同的交易品种周期上请求数据是不可取的,这是由于在指标操作的同一线程中执行历史数据更新,出现死锁的可能性很高。要检查这一点,请使用函数MQL5InfoInteger() 同时使用 MQL5_PROGRAM_TYPE修饰符。

   if(MQL5InfoInteger(MQL5_PROGRAM_TYPE)==PROGRAM_INDICATOR && Period()==period && Symbol()==symbol)
      return(-4);
1
2

如果所有的检查都成功地通过了,那么在没有引用交易服务器的情况下进行最后一次尝试。首先让我们看看开始日期,在HCC格式中有哪些一分钟(M1)数据可用。使用函数SeriesInfoInteger()并使用 SERIES_TERMINAL_FIRSTDATE修饰符来请求该值,并再次将其与start_date参数的值进行比较。

if(SeriesInfoInteger(symbol,PERIOD_M1,SERIES_TERMINAL_FIRSTDATE,first_date))
     {
      //--- 有建立时间序列的加载数据
      if(first_date > 0)
        {
         //--- 强制创建时间序列
         CopyTime(symbol,period,first_date+PeriodSeconds(period),1,times);
         //--- 检测日期
         if(SeriesInfoInteger(symbol,period,SERIES_FIRSTDATE,first_date))
            if(first_date > 0 && first_date <= start_date) return(2);
        }
     }
1
2
3
4
5
6
7
8
9
10
11
12

如果在所有检查之后,执行线程仍然位于CheckLoadHistory()函数的主体中,这意味着有必要从交易服务器请求缺失的报价数据。首先,使用TerminalInfoInteger()函数返回“图表中最多柱数””最大图表数据量”(MT5)的值:

int max_bars=TerminalInfoInteger(TERMINAL_MAXBARS);
1

需要阻止额外调回数据,在服务器中找回字符历史的第一个日期(忽略周期),使用已知函数SeriesInfoInteger() 的修饰语 SERIES_SERVER_FIRSTDATE 。

我们需要它来防止请求额外的数据。然后使用函数SeriesInfoInteger()并使用SERIES_SERVER_FIRSTDATE修饰符,查找交易服务器上已知的交易品种历史数据中的第一个日期(无论周期)。

   datetime first_server_date=0;
   while(!SeriesInfoInteger(symbol,PERIOD_M1,SERIES_SERVER_FIRSTDATE,first_server_date) && !IsStopped())
      Sleep(5);
1
2
3

由于请求是一个异步操作,所以在循环中调用函数Sleep(),只有5毫秒的延迟,直到first_server_date变量接收到一个值,或者循环执行被一个用户终止(Isstop()在这种情况下返回true)。让我们指定开始日期的正确值,从该值开始,我们从交易服务器请求价格数据。

   if(first_server_date > start_date) start_date=first_server_date;
   if(first_date > 0 && first_date<first_server_date)
      Print("Warning: first server date ",first_server_date," for ", 
symbol," does not match to first series date ",first_date);
1
2
3
4

如果服务器的开始日期first_server_date低于HCC格式符号的开始日期first_date,则相应的文字消息将在会输出到日志中。

现在我们准备向交易服务器请求缺失的历史价格数据。以循环的形式发出请求,并开始填充它的主体:

   while(!IsStopped())
     {
      //1. 等候如同HHC一样重新建立时间序列与中间历史记录的同步化
      //2. 接收这个时间序列的当前n个柱数
      //    如果K线柱的数量已 大于 图表中允许的最大柱数量,可以退出,工作结束
      //3. 获得重建时间序列开始日期的初始日期并且与开始日期相比较
      //    如果初始日期 低于 开始日期,则退出,工作结束
      //4. 从服务器请求历史记录的新部分-从最近有效标有'bars'的柱中启动的100个K线柱 
     }
1
2
3
4
5
6
7
8
9

前三点是用已知的方法实现的。

   while(!IsStopped())
     {
      //--- 1.等待直到 时间序列 重建程序结束
      while(!SeriesInfoInteger(symbol,period,SERIES_SYNCHRONIZED) && !IsStopped())
         Sleep(5);
      //--- 2.请求多少K线柱
      int bars=Bars(symbol,period);
      if(bars>0)
        { 
         //--- 超过图表中所画的K线柱,退出
         if(bars>=max_bars) return(-2); 
         //--- 3. 返回 时间序列 的当前开始日期
         if(SeriesInfoInteger(symbol,period,SERIES_FIRSTDATE,first_date)) 
            // 开始日期早于要求日期,任务完成
            if(first_date > 0 && first_date<=start_date) return(0);
        }
      //4. 从服务器请求历史记录的新部分-从最近有效标有'bars'的柱中启动的100根K线柱
     }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

剩下第四步 —— 请求索取历史数据。我们不能直接引用服务器,但是如果HCC格式的历史记录不够的话,任何复制功能都会自动启动发送到服务器的请求。由于first_date变量中第一个开始日期的时间是评估请求执行程度的简单而自然的标准,因此最简单的方法是使用CopyTime()函数。

当调用从 时间序列 中复制任何数据的函数时,应该注意,start参数(开始条数,从哪个价格数据开始)必须始终位于可用的终端历史记录中。如果只有100根K线柱,那么从索引500开始复制300根K线柱就没有意义了。这样的请求将被理解为一个错误,不会被处理,即不会从交易服务器加载任何附加的历史记录。

这就是为什么我们要以100为一组从K线柱索引开始复制K线柱的原因。这将使交易服务器顺利地加载缺失的历史记录。实际上,将加载比请求的100根K线柱多一点的内存,而服务器将发送过大的历史记录。

 int copied=CopyTime(symbol,period,bars,100,times);
1

在复制操作之后,我们应该分析复制的元素的数量。如果尝试失败,则复制的值将等于null, fail_cnt计数器的值将增加1。在尝试100次失败后,函数的操作将被停止。

int fail_cnt=0; 
...
   int copied=CopyTime(symbol,period,bars,100,times);
   if(copied>0)
     {
      //--- 检测数据
      if(times[0]<=start_date)  return(0);  // 复制值更小,准备完毕
      if(bars+copied>=max_bars) return(-2); // 柱多于图表中所画的柱,准备完毕
      fail_cnt=0;
     }
   else
     {
      //--- 成功的话失败尝试少于100
      fail_cnt++;
      if(fail_cnt>=100) return(-5);
      Sleep(10);
     }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

因此,不仅在执行的每个时刻正确地处理当前情况,而且返回终止代码,这些代码可以在调用CheckLoadHistory()函数之后进行处理,以获取更多信息。例如,这种方式:

int res=CheckLoadHistory(InpLoadedSymbol,InpLoadedPeriod,InpStartDate);
   switch(res)
     {
      case -1 : Print("Unknown symbol ",InpLoadedSymbol);                     break;
      case -2 : Print("More requested bars than can be drawn in the chart"); break;
      case -3 : Print("Execution stopped by user");                          break;
      case -4 : Print("Indicator mustn't load its own data");                break;
      case -5 : Print("Loading failed");                                     break;
      case  0 : Print("All data loaded");                                    break;
      case  1 : Print("Already available data in timeseries are enough");    break;
      case  2 : Print("Timeseries is built from available terminal data");   break;
      default : Print("Execution result undefined");
     }
1
2
3
4
5
6
7
8
9
10
11
12
13

该函数的完整代码可以在脚本的示例中找到,该脚本通过处理请求的结果显示对任何数据的访问的正确组织。

示例代码:

//+------------------------------------------------------------------+ 
//|                                              TestLoadHistory.mq5 | 
//|                        Copyright 2009, MetaQuotes Software Corp. | 
//|                                              https://www.mql5.com | 
//+------------------------------------------------------------------+ 
#property copyright "2009, MetaQuotes Software Corp." 
#property link      "https://www.mql5.com" 
#property version   "1.02" 
#property script_show_inputs 
//--- 输入参量 
input string          InpLoadedSymbol="NZDUSD";   // 被加载的交易品种 
input ENUM_TIMEFRAMES InpLoadedPeriod=PERIOD_H1;  // 被加载的周期 
input datetime        InpStartDate=D'2006.01.01'; // 开始日期 
//+------------------------------------------------------------------+ 
//| 脚本程序启动函数                                                   | 
//+------------------------------------------------------------------+ 
void OnStart() 
  { 
   Print("Start load",InpLoadedSymbol+","+GetPeriodName(InpLoadedPeriod),"from",InpStartDate); 
//--- 
   int res=CheckLoadHistory(InpLoadedSymbol,InpLoadedPeriod,InpStartDate); 
   switch(res) 
     { 
      case -1 : Print("Unknown symbol ",InpLoadedSymbol);             break; 
      case -2 : Print("Requested bars more than max bars in chart"); break; 
      case -3 : Print("Program was stopped");                        break; 
      case -4 : Print("Indicator shouldn't load its own data");      break; 
      case -5 : Print("Load failed");                                break; 
      case  0 : Print("Loaded OK");                                  break; 
      case  1 : Print("Loaded previously");                          break; 
      case  2 : Print("Loaded previously and built");                break; 
      default : Print("Unknown result"); 
     } 
//--- 
   datetime first_date; 
   SeriesInfoInteger(InpLoadedSymbol,InpLoadedPeriod,SERIES_FIRSTDATE,first_date); 
   int bars=Bars(InpLoadedSymbol,InpLoadedPeriod); 
   Print("First date ",first_date," - ",bars," bars"); 
//--- 
  } 
//+------------------------------------------------------------------+ 
//|                                                                  | 
//+------------------------------------------------------------------+ 
int CheckLoadHistory(string symbol,ENUM_TIMEFRAMES period,datetime start_date) 
  { 
   datetime first_date=0; 
   datetime times[100]; 
//--- 检测交易品种 & 周期 
   if(symbol==NULL || symbol=="") symbol=Symbol(); 
   if(period==PERIOD_CURRENT)     period=Period(); 
//--- 检测市场报价是否选定了交易品种 
   if(!SymbolInfoInteger(symbol,SYMBOL_SELECT)) 
     { 
      if(GetLastError()==ERR_MARKET_UNKNOWN_SYMBOL) return(-1); 
      SymbolSelect(symbol,true); 
     } 
//--- 检测数据是否存在 
   SeriesInfoInteger(symbol,period,SERIES_FIRSTDATE,first_date); 
   if(first_date > 0 && first_date <= start_date) return(1); 
//--- 如果是指标的话不需要加载自己的数据 
   if(MQL5InfoInteger(MQL5_PROGRAM_TYPE)==PROGRAM_INDICATOR && Period()==period && Symbol()==symbol) 
      return(-4); 
//--- 第二尝试 
   if(SeriesInfoInteger(symbol,PERIOD_M1,SERIES_TERMINAL_FIRSTDATE,first_date)) 
     { 
      //--- 有建立时间序列加载的数据 
      if(first_date>0) 
        { 
         //--- 强制创建时间序列 
         CopyTime(symbol,period,first_date+PeriodSeconds(period),1,times); 
         //--- 检测日期 
         if(SeriesInfoInteger(symbol,period,SERIES_FIRSTDATE,first_date)) 
            if(first_date > 0 && first_date <= start_date) return(2); 
        } 
     } 
//--- 图表中来自程序端选项的最大柱 
   int max_bars=TerminalInfoInteger(TERMINAL_MAXBARS); 
//--- 加载交易品种历史记录信息 
   datetime first_server_date=0; 
   while(!SeriesInfoInteger(symbol,PERIOD_M1,SERIES_SERVER_FIRSTDATE,first_server_date) && !IsStopped()) 
      Sleep(5); 
//--- 为加载确定开始日期 
   if(first_server_date > start_date) start_date=first_server_date; 
   if(first_date > 0 && first_date < first_server_date)
      Print("Warning: first server date ",first_server_date," for ",symbol, 
            " does not match to first series date ",first_date); 
//--- 逐步地加载数据 
   int fail_cnt=0; 
   while(!IsStopped()) 
     { 
      //--- 等待建立时间序列 
      while(!SeriesInfoInteger(symbol,period,SERIES_SYNCHRONIZED) && !IsStopped()) 
         Sleep(5); 
      //--- 要求建成的柱 
      int bars=Bars(symbol,period); 
      if(bars>0) 
        { 
         if(bars >= max_bars) return(-2); 
         //--- 请求初始日期 
         if(SeriesInfoInteger(symbol,period,SERIES_FIRSTDATE,first_date)) 
            if(first_date > 0 && first_date <= start_date) return(0); 
        } 
      //--- 复制部分强制数据加载 
      int copied=CopyTime(symbol,period,bars,100,times); 
      if(copied>0) 
        { 
         //--- 数据检测 
         if(times[0]<=start_date)  return(0); 
         if(bars+copied >= max_bars) return(-2); 
         fail_cnt=0; 
        } 
      else 
        { 
         //--- 失败尝试少于100 
         fail_cnt++; 
         if(fail_cnt>=100) return(-5); 
         Sleep(10); 
        } 
     } 
//--- 停止 
   return(-3); 
  } 
//+------------------------------------------------------------------+ 
//| 返回该周期的字符串值                                                | 
//+------------------------------------------------------------------+ 
string GetPeriodName(ENUM_TIMEFRAMES period) 
  { 
   if(period==PERIOD_CURRENT) period=Period(); 
//--- 
   switch(period) 
     { 
      case PERIOD_M1:  return("M1"); 
      case PERIOD_M2:  return("M2"); 
      case PERIOD_M3:  return("M3"); 
      case PERIOD_M4:  return("M4"); 
      case PERIOD_M5:  return("M5"); 
      case PERIOD_M6:  return("M6"); 
      case PERIOD_M10: return("M10"); 
      case PERIOD_M12: return("M12"); 
      case PERIOD_M15: return("M15"); 
      case PERIOD_M20: return("M20"); 
      case PERIOD_M30: return("M30"); 
      case PERIOD_H1:  return("H1"); 
      case PERIOD_H2:  return("H2"); 
      case PERIOD_H3:  return("H3"); 
      case PERIOD_H4:  return("H4"); 
      case PERIOD_H6:  return("H6"); 
      case PERIOD_H8:  return("H8"); 
      case PERIOD_H12: return("H12"); 
      case PERIOD_D1:  return("Daily"); 
      case PERIOD_W1:  return("Weekly"); 
      case PERIOD_MN1: return("Monthly"); 
     } 
//--- 
   return("unknown period"); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156

# 16.3 SeriesInfoInteger

返回有关历史数据状态的信息。这个函数有2个变体。

  1. 直接返回属性值
long  SeriesInfoInteger( 
   string                     symbol_name,     // 交易品种名称 
   ENUM_TIMEFRAMES            timeframe,       // 周期 
   ENUM_SERIES_INFO_INTEGER   prop_id,         // 属性标识符 
   );
1
2
3
4
5
  1. 返回true或false,取决于函数运行的结果。
bool  SeriesInfoInteger( 
   string                     symbol_name,     // 交易品种名称 
   ENUM_TIMEFRAMES            timeframe,       // 周期 
   ENUM_SERIES_INFO_INTEGER   prop_id,         // 属性ID 
   long&                      long_var         // 用于获得属性信息的变量 
   );
1
2
3
4
5
6

参数 symbol_name

[in] 交易品种名称。

timeframe

[in] 周期。

prop_id

[in] 请求属性的标识符,取值范围为ENUM_SERIES_INFO_INTEGER枚举值之一。

long_var

[out] 用于保存请求属性值的变量。

返回值 第一种情况,返回一个长整型数值。

对于第二种情况,如果指定的属性可用 且 其值已放入long_var变量中,则返回true,否则返回false。有关错误的更多详细信息,请调用GetLastError()。

示例:

void OnStart() 
  { 
//--- 打印输出当前交易品种时间周期图表上的K线柱总数
   Print("Total number of bars for the symbol-period at this moment = ", 
         SeriesInfoInteger(Symbol(),0,SERIES_BARS_COUNT)); 
//--- 打印输出当前交易品种时间周期图表上K线柱开始的时间  
   Print("The first date for the symbol-period at this moment = ", 
         (datetime)SeriesInfoInteger(Symbol(),0,SERIES_FIRSTDATE)); 
//--- 打印输出当前交易品种时间周期历史图表上K线柱开始的时间   
   Print("The first date in the history for the symbol-period on the server = ", 
         (datetime)SeriesInfoInteger(Symbol(),0,SERIES_SERVER_FIRSTDATE)); 
//--- 交易品种历史数据同步   
   Print("Symbol data are synchronized = ", 
         (bool)SeriesInfoInteger(Symbol(),0,SERIES_SYNCHRONIZED)); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 16.4 Bars

返回指定交易品种 和 周期的历史数据K线柱数量。这个函数有2个变体。

  1. 请求所有历史数据K线柱数量
int  Bars( 
   string           symbol_name,     // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe        // 周期 
   );
1
2
3
4
  1. 请求指定时间间隔内的历史数据K线柱数量
int  Bars( 
   string           symbol_name,     // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,       // 周期 
   datetime         start_time,      // 开始 日期和时间 
   datetime         stop_time        // 结束 日期和时间 
   );
1
2
3
4
5
6

参数 symbol_name

[in] 交易品种名称。

timeframe

[in] 周期。

start_time

[in] 指定时间间隔的开始时间。

stop_time

[in] 指定时间间隔的结束时间。

返回值 如果定义了start_time和stop_time参数,则该函数返回指定时间间隔内的K线柱数量,否则返回K线柱数量的总数。

注意 如果在Bars()函数调用时客户端中没有形成具有指定参数的 时间序列 的数据,或者在函数调用期间 时间序列 的数据未与交易服务器同步,则函数返回 0 值。

当请求指定时间间隔内的K线柱数量,只考虑时间间隔内开盘时间的K线柱。例如,如果当前是星期六,并且请求就是W1周期的K线柱数量,开始时间为 start_time=last_tuesday ,结束时间为 stop_time=last_friday。因为在W1时间框架范围的开盘时间始终为星期日,并且在指定间隔内W1图表上没有一根单独的K线柱,所以函数将返回0。

请求所有历史K线柱数量的示例:

   int bars=Bars(_Symbol,_Period);
   if(bars>0)
     {
      Print("Number of bars in the terminal history for the symbol-period at the moment = ",bars); // 当前客户端交易品种周期图表中历史K线柱的数量 =
     }
   else  //无有效柱
     {
      //--- 交易品种数据不能和服务器数据同步
      bool synchronized=false;
      //--- 循环计数器
      int attempts=0;
      // 进行5次尝试等候同步进行
      while(attempts<5)
        {
         if(SeriesInfoInteger(Symbol(),0,SERIES_SYNCHRONIZED))
           {
            //--- 同步化完成,退出
            synchronized=true;
            break;
           }
         //--- 增加计数器
         attempts++;
         //--- 等候10毫秒直至嵌套反复
         Sleep(10);
        }
      //--- 同步化后退出循环
      if(synchronized)
        {
         Print("Number of bars in the terminal history for the symbol-period at the moment = ",bars); // 当前客户端交易品种周期图表中历史K线柱的数量
         Print("The first date in the terminal history for the symbol-period at the moment = ",
               (datetime)SeriesInfoInteger(Symbol(),0,SERIES_FIRSTDATE));
              // 在客户端中该交易品种的历史数据中的第一根K线柱的日期时间
          Print("The first date in the history for the symbol on the server = ",
   (datetime)SeriesInfoInteger(Symbol(),0,SERIES_SERVER_FIRSTDATE));
                // 在服务器上的该交易品种的历史数据中的第一根K线柱的日期时间
        }
      //--- 不发生数据同步
      else
        {
         Print("Failed to get number of bars for ",_Symbol);
        }  // 获取K线柱数量失败
     }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

请求指定时间间隔内K线柱数量的示例:

   int n; 
   datetime date1 = D'2016.09.02 23:55'; // 星期五 
   datetime date2 = D'2016.09.05 00:00'; // 星期一 
   datetime date3 = D'2016.09.08 00:00'; // 星期四 
   //--- 
   n=Bars(_Symbol,PERIOD_H1,D'2016.09.02 02:05',D'2016.09.02 10:55'); 
   Print("Number of bars: ",n); // 输出:"柱形图数:8",计算中考虑H2柱形图,而非H11柱形图 
   n=Bars(_Symbol,PERIOD_D1,date1,date2); 
   Print("Number of bars: ",n); // 输出:"柱形图数:1",由于D1图表上有一根单独的K线柱(星期一),开盘时间在指定的时间间隔内 
   n=Bars(_Symbol,PERIOD_W1,date2,date3); 
   Print("Number of bars: ",n); // 输出:"柱形图数:0",由于W1图表上没有一根K线柱的开盘时间在指定的时间间隔内
1
2
3
4
5
6
7
8
9
10
11

# 16.5 BarsCalculated

返回指定指标的计算数据的数量。

int  BarsCalculated( 
   int       indicator_handle,     // 指标处理 
   );
1
2
3

参数
indicator_handle

[in] 指标的句柄,通过相应的指标函数返回。

返回值
在指标缓冲区返回计算数据的数量 或者 发生错误时返回 -1(数据不能进行计算)。

注意
当需要在其创建后立即获取指标数据(指标句柄可用)时,该函数非常有用。 示例:

void OnStart() 
  { 
   double Ups[]; 
//--- 设置整理数组的 时间序列 
   ArraySetAsSeries(Ups,true); 
//--- 为分形指标创建处理程序 
   int FractalsHandle=iFractals(NULL,0); 
//--- 重置错误代码 
   ResetLastError(); 
//--- 复制指标值 
   int i,copied=CopyBuffer(FractalsHandle,0,0,1000,Ups); 
   if(copied<=0) 
     { 
      Sleep(50); 
      for(i=0;i<100;i++) 
        { 
         if(BarsCalculated(FractalsHandle)>0) 
            break; 
         Sleep(50); 
        } 
      copied=CopyBuffer(FractalsHandle,0,0,1000,Ups); 
      if(copied<=0) 
        { 
         Print("Failed to copy upper fractals. Error = ",GetLastError(), 
         "i = ",i,"    copied = ",copied); 
         return; 
        } 
       else 
         Print("Upper fractals copied", 
         "i = ",i,"    copied = ",copied); 
     } 
   else Print("Upper fractals copied. ArraySize = ",ArraySize(Ups)); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 16.6 IndicatorCreate

该函数返回基于MqlParam类型参数数组创建的指定技术指标的句柄。

int  IndicatorCreate( 
   string           symbol,                            // 交易品种名称 
   ENUM_TIMEFRAMES  period,                            // 时间表 
   ENUM_INDICATOR   indicator_type,                    // ENUM_INDICATOR枚举的指标类型之一 
   int              parameters_cnt=0,                  // 参数编号 
   const MqlParam&  parameters_array[]=NULL,           // 参量数组 
   );
1
2
3
4
5
6
7

参数 symbol

[in] 交易品种名称,指标的计算数据,NULL 表示当前交易品种。

period

[in] 时间周期,取值范围是 ENUM_TIMEFRAMES 枚举值之一,0 代表当前时间框架。

indicator_type

[in] 指标类型,取值范围是 ENUM_INDICATOR 枚举值之一。

parameters_cnt

[in] 在parameters_array []数组中传递的参数数量。 数组元素具有特殊的结构类型MqlParam。 默认情况下,0表示不传递参数。如果您指定了 非零 数量的参数,则参数parameters_array是强制性的。您可以传递的参数数量不得超过256个。

parameters_array[]=NULL

[in] MqlParam 类型数组,元素包括类型和每个技术指标 输入参数 的类型值。

返回值 返回指定技术指标的句柄,如果失败,则返回INVALID_HANDLE。

注意 如果创建了IND_CUSTOM类型(自定义指标)的指标句柄,则输入参数array_array的第一个元素的类型字段必须具有ENUM_DATATYPE枚举的TYPE_STRING值,并且第一个元素的string_value字段必须包含自定义指标的名称。自定义指标必须进行编译(具有EX5扩展名的文件),并位于客户端MQL5 / Indicators目录中或子目录中。

如果通过常量字符串设置相应的参数,那么需要测试的指标会自动从iCustom()函数的调用中定义。对于所有其他情况(使用IndicatorCreate()函数或在设置指标名称的参数中使用非常量字符串),则属性 #property tester_indicator是必需的:

#property tester_indicator "indicator_name.ex5" 如果调用的自定义指标,是第一种版本格式,则可以另外指示传递输入参数时将计算哪些数据的最后一个参数。如果没有明确指定“应用于”参数,则默认计算基于PRICE_CLOSE值。

示例:

void OnStart() 
  { 
   MqlParam params[]; 
   int      h_MA,h_MACD; 
//--- 创建 iMA("EURUSD",PERIOD_M15,8,0,MODE_EMA,PRICE_CLOSE); 
   ArrayResize(params,4); 
//--- 设置 ma_period 
   params[0].type         =TYPE_INT; 
   params[0].integer_value=8; 
//--- 设置 ma_shift 
   params[1].type         =TYPE_INT; 
   params[1].integer_value=0; 
//--- 设置 ma_method 
   params[2].type         =TYPE_INT; 
   params[2].integer_value=MODE_EMA; 
//--- 数组 applied_price 
   params[3].type         =TYPE_INT; 
   params[3].integer_value=PRICE_CLOSE; 
//--- 创建 MA 
   h_MA=IndicatorCreate("EURUSD",PERIOD_M15,IND_MA,4,params); 
//--- 创建 iMACD("EURUSD",PERIOD_M15,12,26,9,h_MA); 
   ArrayResize(params,4); 
//--- 设置快速 ma_period 
   params[0].type         =TYPE_INT; 
   params[0].integer_value=12; 
//--- 设置慢速 ma_period 
   params[1].type         =TYPE_INT; 
   params[1].integer_value=26; 
//--- 为不同性设置平滑周期 
   params[2].type         =TYPE_INT; 
   params[2].integer_value=9; 
//--- 设置指标处理程序为 applied_price 
   params[3].type         =TYPE_INT; 
   params[3].integer_value=h_MA; 
//--- 创建基于移动平均数的MACD  
   h_MACD=IndicatorCreate("EURUSD",PERIOD_M15,IND_MACD,4,params); 
//--- 使用指标 
//--- . . . 
//--- 发布指标 (首先 h_MACD) 
   IndicatorRelease(h_MACD); 
   IndicatorRelease(h_MA); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# 16.7 IndicatorParameters

根据指定的指标句柄,返回指标的输入参数数量,以及参数的值和类型。

int  IndicatorParameters( 
   int               indicator_handle,     // 指标处理 
   ENUM_INDICATOR&   indicator_type,       // 接收指标类型的变量 
   MqlParam&         parameters[]          // 接收参数的数组 
   );
1
2
3
4
5

参数 indicator_handle

[in] 指标的句柄,您需要知道其计算参数的数量。

indicator_type

[out] 接收指标类型的变量一个变量,取值范围是ENUM_INDICATOR枚举类型之一,指标类型将写入其中。

parameters[]

[out] 接收MqlParam类型值的动态数组,在这里写入指标参数列表。数组大小通过IndicatorParameters()函数返回。

返回值 指定指标句柄的输入参数数量。如果错误则返回-1。要了解有关错误的更多信息,请访问GetLastError()函数。

例:(此例仅适用于 MT5 客户端)

//+------------------------------------------------------------------+ 
//| 脚本程序起始函数                                                   | 
//+------------------------------------------------------------------+ 
void OnStart() 
  { 
  
//--- 图表上的窗口数量(至少有一个窗口始终存在) 
   int windows=(int)ChartGetInteger(0,CHART_WINDOWS_TOTAL); 
//--- 检查图表窗口 
   for(int w=0;w<windows;w++) 
     { 
      //--- 该窗口/子窗口的指标数量 
      int total=ChartIndicatorsTotal(0,w); 
      //--- 从窗口获取所有指标 
      for(int i=0;i<total;i++) 
        { 
         //--- 获得指标的缩略名称 
         string name=ChartIndicatorName(0,w,i); 
         //--- 获得指标句柄 
         int handle=ChartIndicatorGet(0,w,name); 
         //--- 添加到日志 
         PrintFormat("Window=%d,  indicator #%d,  handle=%d",w,i,handle); 
         //--- 
         MqlParam parameters[]; 
         ENUM_INDICATOR indicator_type; 
         int params=IndicatorParameters(handle,indicator_type,parameters); 
         //--- 信息的标头 
         string par_info="Short name "+name+", type " 
                         +EnumToString(ENUM_INDICATOR(indicator_type))+"\r\n"; 
         //---  
         for(int p=0;p<params;p++) 
           { 
            par_info+=StringFormat("parameter %d: type=%s, long_value=%d, double_value=%G,string_value=%s\r\n", 
                                   p, 
                                   EnumToString((ENUM_DATATYPE)parameters[p].type), 
                                   parameters[p].integer_value, 
                                   parameters[p].double_value, 
                                   parameters[p].string_value 
                                   ); 
           } 
         Print(par_info); 
        } 
      //--- 完成窗口的所有指标 
     } 
//---     
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

# 16.8 IndicatorRelease

如果没有其他人使用,该函数将删除指标器句柄并释放指标的计算块。

bool  IndicatorRelease( 
   int       indicator_handle     // 指标处理 
   );
1
2
3

返回值 如果成功返回TRUE,否则返回FALSE。

注意 该函数允许删除指标句柄(如果不再需要),从而节省内存。句柄会被立即移除,计算块会在一段时间内被删除(如果它不再被调用)。

当在策略测试器中工作时,不会执行IndicatorRelease()函数。

示例:

//+------------------------------------------------------------------+ 
//|                                        Test_IndicatorRelease.mq5 | 
//|                        Copyright 2010, MetaQuotes Software Corp. | 
//|                                             https://www.mql5.com | 
//+------------------------------------------------------------------+ 
#property copyright "2010, MetaQuotes Software Corp." 
#property link      "https://www.mql5.com" 
#property version   "1.00" 
//--- 输入参量 
input int                MA_Period=15; 
input int                MA_shift=0; 
input ENUM_MA_METHOD     MA_smooth=MODE_SMA; 
input ENUM_APPLIED_PRICE price=PRICE_CLOSE; 
//--- 存储指标处理程序 
int MA_handle=INVALID_HANDLE; 
//+------------------------------------------------------------------+ 
//| EA初始化函数                                                      | 
//+------------------------------------------------------------------+ 
int OnInit() 
  { 
//--- 创建指标处理程序 
   MA_handle=iMA(Symbol(),0,MA_Period,MA_shift,MA_smooth,PRICE_CLOSE); 
//--- 删除全局变量 
   if(GlobalVariableCheck("MA_value")) 
      GlobalVariableDel("MA_value"); 
//--- 
   return(INIT_SUCCEEDED); 
  } 
//+------------------------------------------------------------------+ 
//| EA订单号函数                                                      | 
//+------------------------------------------------------------------+ 
void OnTick() 
  { 
//--- 如果全局变量值不存在 
   if(!GlobalVariableCheck("MA_value")) 
     { 
      //--- 在最近2柱获得指标值 
      if(MA_handle!=INVALID_HANDLE) 
        { 
         //--- 指标值的动态数组 
         double values[]; 
         if(CopyBuffer(MA_handle,0,0,2,values)==2 && values[0]!=EMPTY_VALUE) 
           { 
            //--- 记住倒数第二柱的全局变量值 
            if(GlobalVariableSet("MA_value",values[0])) 
              { 
               //--- 释放指标处理程序 
               if(!IndicatorRelease(MA_handle)) 
                  Print("IndicatorRelease() failed. Error ",GetLastError()); 
               else MA_handle=INVALID_HANDLE; 
              } 
            else 
               Print("GlobalVariableSet failed. Error ",GetLastError()); 
           } 
        } 
     } 
//--- 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

# 16.9 CopyBuffer

获取必要数量的某个指标的指定缓冲区的数据。

copyBuffer

从开始位置开始计数复制数据(具有索引buffer_num的指标缓冲区)的元素从当前到过去,即,开始位置0表示当前K线柱(当前K线柱的指标值)。

在复制未知数量的数据时,建议使用动态数组作为buffer[]接收缓冲区,因为CopyBuffer()函数会尝试将接收数组的大小分配给复制数据的大小。如果指标缓冲区(通过SetIndexBufer()函数预先分配用于存储指标值的数组)用作buffer[]接收数组,则允许进行部分复制。可以在标准客户端安装包中的Awesome_Oscillator.mql5自定义指标中找到一个示例。

如果您需要将指标值的部分副本复制到另一个数组(非指标缓冲区),则应使用中间数组,并将所需的数量复制到该数组中。之后,将所需数量值的元素明细复制到接收数组的所需位置。

如果您知道需要复制的数据量,最好对静态分配的缓冲区执行操作,以防止分配过多的内存。

无论目标数组的属性是什么,即标帜 - as_series = true或as_series = false。数据都将被复制,因为便最旧的元素将位于为数组分配的物理内存的开始位置。此函数有3种变体。

  1. 按开始位置和所需元素的数量调用
int  CopyBuffer( 
   int       indicator_handle,     // 指标处理 
   int       buffer_num,           // 指标缓冲区数 
   int       start_pos,            // 启动位置 
   int       count,                // 复制总额 
   double    buffer[]              // 复制的目标数组 
   );
1
2
3
4
5
6
7
  1. 按开始日期和所需元素的数量调用
int  CopyBuffer( 
   int       indicator_handle,     // 指标处理 
   int       buffer_num,           // 指标缓冲区数 
   datetime  start_time,           // 启动日期和时间 
   int       count,                // 复制总额 
   double    buffer[]              // 复制的目标数组 
   );
1
2
3
4
5
6
7
  1. 按所需时间间隔的开始和结束日期进行调用
int  CopyBuffer( 
   int       indicator_handle,     // 指标处理 
   int       buffer_num,           // 指标缓冲区数 
   datetime  start_time,           // 启动日期和时间 
   datetime  stop_time,            // 结束日期和时间 
   double    buffer[]              // 复制的目标数组 
   );
1
2
3
4
5
6
7

参数 indicator_handle

[in] 指标句柄,由相应的指标函数返回。

buffer_num

[in] 指标缓冲区数量。

start_pos

[in] 开始复制元素的索引位置。

count

[in] 复制数据元素的数量。

start_time

[in] K线柱的时间,对应要复制的第一个元素。

stop_time

[in] K线柱的时间,对应要复制的最后一个元素。

buffer[]

[out] 双精度 类型数组。

返回值 返回复制数据的数量 或 发生错误时返回 -1。

注意 当从指标中请求数据时,如果请求的 时间序列 尚未建立 或 需要从服务器下载,函数将立即返回 -1,但随后,将启动 下载/构建 过程。

从EA交易程序 或 脚本请求数据时,如果终端在本地没有这些数据,则将启动从服务器下载数据,或者如果数据可以从本地历史数据构建,但所需的 时间序列 仍未准备好。该函数将返回在 超时 到期之前准备就绪的数据量。但是历史下载会继续,在下一个类似要求函数中会返回更多数据。

示例:

//+------------------------------------------------------------------+ 
//|                                              TestCopyBuffer3.mq5 | 
//|                        Copyright 2009, MetaQuotes Software Corp. | 
//|                                             https://www.mql5.com | 
//+------------------------------------------------------------------+ 
#property copyright "2009, MetaQuotes Software Corp." 
#property link      "https://www.mql5.com" 
#property version   "1.00" 
  
#property indicator_separate_window 
#property indicator_buffers 1 
#property indicator_plots   1 
//---- 图 MA 
#property indicator_label1  "MA" 
#property indicator_type1   DRAW_LINE 
#property indicator_color1  clrRed 
#property indicator_style1  STYLE_SOLID 
#property indicator_width1  1 
//--- 输入参量 
input bool               AsSeries=true; 
input int                period=15; 
input ENUM_MA_METHOD     smootMode=MODE_EMA; 
input ENUM_APPLIED_PRICE price=PRICE_CLOSE; 
input int                shift=0; 
//--- 指标缓冲区 
double                   MABuffer[]; 
int                      ma_handle; 
//+------------------------------------------------------------------+ 
//| 自定义指标初始化函数                                                | 
//+------------------------------------------------------------------+ 
int OnInit() 
  { 
//--- 指标缓冲区绘图 
   SetIndexBuffer(0,MABuffer,INDICATOR_DATA); 
   Print("Parameter AsSeries = ",AsSeries); 
   Print("Indicator buffer after SetIndexBuffer() is a timeseries = ", 
         ArrayGetAsSeries(MABuffer)); 
//--- 设置短小的指标名称 
   IndicatorSetString(INDICATOR_SHORTNAME,"MA("+period+")"+AsSeries); 
//--- 设置 AsSeries(依据输入参量) 
   ArraySetAsSeries(MABuffer,AsSeries); 
   Print("Indicator buffer after ArraySetAsSeries(MABuffer,true); is a timeseries = ", 
         ArrayGetAsSeries(MABuffer)); 
//--- 
   ma_handle=iMA(Symbol(),0,period,shift,smootMode,price); 
   return(INIT_SUCCEEDED); 
  } 
//+------------------------------------------------------------------+ 
//| 自定义指标重复函数                                                  | 
//+------------------------------------------------------------------+ 
int OnCalculate(const int rates_total, 
                const int prev_calculated, 
                const datetime &time[], 
                const double &open[], 
                const double &high[], 
                const double &low[], 
                const double &close[], 
                const long &tick_volume[], 
                const long &volume[], 
                const int &spread[]) 
  { 
//--- 检测是否计算了所有数据 
   if(BarsCalculated(ma_handle)<rates_total) return(0); 
//--- 不复制所有数据 
   int to_copy; 
   if(prev_calculated>rates_total || prev_calculated<=0) to_copy=rates_total; 
   else 
     { 
      to_copy=rates_total-prev_calculated; 
      //--- 常常复制最后的值 
      to_copy++; 
     } 
//--- 复制 
   if(CopyBuffer(ma_handle,0,0,to_copy,MABuffer)<=0) return(0); 
//--- 为下次调用返回prev_calculated值 
   return(rates_total); 
  } 
//+------------------------------------------------------------------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

上面的例子说明了如何使用同一 交易品种/周期 中指标的另一个指标缓冲区的值填充指标缓冲区。

请参阅对象绑定方法一节中有关历史请求数据的详细示例。该部分提供的脚本显示了如何获取最近1000根K线柱上的指标iFractals的值以及如何显示图表上的最近的10个上下分形箭头。对于缺少数据并且通常使用以下样式绘制的所有指标都可以使用类似的技术:
• DRAW_SECTION,
• DRAW_ARROW,
• DRAW_ZIGZAG,
• DRAW_COLOR_SECTION,
• DRAW_COLOR_ARROW,
• DRAW_COLOR_ZIGZAG.

相关参考
自定义指标属性 , SetIndexBuffer

# 16.10 CopyRates

将指定交易品种、周期和数量的MqlRates结构的历史数据获取到rates_array数组中。复制数据的元素顺序是从现在到过去,即,从当前位置开始,0表示当前的K线柱。

CopyRates

当复制的元素数量未知时,建议使用动态数组作为目标数组,因为如果请求的数据数量小于(或大于)目标数组的长度,函数将尝试重新分配内存,以便完全适应数据请求的要求。

如果您知道需要复制的数据量,最好对静态分配的缓冲区执行操作,以防止分配过多的内存。

无论目标数组的属性是什么,即标帜 - as_series = true或as_series = false。数据都将被复制,因为便最旧的元素将位于为数组分配的物理内存的开始位置。此函数有3种变体。

  1. 按开始位置和所需元素的数量调用
int  CopyRates( 
   string           symbol_name,       // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,         // 周期 
   int              start_pos,         // 启动位置 
   int              count,             // 复制数据计算 
   MqlRates         rates_array[]      // 复制目标数组 
   );
1
2
3
4
5
6
7
  1. 按开始日期和所需元素的数量调用
int  CopyRates( 
   string           symbol_name,       // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,         // 周期 
   datetime         start_time,        // 开始日期和时间 
   int              count,             // 复制数据计算 
   MqlRates         rates_array[]      // 复制目标数组 
   );
1
2
3
4
5
6
7
  1. 按所需时间间隔的开始和结束日期进行调用
int  CopyRates( 
   string           symbol_name,       // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,         // 周期 
   datetime         start_time,        // 开始日期和时间 
   datetime         stop_time,         // 结束日期和时间 
   MqlRates         rates_array[]      // 复制目标数组 
   );
1
2
3
4
5
6
7

参数 symbol_name

[in] 交易品种名称。

timeframe

[in] 时间周期(框架)。

start_time

[in] K线柱的时间,对应要复制的第一个元素。

start_pos

[in] 开始复制元素的索引位置。

count

[in] 复制的元素数量。

stop_time

[in] K线柱的时间,对应要复制的最后一个元素。

rates_array[]

[out] MqlRates 类型数组

返回值 返回复制数据的数量 或 发生错误时返回 -1。

注意 如果请求数据的整个时间间隔超出服务器上的可用数据,则函数返回 -1。如果在TERMINAL_MAXBARS(图表中最多柱数”最大图表数据量”(MT5))之外请求数据,函数也将返回 -1。

当从指标请求数据时,如果所请求的 时间序列 尚未构建,或者需要从服务器上下载,该函数将立即返回 -1,但随后,将启动 下载/构建 过程。

从EA交易程序 或 脚本请求数据时,如果终端在本地没有这些数据,则将启动从服务器下载数据,或者如果数据可以从本地历史数据构建,但所需的 时间序列 仍未准备好。该函数将返回在 超时 到期之前准备就绪的数据量。但是历史下载会继续,在下一个类似要求函数中会返回更多数据。

当用 2. 按开始日期和所需元素的数量调用 时,只返回日期小于(更早) 或 等于指定日期的数据。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

当用 3. 按所需时间间隔的开始和结束日期进行调用 时,将只返回来自此间隔内的数据。间隔被设置并且最小单位为秒。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

因此,如果当前日期是星期六,那么在尝试复制指定时间间隔为 start_time = Last_Tuesday和stop_time=Last_Friday的周(W1)时间框架上的数据时,函数将返回0,因为周(W1)时间框架上的开盘时间总是周日,但一根星期的K线柱不属于指定的时间间隔内的数据。

如果需要返回与当前未完成的(正在跳动的)K线柱对应的值,可以使用第一种调用形式指定start_pos = 0和count = 1。

示例:

void OnStart() 
  { 
//--- 
   MqlRates rates[]; 
   ArraySetAsSeries(rates,true); 
   int copied=CopyRates(Symbol(),0,0,100,rates); 
   if(copied>0) 
     { 
      Print("Bars copied: "+copied); 
      string format="open = %G, high = %G, low = %G, close = %G, volume = %d"; 
      string out; 
      int size=fmin(copied,10); 
      for(int i=0;i size;i++) 
        { 
         out=i+":"+TimeToString(rates[i].time); 
         out=out+" "+StringFormat(format, 
                                  rates[i].open, 
                                  rates[i].high, 
                                  rates[i].low, 
                                  rates[i].close, 
                                  rates[i].tick_volume); 
         Print(out); 
        } 
     } 
   else Print("Failed to get history data for the symbol ",Symbol()); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

请参阅对象绑定方法一节中有关历史请求数据的详细示例。该部分提供的脚本显示了如何获取最近1000根K线柱上的指标iFractals的值以及如何显示图表上的最近的10个上下分形箭头。对于缺少数据并且通常使用以下样式绘制的所有指标都可以使用类似的技术: • DRAW_SECTION, • DRAW_ARROW, • DRAW_ZIGZAG, • DRAW_COLOR_SECTION, • DRAW_COLOR_ARROW, • DRAW_COLOR_ZIGZAG.

相关参考 结构和类 , 时间到字符串 , 字符串格式

# 16.11 CopyTime

将指定交易品种、周期和数量的 开盘时间 数据获取到time_array数组中。复制数据的元素顺序是从现在到过去,即,从当前位置开始,0表示当前的K线柱。

CopyTime

当复制的元素数量未知时,建议使用动态数组作为目标数组,因为如果请求的数据数量小于(或大于)目标数组的长度,函数将尝试重新分配内存,以便完全适应数据请求的要求。

如果您知道需要复制的数据量,最好对静态分配的缓冲区执行操作,以防止分配过多的内存。

无论目标数组的属性是什么,即标帜 - as_series = true或as_series = false。数据都将被复制,因为便最旧的元素将位于为数组分配的物理内存的开始位置。此函数有3种变体。

  1. 按开始位置和所需元素的数量调用
int  CopyTime( 
   string           symbol_name,     // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,       // 周期 
   int              start_pos,       // 开始复制元素的索引位置 
   int              count,           // 复制的数据元素数量 
   datetime         time_array[]     // 复制开盘时间的目标数组 
   );
1
2
3
4
5
6
7
  1. 按开始日期和所需元素的数量调用
int  CopyTime( 
   string           symbol_name,     // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,       // 周期 
   datetime         start_time,      // 启动日期和时间 
   int              count,           // 复制的数据计算 
   datetime         time_array[]     // 复制开仓时间的目标数组   
   );
1
2
3
4
5
6
7
  1. 按所需时间间隔的开始和结束日期进行调用
int  CopyTime( 
   string           symbol_name,     // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,       // 周期 
   datetime         start_time,      // 启动日期和时间 
   datetime         stop_time,       // 结束日期和时间 
   datetime         time_array[]     // 复制开仓时间的目标数组 
   );
1
2
3
4
5
6
7

参数 symbol_name

[in] 交易品种名称。

timeframe

[in] 时间周期(框架)。

start_pos

[in] 开始复制元素的索引位置。

count

[in] 复制的元素数量。

start_time

[in] K线柱的时间,对应要复制的第一个元素。

stop_time

[in] K线柱的时间,对应要复制的最后一个元素。

time_array[]

[out] 日期时间 类型的数组

返回值 返回复制数据的数量 或 发生错误时返回 -1。

注意 如果请求数据的整个时间间隔超出服务器上的可用数据,则函数返回 -1。如果在TERMINAL_MAXBARS(图表中最多柱数”最大图表数据量”(MT5))之外请求数据,函数也将返回 -1。

当从指标请求数据时,如果所请求的 时间序列 尚未构建,或者需要从服务器上下载,该函数将立即返回 -1,但随后,将启动 下载/构建 过程。

从EA交易程序 或 脚本请求数据时,如果终端在本地没有这些数据,则将启动从服务器下载数据,或者如果数据可以从本地历史数据构建,但所需的 时间序列 仍未准备好。该函数将返回在 超时 到期之前准备就绪的数据量。但是历史下载会继续,在下一个类似要求函数中会返回更多数据。

当用 2. 按开始日期和所需元素的数量调用 时,只返回日期小于(更早) 或 等于指定日期的数据。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

当用 3. 按所需时间间隔的开始和结束日期进行调用 时,将只返回来自此间隔内的数据。间隔被设置并且最小单位为秒。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

因此,如果当前日期是星期六,那么在尝试复制指定时间间隔为 start_time = Last_Tuesday和stop_time=Last_Friday的周(W1)时间框架上的数据时,函数将返回0,因为周(W1)时间框架上的开盘时间总是周日,但一根星期的K线柱不属于指定的时间间隔内的数据。

如果需要返回与当前未完成的(正在跳动的)K线柱对应的值,可以使用第一种调用形式指定start_pos = 0和count = 1。

请参阅对象绑定方法一节中有关历史请求数据的详细示例。该部分提供的脚本显示了如何获取最近1000根K线柱上的指标iFractals的值以及如何显示图表上的最近的10个上下分形箭头。对于缺少数据并且通常使用以下样式绘制的所有指标都可以使用类似的技术:

• DRAW_SECTION, • DRAW_ARROW, • DRAW_ZIGZAG, • DRAW_COLOR_SECTION, • DRAW_COLOR_ARROW, • DRAW_COLOR_ZIGZAG.

# 16.12 CopyOpen

将指定交易品种、周期和数量的 开盘价格 数据获取到open_array数组中。复制数据的元素顺序是从现在到过去,即,从当前位置开始,0表示当前的K线柱。

CopyOpen

当复制的元素数量未知时,建议使用动态数组作为目标数组,因为如果请求的数据数量小于(或大于)目标数组的长度,函数将尝试重新分配内存,以便完全适应数据请求的要求。

如果您知道需要复制的数据量,最好对静态分配的缓冲区执行操作,以防止分配过多的内存。

无论目标数组的属性是什么,即标帜 - as_series = true或as_series = false。数据都将被复制,因为便最旧的元素将位于为数组分配的物理内存的开始位置。此函数有3种变体。

  1. 按开始位置和所需元素的数量调用
int  CopyOpen( 
   string           symbol_name,     // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,       // 周期 
   int              start_pos,       // 启动位置 
   int              count,           // 复制的数据计算 
   double           open_array[]     // 复制开仓时间的目标数组 
   );
1
2
3
4
5
6
7
  1. 按开始日期和所需元素的数量调用
int  CopyOpen( 
   string           symbol_name,     // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,       // 周期 
   datetime         start_time,      // 启动日期和时间 
   int              count,           // 复制的数据计算 
   double           open_array[]     // 用于开盘柱的目标数组 
   );
1
2
3
4
5
6
7
  1. 按所需时间间隔的开始和结束日期进行调用
int  CopyOpen( 
   string           symbol_name,     // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,       // 周期 
   datetime         start_time,      // 启动日期和时间 
   datetime         stop_time,       // 结束日期和时间 
   double           open_array[]     // 用于开盘柱的目标数组 
   );
1
2
3
4
5
6
7

参数 symbol_name

[in] 交易品种名称。

timeframe

[in] 时间周期(框架)。

start_pos

[in] 开始复制元素的索引位置。

count

[in] 复制的元素数量。

start_time

[in] K线柱的时间,对应要复制的第一个元素。

stop_time

[in] K线柱的时间,对应要复制的最后一个元素。

open_array[]

[out] 双精度 类型数组

返回值 返回复制数据的数量 或 发生错误时返回 -1。

注意 如果请求数据的整个时间间隔超出服务器上的可用数据,则函数返回 -1。如果在TERMINAL_MAXBARS(图表中最多柱数”最大图表数据量”(MT5))之外请求数据,函数也将返回 -1。

当从指标请求数据时,如果所请求的 时间序列 尚未构建,或者需要从服务器上下载,该函数将立即返回 -1,但随后,将启动 下载/构建 过程。

从EA交易程序 或 脚本请求数据时,如果终端在本地没有这些数据,则将启动从服务器下载数据,或者如果数据可以从本地历史数据构建,但所需的 时间序列 仍未准备好。该函数将返回在 超时 到期之前准备就绪的数据量。但是历史下载会继续,在下一个类似要求函数中会返回更多数据。

当用 2. 按开始日期和所需元素的数量调用 时,只返回日期小于(更早) 或 等于指定日期的数据。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

当用 3. 按所需时间间隔的开始和结束日期进行调用 时,将只返回来自此间隔内的数据。间隔被设置并且最小单位为秒。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

因此,如果当前日期是星期六,那么在尝试复制指定时间间隔为 start_time = Last_Tuesday和stop_time=Last_Friday的周(W1)时间框架上的数据时,函数将返回0,因为周(W1)时间框架上的开盘时间总是周日,但一根星期的K线柱不属于指定的时间间隔内的数据。

如果需要返回与当前未完成的(正在跳动的)K线柱对应的值,可以使用第一种调用形式指定start_pos = 0和count = 1。

请参阅对象绑定方法一节中有关历史请求数据的详细示例。该部分提供的脚本显示了如何获取最近1000根K线柱上的指标iFractals的值以及如何显示图表上的最近的10个上下分形箭头。对于缺少数据并且通常使用以下样式绘制的所有指标都可以使用类似的技术:

• DRAW_SECTION,
• DRAW_ARROW,
• DRAW_ZIGZAG,
• DRAW_COLOR_SECTION,
• DRAW_COLOR_ARROW,
• DRAW_COLOR_ZIGZAG.

# 16.13 CopyHigh

将指定交易品种、周期和数量的 最高价 数据获取到high_array数组中。复制数据的元素顺序是从现在到过去,即,从当前位置开始,0表示当前的K线柱。

当复制的元素数量未知时,建议使用动态数组作为目标数组,因为如果请求的数据数量小于(或大于)目标数组的长度,函数将尝试重新分配内存,以便完全适应数据请求的要求。

如果您知道需要复制的数据量,最好对静态分配的缓冲区执行操作,以防止分配过多的内存。

无论目标数组的属性是什么,即标帜 - as_series = true或as_series = false。数据都将被复制,因为便最旧的元素将位于为数组分配的物理内存的开始位置。此函数有3种变体。

  1. 按开始位置和所需元素的数量调用
int  CopyHigh( 
   string           symbol_name,      // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,        // 周期 
   int              start_pos,        // 启动位置 
   int              count,            // 复制的数据计算 
   double           high_array[]      // 复制的目标数组 
   );
1
2
3
4
5
6
7
  1. 按开始日期和所需元素的数量调用
int  CopyHigh( 
   string           symbol_name,      // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,        // 周期 
   datetime         start_time,       // 启动日期和时间 
   int              count,            // 复制的数据计算 
   double           high_array[]      // 复制的目标数组 
   );
1
2
3
4
5
6
7
  1. 按所需时间间隔的开始和结束日期进行调用
int  CopyHigh( 
   string           symbol_name,      // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,        // 周期 
   datetime         start_time,       // 启动日期和时间 
   datetime         stop_time,        // 结束日期和时间 
   double           high_array[]      // 复制的目标数组 
   );
1
2
3
4
5
6
7

参数 symbol_name

[in] 交易品种名称。

timeframe

[in] 时间周期(框架)。

start_pos

[in] 开始复制元素的索引位置。

count

[in] 复制的元素数量。

start_time

[in] K线柱的时间,对应要复制的第一个元素。

stop_time

[in] K线柱的时间,对应要复制的最后一个元素。

open_array[]

[out] 双精度 类型数组

返回值 返回复制数据的数量 或 发生错误时返回 -1。

注意 如果请求数据的整个时间间隔超出服务器上的可用数据,则函数返回 -1。如果在TERMINAL_MAXBARS(图表中最多柱数”最大图表数据量”(MT5))之外请求数据,函数也将返回 -1。

当从指标请求数据时,如果所请求的 时间序列 尚未构建,或者需要从服务器上下载,该函数将立即返回 -1,但随后,将启动 下载/构建 过程。

从EA交易程序 或 脚本请求数据时,如果终端在本地没有这些数据,则将启动从服务器下载数据,或者如果数据可以从本地历史数据构建,但所需的 时间序列 仍未准备好。该函数将返回在 超时 到期之前准备就绪的数据量。但是历史下载会继续,在下一个类似要求函数中会返回更多数据。

当用 2. 按开始日期和所需元素的数量调用 时,只返回日期小于(更早) 或 等于指定日期的数据。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

当用 3. 按所需时间间隔的开始和结束日期进行调用 时,将只返回来自此间隔内的数据。间隔被设置并且最小单位为秒。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

因此,如果当前日期是星期六,那么在尝试复制指定时间间隔为 start_time = Last_Tuesday和stop_time=Last_Friday的周(W1)时间框架上的数据时,函数将返回0,因为周(W1)时间框架上的开盘时间总是周日,但一根星期的K线柱不属于指定的时间间隔内的数据。

如果需要返回与当前未完成的(正在跳动的)K线柱对应的值,可以使用第一种调用形式指定start_pos = 0和count = 1。

示例:

#property copyright "2009, MetaQuotes Software Corp." 
#property link      "https://www.mql5.com" 
#property version   "1.00" 
  
#property description "An example for output of the High[i] and Low[i]" 
#property description "for a random chosen bars" 
  
double High[],Low[]; 
//+------------------------------------------------------------------+ 
//| 为指定柱指数获得低价                                                | 
//+------------------------------------------------------------------+ 
double iLow(string symbol,ENUM_TIMEFRAMES timeframe,int index) 
  { 
   double low=0; 
   ArraySetAsSeries(Low,true); 
   int copied=CopyLow(symbol,timeframe,0,Bars(symbol,timeframe),Low); 
   if(copied > 0 && index<copied) low=Low[index]; 
   return(low); 
  } 
//+------------------------------------------------------------------+ 
//| 为指定柱指数获得高价                                                | 
//+------------------------------------------------------------------+ 
double iHigh(string symbol,ENUM_TIMEFRAMES timeframe,int index) 
  { 
   double high=0; 
   ArraySetAsSeries(High,true); 
   int copied=CopyHigh(symbol,timeframe,0,Bars(symbol,timeframe),High); 
   if(copied > 0 && index<copied) high=High[index]; 
   return(high); 
  } 
//+------------------------------------------------------------------+ 
//| 专家订单号函数                                                     | 
//+------------------------------------------------------------------+ 
void OnTick() 
  { 
//--- 每个订单号为带有指数的柱输出高低值, 
//--- 等同第二订单号 
   datetime t=TimeCurrent(); 
   int sec=t%60; 
   printf("High[%d] = %G  Low[%d] = %G", 
          sec,iHigh(Symbol(),0,sec), 
          sec,iLow(Symbol(),0,sec)); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

请参阅对象绑定方法一节中有关历史请求数据的详细示例。该部分提供的脚本显示了如何获取最近1000根K线柱上的指标iFractals的值以及如何显示图表上的最近的10个上下分形箭头。对于缺少数据并且通常使用以下样式绘制的所有指标都可以使用类似的技术: • DRAW_SECTION,
• DRAW_ARROW,
• DRAW_ZIGZAG,
• DRAW_COLOR_SECTION,
• DRAW_COLOR_ARROW,
• DRAW_COLOR_ZIGZAG.

# 16.14 CopyLow

将指定交易品种、周期和数量的 最低价 数据获取到low_array数组中。复制数据的元素顺序是从现在到过去,即,从当前位置开始,0表示当前的K线柱。

当复制的元素数量未知时,建议使用动态数组作为目标数组,因为如果请求的数据数量小于(或大于)目标数组的长度,函数将尝试重新分配内存,以便完全适应数据请求的要求。

如果您知道需要复制的数据量,最好对静态分配的缓冲区执行操作,以防止分配过多的内存。

无论目标数组的属性是什么,即标帜 - as_series = true或as_series = false。数据都将被复制,因为便最旧的元素将位于为数组分配的物理内存的开始位置。此函数有3种变体。

  1. 按开始位置和所需元素的数量调用
int  CopyLow( 
   string           symbol_name,     // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,       // 周期 
   int              start_pos,       // 启动位置 
   int              count,           // 复制的数据计算 
   double           low_array[]      // 复制的目标数组 
   );
1
2
3
4
5
6
7
  1. 按开始日期和所需元素的数量调用
int  CopyLow( 
   string           symbol_name,     // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,       // 周期 
   datetime         start_time,      // 启动日期和时间 
   int              count,           // 复制的数据计算 
   double           low_array[]      // 复制的目标数组 
   );
1
2
3
4
5
6
7
  1. 按所需时间间隔的开始和结束日期进行调用
int  CopyLow( 
   string           symbol_name,     // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,       // 周期 
   datetime         start_time,      // 启动日期和时间 
   datetime         stop_time,       // 结束日期和时间 
   double           low_array[]      // 复制的目标数组 
   );
1
2
3
4
5
6
7

参数 symbol_name

[in] 交易品种名称。

timeframe

[in] 时间周期(框架)。

start_pos

[in] 开始复制元素的索引位置。

count

[in] 复制的元素数量。

start_time

[in] K线柱的时间,对应要复制的第一个元素。

stop_time

[in] K线柱的时间,对应要复制的最后一个元素。

open_array[]

[out] 双精度 类型数组

返回值 返回复制数据的数量 或 发生错误时返回 -1。

注意 如果请求数据的整个时间间隔超出服务器上的可用数据,则函数返回 -1。如果在TERMINAL_MAXBARS(图表中最多柱数”最大图表数据量”(MT5))之外请求数据,函数也将返回 -1。

当从指标请求数据时,如果所请求的 时间序列 尚未构建,或者需要从服务器上下载,该函数将立即返回 -1,但随后,将启动 下载/构建 过程。

从EA交易程序 或 脚本请求数据时,如果终端在本地没有这些数据,则将启动从服务器下载数据,或者如果数据可以从本地历史数据构建,但所需的 时间序列 仍未准备好。该函数将返回在 超时 到期之前准备就绪的数据量。但是历史下载会继续,在下一个类似要求函数中会返回更多数据。

当用 2. 按开始日期和所需元素的数量调用 时,只返回日期小于(更早) 或 等于指定日期的数据。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

当用 3. 按所需时间间隔的开始和结束日期进行调用 时,将只返回来自此间隔内的数据。间隔被设置并且最小单位为秒。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

因此,如果当前日期是星期六,那么在尝试复制指定时间间隔为 start_time = Last_Tuesday和stop_time=Last_Friday的周(W1)时间框架上的数据时,函数将返回0,因为周(W1)时间框架上的开盘时间总是周日,但一根星期的K线柱不属于指定的时间间隔内的数据。

如果需要返回与当前未完成的(正在跳动的)K线柱对应的值,可以使用第一种调用形式指定start_pos = 0和count = 1。

请参阅对象绑定方法一节中有关历史请求数据的详细示例。该部分提供的脚本显示了如何获取最近1000根K线柱上的指标iFractals的值以及如何显示图表上的最近的10个上下分形箭头。对于缺少数据并且通常使用以下样式绘制的所有指标都可以使用类似的技术: • DRAW_SECTION,
• DRAW_ARROW,
• DRAW_ZIGZAG,
• DRAW_COLOR_SECTION,
• DRAW_COLOR_ARROW,
• DRAW_COLOR_ZIGZAG.

相关参考 复制最高价(CopyHigh)

# 16.15 CopyClose

将指定交易品种、周期和数量的 收盘价格 数据获取到close_array数组中。复制数据的元素顺序是从现在到过去,即,从当前位置开始,0表示当前的K线柱。

当复制的元素数量未知时,建议使用动态数组作为目标数组,因为如果请求的数据数量小于(或大于)目标数组的长度,函数将尝试重新分配内存,以便完全适应数据请求的要求。

如果您知道需要复制的数据量,最好对静态分配的缓冲区执行操作,以防止分配过多的内存。

无论目标数组的属性是什么,即标帜 - as_series = true或as_series = false。数据都将被复制,因为便最旧的元素将位于为数组分配的物理内存的开始位置。此函数有3种变体。

  1. 按开始位置和所需元素的数量调用
int  CopyClose( 
   string           symbol_name,       // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,         // 周期 
   int              start_pos,         // 启动位置 
   int              count,             // 复制的数据计算 
   double           close_array[]      // 复制的目标数组 
   );
1
2
3
4
5
6
7
  1. 按开始日期和所需元素的数量调用
int  CopyClose( 
   string           symbol_name,       // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,         // 周期 
   datetime         start_time,        // 启动日期和时间 
   int              count,             // 复制的数据计算 
   double           close_array[]      // 复制的目标数组 
   );
1
2
3
4
5
6
7
  1. 按所需时间间隔的开始和结束日期进行调用
int  CopyClose( 
   string           symbol_name,       // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,         // 周期 
   datetime         start_time,        // 启动日期和时间 
   datetime         stop_time,         // 结束日期和时间 
   double           close_array[]      // 复制的目标数组 
   );
1
2
3
4
5
6
7

参数 symbol_name

[in] 交易品种名称。

timeframe

[in] 时间周期(框架)。

start_pos

[in] 开始复制元素的索引位置。

count

[in] 复制的元素数量。

start_time

[in] K线柱的时间,对应要复制的第一个元素。

stop_time

[in] K线柱的时间,对应要复制的最后一个元素。

open_array[]

[out] 双精度 类型数组

返回值 返回复制数据的数量 或 发生错误时返回 -1。

注意 如果请求数据的整个时间间隔超出服务器上的可用数据,则函数返回 -1。如果在TERMINAL_MAXBARS(图表中最多柱数”最大图表数据量”(MT5))之外请求数据,函数也将返回 -1。

当从指标请求数据时,如果所请求的 时间序列 尚未构建,或者需要从服务器上下载,该函数将立即返回 -1,但随后,将启动 下载/构建 过程。

从EA交易程序 或 脚本请求数据时,如果终端在本地没有这些数据,则将启动从服务器下载数据,或者如果数据可以从本地历史数据构建,但所需的 时间序列 仍未准备好。该函数将返回在 超时 到期之前准备就绪的数据量。但是历史下载会继续,在下一个类似要求函数中会返回更多数据。

当用 2. 按开始日期和所需元素的数量调用 时,只返回日期小于(更早) 或 等于指定日期的数据。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

当用 3. 按所需时间间隔的开始和结束日期进行调用 时,将只返回来自此间隔内的数据。间隔被设置并且最小单位为秒。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

因此,如果当前日期是星期六,那么在尝试复制指定时间间隔为 start_time = Last_Tuesday和stop_time=Last_Friday的周(W1)时间框架上的数据时,函数将返回0,因为周(W1)时间框架上的开盘时间总是周日,但一根星期的K线柱不属于指定的时间间隔内的数据。

如果需要返回与当前未完成的(正在跳动的)K线柱对应的值,可以使用第一种调用形式指定start_pos = 0和count = 1。

请参阅对象绑定方法一节中有关历史请求数据的详细示例。该部分提供的脚本显示了如何获取最近1000根K线柱上的指标iFractals的值以及如何显示图表上的最近的10个上下分形箭头。对于缺少数据并且通常使用以下样式绘制的所有指标都可以使用类似的技术: • DRAW_SECTION,
• DRAW_ARROW,
• DRAW_ZIGZAG,
• DRAW_COLOR_SECTION,
• DRAW_COLOR_ARROW,
• DRAW_COLOR_ZIGZAG.

# 16.16 CopyTickVolume

将指定交易品种、周期和数量的 报价数据 数据获取到volume_array数组中。复制数据的元素顺序是从现在到过去,即,从当前位置开始,0表示当前的K线柱。

当复制的元素数量未知时,建议使用动态数组作为目标数组,因为如果请求的数据数量小于(或大于)目标数组的长度,函数将尝试重新分配内存,以便完全适应数据请求的要求。

如果您知道需要复制的数据量,最好对静态分配的缓冲区执行操作,以防止分配过多的内存。

无论目标数组的属性是什么,即标帜 - as_series = true或as_series = false。数据都将被复制,因为便最旧的元素将位于为数组分配的物理内存的开始位置。此函数有3种变体。

  1. 按开始位置和所需元素的数量调用
int  CopyTickVolume( 
   string           symbol_name,      // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,        // 周期 
   int              start_pos,        // 启动位置 
   int              count,            // 复制的数据计算 
   long             volume_array[]    // 订单号交易量的目标数组 
   );
1
2
3
4
5
6
7
  1. 按开始日期和所需元素的数量调用
int  CopyTickVolume( 
   string           symbol_name,      // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,        // 周期 
   datetime         start_time,       // 启动日期和时间 
   int              count,            // 复制的数据计算 
   long             volume_array[]    // 订单号交易量的目标数组 
   );
1
2
3
4
5
6
7
  1. 按所需时间间隔的开始和结束日期进行调用
int  CopyTickVolume( 
   string           symbol_name,      // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,        // 周期 
   datetime         start_time,       // 开始日期和时间 
   datetime         stop_time,        // 结束日期和时间 
   long             volume_array[]    // 订单号交易量的目标数组 
   );
1
2
3
4
5
6
7

参数

symbol_name

[in] 交易品种名称。

timeframe

[in] 时间周期(框架)。

start_pos

[in] 开始复制元素的索引位置。

count

[in] 复制的元素数量。

start_time

[in] K线柱的时间,对应要复制的第一个元素。

stop_time

[in] K线柱的时间,对应要复制的最后一个元素。

open_array[]

[out] 长整型数组

返回值 返回复制数据的数量 或 发生错误时返回 -1。

注意

如果请求数据的整个时间间隔超出服务器上的可用数据,则函数返回 -1。如果在TERMINAL_MAXBARS(图表中最多柱数”最大图表数据量”(MT5))之外请求数据,函数也将返回 -1。

当从指标请求数据时,如果所请求的 时间序列 尚未构建,或者需要从服务器上下载,该函数将立即返回 -1,但随后,将启动 下载/构建 过程。

从EA交易程序 或 脚本请求数据时,如果终端在本地没有这些数据,则将启动从服务器下载数据,或者如果数据可以从本地历史数据构建,但所需的 时间序列 仍未准备好。该函数将返回在 超时 到期之前准备就绪的数据量。但是历史下载会继续,在下一个类似要求函数中会返回更多数据。

当用 2. 按开始日期和所需元素的数量调用 时,只返回日期小于(更早) 或 等于指定日期的数据。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

当用 3. 按所需时间间隔的开始和结束日期进行调用 时,将只返回来自此间隔内的数据。间隔被设置并且最小单位为秒。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

因此,如果当前日期是星期六,那么在尝试复制指定时间间隔为 start_time = Last_Tuesday和stop_time=Last_Friday的周(W1)时间框架上的数据时,函数将返回0,因为周(W1)时间框架上的开盘时间总是周日,但一根星期的K线柱不属于指定的时间间隔内的数据。

如果需要返回与当前未完成的(正在跳动的)K线柱对应的值,可以使用第一种调用形式指定start_pos = 0和count = 1。 示例:

#property indicator_separate_window 
#property indicator_buffers 1 
#property indicator_plots   1 
//---- 订单号交易量图 
#property indicator_label1  "TickVolume" 
#property indicator_type1   DRAW_HISTOGRAM 
#property indicator_color1  C'143,188,139' 
#property indicator_style1  STYLE_SOLID 
#property indicator_width1  1 
//--- 输入参量 
input int      bars=3000; 
//--- 指标缓冲区 
double         TickVolumeBuffer[]; 
//+------------------------------------------------------------------+ 
//| 自定义指标初始化函数                                                | 
//+------------------------------------------------------------------+ 
void OnInit() 
  { 
//--- 指标缓冲区绘图 
   SetIndexBuffer(0,TickVolumeBuffer,INDICATOR_DATA); 
   IndicatorSetInteger(INDICATOR_DIGITS,0); 
//--- 
  } 
//+------------------------------------------------------------------+ 
//| 自定义指标重复函数                                                  | 
//+------------------------------------------------------------------+ 
int OnCalculate(const int rates_total, 
                 const int prev_calculated, 
                 const datetime &time[], 
                 const double &open[], 
                 const double &high[], 
                 const double &low[], 
                 const double &close[], 
                 const long &tick_volume[], 
                 const long &volume[], 
                 const int &spread[]) 
  { 
//--- 
   if(prev_calculated==0) 
     { 
      long timeseries[]; 
      ArraySetAsSeries(timeseries,true); 
      int prices=CopyTickVolume(Symbol(),0,0,bars,timeseries); 
      for(int i=0;i<rates_total-prices;i++) TickVolumeBuffer[i]=0.0;  
      for(int i=0;i<prices;i++) TickVolumeBuffer[rates_total-1-i]=timeseries[prices-1-i];  
      Print("We have received the following number of TickVolume values: "+prices); 
     } 
   else 
     { 
      long timeseries[]; 
      int prices=CopyTickVolume(Symbol(),0,0,1,timeseries); 
      TickVolumeBuffer[rates_total-1]=timeseries[0];  
     }   
//--- 为下次调用返回prev_calculated值 
   return(rates_total); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

请参阅对象绑定方法一节中有关历史请求数据的详细示例。该部分提供的脚本显示了如何获取最近1000根K线柱上的指标iFractals的值以及如何显示图表上的最近的10个上下分形箭头。对于缺少数据并且通常使用以下样式绘制的所有指标都可以使用类似的技术: • DRAW_SECTION,
• DRAW_ARROW,
• DRAW_ZIGZAG,
• DRAW_COLOR_SECTION,
• DRAW_COLOR_ARROW,
• DRAW_COLOR_ZIGZAG.

# 16.17 CopyRealVolumn

将指定交易品种、周期和数量的 实际成交量 数据获取到 volume_array 数组中。复制数据的元素顺序是从现在到过去,即,从当前位置开始,0表示当前的K线柱。

当复制的元素数量未知时,建议使用动态数组作为目标数组,因为如果请求的数据数量小于(或大于)目标数组的长度,函数将尝试重新分配内存,以便完全适应数据请求的要求。

如果您知道需要复制的数据量,最好对静态分配的缓冲区执行操作,以防止分配过多的内存。

无论目标数组的属性是什么,即标帜 - as_series = true或as_series = false。数据都将被复制,因为便最旧的元素将位于为数组分配的物理内存的开始位置。此函数有3种变体。

  1. 按开始位置和所需元素的数量调用
int  CopyRealVolume( 
   string           symbol_name,      // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,        // 周期 
   int              start_pos,        // 启动位置 
   int              count,            // 复制的数据计算 
   long             volume_array[]    // 交易量值的目标数组 
   );
1
2
3
4
5
6
7
  1. 按开始日期和所需元素的数量调用
int  CopyRealVolume( 
   string           symbol_name,      // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,        // 周期 
   datetime         start_time,       // 启动日期和时间 
   int              count,            // 复制的数据计算 
   long             volume_array[]    // 交易量值的目标数组 
   );
1
2
3
4
5
6
7
  1. 按所需时间间隔的开始和结束日期进行调用
int  CopyRealVolume( 
   string           symbol_name,      // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,        // 周期 
   datetime         start_time,       // 启动日期和时间 
   datetime         stop_time,        // 结束日期和时间 
   long             volume_array[]    // 交易量值的目标数组 
   );
1
2
3
4
5
6
7

参数 symbol_name

[in] 交易品种名称。

timeframe

[in] 时间周期(框架)。

start_pos

[in] 开始复制元素的索引位置。

count

[in] 复制的元素数量。

start_time

[in] K线柱的时间,对应要复制的第一个元素。

stop_time

[in] K线柱的时间,对应要复制的最后一个元素。

open_array[]

[out] 长整型数组

返回值 返回复制数据的数量 或 发生错误时返回 -1。

注意 如果请求数据的整个时间间隔超出服务器上的可用数据,则函数返回 -1。如果在TERMINAL_MAXBARS(图表中最多柱数”最大图表数据量”(MT5))之外请求数据,函数也将返回 -1。

当从指标请求数据时,如果所请求的 时间序列 尚未构建,或者需要从服务器上下载,该函数将立即返回 -1,但随后,将启动 下载/构建 过程。

从EA交易程序 或 脚本请求数据时,如果终端在本地没有这些数据,则将启动从服务器下载数据,或者如果数据可以从本地历史数据构建,但所需的 时间序列 仍未准备好。该函数将返回在 超时 到期之前准备就绪的数据量。但是历史下载会继续,在下一个类似要求函数中会返回更多数据。

当用 2. 按开始日期和所需元素的数量调用 时,只返回日期小于(更早) 或 等于指定日期的数据。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

当用 3. 按所需时间间隔的开始和结束日期进行调用 时,将只返回来自此间隔内的数据。间隔被设置并且最小单位为秒。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

因此,如果当前日期是星期六,那么在尝试复制指定时间间隔为 start_time = Last_Tuesday和stop_time=Last_Friday的周(W1)时间框架上的数据时,函数将返回0,因为周(W1)时间框架上的开盘时间总是周日,但一根星期的K线柱不属于指定的时间间隔内的数据。

如果需要返回与当前未完成的(正在跳动的)K线柱对应的值,可以使用第一种调用形式指定start_pos = 0和count = 1。

请参阅对象绑定方法一节中有关历史请求数据的详细示例。该部分提供的脚本显示了如何获取最近1000根K线柱上的指标iFractals的值以及如何显示图表上的最近的10个上下分形箭头。对于缺少数据并且通常使用以下样式绘制的所有指标都可以使用类似的技术:

• DRAW_SECTION, • DRAW_ARROW, • DRAW_ZIGZAG, • DRAW_COLOR_SECTION, • DRAW_COLOR_ARROW, • DRAW_COLOR_ZIGZAG.

# 16.18 CopySpread

将指定交易品种、周期和数量的 点差 数据获取到spread_array数组中。复制数据的元素顺序是从现在到过去,即,从当前位置开始,0表示当前的K线柱。

当复制的元素数量未知时,建议使用动态数组作为目标数组,因为如果请求的数据数量小于(或大于)目标数组的长度,函数将尝试重新分配内存,以便完全适应数据请求的要求。

如果您知道需要复制的数据量,最好对静态分配的缓冲区执行操作,以防止分配过多的内存。

无论目标数组的属性是什么,即标帜 - as_series = true或as_series = false。数据都将被复制,因为便最旧的元素将位于为数组分配的物理内存的开始位置。此函数有3种变体。

  1. 按开始位置和所需元素的数量调用
int  CopySpread( 
   string           symbol_name,      // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,        // 周期 
   int              start_pos,        // 启动位置 
   int              count,            // 复制的数据计算 
   int              spread_array[]    // 点差值的目标数组 
   );
1
2
3
4
5
6
7
  1. 按开始日期和所需元素的数量调用
int  CopySpread( 
   string           symbol_name,      // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,        // 周期 
   datetime         start_time,       // 启动日期和时间 
   int              count,            // 复制的数据计算 
   int              spread_array[]    // 点差值的目标数组 
   );
1
2
3
4
5
6
7
  1. 按所需时间间隔的开始和结束日期进行调用
int  CopySpread( 
   string           symbol_name,      // 交易品种名称 
   ENUM_TIMEFRAMES  timeframe,        // 周期 
   datetime         start_time,       // 启动日期和时间 
   datetime         stop_time,        // 结束日期和时间 
   int              spread_array[]    // 点差值的目标数组 
   );
1
2
3
4
5
6
7

参数 symbol_name

[in] 交易品种名称。

timeframe

[in] 时间周期(框架)。

start_pos

[in] 开始复制元素的索引位置。

count

[in] 复制的元素数量。

start_time

[in] K线柱的时间,对应要复制的第一个元素。

stop_time

[in] K线柱的时间,对应要复制的最后一个元素。

open_array[]

[out] 整型数组

返回值 返回复制数据的数量 或 发生错误时返回 -1。

注意 如果请求数据的整个时间间隔超出服务器上的可用数据,则函数返回 -1。如果在TERMINAL_MAXBARS(图表中最多柱数”最大图表数据量”(MT5))之外请求数据,函数也将返回 -1。

当从指标请求数据时,如果所请求的 时间序列 尚未构建,或者需要从服务器上下载,该函数将立即返回 -1,但随后,将启动 下载/构建 过程。

从EA交易程序 或 脚本请求数据时,如果终端在本地没有这些数据,则将启动从服务器下载数据,或者如果数据可以从本地历史数据构建,但所需的 时间序列 仍未准备好。该函数将返回在 超时 到期之前准备就绪的数据量。但是历史下载会继续,在下一个类似要求函数中会返回更多数据。

当用 2. 按开始日期和所需元素的数量调用 时,只返回日期小于(更早) 或 等于指定日期的数据。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

当用 3. 按所需时间间隔的开始和结束日期进行调用 时,将只返回来自此间隔内的数据。间隔被设置并且最小单位为秒。这意味着,返回值的任何K线柱的打开时间(成交量、点差、指标缓冲区的值、开盘价、最高价、最低价、收盘价以及的开/收盘时间)总是 小于 或 等于 指定的时间。

因此,如果当前日期是星期六,那么在尝试复制指定时间间隔为 start_time = Last_Tuesday和stop_time=Last_Friday的周(W1)时间框架上的数据时,函数将返回0,因为周(W1)时间框架上的开盘时间总是周日,但一根星期的K线柱不属于指定的时间间隔内的数据。

如果需要返回与当前未完成的(正在跳动的)K线柱对应的值,可以使用第一种调用形式指定start_pos = 0和count = 1。

示例:

#property indicator_separate_window 
#property indicator_buffers 1 
#property indicator_plots   1 
//---- 点差图 
#property indicator_label1  "Spread" 
#property indicator_type1   DRAW_HISTOGRAM 
#property indicator_color1  clrRed 
#property indicator_style1  STYLE_SOLID 
#property indicator_width1  1 
//--- 输入参量 
input int      bars=3000; 
//--- 指标缓冲区 
double         SpreadBuffer[]; 
//+------------------------------------------------------------------+ 
//| 自定义指标初始化函数                                                | 
//+------------------------------------------------------------------+ 
void OnInit() 
  { 
//--- 指标缓冲区绘图 
   SetIndexBuffer(0,SpreadBuffer,INDICATOR_DATA); 
   IndicatorSetInteger(INDICATOR_DIGITS,0); 
//--- 
  } 
//+------------------------------------------------------------------+ 
//| 自定义指标重复函数                                                  | 
//+------------------------------------------------------------------+ 
int OnCalculate(const int rates_total, 
                 const int prev_calculated, 
                 const datetime &time[], 
                 const double &open[], 
                 const double &high[], 
                 const double &low[], 
                 const double &close[], 
                 const long &tick_volume[], 
                 const long &volume[], 
                 const int &spread[]) 
  { 
//--- 
   if(prev_calculated==0) 
     { 
      int spread_int[]; 
      ArraySetAsSeries(spread_int,true); 
      int spreads=CopySpread(Symbol(),0,0,bars,spread_int); 
      Print("We have received the following number of Spread values: ",spreads); 
      for (int i=0;i<spreads;i++)  
      { 
      SpreadBuffer[rates_total-1-i]=spread_int[i]; 
      if(i<=30) Print("spread["+i+"] = ",spread_int[i]); 
      } 
     } 
   else 
     { 
      double Ask,Bid; 
      Ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK); 
      Bid=SymbolInfoDouble(Symbol(),SYMBOL_BID); 
      Comment("Ask = ",Ask,"  Bid = ",Bid); 
      SpreadBuffer[rates_total-1]=(Ask-Bid)/Point(); 
     } 
//--- 为下次调用返回prev_calculated值 
   return(rates_total); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

请参阅对象绑定方法一节中有关历史请求数据的详细示例。该部分提供的脚本显示了如何获取最近1000根K线柱上的指标iFractals的值以及如何显示图表上的最近的10个上下分形箭头。对于缺少数据并且通常使用以下样式绘制的所有指标都可以使用类似的技术: • DRAW_SECTION,
• DRAW_ARROW,
• DRAW_ZIGZAG,
• DRAW_COLOR_SECTION,
• DRAW_COLOR_ARROW,
• DRAW_COLOR_ZIGZAG.

# 16.19 CopyTicks

该函数以 MqlTick 格式接收每次报价数据到ticks_array。 在这种情况下,每次报价从过去一直被索引到现在,也就是说,索引编号为0的报价数据是数组中最早的报价。对于报价分析,请检查flags 字段,该字段显示了每次报价中发生了什么变化。

int  CopyTicks( 
   string           symbol_name,           // 交易品种名称 
   MqlTick&         ticks_array[],         // 报价接收数组 
   uint             flags=COPY_TICKS_ALL,  // 决定接收报价类型的标记 
   ulong            from=0,                // 您想请求报价的日期 
   uint             count=0                // 您想接收报价的数量 
   );
1
2
3
4
5
6
7

参数

symbol_name

[in] 交易品种。

ticks_array

[out] 接收报价的MqlTick 类型的数组。

flags

[in] 用于定义所请求的报价类型的标志。 COPY_TICKS_INFO ---- Bid 和/或 Ask 价格发生变化的报价; COPY_TICKS_TRADE ---- 最新的报价和成交量变化的报价; COPY_TICKS_ALL ---- 所有报价。 对于任何类型的请求,前一个标记的值都被添加到MqlTick结构的其余字段中。

from

[in] 您想请求报价的开始日期。从1970.01.01开始以毫秒计算。如果from=0,将返回最近的count 报价。

count

[in] 请求报价的数量。如果没有指定'from' 和 'count' 参数,所有可用的现有报价(不超过2000)将被写入ticks_array[]。

返回值

返回复制数据的数量 或 发生错误时返回 -1。

注意

CopyTicks() 函数允许请求和分析所有接收的报价。第一次调用CopyTicks() 即开始同步硬盘上存储的交易品种的每次报价(tick)数据库。如果本地数据库没有提供所有请求的报价,那么缺失的报价将会自动从交易服务器下载。从CopyTicks()指定的 from 开始日期直到当前时刻的报价将会同步。在那之后,该交易品种接收到的所有报价都将被添加到报价(tick)数据库中,从而使其保持同步状态。

如果没有指定from 和 count 参数,所有可用的现有报价(不超过2000)将被写入ticks_array[]。flags 参数允许指定所需报价的类型。

COPY_TICKS_INFO —— 返回 Bid 和/或 Ask 发生变化的报价。其它字段的数据也将被添加。例如,如果只有卖价(Bid)改变,买价(Ask) 和 交易量(Volume) 字段将填入最近获得的值。若要找出实际变化的内容,请分析具有TICK_FLAG_BID和/或TICK_FLAG_ASK值的flags字段。如果报价中 Bid 和/或 Ask 有 零0值,那么标记会显示这些数据已经更改(flags=TICK_FLAG_BID|TICK_FLAG_ASK),这意味着订单簿 (市场深度) 为空。换句话说,没有买入(buy)和卖出(sell)订单。

COPY_TICKS_TRADE —— 返回最新的报价 和 交易量变化 的报价。其它字段的数据也将被添加,例如最近得到的 卖价(Bid) 和 买价(Ask) 将在适当字段指明。若要找出实际变化的内容,请分析具有TICK_FLAG_LAST 和 TICK_FLAG_VOLUME值的flags 字段。

COPY_TICKS_ALL —— 返回任何变化的所有报价。未改变的字段将会填入最近获得的值。

调用COPY_TICKS_ALL标记的CopyTicks() 立即返回请求间隔内的全部报价,而其它模式的调用则需要一定的时间来处理和选择报价,因此它们不提供显著的速度优势。

请求报价时 (包含 COPY_TICKS_INFO 和/或 COPY_TICKS_TRADE),每个报价都包括直至报价时间为止的完整的价格信息(卖价(Bid) , 买价(Ask),最新价 和 交易量)。该功能主要用于更轻松的分析每次报价时的交易状态,所以不需要请求深度历史报价和搜索其它字段的值。

在指标中,CopyTicks() 函数返回结果:从指标调用时,CopyTick()立即返回交易品种的所有可用报价,并且如果可用数据不足时,将启动同步报价(tick)数据库。一个交易品种的所有指标都在一个公共线程中运行,因此指标不会等候同步完成。同步之后,CopyTicks() 将在下一次调用期间返回所有的请求报价。在指标中,每次报价到达后都会调用一次OnCalculate() 函数。

在EA交易和脚本中,CopyTicks()可以等候45秒来等待处理的结果:不同于指标,每个EA交易和脚本都在独立的线程中运行,因此可以等待45秒,直到同步完成。如果所需的报价数在此期间同步失败,那么CopyTicks() 将通过timeout返回可用的报价并将继续同步。EA交易中的OnTick() 并不是每个报价处理程序,它仅通知EA交易有关市场中的变化。如果产生大量变化:程序端可以同时做出几个报价,但是OnTick() 将只能调用一次来通知EA最新市场状态。

数据返回速度: 对于每个 金融工具(交易品种),客户端可以快速访问存储在缓存中的4,096个最新的报价(具有运行市场深度的 交易品种 有65,536个报价)。如果当前交易会话的请求报价超出了缓存,Copytick()则会调用存储在客户端内存中的报价。这些请求需要更多的执行时间。最慢的请求就是那些其他日期的请求报价,因为在这种情况下从磁盘读取数据。

例:

#property copyright "Copyright 2016, MetaQuotes Software Corp." 
#property link      "https://www.mql5.com" 
#property version   "1.00" 
#property script_show_inputs 
//--- Requesting 100 million ticks to be sure we receive the entire tick history 
input int      getticks=100000000; // The number of required ticks 
//+------------------------------------------------------------------+ 
//| Script program start function                                    | 
//+------------------------------------------------------------------+ 
void OnStart() 
  { 
//---   
   int     attempts=0;     // Count of attempts 
   bool    success=false;  // The flag of a successful copying of ticks 
   MqlTick tick_array[];   // Tick receiving array 
   MqlTick lasttick;       // To receive last tick data 
   SymbolInfoTick(_Symbol,lasttick); 
//--- Make 3 attempts to receive ticks 
   while(attempts<3) 
     { 
      //--- Measuring start time before receiving the ticks 
      uint start=GetTickCount(); 
//--- Requesting the tick history since 1970.01.01 00:00.001 (parameter from=1 ms) 
      int received=CopyTicks(_Symbol,tick_array,COPY_TICKS_ALL,1,getticks); 
      if(received!=-1) 
        { 
         //--- Showing information about the number of ticks and spent time 
         PrintFormat("%s: received %d ticks in %d ms",_Symbol,received,GetTickCount()-start); 
         //--- If the tick history is synchronized, the error code is equal to zero 
         if(GetLastError()==0) 
           { 
            success=true; 
            break; 
           } 
         else 
            PrintFormat("%s: Ticks are not synchronized yet, %d ticks received for %d ms. Error=%d", 
            _Symbol,received,GetTickCount()-start,_LastError); 
        } 
      //--- Counting attempts 
      attempts++; 
      //--- A one-second pause to wait for the end of synchronization of the tick database 
      Sleep(1000); 
     } 
//--- Receiving the requested ticks from the beginning of the tick history failed in three attempts 
   if(!success) 
     { 
      PrintFormat("Error! Failed to receive %d ticks of %s in three attempts",getticks,_Symbol); 
      return; 
     } 
   int ticks=ArraySize(tick_array); 
//--- Showing the time of the first tick in the array 
   datetime firstticktime=tick_array[ticks-1].time; 
   PrintFormat("Last tick time = %s.%03I64u", 
               TimeToString(firstticktime,TIME_DATE|TIME_MINUTES|TIME_SECONDS),tick_array[ticks-1].time_msc%1000); 
//--- выведем время последнего тика в массиве 
   datetime lastticktime=tick_array[0].time; 
   PrintFormat("First tick time = %s.%03I64u", 
               TimeToString(lastticktime,TIME_DATE|TIME_MINUTES|TIME_SECONDS),tick_array[0].time_msc%1000); 
  
//---                                                            
   MqlDateTime today; 
   datetime current_time=TimeCurrent();                          
   TimeToStruct(current_time,today);                             
   PrintFormat("current_time=%s",TimeToString(current_time));    
   today.hour=0; 
   today.min=0; 
   today.sec=0; 
   datetime startday=StructToTime(today); 
   datetime endday=startday+24*60*60; 
   if((ticks=CopyTicksRange(_Symbol,tick_array,COPY_TICKS_ALL,startday*1000,endday*1000))==-1)  
     { 
      PrintFormat("CopyTicksRange(%s,tick_array,COPY_TICKS_ALL,%s,%s) failed, error %d",        
                  _Symbol,TimeToString(startday),TimeToString(endday),GetLastError());           
      return;                                                                                   
     } 
   ticks=MathMax(100,ticks); 
//--- Showing the first 100 ticks of the last day 
   int counter=0; 
   for(int i=0;i<ticks;i++) 
     { 
      datetime time=tick_array[i].time; 
      if((time>=startday) && (time<endday) && counter<100) 
        { 
         counter++; 
         PrintFormat("%d. %s",counter,GetTickDescription(tick_array[i])); 
        } 
     } 
//--- Showing the first 100 deals of the last day 
   counter=0; 
   for(int i=0;i<ticks;i++) 
     { 
      datetime time=tick_array[i].time; 
      if((time>=startday) && (time<endday) && counter<100) 
        { 
         if(((tick_array[i].flags & TICK_FLAG_BUY)==TICK_FLAG_BUY) || ((tick_array[i].flags & TICK_FLAG_SELL)==TICK_FLAG_SELL)) 
           { 
            counter++; 
            PrintFormat("%d. %s",counter,GetTickDescription(tick_array[i])); 
           } 
        } 
     } 
  } 
//+------------------------------------------------------------------+ 
//| Returns the string description of a tick                         | 
//+------------------------------------------------------------------+ 
string GetTickDescription(MqlTick &tick) 
  { 
   string desc=StringFormat("%s.%03d ", 
                            TimeToString(tick.time),tick.time_msc%1000); 
//--- Checking flags 
   bool buy_tick=((tick.flags&tick_FLAG_BUY)==TICK_FLAG_BUY); 
   bool sell_tick=((tick.flags&tick_FLAG_SELL)==TICK_FLAG_SELL); 
   bool ask_tick=((tick.flags&tick_FLAG_ASK)==TICK_FLAG_ASK); 
   bool bid_tick=((tick.flags&tick_FLAG_BID)==TICK_FLAG_BID); 
   bool last_tick=((tick.flags&tick_FLAG_LAST)==TICK_FLAG_LAST); 
   bool volume_tick=((tick.flags&tick_FLAG_VOLUME)==TICK_FLAG_VOLUME); 
//--- Checking trading flags in a tick first 
   if(buy_tick || sell_tick) 
     { 
      //--- Forming an output for the trading tick 
      desc=desc+(buy_tick?StringFormat("Buy Tick: Last=%G Volume=%d ",tick.last,tick.volume):""); 
      desc=desc+(sell_tick?StringFormat("Sell Tick: Last=%G Volume=%d ",tick.last,tick.volume):""); 
      desc=desc+(ask_tick?StringFormat("Ask=%G ",tick.ask):""); 
      desc=desc+(bid_tick?StringFormat("Bid=%G ",tick.ask):""); 
      desc=desc+"(Trade tick)"; 
     } 
   else 
     { 
      //--- Form a different output for an info tick 
      desc=desc+(ask_tick?StringFormat("Ask=%G ",tick.ask):""); 
      desc=desc+(bid_tick?StringFormat("Bid=%G ",tick.ask):""); 
      desc=desc+(last_tick?StringFormat("Last=%G ",tick.last):""); 
      desc=desc+(volume_tick?StringFormat("Volume=%d ",tick.volume):""); 
      desc=desc+"(Info tick)"; 
     } 
//--- Returning tick description 
   return desc; 
  } 
//+------------------------------------------------------------------+ 
/* Example of the output 
Si-12.16: received 11048387 ticks in 4937 ms 
Last tick time = 2016.09.26 18:32:59.775  
First tick time = 2015.06.18 09:45:01.000  
1.  2016.09.26 09:45.249 Ask=65370 Bid=65370 (Info tick) 
2.  2016.09.26 09:47.420 Ask=65370 Bid=65370 (Info tick) 
3.  2016.09.26 09:50.893 Ask=65370 Bid=65370 (Info tick) 
4.  2016.09.26 09:51.827 Ask=65370 Bid=65370 (Info tick) 
5.  2016.09.26 09:53.810 Ask=65370 Bid=65370 (Info tick) 
6.  2016.09.26 09:54.491 Ask=65370 Bid=65370 (Info tick) 
7.  2016.09.26 09:55.913 Ask=65370 Bid=65370 (Info tick) 
8.  2016.09.26 09:59.350 Ask=65370 Bid=65370 (Info tick) 
9.  2016.09.26 09:59.678 Bid=65370 (Info tick) 
10. 2016.09.26 10:00.000 Sell Tick: Last=65367 Volume=3 (Trade tick) 
11. 2016.09.26 10:00.000 Sell Tick: Last=65335 Volume=45 (Trade tick) 
12. 2016.09.26 10:00.000 Sell Tick: Last=65334 Volume=95 (Trade tick) 
13. 2016.09.26 10:00.191 Sell Tick: Last=65319 Volume=1 (Trade tick) 
14. 2016.09.26 10:00.191 Sell Tick: Last=65317 Volume=1 (Trade tick) 
15. 2016.09.26 10:00.191 Sell Tick: Last=65316 Volume=1 (Trade tick) 
16. 2016.09.26 10:00.191 Sell Tick: Last=65316 Volume=10 (Trade tick) 
17. 2016.09.26 10:00.191 Sell Tick: Last=65315 Volume=5 (Trade tick) 
18. 2016.09.26 10:00.191 Sell Tick: Last=65313 Volume=3 (Trade tick) 
19. 2016.09.26 10:00.191 Sell Tick: Last=65307 Volume=25 (Trade tick) 
20. 2016.09.26 10:00.191 Sell Tick: Last=65304 Volume=1 (Trade tick) 
21. 2016.09.26 10:00.191 Sell Tick: Last=65301 Volume=1 (Trade tick) 
22. 2016.09.26 10:00.191 Sell Tick: Last=65301 Volume=10 (Trade tick) 
23. 2016.09.26 10:00.191 Sell Tick: Last=65300 Volume=5 (Trade tick) 
24. 2016.09.26 10:00.191 Sell Tick: Last=65300 Volume=1 (Trade tick) 
25. 2016.09.26 10:00.191 Sell Tick: Last=65300 Volume=6 (Trade tick) 
26. 2016.09.26 10:00.191 Sell Tick: Last=65299 Volume=1 (Trade tick) 
27. 2016.09.26 10:00.191 Bid=65370 (Info tick) 
28. 2016.09.26 10:00.232 Ask=65297 (Info tick) 
29. 2016.09.26 10:00.276 Sell Tick: Last=65291 Volume=31 (Trade tick) 
30. 2016.09.26 10:00.276 Sell Tick: Last=65290 Volume=1 (Trade tick) 
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

相关参考 SymbolInfoTick,当前价格的结构,OnTick()

# 16.20 CopyTicksRange

该函数可以在指定日期范围内以MqlTick格式接收报价到ticks_array数组。在这种情况下,每次报价从过去一直被索引到现在,也就是说,索引编号为0的报价数据是数组中最早的报价。对于报价分析,请检查flags 字段,该字段显示了每次报价中发生了什么变化。

int  CopyTicksRange( 
   const string     symbol_name,           //交易品种名称 
   MqlTick&         ticks_array[],         // 报价接收数组 
   uint             flags=COPY_TICKS_ALL,  // 定义接收报价类型的标记 
   ulong            from_msc=0,            // 请求报价开始的日期 
   ulong            to_msc=0               // 请求报价截至日期 
   );
1
2
3
4
5
6
7

参数 symbol_name

[in] 交易品种。

ticks_array

[out] MqlTick 接收报价的静态或动态数组。如果静态数组不能保存来自请求间隔内的全部报价,则会尽可能多的接收报价量。在这种情况下,该函数生成ERR_HISTORY_SMALL_BUFFER (4407)错误。

flags

[in] 用于定义所请求的报价类型的标志。 COPY_TICKS_INFO ---- Bid 和/或 Ask 价格发生变化的报价; COPY_TICKS_TRADE ---- 最新的报价和成交量变化的报价; COPY_TICKS_ALL ---- 所有报价。 对于任何类型的请求,前一个标记的值都被添加到MqlTick结构的其余字段中。

from_msc

[in] 您想请求报价的开始日期。从1970.01.01开始以毫秒计算。如果没有指定from_msc 参数,则从历史记录中最初的报价开始。报价时间 >= from_msc 已发送。

to_msc

[in] 您想请求报价的结束日期。从1970.01.01开始,以毫秒计算。报价时间 <= to_msc 已发送。如果没有指定to_msc 参数,则发送截至到历史记录结束的报价。

返回值 成功复制的报价数量 或 错误时返回 -1。GetLastError()可能返回以下错误: • ERR_HISTORY_TIMEOUT —— 报价同步等待时间到达上限,函数已发送具有的全部报价。 • ERR_HISTORY_SMALL_BUFFER —— 静态缓冲区过小。只有数组可存储的数量已经发送。 • ERR_NOT_ENOUGH_MEMORY —— 接收指定范围的历史记录到动态报价数组的内存不足。无法为报价数组分配足够的内存。

注意 CopyTicksRange()函数用于严格的从一个指定范围请求报价,例如,从历史的某一天。与此同时,CopyTicks()还可以仅指定开始日期,例如 —— 接收月初至当前时间的全部报价。

相关参考 SymbolInfoTick,当前价格结构,OnTick,CopyTicks

# 16.21 iBars

返回可用于历史记录的相应交易品种和周期的柱形图的数量。

int  iBars( 
   const string           symbol,          // 交易品种 
   ENUM_TIMEFRAMES        timeframe        // 周期 
   );
1
2
3
4

参数

交易品种

[in] 金融工具的交易品种名称。NULL表示当前交易品种。

timeframe

[in] 周期。它可以是ENUM_TIMEFRAMES其中一个枚举值。0 表示当前图表周期。

返回值

可用于历史记录的对应交易品种和周期的柱形图的数量,最多不超过平台设置中“图表最大柱形图”可允许的参数。

例如:

Print("Bar count on the 'EURUSD,H1' is ",iBars("EURUSD",PERIOD_H1));
1

另见 Bars

# 16.22 iBarShift

根据时间搜索柱形图。这个函数返回与指定时间对应的柱形图指数。

int  iBarShift( 
   const string        symbol,          // 交易品种 
   ENUM_TIMEFRAMES     timeframe,       // 周期 
   datetime            time,            // 时间 
   bool                exact=false      // 模式 
   );
1
2
3
4
5
6

参数 交易品种

[in] 金融工具的交易品种名称。NULL表示当前交易品种。

timeframe

[in] 周期。它可以是ENUM_TIMEFRAMES其中一个枚举值。PERIOD_CURRENT 表示当前图表周期。

时间 [in] 要搜索的时间值。

exact=false

[in] 返回值,如果指定时间的柱形图没有找到。如果exact=false,iBarShift返回最近柱形图的指数,其开仓时间小于指定时间(time_open<time)。如果这个柱形图没有找到(没有指定时间之前的历史记录),那么该函数返回 -1。如果exact=true,iBarShift不会搜索最近的柱形图而是立即返回 -1。

返回值 与指定时间对应的柱形图指数。如果与指定时间对应的柱形图没有找到(历史记录中有一个空白),那么函数返回 -1或最近柱形图的指数(取决于'exact'参数)。

例如:

//+------------------------------------------------------------------+ 
//| 脚本程序起始函数                                                   | 
//+------------------------------------------------------------------+ 
void OnStart() 
  { 
//--- 日期为星期日 
   datetime time=D'2002.04.25 12:00'; 
   string symbol="GBPUSD"; 
   ENUM_TIMEFRAMES tf=PERIOD_H1; 
   bool exact=false; 
//--- 如果在指定时间没有柱形图,那么iBarShift将返回最近柱形图的指数。 
   int bar_index=iBarShift(symbol,tf,time,exact); 
//--- 调用iBarShift()之后,检查错误代码 
   int error=GetLastError(); 
   if(error!=0) 
     { 
      PrintFormat("iBarShift(): GetLastError=%d - The requested date %s "+ 
                  "for %s %s is not found in the available history", 
                  error,TimeToString(time),symbol,EnumToString(tf)); 
      return; 
     } 
//--- iBarShift()函数被成功执行,返回结果exact=false 
   PrintFormat("1. %s %s %s(%s): bar index is %d (exact=%s)", 
               symbol,EnumToString(tf),TimeToString(time), 
               DayOfWeek(time),bar_index,string(exact)); 
   datetime bar_time=iTime(symbol,tf,bar_index); 
   PrintFormat("Time of bar #%d is %s (%s)", 
               bar_index,TimeToString(bar_time),DayOfWeek(bar_time)); 
//--- 请求指定时间的柱形图指数;如果没有柱形图则将返回-1 
   exact=true; 
   bar_index=iBarShift(symbol,tf,time,exact); 
//--- iBarShift()函数被成功执行,返回结果exact=true 
   PrintFormat("2. %s %s %s (%s):bar index is %d (exact=%s)", 
               symbol,EnumToString(tf),TimeToString(time) 
               ,DayOfWeek(time),bar_index,string(exact)); 
  } 
//+------------------------------------------------------------------+ 
//| 返回一周的每日名称                                                  | 
//+------------------------------------------------------------------+ 
string DayOfWeek(const datetime time) 
  { 
   MqlDateTime dt; 
   string day=""; 
   TimeToStruct(time,dt); 
   switch(dt.day_of_week) 
     { 
      case 0: day=EnumToString(SUNDAY); 
      break; 
      case 1: day=EnumToString(MONDAY); 
      break; 
      case 2: day=EnumToString(TUESDAY); 
      break; 
      case 3: day=EnumToString(WEDNESDAY); 
      break; 
      case 4: day=EnumToString(THURSDAY); 
      break; 
      case 5: day=EnumToString(FRIDAY); 
      break; 
      default:day=EnumToString(SATURDAY); 
      break; 
     } 
//--- 
   return day; 
  } 
//+------------------------------------------------------------------+ 
/* Execution result 
   1. GBPUSD PERIOD_H1 2018.06.10 12:00(SUNDAY): bar index is 64 (exact=false) 
   Time of bar #64 is 2018.06.08 23:00 (FRIDAY) 
   2. GBPUSD PERIOD_H1 2018.06.10 12:00 (SUNDAY):bar index is -1 (exact=true) 
*/ 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

# 16.23 iClose

返回对应的图表上柱形图的收盘价(通过'shift'参数表示)。

double  iClose( 
   const string        symbol,          // 交易品种 
   ENUM_TIMEFRAMES     timeframe,       // 周期 
   int                 shift            // 转移 
   );
1
2
3
4
5

参数

交易品种

[in] 金融工具的交易品种名称。NULL表示当前交易品种。

timeframe

[in] 周期。它可以是ENUM_TIMEFRAMES其中一个枚举值。0表示当前图表周期。

shift

[in] 来自时间序列返回值的指数(相对于当前柱形图的指定柱形图数量的向后偏移)。

返回值

对应的图表上柱形图的收盘价(通过'shift'参数表示)或者错误情况下为0。错误详情,请调用GetLastError()函数。

注意

这个函数始终返回实际数据。为此,它对每次调用期间指定交易品种/周期的时间序列执行请求。这意味着如果第一次函数调用时没有准备好的数据,则可能需要一些时间来准备结果。

这个函数不会存储之前的调用结果,也没有快速返回值的本地缓存。

例如:

input int shift=0; 
//+------------------------------------------------------------------+ 
//| 函数-事件处理程序"tick"                                            | 
//+------------------------------------------------------------------+ 
void OnTick() 
  { 
   datetime time  = iTime(Symbol(),Period(),shift); 
   double   open  = iOpen(Symbol(),Period(),shift); 
   double   high  = iHigh(Symbol(),Period(),shift); 
   double   low   = iLow(Symbol(),Period(),shift); 
   double   close = iClose(NULL,PERIOD_CURRENT,shift); 
   long     volume= iVolume(Symbol(),0,shift); 
   int      bars  = iBars(NULL,0); 
  
   Comment(Symbol(),",",EnumToString(Period()),"\n", 
           "Time: "  ,TimeToString(time,TIME_DATE|TIME_SECONDS),"\n", 
           "Open: "  ,DoubleToString(open,Digits()),"\n", 
           "High: "  ,DoubleToString(high,Digits()),"\n", 
           "Low: "   ,DoubleToString(low,Digits()),"\n", 
           "Close: " ,DoubleToString(close,Digits()),"\n", 
           "Volume: ",IntegerToString(volume),"\n", 
           "Bars: "  ,IntegerToString(bars),"\n" 
           ); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

另见 CopyClose, CopyRates

# 16.24 iHigh

返回对应的图表上柱形图的最高价(通过'shift'参数表示)。

double  iHigh( 
   const string        symbol,          // 交易品种 
   ENUM_TIMEFRAMES     timeframe,       // 周期 
   int                 shift            // 转移 
   );
1
2
3
4
5

参数

交易品种

[in] 金融工具的交易品种名称。NULL表示当前交易品种。

timeframe

[in] 周期。它可以是ENUM_TIMEFRAMES其中一个枚举值。0表示当前图表周期。

shift

[in] 来自时间序列返回值的指数(相对于当前柱形图的指定柱形图数量的向后偏移)。

返回值

对应的图表上柱形图的最高价(通过'shift'参数表示)或者错误情况下为0。错误详情,请调用GetLastError()函数。

注意

这个函数始终返回实际数据。为此,它对每次调用期间指定交易品种/周期的时间序列执行请求。这意味着如果第一次函数调用时没有准备好的数据,则可能需要一些时间来准备结果。

这个函数不会存储之前的调用结果,也没有快速返回值的本地缓存。

例如:

input int shift=0; 
//+------------------------------------------------------------------+ 
//| 函数-事件处理程序"tick"                                            | 
//+------------------------------------------------------------------+ 
void OnTick() 
  { 
   datetime time  = iTime(Symbol(),Period(),shift); 
   double   open  = iOpen(Symbol(),Period(),shift); 
   double   high  = iHigh(Symbol(),Period(),shift); 
   double   low   = iLow(Symbol(),Period(),shift); 
   double   close = iClose(NULL,PERIOD_CURRENT,shift); 
   long     volume= iVolume(Symbol(),0,shift); 
   int      bars  = iBars(NULL,0); 
  
   Comment(Symbol(),",",EnumToString(Period()),"\n", 
           "Time: "  ,TimeToString(time,TIME_DATE|TIME_SECONDS),"\n", 
           "Open: "  ,DoubleToString(open,Digits()),"\n", 
           "High: "  ,DoubleToString(high,Digits()),"\n", 
           "Low: "   ,DoubleToString(low,Digits()),"\n", 
           "Close: " ,DoubleToString(close,Digits()),"\n", 
           "Volume: ",IntegerToString(volume),"\n", 
           "Bars: "  ,IntegerToString(bars),"\n" 
           ); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

另见 CopyHigh, CopyRates

# 16.25 iHighest

返回在对应图表上找到的最高值的指数(相对于当前柱形图的转移)。

int  iHighest( 
   const string        symbol,              // 交易品种 
   ENUM_TIMEFRAMES     timeframe,           // 周期 
   ENUM_SERIESMODE     type,                // 时间序列标识符 
   int                 count=WHOLE_ARRAY,   // 元素数量 
   int                 start=0              // 指数 
  );
1
2
3
4
5
6
7

参数

交易品种

[in] 将要执行搜索的交易品种。NULL表示当前交易品种。

timeframe

[in] 周期。它可以是ENUM_TIMEFRAMES其中一个枚举值。0表示当前图表周期。

类型

[in] 将要执行搜索的时间序列标识符。可以等于ENUM_SERIESMODE的任何值。

ount=WHOLE_ARRAY

[in] 时间序列中的元素数量(从当前柱形图向指数递增的方向),搜索应在其中执行。

start=0

[in] 初始柱形图的指数(相对于当前柱形图的转移),从这里开始搜索最高的值。忽略负值并用0零代替。

返回值

在对应图表上找到的最高值的指数(相对于当前柱形图的转移)或者错误情况下为0。错误详情,请调用GetLastError()函数。

例如:

double val; 
//--- 在20个连续柱形图中计算最高收盘值 
//--- 从指数4到指数23,在当前时间表 
   int val_index=iHighest(NULL,0,MODE_CLOSE,20,4); 
   if(val_index!=-1)  
      val=High[val_index]; 
   else  
      PrintFormat("iHighest() call error. Error code=%d",GetLastError());
1
2
3
4
5
6
7
8

参数

交易品种

[in] 将要执行搜索的交易品种。NULL表示当前交易品种。

timeframe

[in] 周期。它可以是ENUM_TIMEFRAMES其中一个枚举值。0表示当前图表周期。

类型

[in] 将要执行搜索的时间序列标识符。可以等于ENUM_SERIESMODE的任何值。

count=WHOLE_ARRAY

[in] 时间序列中的元素数量(从当前柱形图向指数递增的方向),搜索应在其中执行。

start=0

[in] 初始柱形图的指数(相对于当前柱形图的转移),从这里开始搜索最高的值。忽略负值并用0零代替。

返回值

在对应图表上找到的最高值的指数(相对于当前柱形图的转移)或者错误情况下为0。错误详情,请调用GetLastError()函数。

例如:

   double val; 
//--- 在20个连续柱形图中计算最高收盘值 
//--- 从指数4到指数23,在当前时间表 
   int val_index=iHighest(NULL,0,MODE_CLOSE,20,4); 
   if(val_index!=-1)  
      val=High[val_index]; 
   else  
      PrintFormat("iHighest() call error. Error code=%d",GetLastError());
1
2
3
4
5
6
7
8

# 16.26 iLow

返回对应的图表上柱形图的最低价(通过'shift'参数表示)。

double  iLow( 
   const string        symbol,          // 交易品种 
   ENUM_TIMEFRAMES     timeframe,       // 周期 
   int                 shift            // 转移 
   );
1
2
3
4
5

参数

交易品种

[in] 金融工具的交易品种名称。NULL表示当前交易品种。

timeframe

[in] 周期。它可以是ENUM_TIMEFRAMES其中一个枚举值。0表示当前图表周期。

shift

[in] 来自时间序列返回值的指数(相对于当前柱形图的指定柱形图数量的向后偏移)。

返回值

对应的图表上柱形图的最低价(通过'shift'参数表示)或者错误情况下为0。错误详情,请调用GetLastError()函数。

注意

这个函数始终返回实际数据。为此,它对每次调用期间指定交易品种/周期的时间序列执行请求。这意味着如果第一次函数调用时没有准备好的数据,则可能需要一些时间来准备结果。

这个函数不会存储之前的调用结果,也没有快速返回值的本地缓存。

例如:

input int shift=0; 
//+------------------------------------------------------------------+ 
//| 函数-事件处理程序"tick"                                            | 
//+------------------------------------------------------------------+ 
void OnTick() 
  { 
   datetime time  = iTime(Symbol(),Period(),shift); 
   double   open  = iOpen(Symbol(),Period(),shift); 
   double   high  = iHigh(Symbol(),Period(),shift); 
   double   low   = iLow(Symbol(),Period(),shift); 
   double   close = iClose(NULL,PERIOD_CURRENT,shift); 
   long     volume= iVolume(Symbol(),0,shift); 
   int      bars  = iBars(NULL,0); 
  
   Comment(Symbol(),",",EnumToString(Period()),"\n", 
           "Time: "  ,TimeToString(time,TIME_DATE|TIME_SECONDS),"\n", 
           "Open: "  ,DoubleToString(open,Digits()),"\n", 
           "High: "  ,DoubleToString(high,Digits()),"\n", 
           "Low: "   ,DoubleToString(low,Digits()),"\n", 
           "Close: " ,DoubleToString(close,Digits()),"\n", 
           "Volume: ",IntegerToString(volume),"\n", 
           "Bars: "  ,IntegerToString(bars),"\n" 
           ); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

另见 CopyLow, CopyRates

# 16.27 iLowest

返回在对应图表上找到的最小值的指数(相对于当前柱形图的转移)。

int  iLowest( 
   const string        symbol,              // 交易品种 
   ENUM_TIMEFRAMES     timeframe,           // 周期 
   ENUM_SERIESMODE     type,                // 时间序列标识符 
   int                 count=WHOLE_ARRAY,   // 元素数量 
   int                 start=0              // 指数 
  );
1
2
3
4
5
6
7

参数

交易品种

[in] 将要执行搜索的交易品种。NULL表示当前交易品种。

timeframe

[in] 周期。它可以是ENUM_TIMEFRAMES其中一个枚举值。0表示当前图表周期。

类型

[in] 将要执行搜索的时间序列标识符。可以等于ENUM_SERIESMODE的任何值。

count=WHOLE_ARRAY

[in] 时间序列中的元素数量(从当前柱形图向指数递增的方向),搜索应在其中执行。

start=0

[in] 初始柱形图的指数(相对于当前柱形图的转移),从这里开始搜索最低的值。忽略负值并用0零代替。

返回值

在对应图表上找到的最低值的指数(相对于当前柱形图的转移)或者错误情况下为0。错误详情,请调用GetLastError()函数。

例如:

   double val; 
//--- 在15个连续柱形图中搜索真实交易量的最低值的柱形图 
//--- 从指数10到指数24,在当前时间表 
   int val_index=iLowest(NULL,0,MODE_REAL_VOLUME,15,10); 
   if(val_index!=-1)  
      val=Low[val_index]; 
   else  
      PrintFormat("iLowest() call error. Error code=%d",GetLastError());
1
2
3
4
5
6
7
8

# 16.28 iOpen

返回对应的图表上柱形图的开盘价(通过'shift'参数表示)。

double  iOpen( 
   const string        symbol,          // 交易品种 
   ENUM_TIMEFRAMES     timeframe,       // 周期 
   int                 shift            // 转移 
   );
1
2
3
4
5

参数

交易品种

[in] 金融工具的交易品种名称。NULL表示当前交易品种。

timeframe

[in] 周期。它可以是ENUM_TIMEFRAMES其中一个枚举值。0表示当前图表周期。

shift

[in] 来自时间序列返回值的指数(相对于当前柱形图的指定柱形图数量的向后偏移)。

返回值

对应的图表上柱形图的开盘价(通过'shift'参数表示)或者错误情况下为0。错误详情,请调用GetLastError()函数。

注意

这个函数始终返回实际数据。为此,它对每次调用期间指定交易品种/周期的时间序列执行请求。这意味着如果第一次函数调用时没有准备好的数据,则可能需要一些时间来准备结果。

这个函数不会存储之前的调用结果,也没有快速返回值的本地缓存。

例如:

input int shift=0; 
//+------------------------------------------------------------------+ 
//| 函数-事件处理程序"tick"                                            | 
//+------------------------------------------------------------------+ 
void OnTick() 
  { 
   datetime time  = iTime(Symbol(),Period(),shift); 
   double   open  = iOpen(Symbol(),Period(),shift); 
   double   high  = iHigh(Symbol(),Period(),shift); 
   double   low   = iLow(Symbol(),Period(),shift); 
   double   close = iClose(NULL,PERIOD_CURRENT,shift); 
   long     volume= iVolume(Symbol(),0,shift); 
   int      bars  = iBars(NULL,0); 
  
   Comment(Symbol(),",",EnumToString(Period()),"\n", 
           "Time: "  ,TimeToString(time,TIME_DATE|TIME_SECONDS),"\n", 
           "Open: "  ,DoubleToString(open,Digits()),"\n", 
           "High: "  ,DoubleToString(high,Digits()),"\n", 
           "Low: "   ,DoubleToString(low,Digits()),"\n", 
           "Close: " ,DoubleToString(close,Digits()),"\n", 
           "Volume: ",IntegerToString(volume),"\n", 
           "Bars: "  ,IntegerToString(bars),"\n" 
           ); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

另见 CopyOpen, CopyRates

# 16.29 iTime

返回对应的图表上柱形图的开盘时间(通过'shift'参数表示)。

datetime  iTime( 
   const string        symbol,          // 交易品种 
   ENUM_TIMEFRAMES     timeframe,       // 周期 
   int                 shift            // 转移 
   );
1
2
3
4
5

参数

交易品种

[in] 金融工具的交易品种名称。NULL表示当前交易品种。

timeframe

[in] 周期。它可以是ENUM_TIMEFRAMES其中一个枚举值。0表示当前图表周期。

shift

[in] 来自时间序列返回值的指数(相对于当前柱形图的指定柱形图数量的向后偏移)。

返回值

对应的图表上柱形图的开盘时间(通过'shift'参数表示)或者错误情况下为0。错误详情,请调用GetLastError()函数。

注意

这个函数始终返回实际数据。为此,它对每次调用期间指定交易品种/周期的时间序列执行请求。这意味着如果第一次函数调用时没有准备好的数据,则可能需要一些时间来准备结果。

这个函数不会存储之前的调用结果,也没有快速返回值的本地缓存。

例如:

//+------------------------------------------------------------------+ 
//| 脚本程序起始函数                                                   | 
//+------------------------------------------------------------------+ 
void OnStart() 
  { 
//--- 日期为星期日 
   datetime time=D'2018.06.10 12:00'; 
   string symbol="GBPUSD"; 
   ENUM_TIMEFRAMES tf=PERIOD_H1; 
   bool exact=false; 
//--- 在指定时间没有柱形图,那么iBarShift将返回最近柱形图的指数 
   int bar_index=iBarShift(symbol,tf,time,exact); 
   PrintFormat("1. %s %s %s(%s): bar index is %d (exact=%s)", 
               symbol,EnumToString(tf),TimeToString(time),DayOfWeek(time),bar_index,string(exact)); 
   datetime bar_time=iTime(symbol,tf,bar_index); 
   PrintFormat("Time of bar #%d is %s (%s)", 
               bar_index,TimeToString(bar_time),DayOfWeek(bar_time)); 
//PrintFormat(iTime(symbol,tf,bar_index)); 
//--- 请求指定时间的柱形图指数;但如果没有柱形图则将返回-1 
   exact=true; 
   bar_index=iBarShift(symbol,tf,time,exact); 
   PrintFormat("2. %s %s %s (%s):bar index is %d (exact=%s)", 
               symbol,EnumToString(tf),TimeToString(time),DayOfWeek(time),bar_index,string(exact)); 
  } 
//+------------------------------------------------------------------+ 
//| 返回一周的每日名称                         | 
//+------------------------------------------------------------------+ 
string DayOfWeek(const datetime time) 
  { 
   MqlDateTime dt; 
   string day=""; 
   TimeToStruct(time,dt); 
   switch(dt.day_of_week) 
     { 
      case 0: day=EnumToString(SUNDAY); 
      break; 
      case 1: day=EnumToString(MONDAY); 
      break; 
      case 2: day=EnumToString(TUESDAY); 
      break; 
      case 3: day=EnumToString(WEDNESDAY); 
      break; 
      case 4: day=EnumToString(THURSDAY); 
      break; 
      case 5: day=EnumToString(FRIDAY); 
      break;    
      default:day=EnumToString(SATURDAY); 
      break; 
     } 
//--- 
   return day; 
  } 
/* The result: 
   1. GBPUSD PERIOD_H1 2018.06.10 12:00(SUNDAY): bar index is 64 (exact=false) 
   Time of bar #64 is 2018.06.08 23:00 (FRIDAY) 
   2. GBPUSD PERIOD_H1 2018.06.10 12:00 (SUNDAY):bar index is -1 (exact=true) 
*/  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

另见 CopyTime, CopyRates

# 16.30 iTickVolume

返回对应的图表上柱形图的报价量(通过'shift'参数表示)。

long  iTickVolume( 
   const string        symbol,          // 交易品种 
   ENUM_TIMEFRAMES     timeframe,       // 周期 
   int                 shift            // 转移 
   );
1
2
3
4
5

参数

易品种

[in] 金融工具的交易品种名称。NULL表示当前交易品种。

timeframe

[in] 周期。它可以是ENUM_TIMEFRAMES其中一个枚举值。0表示当前图表周期。

shift

[in] 来自时间序列返回值的指数(相对于当前柱形图的指定柱形图数量的向后偏移)。

返回值

对应的图表上柱形图的报价量(通过'shift'参数表示)或者错误情况下为0。错误详情,请调用GetLastError()函数。

注意

这个函数始终返回实际数据。为此,它对每次调用期间指定交易品种/周期的时间序列执行请求。这意味着如果第一次函数调用时没有准备好的数据,则可能需要一些时间来准备结果。

这个函数不会存储之前的调用结果,也没有快速返回值的本地缓存。

例如:

input int shift=0; 
//+------------------------------------------------------------------+ 
//| 函数-事件处理程序"tick"                                            | 
//+------------------------------------------------------------------+ 
void OnTick() 
  { 
   datetime time  = iTime(Symbol(),Period(),shift); 
   double   open  = iOpen(Symbol(),Period(),shift); 
   double   high  = iHigh(Symbol(),Period(),shift); 
   double   low   = iLow(Symbol(),Period(),shift); 
   double   close = iClose(NULL,PERIOD_CURRENT,shift); 
   long     volume= iVolume(Symbol(),0,shift); 
   int      bars  = iBars(NULL,0); 
  
   Comment(Symbol(),",",EnumToString(Period()),"\n", 
           "Time: "  ,TimeToString(time,TIME_DATE|TIME_SECONDS),"\n", 
           "Open: "  ,DoubleToString(open,Digits()),"\n", 
           "High: "  ,DoubleToString(high,Digits()),"\n", 
           "Low: "   ,DoubleToString(low,Digits()),"\n", 
           "Close: " ,DoubleToString(close,Digits()),"\n", 
           "Volume: ",IntegerToString(volume),"\n", 
           "Bars: "  ,IntegerToString(bars),"\n" 
           ); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

另见 CopyTickVolume, CopyRates

# 16.31 iRealVolume

返回对应的图表上柱形图的报价量(通过'shift'参数表示)。

long  iVolume( 
   const string        symbol,          // 交易品种 
   ENUM_TIMEFRAMES     timeframe,       // 周期 
   int                 shift            // 转移 
   );
1
2
3
4
5

参数

交易品种

[in] 金融工具的交易品种名称。NULL表示当前交易品种。

timeframe

[in] 周期。它可以是ENUM_TIMEFRAMES其中一个枚举值。0表示当前图表周期。

shift

[in] 来自时间序列返回值的指数(相对于当前柱形图的指定柱形图数量的向后偏移)。

返回值

对应的图表上柱形图的报价量(通过'shift'参数表示)或者错误情况下为0。错误详情,请调用GetLastError()函数。

注意

这个函数始终返回实际数据。为此,它对每次调用期间指定交易品种/周期的时间序列执行请求。这意味着如果第一次函数调用时没有准备好的数据,则可能需要一些时间来准备结果。

这个函数不会存储之前的调用结果,也没有快速返回值的本地缓存。

例如:

input int shift=0; 
//+------------------------------------------------------------------+ 
//| 函数-事件处理程序"tick"                                            | 
//+------------------------------------------------------------------+ 
void OnTick() 
  { 
   datetime time  = iTime(Symbol(),Period(),shift); 
   double   open  = iOpen(Symbol(),Period(),shift); 
   double   high  = iHigh(Symbol(),Period(),shift); 
   double   low   = iLow(Symbol(),Period(),shift); 
   double   close = iClose(NULL,PERIOD_CURRENT,shift); 
   long     volume= iVolume(Symbol(),0,shift); 
   int      bars  = iBars(NULL,0); 
  
   Comment(Symbol(),",",EnumToString(Period()),"\n", 
           "Time: "  ,TimeToString(time,TIME_DATE|TIME_SECONDS),"\n", 
           "Open: "  ,DoubleToString(open,Digits()),"\n", 
           "High: "  ,DoubleToString(high,Digits()),"\n", 
           "Low: "   ,DoubleToString(low,Digits()),"\n", 
           "Close: " ,DoubleToString(close,Digits()),"\n", 
           "Volume: ",IntegerToString(volume),"\n", 
           "Bars: "  ,IntegerToString(bars),"\n" 
           ); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

另见 CopyTickVolume, CopyRates

# 16.32 iVolume

返回对应的图表上柱形图的报价量(通过'shift'参数表示)。

long  iVolume( 
   const string        symbol,          // 交易品种 
   ENUM_TIMEFRAMES     timeframe,       // 周期 
   int                 shift            // 转移 
   );
1
2
3
4
5

参数

交易品种

[in] 金融工具的交易品种名称。NULL表示当前交易品种。

timeframe

[in] 周期。它可以是ENUM_TIMEFRAMES其中一个枚举值。0表示当前图表周期。

shift

[in] 来自时间序列返回值的指数(相对于当前柱形图的指定柱形图数量的向后偏移)。

返回值

对应的图表上柱形图的报价量(通过'shift'参数表示)或者错误情况下为0。错误详情,请调用GetLastError()函数。

注意

这个函数始终返回实际数据。为此,它对每次调用期间指定交易品种/周期的时间序列执行请求。这意味着如果第一次函数调用时没有准备好的数据,则可能需要一些时间来准备结果。

这个函数不会存储之前的调用结果,也没有快速返回值的本地缓存。

例如:

input int shift=0; 
//+------------------------------------------------------------------+ 
//| 函数-事件处理程序"tick"                                            | 
//+------------------------------------------------------------------+ 
void OnTick() 
  { 
   datetime time  = iTime(Symbol(),Period(),shift); 
   double   open  = iOpen(Symbol(),Period(),shift); 
   double   high  = iHigh(Symbol(),Period(),shift); 
   double   low   = iLow(Symbol(),Period(),shift); 
   double   close = iClose(NULL,PERIOD_CURRENT,shift); 
   long     volume= iVolume(Symbol(),0,shift); 
   int      bars  = iBars(NULL,0); 
  
   Comment(Symbol(),",",EnumToString(Period()),"\n", 
           "Time: "  ,TimeToString(time,TIME_DATE|TIME_SECONDS),"\n", 
           "Open: "  ,DoubleToString(open,Digits()),"\n", 
           "High: "  ,DoubleToString(high,Digits()),"\n", 
           "Low: "   ,DoubleToString(low,Digits()),"\n", 
           "Close: " ,DoubleToString(close,Digits()),"\n", 
           "Volume: ",IntegerToString(volume),"\n", 
           "Bars: "  ,IntegerToString(bars),"\n" 
           ); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

另见 CopyTickVolume, CopyRates

# 16.33 iSpread

返回对应的图表上柱形图的点差值(通过'shift'参数表示)。

long  iSpread( 
   const string        symbol,          // 交易品种 
   ENUM_TIMEFRAMES     timeframe,       // 周期 
   int                 shift            // 转移 
   );
1
2
3
4
5

参数

交易品种

[in] 金融工具的交易品种名称。NULL表示当前交易品种。

timeframe

[in] 周期。它可以是ENUM_TIMEFRAMES其中一个枚举值。0表示当前图表周期。

shift

[in] 来自时间序列返回值的指数(相对于当前柱形图的指定柱形图数量的向后偏移)。

返回值

对应的图表上柱形图的点差值(通过'shift'参数表示)或者错误情况下为0。错误详情,请调用GetLastError()函数。

注意

这个函数始终返回实际数据。为此,它对每次调用期间指定交易品种/周期的时间序列执行请求。这意味着如果第一次函数调用时没有准备好的数据,则可能需要一些时间来准备结果。

这个函数不会存储之前的调用结果,也没有快速返回值的本地缓存。

例如:

input int shift=0; 
//+------------------------------------------------------------------+ 
//| 函数-事件处理程序"tick"                                            | 
//+------------------------------------------------------------------+ 
void OnTick() 
  { 
   datetime time  = iTime(Symbol(),Period(),shift); 
   double   open  = iOpen(Symbol(),Period(),shift); 
   double   high  = iHigh(Symbol(),Period(),shift); 
   double   low   = iLow(Symbol(),Period(),shift); 
   double   close = iClose(NULL,PERIOD_CURRENT,shift); 
   long     volume= iVolume(Symbol(),0,shift); 
   int      bars  = iBars(NULL,0); 
  
   Comment(Symbol(),",",EnumToString(Period()),"\n", 
           "Time: "  ,TimeToString(time,TIME_DATE|TIME_SECONDS),"\n", 
           "Open: "  ,DoubleToString(open,Digits()),"\n", 
           "High: "  ,DoubleToString(high,Digits()),"\n", 
           "Low: "   ,DoubleToString(low,Digits()),"\n", 
           "Close: " ,DoubleToString(close,Digits()),"\n", 
           "Volume: ",IntegerToString(volume),"\n", 
           "Bars: "  ,IntegerToString(bars),"\n" 
           ); 
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

另见 CopySpread, CopyRates