在过去的几章中,我们致力于创建一系列用于执行订单处理机制的函数。这些函数是几乎所有EA都通用的基础模块,设计它们的初衷是希望它们能在各种交易场景中被复用,并尽可能保持灵活性。这样做的目的是让我们能够从繁琐的订单操作细节中解放出来,从而更专注于编码实现我们交易系统独特的交易逻辑和入场/出场条件。
接下来的核心工作,也将是您开发 EA 的主要精力所在——即如何让 EA 尽可能精确地执行您的交易系统规则。这包括识别开仓和平仓订单的确切条件,以及如何确定止损和止盈价格。几乎所有的交易系统都会用到价格数据和/或技术指标数据。下面我们就来探讨如何在 EA 中访问和使用这些关键信息。
价格数据
除了我们之前章节已经讨论过的当前即时报价——买价 (Bid) 和 卖价 (Ask) 之外,在构建交易逻辑时,您很可能还需要用到历史 K 线的价格数据,特别是每根 K 线的最高价 (High)、最低价 (Low)、开盘价 (Open) 和 收盘价 (Close)(通常合称为 OHLC 数据)。
1. 访问当前图表的 K 线数据:预定义时间序列数组
    对于 EA 当前运行所在图表的历史 K 线数据,MQL4提供了一组非常方便的预定义时间序列数组:High[], Low[], Open[] 和 Close[]。
- 数组: 在编程中,数组是一种可以存储多个同类型值的变量。您可以通过索引(一个整数,写在方括号 []内)来访问数组中的特定元素。
- 索引规则:
- Open[0]代表当前正在形成的 K 线(第 0 根 K 线)的开盘价。它的值会随着当前 K 线的价格跳动而变化。
- Open[1]代表前一根已完成的 K 线(第 1 根 K 线)的开盘价。这是一个固定值。
- Open[2]代表再往前一根 K 线的开盘价,依此类推。 这些数组通常用于获取最近几根 K 线的价格信息,例如判断突破、形态等。
 
2. 访问其他品种或其他周期的 K 线数据:iHigh(), iLow(), iOpen(), iClose() 函数 如果您需要获取:
- 非当前图表交易品种的 OHLC 数据(例如,EA 运行在 EURUSD 图表上,但需要 USDJPY 的数据)。
- 非当前图表时间周期的 OHLC 数据(例如,EA 运行在 H1 图表上,但需要 D1 周期的数据)。 那么,您就需要使用 MQL 内置的 i*()系列函数,如iHigh(),iLow(),iOpen()和iClose()。
以 iClose() 函数为例,其语法如下:
double iClose(
   string symbol,     // 交易品种名称 (例如 "EURUSD", NULL 表示当前品种)
   int    timeframe,  // 图表时间周期 (例如 PERIOD_H1, 0 表示当前周期)
   int    shift       // K线柱的位移量 (0代表当前K线, 1代表前一根, ...)
   );
- symbol: 您想获取数据的交易品种名称。如果为- NULL或使用- Symbol()函数,则表示当前 EA 运行的图表品种。
- timeframe: 您想获取数据的时间周期。可以是预定义的时间周期常量 (如- PERIOD_M1,- PERIOD_H4,- PERIOD_D1等),也可以是自定义的周期(以分钟为单位的整数,如 60 代表 1 小时)。如果为- 0,则表示使用当前 EA 运行的图表周期。
- shift: K 线的位移量。- 0指的是当前 K 线(对于历史数据函数,通常指正在形成的、其收盘价会随价格跳动而变化的K线,直到该 K 线结束),- 1指的是已完成的前一根 K 线,- 2指的是再往前一根,以此类推。
iClose() 使用示例:
- 
示例 1: EA 运行在 H1 图表上,获取当前品种 H4 图表上前一根 K 线的收盘价。 double H4_Previous_Close = iClose(NULL, PERIOD_H4, 1); // NULL: 当前品种 // PERIOD_H4: H4 时间周期 // 1: 前一根已完成的K线
- 
示例 2: 获取 GBPUSD 在与当前图表相同时间周期下,当前 K 线的(最新)收盘价。 double GBPUSD_Current_Close = iClose("GBPUSD", 0, 0); // "GBPUSD": 指定品种为 GBPUSD // 0: 使用当前图表的时间周期 // 0: 当前K线 (正在形成的K线)
3. 使用循环遍历历史K线数据
您可以结合 for 或 while 等循环运算符,通过改变 i*() 函数中的 shift 参数,来系统地访问一段历史 K 线的数据。
例如,以下 for 循环获取并打印当前品种、当前周期下,从当前 K 线(shift=0)开始往前共 10 根 K 线的收盘价:
Print("最近 10 根 K 线的收盘价 (0=当前K线, 1=前一根, ...):");
for (int bar_shift = 0; bar_shift < 10; bar_shift++) // 遍历 shift 从 0 到 9
{
    double historical_close = iClose(NULL, 0, bar_shift);
    if (historical_close != EMPTY_VALUE) // 检查数据是否有效 (例如,K线是否存在)
    {
        Print("Bar[", bar_shift, "] Close: ", DoubleToStr(historical_close, Digits)); // 使用 DoubleToStr 格式化输出
    }
    else
    {
        Print("Bar[", bar_shift, "] 数据获取失败!");
    }
}
 
			


