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]  ВременнАя координата указанной точки привязки.

price

[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"  // имя графического объекта для цены Ask
#define   OBJ_NAME_BID     "TestObjectMoveBid"  // имя графического объекта для цены Bid
#define   COUNT            100000000            // количество тиков для загрузки истории
#define   DELAY            1                    // задержка между тиками в мсек
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- идентификатор текущего графика, символ этого графика и Digits символа
   long   chart_id= ChartID();
   string symbol  = ChartSymbol(chart_id);
   int    digits  = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
   
//--- создаём две ценовые метки для отображения цены Ask и цены Bid на графике
   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;                  // количество обработанных тиков
   int changes=0;                // количество обработанных изменений цен
   int total=(int)ticks.Size();  // размер массива тиков
   
//--- в цикле по массиву тиков
   for(int i=0; i<total && !IsStopped(); i++)
     {
      //--- получаем тик из массива и увеличиваем счётчик тиков
      MqlTick  tick=ticks[i];
      count++;
      
      //--- проверим флаги Ask и Bid тика
      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;
      
      //--- если изменение цены Ask
      if(ask_tick)
        {
         if(Move(chart_id, OBJ_NAME_ASK, tick.time, tick.ask))
           {
            changes++;
            done=true;
           }
        }
      //--- если изменение цены Bid
      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);
   /*
   в результате работы скрипта на видимом графике будет отображено движение цен Ask и Bid,
   начиная от левого края графика и до конца исторических данных,
   в журнал будет выведена информация:
   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 (параметр 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); 
         //--- если тиковая история синхронизирована, то код ошибки равен нулю 
         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++; 
      //--- пауза в 1 секунду в ожидании завершения синхронизации тиковой базы 
      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]);
  }