某一指标的唯一ID生成器

 

我想在指标代码中获得一个唯一的ID,以确保图表上的指标不会相互干扰。

最初,我使用了MathRand()函数,不幸的是,它并没有像我预期的那样返回唯一的数字。可能是随机发生器在每个指标中独立运行,并获得相同的初始种子(我猜可能是GetTickCount),因为多个指标获得相同的ID。

因此,目前我从指标名称和子窗口得出ID,其组合可能是唯一的。然而,终端的实现最近并不稳定,所以我想找到独立于子窗口号码的ID。

有什么想法吗?

 
Ovo:

有什么想法吗?


...这要看你是否想要一个在MT4重启时也能持续的ID。鉴于你已经尝试使用MathRand(),可能不会。

如果你想要一个强大的唯一ID,那么你可以使用CoCreateGuid()调用向操作系统要一个Guid。如果你想要一个不涉及DLL导入的选项,那么你可以尝试在MT4全局变量中增加一个计数器:第一个指标的值为0,并将计数器增加到1;第二个指标的值为1,并将计数器增加到2等等。

 
Ovo:

我想在指标代码中获得一个唯一的ID,以确保图表上的指标不会相互干扰。

最初,我使用了MathRand()函数,不幸的是,它并没有像我预期的那样返回唯一的数字。可能是随机发生器在每个指标中独立运行,并获得相同的初始种子(我猜可能是GetTickCount),因为多个指标获得相同的ID。

因此,目前我从指标名称和子窗口得出ID,其组合可能是唯一的。然而,终端的实现最近并不稳定,所以我想找到独立于子窗口号码的ID。

有什么想法吗?


你在使用MathRand()之前是否使用了MathSRand()?
 
angevoyageur:
你在使用MathRand()之前是否使用了MathSRand()?

这不是推迟了问题的解决吗?你用什么作为MathSRand()的种子?如果你有一个MT4的拷贝,并且指标已经连接到图表上,那么它们很可能在GetTickCount()这样的东西上得到相同的值。你仍然需要一个唯一的标识符,但现在你需要一个唯一的标识符,可以传递给MathSRand...
 
gchrmt4:
这不是把问题推迟了吗?你用什么作为MathSRand()的种子?如果你的MT4启动时,图表上已经有了指标,那么它们很可能在GetTickCount()这样的情况下得到相同的值。你仍然需要一个唯一的标识符,但现在你需要一个唯一的标识符,可以传递给MathSRand...

如果指标已经附在图表上,我想它们已经有一个唯一的ID,以某种方式存储。我可能不明白这个唯一的ID的用途。

 
gchrmt4:


...这要看你是否想要一个在MT4重启时也能持续的ID。鉴于你已经尝试使用MathRand(),可能不会。

如果你想要一个可靠的唯一 ID,那么你可以使用 CoCreateGuid() 调用向操作系统索取一个 Guid。如果你想要一个不涉及DLL导入的选项,那么你可以尝试在MT4全局变量中增加一个计数器:第一个指标的值为0,将计数器增加到1;第二个指标的值为1,将计数器增加到2等等。


谢谢。我明白了。是的,我想避免使用DLL,而且我想避免留下垃圾--我主要使用GV池进行全局设置,周围的垃圾使我的概述更加困难。不过,同样的技巧也可以用标签对象 来完成--我可以考虑。

唯一ID的目的是为了区分图表上的对象,这些对象是由一个指标的多个实例(在不同的子窗口)创建的。我相信我不是第一个面临这个问题的人。它们不需要是持久的,因为对象会在删除时消失。

其他简单的方法是等待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池进行全局设置,周围的垃圾使我的概述更加困难。不过,同样的技巧也可以用标签对象来完成--我可以考虑。

......尝试创建一个ID为xxxx1的隐藏对象,如果失败了,可以尝试xxxx2,然后xxx3等等?这样你就有了用于其他对象的ID--尽管它在图表对象而不是全局变量方面创造了临时垃圾。
 
gchrmt4:
......试着创建一个ID为xxxx1的隐藏对象,如果失败了,再试试xxxx2,然后xxx3等等?这样你就有了可用于其他对象的ID--尽管它在图表对象而不是全局变量方面创造了临时垃圾。
如果你想减少可见的垃圾,你可以尝试用独占访问打开文件xxxx1,然后是xxxx2,然后是xxx3等等。
 
Ovo:

我想在指标代码中获得一个唯一的ID,以确保图表上的指标不会相互干扰。

最初,我使用了MathRand()函数,不幸的是,它并没有像我预期的那样返回唯一的数字。可能是随机发生器在每个指标中独立运行,并获得相同的初始种子(我猜可能是GetTickCount),因为多个指标获得相同的ID。

因此,目前我从指标名称和子窗口得出ID,其组合可能是唯一的。然而,终端的实现最近并不稳定,所以我想找到独立于子窗口号码的ID。

有什么想法吗?


子窗口号码的问题是什么?
 
gchrmt4:
如果你想减少可见的垃圾,你可以尝试用独占权限打开文件xxxx1,然后是xxxx2,然后是xxx3等等。

例如(使用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);
}