In MT4, is there a simple way to get a UniqueID per *each* instance of an indicator? - page 3

 

Uses 1 temporary GV and bitwise operators.

#property strict
#property indicator_chart_window

string GVName   = "MyIndicator";
string tag      = "MyObject";
int instance    = -1;
int instances[] = {1,2,4,8,16,32,64,128,256,512};

int OnInit()
  {
   GVName+=(string)ChartID();
   if(!GlobalVariableCheck(GVName))
     {
      if(!GlobalVariableTemp(GVName)) return(INIT_FAILED);
      GlobalVariableSet(GVName,instances[0]);
      ObjectsDeleteAll(0,tag);
      instance = instances[0];
      tag+=(string)instance;
      Print("No GV found... Assigning 1, deleting ALL orphaned objects");
     }
   else
     {
      int val = (int)GlobalVariableGet(GVName),
          cnt = ArraySize(instances);
      for(int i=0; i<cnt; i++)
        {
         if((val&instances[i])==0)
           {
            instance=instances[i];
            GlobalVariableSet(GVName,val|instance);
            tag+=(string)instance;
            ObjectsDeleteAll(0,tag);
            printf("Assigning %i, deleting all orphaned '~%i' objects",instance,instance);
            break;
           }
        }
     }
   if(instance<0) return(INIT_FAILED);
   ObjectCreate(0,tag,OBJ_LABEL,0,0,0);
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
   ObjectsDeleteAll(0,tag);
   int val=(int)GlobalVariableGet(GVName);
   GlobalVariableSet(GVName,val&~instance);
   printf("Freeing up %i and deleting all '~%i' objects",instance,instance);
  }

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
  
   return(rates_total);
  }
 
honest_knave:

Uses 1 temporary GV and bitwise operators.

//         if((val&instances[i])==0)
//           {
//            instance=instances[i];

         if((val&(1 << i))==0)
           {
            instance=(1 << i);
 
fxsaber:

Nice variation on the bitwise methodology. Slightly quicker too, I imagine
 
fxsaber #:

Using the previous ideas, I implemented the two functions below with some modifications to the code in MQL5:

//+------------------------------------------------------------------+
//| GetUniqueID function                                             |
//+------------------------------------------------------------------+
int GetUniqueID(string GVName="unique_id")
  {
   ulong instance_bit = 0;    // Instance by bit representation: 64 bit -> 64 instances
   int   instance_pos = -1;   // Instance by bit position on instance_bit
//---
   if(!GlobalVariableCheck(GVName))
     {
      if(!GlobalVariableTemp(GVName)) return(instance_pos);
      instance_bit = 1;
      instance_pos = 0;
      GlobalVariableSet(GVName, instance_bit);
     }
   else
     {
      ulong instances = (ulong)GlobalVariableGet(GVName);
      const int instance_max = sizeof(instance_bit) * 8;
      for(int i = 0; i < instance_max; i++)
        {
         if( (instances & ( (ulong)(1) << i) ) == 0 )
           {
            instance_bit = (ulong)(1) << i;
            instance_pos = i;
            GlobalVariableSet(GVName, instances|instance_bit);
            break;
           }
        }
     }
//---
   return(instance_pos);
  }
//+------------------------------------------------------------------+
//| FreeUniqueID function                                            |
//+------------------------------------------------------------------+
bool FreeUniqueID(int instance_pos, string GVName="unique_id")
  {
   if(GlobalVariableCheck(GVName))
     {
      ulong val = (ulong)GlobalVariableGet(GVName);
      ulong instance_bit = (ulong)(1) << instance_pos;
      if( GlobalVariableSet(GVName, val&(~instance_bit)) ) return true;
     }
   return false;
  }

Here is an example of how to use these functions to create a unique ID in the name of an indicator:

//+------------------------------------------------------------------+
//|                                                     UniqueID.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_plots 0

int GetUniqueID(string GVName="unique_id");

input int InpParameter=0; // Indicator Parameter

string ind_prefix_name = "UniqueID_" + (string)ChartID(); // Indicator prefix name
int unique_id = GetUniqueID(ind_prefix_name);
string ind_name = ind_prefix_name + "_" + IntegerToString(unique_id);

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   IndicatorSetString(INDICATOR_SHORTNAME, ind_name);
   Print(ind_name, ": instance #", unique_id, " reserved");
//---
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   if ( FreeUniqueID(unique_id, ind_prefix_name) )
      Print(ind_name, ": instance #", unique_id, " free");
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| GetUniqueID function                                             |
//+------------------------------------------------------------------+
int GetUniqueID(string GVName="unique_id")
  {
   ulong instance_bit = 0;    // Instance by bit representation: 64 bit -> 64 instances
   int   instance_pos = -1;   // Instance by bit position on instance_bit
//---
   if(!GlobalVariableCheck(GVName))
     {
      if(!GlobalVariableTemp(GVName)) return(instance_pos);
      instance_bit = 1;
      instance_pos = 0;
      GlobalVariableSet(GVName, instance_bit);
     }
   else
     {
      ulong instances = (ulong)GlobalVariableGet(GVName);
      const int instance_max = sizeof(instance_bit) * 8;
      for(int i = 0; i < instance_max; i++)
        {
         if( (instances & ( (ulong)(1) << i) ) == 0 )
           {
            instance_bit = (ulong)(1) << i;
            instance_pos = i;
            GlobalVariableSet(GVName, instances|instance_bit);
            break;
           }
        }
     }
//---
   return(instance_pos);
  }
//+------------------------------------------------------------------+
//| FreeUniqueID function                                            |
//+------------------------------------------------------------------+
bool FreeUniqueID(int instance_pos, string GVName="unique_id")
  {
   if(GlobalVariableCheck(GVName))
     {
      ulong val = (ulong)GlobalVariableGet(GVName);
      ulong instance_bit = (ulong)(1) << instance_pos;
      if( GlobalVariableSet(GVName, val&(~instance_bit)) ) return true;
     }
   return false;
  }
//+------------------------------------------------------------------+
 

Complement to: https://www.mql5.com/en/forum/191997/page3#comment_54114970

Remember that, although the instance_bit variable has 64 bits, only 53 bits can actually be used due to the conversion to the double type when assigning to the global variable. Therefore, the maximum number of instances that can be managed through a global variable, which is of the double type in MQL5, is 53.