Download MetaTrader 5

Unique ID Generator for a Particular Indicator

To add comments, please log in or register
Need mobile version of MetaTrader 5? Download it and trade!
Ex Ovo Omnia
3154
Ex Ovo Omnia 2014.03.08 08:17 

I would like to obtain a unique ID in indicator code, to ensure that indicators on a chart do not interfere with each other.

Originally, I used the MathRand() function, which unfortunately does not return unique numbers as I expected. Probably the random generator runs in every indicator independently, and gets the same initial seed (I guess it might be GetTickCount), because multiple indicators gain the same ID.

So currently I derive the ID from the indicator name and subwindow, which combination might be unique. Nevertheless the Terminal implementation is unstable recently, so I would like to find the ID which is independent on a subwindow number.

Any idea?

gchrmt4
356
gchrmt4 2014.03.08 12:00  
Ovo:

Any idea?


... Depends whether you want an ID which persists across restarts of MT4. Probably not given that you have tried using MathRand().

If you want a robust unique ID, then you can ask the operating system for a Guid using the CoCreateGuid() call. If you want an option which doesn't involve DLL imports, then you could try something like incrementing a counter in an MT4 global variable: first indicator gets the value 0 and increases the counter to 1; second indictor gets the value 1 and increases the counter to 2 etc.

Alain Verleyen
Moderator
30743
Alain Verleyen 2014.03.08 12:21  
Ovo:

I would like to obtain a unique ID in indicator code, to ensure that indicators on a chart do not interfere with each other.

Originally, I used the MathRand() function, which unfortunately does not return unique numbers as I expected. Probably the random generator runs in every indicator independently, and gets the same initial seed (I guess it might be GetTickCount), because multiple indicators gain the same ID.

So currently I derive the ID from the indicator name and subwindow, which combination might be unique. Nevertheless the Terminal implementation is unstable recently, so I would like to find the ID which is independent on a subwindow number.

Any idea?


Did you use MathSRand() before using MathRand() ?
gchrmt4
356
gchrmt4 2014.03.08 12:30  
angevoyageur:
Did you use MathSRand() before using MathRand() ?

Isn't that deferring the problem? What do you seed MathSRand() with? If you have a copy of MT4 starting up with indicators already attached to charts, then they are quite likely to get the same value for something like GetTickCount(). You still need a unique identifier, but now you need a unique identifier which you can pass to MathSRand...
Alain Verleyen
Moderator
30743
Alain Verleyen 2014.03.08 12:36  
gchrmt4:
Isn't that deferring the problem? What do you seed MathSRand() with? If you have a copy of MT4 starting up with indicators already attached to charts, then they are quite likely to get the same value for something like GetTickCount(). You still need a unique identifier, but now you need a unique identifier which you can pass to MathSRand...

If indicators are already attached to charts, I suppose they already have a unique ID, stored in one way or an other. I probably don't understand the purpose of this unique ID.

Ex Ovo Omnia
3154
Ex Ovo Omnia 2014.03.08 12:40  
gchrmt4:


... Depends whether you want an ID which persists across restarts of MT4. Probably not given that you have tried using MathRand().

If you want a robust unique ID, then you can ask the operating system for a Guid using the CoCreateGuid() call. If you want an option which doesn't involve DLL imports, then you could try something like incrementing a counter in an MT4 global variable: first indicator gets the value 0 and increases the counter to 1; second indictor gets the value 1 and increases the counter to 2 etc.


Thanks. I understand. Yes, I want to avoid DLL, and I want to avoid leaving garbage behind - I use the GV pool mostly for global settings, and garbage around makes my overview harder. Nevertheless the same trick may be done with a label object - I may consider it.

The intention for unique ID is to differentiate objects on a chart, which were created by multiple instances of a single indicator (in different subwindows). I believe I am not the first one who faces it. They do not need to be persistent, as objects disappear at deinit.

Other easy way would be waiting for the second value of GetTickCount... if I accept lost of time. Or with DLL access I may read the system time structure, since it has nanosecond resolution. But no more DLL for this simple task :)

gchrmt4
356
gchrmt4 2014.03.08 12:43  
angevoyageur:

If indicators are already attached to charts, I suppose they already have a unique ID, stored in one way or an other. I probably don't understand the purpose of this unique ID.

... Another scenario would be applying a template which has multiple copies of the same indicator in it.

I'd personally go to the Windows API for this, but the following code seems to work in terms of allocating a unique number for each indicator per MT4 session:

   GlobalVariableTemp("IndicatorGV");
   GlobalVariableTemp("IndicatorGVMutex");
   while (!GlobalVariableSetOnCondition("IndicatorGVMutex", 1, 0)) {
      // In theory this can enter a 100%-processor-usage loop
      // while waiting for another indicator to free the mutex
      // but in practice this never happens because indicators
      // all run in the same thread (and the mutex is therefore
      // only a safeguard)
   }
   double myVal = GlobalVariableGet("IndicatorGV");
   GlobalVariableSet("IndicatorGV", myVal + 1);
   GlobalVariableSet("IndicatorGVMutex", 0);
gchrmt4
356
gchrmt4 2014.03.08 12:49  
Ovo:

Thanks. I understand. Yes, I want to avoid DLL, and I want to avoid leaving garbage behind - I use the GV pool mostly for global settings, and garbage around makes my overview harder. Nevertheless the same trick may be done with a label object - I may consider it.

... try creating a hidden object with the ID xxxx1, and it that fails try xxxx2, and then xxxx3 etc? That then gives you the ID to use for other objects - though it creates temporary garbage in terms of chart objects rather than global variables.
gchrmt4
356
gchrmt4 2014.03.08 12:51  
gchrmt4:
... try creating a hidden object with the ID xxxx1, and it that fails try xxxx2, and then xxxx3 etc? That then gives you the ID to use for other objects - though it creates temporary garbage in terms of chart objects rather than global variables.
If you want less visible junk, you could try opening the file xxxx1 with exclusive access, and then xxxx2 and then xxxx3 etc.
Alain Verleyen
Moderator
30743
Alain Verleyen 2014.03.08 12:56  
Ovo:

I would like to obtain a unique ID in indicator code, to ensure that indicators on a chart do not interfere with each other.

Originally, I used the MathRand() function, which unfortunately does not return unique numbers as I expected. Probably the random generator runs in every indicator independently, and gets the same initial seed (I guess it might be GetTickCount), because multiple indicators gain the same ID.

So currently I derive the ID from the indicator name and subwindow, which combination might be unique. Nevertheless the Terminal implementation is unstable recently, so I would like to find the ID which is independent on a subwindow number.

Any idea?


What is the problem with subwindow number ?
gchrmt4
356
gchrmt4 2014.03.08 12:57  
gchrmt4:
If you want less visible junk, you could try opening the file xxxx1 with exclusive access, and then xxxx2 and then xxxx3 etc.

For example (using WindowHandle() instead of ChartID(), because ChartID() is unreliable in versions of MT4 which are still in wide use):

int glbMyIdentifier = -1;
int glbLockHandle = 0;
string glbLockFile = "";

int OnInit()
{
   for (int i = 1; i < 10000; i++) {
      string strTestLockFile = StringConcatenate(WindowHandle(Symbol(), Period()), "-", i);
      int lock = FileOpen(strTestLockFile, FILE_WRITE | FILE_BIN);
      if (lock == INVALID_HANDLE) {
      
      } else {
         glbMyIdentifier = i;
         glbLockHandle = lock;
         glbLockFile = strTestLockFile;
         break;
      }
   }   
   
   Print("Allocated: " , glbMyIdentifier);
   
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   FileClose(glbLockHandle);
   FileDelete(glbLockFile);
}
1234
To add comments, please log in or register