Generador de identificación única para un indicador particular

 

Me gustaría obtener un ID único en el código del indicador, para asegurar que los indicadores en un gráfico no interfieran entre sí.

Originalmente, usé la función MathRand(), que desafortunadamente no devuelve números únicos como esperaba. Probablemente el generador aleatorio se ejecuta en cada indicador de forma independiente, y obtiene la misma semilla inicial (supongo que podría ser GetTickCount), porque múltiples indicadores obtienen el mismo ID.

Así que actualmente obtengo el ID del nombre del indicador y de la subventana, cuya combinación podría ser única. Sin embargo, la implementación de la Terminal es inestable recientemente, por lo que me gustaría encontrar el ID que es independiente de un número de subventana.

¿Alguna idea?

 
Ovo:

¿Alguna idea?


... Depende de si quieres un ID que persiste a través de reinicios de MT4. Probablemente no, dado que ha intentado utilizar MathRand().

Si quieres un ID único y robusto, entonces puedes pedirle al sistema operativo un Guid usando la llamada CoCreateGuid(). Si quiere una opción que no implique la importación de DLL, entonces podría intentar algo como incrementar un contador en una variable global de MT4: el primer indicador obtiene el valor 0 y aumenta el contador a 1; el segundo indicador obtiene el valor 1 y aumenta el contador a 2, etc.

 
Ovo:

Me gustaría obtener un ID único en el código del indicador, para asegurar que los indicadores en un gráfico no interfieran entre sí.

Originalmente, usé la función MathRand(), que desafortunadamente no devuelve números únicos como esperaba. Probablemente el generador aleatorio se ejecuta en cada indicador de forma independiente, y obtiene la misma semilla inicial (supongo que podría ser GetTickCount), porque múltiples indicadores obtienen el mismo ID.

Así que actualmente obtengo el ID del nombre del indicador y de la subventana, cuya combinación podría ser única. Sin embargo, la implementación de la Terminal es inestable recientemente, por lo que me gustaría encontrar el ID que es independiente de un número de subventana.

¿Alguna idea?


¿Ha utilizado MathSRand() antes de utilizar MathRand()?
 
angevoyageur:
¿Ha utilizado MathSRand() antes de utilizar MathRand()?

¿No es eso aplazar el problema? ¿Con qué sembró MathSRand()? Si usted tiene una copia de MT4 arrancando con indicadores ya adjuntos a los gráficos, entonces es muy probable que obtengan el mismo valor para algo como GetTickCount(). Todavía necesita un identificador único, pero ahora necesita un identificador único que puede pasar a MathSRand...
 
gchrmt4:
¿No es eso aplazar el problema? ¿Con qué sembraste MathSRand()? Si usted tiene una copia de MT4 arrancando con indicadores ya adjuntos a los gráficos, entonces es muy probable que obtengan el mismo valor para algo como GetTickCount(). Todavía necesita un identificador único, pero ahora necesita un identificador único que puede pasar a MathSRand...

Si los indicadores ya están adjuntos a los gráficos, supongo que ya tienen un identificador único, almacenado de una manera u otra. Probablemente no entiendo el propósito de este identificador único.

 
gchrmt4:


... Depende de si usted quiere un ID que persiste a través de reinicios de MT4. Probablemente no, dado que ha intentado utilizar MathRand().

Si quieres un ID único y robusto, entonces puedes pedirle al sistema operativo un Guid usando la llamada CoCreateGuid(). Si quieres una opción que no implique importaciones de DLL, entonces podrías probar algo como incrementar un contador en una variable global de MT4: el primer indicador obtiene el valor 0 y aumenta el contador a 1; el segundo indicador obtiene el valor 1 y aumenta el contador a 2, etc.


Gracias. Lo entiendo. Sí, quiero evitar la DLL, y quiero evitar dejar basura detrás - yo uso el pool de GV sobre todo para los ajustes globales, y la basura alrededor hace mi visión general más difícil. Sin embargo, el mismo truco se puede hacer con un objeto de etiqueta - puedo considerarlo.

La intención del ID único es diferenciar los objetos en un gráfico, que fueron creados por múltiples instancias de un solo indicador (en diferentes subventanas). Creo que no soy el primero que se enfrenta a ello. No es necesario que sean persistentes, ya que los objetos desaparecen al deinit.

Otra forma fácil sería esperar el segundo valor de GetTickCount... si acepto la pérdida de tiempo. O con acceso a la DLL puedo leer la estructura de tiempo del sistema, ya que tiene resolución de nanosegundos. Pero no más DLL para esta simple tarea :)

 
angevoyageur:

Si los indicadores ya están adjuntos a los gráficos, supongo que ya tienen un ID único, almacenado de una forma u otra. Probablemente no entiendo el propósito de este ID único.

... Otro escenario sería la aplicación de una plantilla que tiene varias copias del mismo indicador en ella.

Yo personalmente iría a la API de Windows para esto, pero el siguiente código parece funcionar en términos de asignar un número único para cada indicador por sesión de MT4:

   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);
 
Ovo:

Gracias. Lo entiendo. Sí, quiero evitar la DLL, y quiero evitar dejar basura detrás - uso el pool de GV sobre todo para los ajustes globales, y la basura alrededor hace mi visión general más difícil. Sin embargo, el mismo truco se puede hacer con un objeto de etiqueta - puedo considerarlo.

... intenta crear un objeto oculto con el ID xxxx1, y si eso falla prueba con xxxx2, y luego con xxxx3, etc. Eso te da el ID para usar para otros objetos - aunque crea basura temporal en términos de objetos de gráfico en lugar de variables globales.
 
gchrmt4:
... prueba a crear un objeto oculto con el ID xxxx1, y si eso falla prueba con xxxx2, y luego con xxxx3, etc. Eso te da el ID para usar para otros objetos - aunque crea basura temporal en términos de objetos de gráfico en lugar de variables globales.
Si quieres menos basura visible, podrías intentar abrir el archivo xxxx1 con acceso exclusivo, y luego xxxx2 y luego xxxx3 etc.
 
Ovo:

Me gustaría obtener un ID único en el código del indicador, para asegurar que los indicadores en un gráfico no interfieran entre sí.

Originalmente, usé la función MathRand(), que desafortunadamente no devuelve números únicos como esperaba. Probablemente el generador aleatorio se ejecuta en cada indicador de forma independiente, y obtiene la misma semilla inicial (supongo que podría ser GetTickCount), porque múltiples indicadores obtienen el mismo ID.

Así que actualmente obtengo el ID del nombre del indicador y de la subventana, cuya combinación podría ser única. Sin embargo, la implementación de la Terminal es inestable recientemente, así que me gustaría encontrar el ID que es independiente de un número de subventana.

¿Alguna idea?


¿Cuál es el problema con el número de subventana?
 
gchrmt4:
Si quieres menos basura visible, podrías intentar abrir el archivo xxxx1 con acceso exclusivo, y luego xxxx2 y luego xxxx3 etc.

Por ejemplo (utilizando WindowHandle() en lugar de ChartID(), porque ChartID() no es fiable en las versiones de MT4 que todavía se utilizan ampliamente):

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);
}