Генератор уникального идентификатора для конкретного показателя

 

Я хотел бы получить уникальный ID в коде индикатора, чтобы индикаторы на графике не мешали друг другу.

Первоначально я использовал функцию MathRand(), которая, к сожалению, не возвращает уникальные числа, как я ожидал. Вероятно, генератор случайных чисел работает в каждом индикаторе независимо и получает одинаковое начальное зерно (я предполагаю, что это может быть GetTickCount), потому что несколько индикаторов получают один и тот же ID.

Поэтому в настоящее время я получаю ID из названия индикатора и подокна, эта комбинация может быть уникальной. Тем не менее, реализация Terminal в последнее время нестабильна, поэтому я хотел бы найти ID, который не зависит от номера подокна.

Есть идеи?

 
Ovo:

Есть идеи?


... Зависит от того, нужен ли вам идентификатор, который сохраняется после перезапуска MT4. Скорее всего, нет, учитывая, что вы пытались использовать MathRand().

Если вам нужен надежный уникальный ID, то вы можете запросить у операционной системы Guid с помощью вызова CoCreateGuid(). Если вам нужен вариант, не требующий импорта DLL, то вы можете попробовать что-то вроде инкремента счетчика в глобальной переменной MT4: первый индикатор получает значение 0 и увеличивает счетчик до 1; второй индикатор получает значение 1 и увеличивает счетчик до 2 и т. д.

 
Ovo:

Я хотел бы получить уникальный ID в коде индикатора, чтобы индикаторы на графике не мешали друг другу.

Первоначально я использовал функцию MathRand(), которая, к сожалению, не возвращает уникальные числа, как я ожидал. Вероятно, генератор случайных чисел работает в каждом индикаторе независимо и получает одинаковое начальное зерно (я предполагаю, что это может быть GetTickCount), потому что несколько индикаторов получают один и тот же ID.

Поэтому в настоящее время я получаю ID из названия индикатора и подокна, эта комбинация может быть уникальной. Тем не менее, реализация Terminal в последнее время нестабильна, поэтому я хотел бы найти ID, который не зависит от номера подокна.

Есть идеи?


Использовали ли вы MathSRand() перед использованием MathRand()?
 
angevoyageur:
Использовали ли вы MathSRand() перед использованием MathRand()?

Разве это не откладывает решение проблемы? Чем вы загружаете MathSRand()? Если у вас запущена копия MT4 с индикаторами, уже прикрепленными к графикам, то вполне вероятно, что они получат одинаковое значение для чего-то вроде GetTickCount(). Вам по-прежнему нужен уникальный идентификатор, но теперь вам нужен уникальный идентификатор, который вы можете передать в MathSRand...
 
gchrmt4:
Разве это не откладывает решение проблемы? Чем вы загружаете MathSRand()? Если у вас запущена копия MT4 с индикаторами, уже прикрепленными к графикам, то они, скорее всего, получат одинаковое значение для чего-то вроде GetTickCount(). Вам по-прежнему нужен уникальный идентификатор, но теперь вам нужен уникальный идентификатор, который вы можете передать в MathSRand...

Если индикаторы уже прикреплены к графикам, я полагаю, что у них уже есть уникальный идентификатор, сохраненный тем или иным способом. Возможно, я не понимаю назначения этого уникального идентификатора.

 
gchrmt4:


... Зависит от того, нужен ли вам идентификатор, который сохраняется после перезапуска MT4. Скорее всего, нет, учитывая, что вы пытались использовать MathRand().

Если вам нужен надежный уникальный ID, то вы можете запросить у операционной системы Guid с помощью вызова CoCreateGuid(). Если вам нужен вариант, не требующий импорта DLL, то вы можете попробовать что-то вроде инкремента счетчика в глобальной переменной MT4: первый индикатор получает значение 0 и увеличивает счетчик до 1; второй индикатор получает значение 1 и увеличивает счетчик до 2 и т. д.


Спасибо. Я понял. Да, я хочу избежать DLL, и я хочу избежать оставления мусора - я использую пул GV в основном для глобальных настроек, и мусор вокруг делает мой обзор сложнее. Тем не менее, тот же самый трюк можно сделать с объектом label - я могу рассмотреть этот вариант.

Замысел уникального ID - различать объекты на графике, которые были созданы несколькими экземплярами одного индикатора (в разных подокнах). Думаю, я не первый, кто с этим сталкивается. Они не должны быть постоянными, так как объекты исчезают при deinit.

Другим простым способом было бы ожидание второго значения GetTickCount... если я допускаю потерю времени. Или с помощью DLL я могу прочитать структуру системного времени, поскольку она имеет наносекундное разрешение. Но больше никаких DLL для этой простой задачи :)

 
angevoyageur:

Если индикаторы уже прикреплены к графикам, я полагаю, что у них уже есть уникальный ID, сохраненный тем или иным способом. Возможно, я не понимаю назначения этого уникального ID.

... Другим сценарием может быть применение шаблона, в котором есть несколько копий одного и того же индикатора.

Я бы лично обратился к Windows API для этого, но следующий код, похоже, работает в плане выделения уникального номера для каждого индикатора на сессию 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:

Спасибо. Я понял. Да, я хочу избежать DLL, и я хочу избежать оставления мусора - я использую пул GV в основном для глобальных настроек, а мусор вокруг усложняет обзор. Тем не менее, тот же трюк можно сделать с объектом label - я могу рассмотреть этот вариант.

... попробуйте создать скрытый объект с ID xxxx1, и если это не удастся, попробуйте xxxx2, затем xxxx3 и т.д.? Это даст вам ID, который можно использовать для других объектов - хотя это создает временный мусор в виде объектов диаграммы, а не глобальных переменных.
 
gchrmt4:
... попробуйте создать скрытый объект с ID xxxx1, и если это не удастся, попробуйте xxxx2, а затем xxxx3 и т.д.? Это даст вам ID, который можно использовать для других объектов - хотя это создает временный мусор в виде объектов диаграммы, а не глобальных переменных.
Если вам нужен менее заметный мусор, вы можете попробовать открыть файл xxxx1 с эксклюзивным доступом, затем xxxx2, затем xxxx3 и т.д.
 
Ovo:

Я хотел бы получить уникальный ID в коде индикатора, чтобы индикаторы на графике не мешали друг другу.

Первоначально я использовал функцию MathRand(), которая, к сожалению, не возвращает уникальные числа, как я ожидал. Вероятно, генератор случайных чисел работает в каждом индикаторе независимо и получает одинаковое начальное зерно (я предполагаю, что это может быть GetTickCount), потому что несколько индикаторов получают один и тот же ID.

Поэтому в настоящее время я получаю ID из названия индикатора и подокна, эта комбинация может быть уникальной. Тем не менее, реализация Terminal в последнее время нестабильна, поэтому я хотел бы найти ID, который не зависит от номера подокна.

Есть идеи?


В чем проблема с номером подокна?
 
gchrmt4:
Если вы хотите получить меньше видимого мусора, вы можете попробовать открыть файл xxxx1 с эксклюзивным доступом, затем xxxx2, затем xxxx3 и т.д.

Например (используя WindowHandle() вместо ChartID(), потому что ChartID() ненадежен в версиях MT4, которые все еще широко используются):

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);
}
Причина обращения: