查找对象

有三个函数可用于在图表上搜索对象。前两个函数 ObjectsTotalObjectName 允许按名称遍历对象,然后在需要时使用每个对象的名称分析其他特性(下一节详述具体实现方法)。第三个函数ObjectFind允许通过已知名称验证对象是否存在。同样,也可以通过 ObjectGet函数直接请求某个特性来实现这一点:如果不存在与传入名称匹配的对象,_LastError 中将返回错误,但这种方式不如调用ObjectFind 便捷。此外,该函数会立即返回对象所在窗口编号。

int ObjectsTotal(long chartId, int window = -1, int type = -1)

该函数返回指定chartId标识符(0 表示当前图表)的图表上的对象数量。计算时仅考虑指定window编号的子窗口中的对象(0 表示主窗口,-1 表示主窗口及所有子窗口)。请注意,仅考虑type参数中指定的特定类型的对象(默认值 -1 表示所有类型)。type的值可以是 ENUM_OBJECT 枚举中的元素。

该函数采用同步执行方式,即会阻塞调用的 MQL 程序,直到获取结果。

string ObjectName(long chartId, int index, int window = -1, int type = -1)

该函数返回标识符为 chartId的图表上指定索引号index 的对象名称。在编译用于搜索对象的内部列表时,会考虑指定的子窗口编号(window)和对象类型(type)。此列表按对象名称的字典序排序,即具体按字母顺序排列且区分大小写。

ObjectsTotal类似,ObjectName 在执行期间会等待获取整个图表命令队列,然后从更新后的对象列表中返回对象名称。

如果发生错误,将返回空字符串,且将 OBJECT_NOT_FOUND (4202) 错误代码存储在 _LastError中。

为了测试这两个函数的功能,我们将创建一个名为ObjectFinder.mq5的脚本,用于记录所有图表上的所有对象。该脚本使用 图表迭代 函数(ChartFirstChartNext),以及获取 图表特性 的函数(ChartSymbolChartPeriodChartGetInteger)。

#include <MQL5Book/Periods.mqh>
   
void OnStart()
{
   int count = 0;
   long id = ChartFirst();
   // loop through charts
   while(id != -1)
   {
      PrintFormat("%s %s (%lld)"ChartSymbol(id), PeriodToString(ChartPeriod(id)), id);
      const int win = (int)ChartGetInteger(idCHART_WINDOWS_TOTAL);
      // loop through windows
      for(int k = 0k < win; ++k)
      {
         PrintFormat("  Window %d"k);
         const int n = ObjectsTotal(idk);
         // loop through objects
         for(int i = 0i < n; ++i)
         {
            const string name = ObjectName(idik);
            const ENUM_OBJECT type = (ENUM_OBJECT)ObjectGetInteger(idnameOBJPROP_TYPE);
            PrintFormat("    %s %s"EnumToString(type), name);
            ++count;
         }
      }
      id = ChartNext(id);
   }
   
   PrintFormat("%d objects found"count);
}

对于每个图表,我们确定子窗口的数量 (ChartGetInteger(id, CHART_WINDOWS_TOTAL)),为每个子窗口调用 ObjectsTotal 函数,并在内层循环中调用ObjectName。接下来,我们通过名称查找对象类型,并将它们一并显示在日志中。

下面是该脚本可能的运行结果(采用缩写形式)。

EURUSD H1 (132358585987782873)
  Window 0
    OBJ_FIBO H1 Fibo 58513
    OBJ_TEXT H1 Text 40688
    OBJ_TREND H1 Trendline 3291
    OBJ_VLINE H1 Vertical Line 28732
    OBJ_VLINE H1 Vertical Line 33752
    OBJ_VLINE H1 Vertical Line 35549
  Window 1
  Window 2
EURUSD D1 (132360375330772909)
  Window 0
EURUSD M15 (132544239145024745)
  Window 0
    OBJ_VLINE H1 Vertical Line 27032
...
XAUUSD D1 (132544239145024746)
  Window 0
    OBJ_EVENT ObjShow-2021.11.25 00:00:00
    OBJ_TEXT ObjShow-2021.11.26 00:00:00
    OBJ_ARROW_SELL ObjShow-2021.11.29 00:00:00
    OBJ_ARROW_BUY ObjShow-2021.11.30 00:00:00
    OBJ_ARROW_RIGHT_PRICE ObjShow-2021.12.01 00:00:00
    OBJ_ARROW_LEFT_PRICE ObjShow-2021.12.02 00:00:00
    OBJ_ARROW_CHECK ObjShow-2021.12.03 00:00:00
    OBJ_ARROW_STOP ObjShow-2021.12.06 00:00:00
    OBJ_ARROW_DOWN ObjShow-2021.12.07 00:00:00
    OBJ_ARROW_UP ObjShow-2021.12.08 00:00:00
    OBJ_ARROW_THUMB_DOWN ObjShow-2021.12.09 00:00:00
    OBJ_ARROW_THUMB_UP ObjShow-2021.12.10 00:00:00
    OBJ_HLINE ObjShow-2021.12.13 00:00:00
    OBJ_VLINE ObjShow-2021.12.14 00:00:00
...
35 objects found

特别是,在此处可以看到,XAUUSD, D1 图表上存在由ObjectSimpleShowcase.mq5脚本生成的对象。部分图表和子窗口中没有对象。

int ObjectFind(long chartId, const string name)

该函数在指定标识符的图表上按名称搜索对象,如果成功,则返回其所在窗口编号。

如果未找到对象,该函数将返回负值。与本节前述函数类似,ObjectFind函数采用同步调用方式。

在下一节 ObjectCopy.mq5脚本中,我们将看到该函数的使用示例。