ObjectMove

The function changes coordinates of the specified anchor point of the object.

bool  ObjectMove(
   long      chart_id,        // chart identifier
   string    name,            // object name
   int       point_index,     // anchor point number
   datetime  time,            // Time
   double    price            // Price
   );

Parameters

chart_id

[in]  Chart identifier. 0 means the current chart.

name

[in]  Name of the object.

point_index

[in]  Index of the anchor point. The number of anchor points depends on the type of object.

time

[in]  Time coordinate of the selected anchor point.

price

[in]  Price coordinate of the selected anchor point.

Return Value

The function returns true if the command has been successfully added to the queue of the specified chart, or false otherwise.

Note

An asynchronous call is always used for ObjectMove(), that is why the function only returns the results of adding the command to a chart queue. In this case, true only means that the command has been successfully enqueued, but the result of its execution is unknown.

To check the command execution result, you can use a function that requests object properties, such as ObjectGetXXX. However, you should keep in mind that such functions are added to the end of the queue of that chart, and they wait for the execution result (due to the synchronous call), and can therefore be time consuming. This feature should be taken into account when working with a large number of objects on a chart.

Example:

#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
 
#define   OBJ_NAME_ASK     "TestObjectMoveAsk"  // name of the graphical object for the Ask price
#define   OBJ_NAME_BID     "TestObjectMoveBid"  // name of the graphical object for the Bid price
#define   COUNT            100000000            // number of ticks to load history
#define   DELAY            1                    // delay between ticks in ms
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- current chart ID, the chart symbol, and symbol Digits
   long   chart_idChartID();
   string symbol  = ChartSymbol(chart_id);
   int    digits  = (int)SymbolInfoInteger(symbolSYMBOL_DIGITS);
   
//--- create two price labels to display the Ask price and Bid price on the chart
   if(!CreatePriceLabel(chart_idtrue) || !CreatePriceLabel(chart_idfalse))
      return;
   
//--- array for receiving ticks
   MqlTick ticks[]={};
   
//--- get the number of the next visible bar on the chart and the opening time of this bar in milliseconds
   int   first= (int)ChartGetInteger(chart_idCHART_FIRST_VISIBLE_BAR)-1;
   ulong from = GetTime(symbolPERIOD_CURRENTfirst)*1000;
   
//--- load the tick history into the array
   Print("Started collecting ticks...");
   if(!GetTicksToArray(symbolticks))
      return;
      
//--- reset the tick array and get ticks from the visible range of bars on the chart
   ZeroMemory(ticks);
   if(CopyTicksRange(symbolticksCOPY_TICKS_INFOfrom)<1)
     {
      PrintFormat("CopyTicksRange() from date %s failed. Error %d"TimeToString(GetTime(symbolPERIOD_CURRENTfirst)), GetLastError());
      return;
     }
   
   Sleep(500);
   PrintFormat("Tick ​​visualization started at %s (%I64u), ticks total: %u"TimeToString(GetTime(symbolPERIOD_CURRENTfirst)), fromticks.Size());
   
   int count=0;                  // number of ticks processed
   int changes=0;                // number of processed price changes
   int total=(int)ticks.Size();  // tick array size
   
//--- in a loop through the tick array
   for(int i=0i<total && !IsStopped(); i++)
     {
      //--- get a tick from the array and increment the tick counter
      MqlTick  tick=ticks[i];
      count++;
      
      //--- check the tick Ask and Bid flags
      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 the Ask price changes
      if(ask_tick)
        {
         if(Move(chart_idOBJ_NAME_ASKtick.timetick.ask))
           {
            changes++;
            done=true;
           }
        }
      //--- if the Bid price changes
      if(bid_tick)
        {
         if(Move(chart_idOBJ_NAME_BIDtick.timetick.bid))
           {
            changes++;
            done=true;
           }
        }
      //--- if any (or both) of the graphical objects have been moved, update the chart
      if(done)
        {
         ChartRedraw(chart_id);
         Sleep(DELAY);
        }
     }
   
//--- at the end of the loop, we will report in the journal the number of ticks processed,
//--- wait a couple of seconds, delete the created objects and redraw the chart
   PrintFormat("Total ticks completed: %u, Total price changes: %d"countchanges);
   Sleep(2000);
   if(ObjectsDeleteAll(chart_id"TestObjectMove")>0)
      ChartRedraw(chart_id);
   /*
   as a result of the script execution, the movement of Ask and Bid prices will be displayed on the visible chart,
   starting from the left edge of the chart and to the end of the historical data,
   the following data will be displayed in the journal:
   Started collecting ticks...
   AUDUSDreceived 13726794 ticks in 969 ms
   Tick ​​visualization started at 2025.01.31 09:00 (1738314000000), ticks total44380
   Total ticks completed44380Total price changes68513
   */
  }
//+------------------------------------------------------------------+
//| Create a "Price label" object                                    |
//+------------------------------------------------------------------+
bool CreatePriceLabel(const long chart_idconst bool obj_ask)
  {
   string obj_name=(obj_ask ? OBJ_NAME_ASK : OBJ_NAME_BID);
   ResetLastError();
   if(!ObjectCreate(chart_idobj_name, (obj_ask ? OBJ_ARROW_RIGHT_PRICE : OBJ_ARROW_LEFT_PRICE), 000))
     {
      PrintFormat("%s: ObjectCreate() failed. Error %d",__FUNCTION__GetLastError());
      return(false);
     }
   return(ObjectSetInteger(chart_idobj_nameOBJPROP_COLOR, (obj_ask ? clrRed : clrBlue)));
  }
//+------------------------------------------------------------------+
//| Move the graphical object to the specified price/time coordinates|
//+------------------------------------------------------------------+
bool Move(const long chart_idconst string obj_nameconst datetime timeconst double price)
  {
   ResetLastError();
   if(!ObjectSetInteger(chart_idobj_nameOBJPROP_TIMEtime))
     {
      PrintFormat("%s: ObjectSetInteger() failed. Error %d",__FUNCTION__GetLastError());
      return(false);
     }
   if(!ObjectSetDouble(chart_idobj_nameOBJPROP_PRICEprice))
     {
      PrintFormat("%s: ObjectSetDouble() failed. Error %d",__FUNCTION__GetLastError());
      return(false);
     }
   return(true);
  }
//+------------------------------------------------------------------+
//| Load ticks into the array                                        |
//+------------------------------------------------------------------+
bool GetTicksToArray(const string symbolMqlTick &array[])
  {
   int  attempts=0;     // counter of attempts to obtain tick history
   bool success =false// flag of successful copying of ticks 
   
//--- make 3 attempts to receive ticks
   while(attempts<3
     {
      //--- measure the start time before receiving the ticks 
      uint start=GetTickCount();
      
      //--- request the tick history since 1970.01.01 00:00.001 (parameter from=1 ms) 
      ResetLastError();
      int received=CopyTicks(symbolarrayCOPY_TICKS_ALL1COUNT); 
      if(received!=-1
        { 
         //--- display data on the number of ticks and spent time 
         PrintFormat("%s: received %d ticks in %d ms"symbolreceivedGetTickCount()-start); 
         //--- if the tick history is synchronized, the error code is equal to zero 
         if(GetLastError()==0
           { 
            success=true
            break
           } 
         else 
            PrintFormat("%s: %s ticks are not synchronized yet, %d ticks received for %d ms. Error=%d"
            __FUNCTION__symbolreceivedGetTickCount()-startGetLastError()); 
        } 
      //--- count attempts 
      attempts++; 
      //--- a one-second pause to wait for the end of synchronization of the tick database
      Sleep(1000); 
     } 
//--- receiving the requested ticks from the beginning of the tick history failed in three attempts  
   if(!success
     { 
      PrintFormat("Error! Failed to get ticks for symbol %s after three attempts"symbol); 
      return(false); 
     }
   return(true);
  }
//+------------------------------------------------------------------+
//| Return the time by bar index                                     |
//+------------------------------------------------------------------+
datetime GetTime(const string symbolconst ENUM_TIMEFRAMES timeframeconst int index)
  {
   datetime array[1]={};
   ResetLastError();
   if(CopyTime(symboltimeframeindex1array)!=1)
      PrintFormat("%s: CopyTime() failed. Error %d",__FUNCTION__GetLastError());
   return(array[0]);
  }