通过柱线索引读取价格、成交量、点差和时间
有时,你需要查询的不是一系列柱线的信息,而仅是某一根柱线的信息。从理论上讲,这可以通过使用前面讨论过的 Copy函数来实现,只需在函数中指定数量(count 参数)为 1,但这种方式并不够便捷。以下函数提供了更简单的方法,它们可以根据柱线在时间序列中的编号,返回该柱线的某个特定类型的单一值。
所有函数都具有相似的原型,但名称和返回类型不同。从历史上看,这些函数名称均以前缀 i开头,形式为 iValue(这些函数属于内置技术指标的大类:毕竟报价的各种特性是技术分析的主要数据来源,而几乎所有指标都是其衍生指标,因此使用字母 i)。
type iValue(const string symbol, ENUM_TIMEFRAMES timeframe, int offset)
其中,type 对应 datetime、double、long 或int 中的一种类型,具体取决于函数本身。symbol 和 timeframe 用于指定要查询的时间序列。所需柱线的索引offset采用时间序列的表示方法:0 表示最新的、最右侧的柱线(通常尚未完成),数值越大,表示越早期的柱线。与 Copy 函数的情况类似,可以使用 NULL 和 0 来指定交易品种和时间周期,使其与当前图表的特性保持一致。
由于 i函数等效于调用 Copy 函数,因此在 获取报价数组的 Copy 函数概述 章节中描述的所有从不同类型程序请求时间序列的特性,同样适用于这些函数。
函数 |
说明 |
|---|---|
iTime |
柱线开盘时间 |
iOpen |
柱线开盘价 |
iHigh |
柱线最高价 |
iLow |
柱线最低价 |
iClose |
柱线收盘价 |
iTickVolume |
柱线的分时报价成交量(与 iVolume 类似) |
iVolume |
柱线的分时报价成交量(与 iTickVolume 类似) |
iRealVolume |
柱线的真实交易量 |
iSpread |
柱线的最小点差(以点为单位) |
这些函数会返回请求的值,如果出错则返回 0(遗憾的是,在某些情况下 0 可能是一个有效值)。如需获取详细的错误信息,可调用 GetLastError 函数。
这些函数不会缓存结果。每次调用时,它们都会从指定交易品种/时间周期的时间序列中返回实时数据。这意味着,在没有现成数据的情况下(首次调用时或同步丢失后),函数可能需要一些时间来准备结果。
举例来说,我们尝试获取每根柱线点差大小的近似真实值估算。由于报价中存储的是最小点差值,这可能会导致在设计交易策略时产生不切实际的过高预期。要获取每根柱线的平均点差、中位数点差或最大点差的绝对精确值,就必须分析实际的分时报价数据,但目前我们还未学习如何处理这类数据。此外,这也会是一个资源消耗极大的过程。更合理的方法是分析较低的 M1 时间范围的点差:对于较高时间范围的柱线,只需在其内部包含的 M1 柱线中查找最大点差即可。当然严格来说,这并非真正的最大值,而是最小点差值中的最大值,但考虑到分钟数据的瞬时特性,我们至少有望在某些 M1 柱线上检测到典型点差扩大情况,这足以在分析精度和速度之间取得可接受的平衡。
脚本SeriesSpread.mq5中实现了该算法的一个版本。在输入变量中,你可以设置用于分析的交易品种、时间范围和柱线数量。默认情况下,处理当前图表的交易品种及其时间周期(必须大于 M1)。
input string WorkSymbol = NULL; // Symbol (leave empty for current)
|
由于每个柱线只需关注其时间和点差信息,因此定义了一个包含两个字段的特殊结构体。我们本可以使用标准的 MqlRates结构体,并将“最大”点差数据添加到某个未使用的字段中(例如外汇交易品种的 real_volume),但这样会复制大部分字段的数据,造成内存浪费。
struct SpreadPerBar
|
通过使用新的结构体类型,我们准备了一个 peaks数组,用于计算指定数量的柱线数据。
void OnStart()
|
随后,算法的主体部分在柱线循环中执行。对于每个柱线,我们使用iTime函数确定定义该柱线边界的两个时间戳。实际上,这两个时间戳分别是第 i 根柱线和相邻的第 i+1 根柱线的开盘时间。根据索引原则,可以认为第 i+1 根柱线是前一根柱线(更早,见变量 prev),而第 i 根柱线是后一根柱线(更新,见变量next)。柱线的开盘时间仅属于该柱线,即标签 prev属于第 i+1 根柱线,而标签next 属于第 i 根柱线。因此,在处理每根柱线时,应将其右边界排除在区间 [prev;next) 之外。
我们关注的是一分钟时间周期上的点差,因此将使用CopySpread函数并指定 PERIOD_M1 参数。在这种情况下,通过将 start/stop参数分别设置为精确的 prev 值和减少 1 秒的next 值,可实现半开区间的设置。点差信息被复制到动态数组 spreads中(内存由函数自动分配)。
for(int i = 0; i < BarCount; ++i)
|
然后,我们在该数组中找出最大值,并将其与柱线时间一起保存在相应的SpreadPerBar结构体中。请注意,零号柱线不完整,未包含在分析中(如有需要,可对算法进行补充)。
循环结束后,我们将结构体数组输出到日志中。
PrintFormat("Maximal speeds per intraday bar\nProcessed %d bars on %s %s",
|
在 EURUSD,H1 图表上运行该脚本后,我们将获得小时柱线内的点差统计数据(节选):
Maximal speeds per intraday bar
|
夜间点差明显扩大:例如临近午夜时,报价中的点差为 7-15 点,而在我们的测量中达到 15-65 点。虽然小时柱线的指标通常显示为零,但在其他时段也能发现非零值。