ObjectMove

函数物件定位点的指定坐标。

bool  ObjectMove(
   long      chart_id,        // 图表标识符
   string    name,            // 物件名称
   int       point_index,     // 定位点数
   datetime  time,            // 时间
   double    price            // 价格
   );

参量

chart_id

[in]  图表标识符。0代表当前图表。

name

[in]  物件名称。

point_index

[in]  定位点检索。定位点数量取决于物件类型。

time

[in]  所选定位点的时间坐标。

价格

[in]  所选定位点的价格坐标。

返回值

如果命令成功添加到指定图表队列那么函数返回true,否则返回false。

注意

非同步调用通常用于ObjectMove(),这也是函数仅返回命令添加到图表队列的结果。在这种情况下,true仅表示命令已成功加入队列,但执行结果尚不可知。

若要检查命令执行结果,您可以使用请求对象属性的函数,例如ObjectGetXXX。但是,您需要牢记的是这类函数将被加入到图表的队尾,需要等待执行结果(因为同步调用),因此,可能会耗费大量时间。当处理图表上的大量对象时应该考虑这个特性。

 

示例:

#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
 
#define   OBJ_NAME_ASK     "TestObjectMoveAsk"  // 要价图形对象的名称
#define   OBJ_NAME_BID     "TestObjectMoveBid"  // 出价图形对象的名称
#define   COUNT            100000000            // 要加载历史的报价数量
#define   DELAY            1                    // 分时报价之间的延迟毫秒数
//+------------------------------------------------------------------+
//| 脚本程序起始函数                                                   |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- 当前图表 ID, 图表交易品种和交易品种小数位数
   long   chart_id= ChartID();
   string symbol  = ChartSymbol(chart_id);
   int    digits  = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
   
//--- 在图表上创建两个标签用于显示要价和出价
   if(!CreatePriceLabel(chart_id, true) || !CreatePriceLabel(chart_id, false))
      return;
   
//--- 用于接收分时报价的数组
   MqlTick ticks[]={};
   
//--- 取得图表上下一个可见柱形的编号和这个柱的开启毫秒数时间
   int   first= (int)ChartGetInteger(chart_id, CHART_FIRST_VISIBLE_BAR)-1;
   ulong from = GetTime(symbol, PERIOD_CURRENT, first)*1000;
   
//--- 把分时报价历史载入数组中
   Print("Started collecting ticks...");
   if(!GetTicksToArray(symbol, ticks))
      return;
      
//--- 重置报价数组并从图表上可见范围的柱形中取得报价
   ZeroMemory(ticks);
   if(CopyTicksRange(symbol, ticks, COPY_TICKS_INFO, from)<1)
     {
      PrintFormat("CopyTicksRange() from date %s failed. Error %d", TimeToString(GetTime(symbol, PERIOD_CURRENT, first)), GetLastError());
      return;
     }
   
   Sleep(500);
   PrintFormat("Tick ​​visualization started at %s (%I64u), ticks total: %u", TimeToString(GetTime(symbol, PERIOD_CURRENT, first)), from, ticks.Size());
   
   int count=0;                  // number of ticks processed
   int changes=0;                // number of processed price changes
   int total=(int)ticks.Size();  // tick array size
   
//--- 在报价数组中循环
   for(int i=0; i<total && !IsStopped(); i++)
     {
      //--- 从数组中取得报价并增加报价计数器
      MqlTick  tick=ticks[i];
      count++;
      
      //--- 检查要价和出价标志
      bool ask_tick=((tick.flags &TICK_FLAG_ASK)==TICK_FLAG_ASK); 
      bool bid_tick=((tick.flags &TICK_FLAG_BID)==TICK_FLAG_BID); 
      bool done=false;
      
      //--- 如果要价改变
      if(ask_tick)
        {
         if(Move(chart_id, OBJ_NAME_ASK, tick.time, tick.ask))
           {
            changes++;
            done=true;
           }
        }
      //--- 如果出价改变
      if(bid_tick)
        {
         if(Move(chart_id, OBJ_NAME_BID, tick.time, tick.bid))
           {
            changes++;
            done=true;
           }
        }
      //--- 如果任意(或两个)图形对象有移动, 更新图表
      if(done)
        {
         ChartRedraw(chart_id);
         Sleep(DELAY);
        }
     }
   
//--- 在循环末尾, 我们将在日志中报告处理的报价数量
//--- 等待几秒, 删除所创建的对象并重绘图表
   PrintFormat("Total ticks completed: %u, Total price changes: %d", count, changes);
   Sleep(2000);
   if(ObjectsDeleteAll(chart_id, "TestObjectMove")>0)
      ChartRedraw(chart_id);
   /*
   脚本执行的结果是, 要价和出价的移动将显示在可见的图表中,
   从图表左侧边缘至历史数据的结束,
   以下数据将会在日志中显示:
   Started collecting ticks...
   AUDUSD: received 13726794 ticks in 969 ms
   Tick ​​visualization started at 2025.01.31 09:00 (1738314000000), ticks total: 44380
   Total ticks completed: 44380, Total price changes: 68513
   */
  }
//+------------------------------------------------------------------+
//| 创建一个 "价格标签" 对象                                            |
//+------------------------------------------------------------------+
bool CreatePriceLabel(const long chart_id, const bool obj_ask)
  {
   string obj_name=(obj_ask ? OBJ_NAME_ASK : OBJ_NAME_BID);
   ResetLastError();
   if(!ObjectCreate(chart_id, obj_name, (obj_ask ? OBJ_ARROW_RIGHT_PRICE : OBJ_ARROW_LEFT_PRICE), 0, 0, 0))
     {
      PrintFormat("%s: ObjectCreate() failed. Error %d",__FUNCTION__, GetLastError());
      return(false);
     }
   return(ObjectSetInteger(chart_id, obj_name, OBJPROP_COLOR, (obj_ask ? clrRed : clrBlue)));
  }
//+------------------------------------------------------------------+
//| 把图形对象移动到指定的价格/时间坐标处                                 |
//+------------------------------------------------------------------+
bool Move(const long chart_id, const string obj_name, const datetime time, const double price)
  {
   ResetLastError();
   if(!ObjectSetInteger(chart_id, obj_name, OBJPROP_TIME, time))
     {
      PrintFormat("%s: ObjectSetInteger() failed. Error %d",__FUNCTION__, GetLastError());
      return(false);
     }
   if(!ObjectSetDouble(chart_id, obj_name, OBJPROP_PRICE, price))
     {
      PrintFormat("%s: ObjectSetDouble() failed. Error %d",__FUNCTION__, GetLastError());
      return(false);
     }
   return(true);
  }
//+------------------------------------------------------------------+
//| 把报价载入至数组中                                                  |
//+------------------------------------------------------------------+
bool GetTicksToArray(const string symbol, MqlTick &array[])
  {
   int  attempts=0;     // 尝试获取报价历史的计数器
   bool success =false; // 复制报价成功的标志
   
//--- 为接收报价做3次尝试
   while(attempts<3) 
     {
      //--- 在接收报价前测量开始时间 
      uint start=GetTickCount();
      
      //--- 请求从 1970.01.01 00:00.001 开始的报价历史 (parameter from=1 ms) 
      ResetLastError();
      int received=CopyTicks(symbol, array, COPY_TICKS_ALL, 1, COUNT); 
      if(received!=-1) 
        { 
         //--- 显示报价的数量和花费时间的数据 
         PrintFormat("%s: received %d ticks in %d ms", symbol, received, GetTickCount()-start); 
         //--- 如果报价历史已同步, 错误代码为0
         if(GetLastError()==0) 
           { 
            success=true; 
            break; 
           } 
         else 
            PrintFormat("%s: %s ticks are not synchronized yet, %d ticks received for %d ms. Error=%d", 
            __FUNCTION__, symbol, received, GetTickCount()-start, GetLastError()); 
        } 
      //--- 计数尝试次数 
      attempts++; 
      //--- 暂停一秒以等待报价数据库同步的结束
      Sleep(1000); 
     } 
//--- 从报价历史的开始接收请求报价三次尝试失败  
   if(!success) 
     { 
      PrintFormat("Error! Failed to get ticks for symbol %s after three attempts", symbol); 
      return(false); 
     }
   return(true);
  }
//+------------------------------------------------------------------+
//| 根据索引返回柱形时间                                                |
//+------------------------------------------------------------------+
datetime GetTime(const string symbol, const ENUM_TIMEFRAMES timeframe, const int index)
  {
   datetime array[1]={};
   ResetLastError();
   if(CopyTime(symbol, timeframe, index, 1, array)!=1)
      PrintFormat("%s: CopyTime() failed. Error %d",__FUNCTION__, GetLastError());
   return(array[0]);
  }