特定指標のユニークIDジェネレーター

 

チャート上のインジケータ同士が干渉しないように、インジケータコードで一意のIDを取得したいのですが、どうすればよいでしょうか。

元々、MathRand()関数を 使用していたのですが、残念ながら期待したようなユニークな数値は返されませんでした。おそらく、ランダム・ジェネレータはすべてのインジケータで独立して実行され、同じ初期シード(GetTickCountかも しれません)を取得するのですが、複数のインジケータが同じIDを取得するためです。

ということで、現在はインジケータ名とサブウィンドウからIDを導き出していますが、この組み合わせはユニークかもしれません。しかし、最近Terminalの実装が不安定なので、サブウィンドウ番号に依存しないIDを探したいと思っています。

何かいい方法はないでしょうか?

 
Ovo:

何か思いつきましたか?


...MT4を再起動しても持続するIDが必要かどうかによります。おそらく、MathRand()を使用 しようとしたことを考えると、そうではないでしょう。

堅牢なユニークIDが必要な場合は、CoCreateGuid()コールを使用してオペレーティングシステムにGuidを要求することができます。DLLインポートを伴わないオプションが必要な場合は、MT4のグローバル変数でカウンターをインクリメントするようなことを試すことができます。

 
Ovo:

チャート上のインジケータ同士が干渉しないように、インジケータコードで一意のIDを取得したいのですが、どうすればよいでしょうか。

元々、MathRand()関数を使用していたのですが、残念ながら期待したようなユニークな数値は返されませんでした。おそらく、ランダム・ジェネレータはすべてのインジケータで独立して実行され、同じ初期シード(GetTickCountかも しれません)を取得するのですが、複数のインジケータが同じIDを取得するためです。

ということで、現在はインジケータ名とサブウィンドウからIDを導き出していますが、この組み合わせはユニークかもしれません。しかし、最近Terminalの実装が不安定なので、サブウィンドウ番号に依存しない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に増加し、2番目のインジケーターは値1を取得してカウンターを2に増加するなど。


ありがとうございます。了解しました。そうですね、DLLは避けたいですし、ゴミが残るのも避けたいです。GVプールはほとんどグローバル設定に使っているので、ゴミがあると概要がわかりにくくなります。とはいえ、同じような仕掛けはラベルオブジェクト でもできるかもしれないので、検討してみようかと思います。

ユニークIDの意図は、1つのインジケータの複数のインスタンスによって(異なるサブウィンドウで)作成された、チャート上のオブジェクトを区別することです。この問題に直面しているのは、私が初めてではないと思います。オブジェクトはdeinitで消えてしまうので、永続的である必要はありません。

他の簡単な方法は、GetTickCountの2番目の値を待つことでしょう...私は時間のロスを受け入れる場合。あるいは、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 のhidden オブジェクトを 作成し、それが失敗したら xxxx2, xxxx3 といった具合に試してみてください。そうすれば、他のオブジェクトに使うIDが得られます。ただし、グローバル変数ではなく、チャートオブジェクトという点で、一時的なゴミを作ることになります。
 
gchrmt4:
... ID xxxx1 の hidden オブジェクトを作成し、それが失敗したら xxxx2, xxxx3 といった具合に試してみてはいかがでしょうか?そうすると、他のオブジェクトに使用するIDが得られます。ただし、グローバル変数ではなく、チャートオブジェクトの観点から、一時的なゴミを作成します。
もし、目に見えるゴミを少なくしたいのであれば、排他アクセスで xxxx1 というファイルを開いてみて、次に xxxx2 と xxxx3 というようにすればよいでしょう。
 
Ovo:

チャート上のインジケータ同士が干渉しないように、インジケータコードで一意のIDを取得したいのですが、どうすればよいでしょうか。

元々、MathRand()関数を使用していたのですが、残念ながら期待したようなユニークな数値は返されませんでした。おそらく、ランダム・ジェネレータはすべてのインジケータで独立して実行され、同じ初期シード(GetTickCountかも しれません)を取得するのですが、複数のインジケータが同じIDを取得するためです。

ということで、現在はインジケータ名とサブウィンドウからIDを導き出していますが、この組み合わせはユニークかもしれません。しかし、最近Terminalの実装が不安定なので、サブウィンドウ番号に依存しないIDを探したいと思っています。

何かいい方法はないでしょうか?


サブウィンドウ番号の問題は何ですか?
 
gchrmt4:
もし、目に見えるジャンクを少なくしたいのであれば、排他的アクセスでファイルxxxx1を開き、次にxxxx2、そしてxxxx3などを開いてみるとよいでしょう。

例えば、(ChartID()の代わりにWindowHandle()を使う。なぜなら、まだ広く使われているMT4のバージョンではChartID()は信頼できないから)。

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);
}
理由: