何か思いつきましたか?
...MT4を再起動しても持続するIDが必要かどうかによります。おそらく、MathRand()を使用 しようとしたことを考えると、そうではないでしょう。
堅牢なユニークIDが必要な場合は、CoCreateGuid()コールを使用してオペレーティングシステムにGuidを要求することができます。DLLインポートを伴わないオプションが必要な場合は、MT4のグローバル変数でカウンターをインクリメントするようなことを試すことができます。
チャート上のインジケータ同士が干渉しないように、インジケータコードで一意のIDを取得したいのですが、どうすればよいでしょうか。
元々、MathRand()関数を使用していたのですが、残念ながら期待したようなユニークな数値は返されませんでした。おそらく、ランダム・ジェネレータはすべてのインジケータで独立して実行され、同じ初期シード(GetTickCountかも しれません)を取得するのですが、複数のインジケータが同じIDを取得するためです。
ということで、現在はインジケータ名とサブウィンドウからIDを導き出していますが、この組み合わせはユニークかもしれません。しかし、最近Terminalの実装が不安定なので、サブウィンドウ番号に依存しないIDを探したいと思っています。
何かいい方法はないでしょうか?
それは問題を先送りしているのでは?MathSRand()に何をシードするのですか?MT4のコピーで、すでにチャートに取り付けられたインジケータを起動した場合、GetTickCount()のようなものに同じ値を取得する可能性が非常に高いです。それでも一意な識別子が必要ですが、今度はMathSRandに渡すことができる一意な識別子が必要です...
もしインジケータがすでにチャートにアタッチされているなら、それらはすでにユニークなIDを持ち、何らかの方法で保存されているのでしょう。この一意なIDの目的を私は多分理解していない。
...MT4の再起動の間持続するIDが必要であるかどうかによります。MathRand()を使用しようとしたことから、おそらくそうではないでしょう。
堅牢なユニークIDが必要な場合は、CoCreateGuid()コールを使用してオペレーティングシステムにGuidを要求することができます。DLLのインポートを伴わないオプションが必要な場合は、MT4のグローバル変数でカウンターをインクリメントするようなことを試すことができます:最初のインジケーターは値0を取得してカウンターを1に増加し、2番目のインジケーターは値1を取得してカウンターを2に増加するなど。
ありがとうございます。了解しました。そうですね、DLLは避けたいですし、ゴミが残るのも避けたいです。GVプールはほとんどグローバル設定に使っているので、ゴミがあると概要がわかりにくくなります。とはいえ、同じような仕掛けはラベルオブジェクト でもできるかもしれないので、検討してみようかと思います。
ユニークIDの意図は、1つのインジケータの複数のインスタンスによって(異なるサブウィンドウで)作成された、チャート上のオブジェクトを区別することです。この問題に直面しているのは、私が初めてではないと思います。オブジェクトはdeinitで消えてしまうので、永続的である必要はありません。
他の簡単な方法は、GetTickCountの2番目の値を待つことでしょう...私は時間のロスを受け入れる場合。あるいは、DLLでシステムの時間構造を読み込むこともできます(ナノ秒の分解能があります)。しかし、この単純なタスクのためにDLLを使うのはもうやめよう :)
もし、インジケータがすでにチャートに添付されているなら、それらはすでにユニークな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);
ありがとうございます。理解できました。そうですね、DLLは避けたいし、ゴミを残すのも避けたい。GVプールは主にグローバル設定に使っているので、ゴミがあると概要がわかりにくくなります。とはいえ、同じトリックがラベルオブジェクトでできるかもしれないので、検討してみようかと思います。
... ID xxxx1 の hidden オブジェクトを作成し、それが失敗したら xxxx2, xxxx3 といった具合に試してみてはいかがでしょうか?そうすると、他のオブジェクトに使用するIDが得られます。ただし、グローバル変数ではなく、チャートオブジェクトの観点から、一時的なゴミを作成します。
チャート上のインジケータ同士が干渉しないように、インジケータコードで一意のIDを取得したいのですが、どうすればよいでしょうか。
元々、MathRand()関数を使用していたのですが、残念ながら期待したようなユニークな数値は返されませんでした。おそらく、ランダム・ジェネレータはすべてのインジケータで独立して実行され、同じ初期シード(GetTickCountかも しれません)を取得するのですが、複数のインジケータが同じIDを取得するためです。
ということで、現在はインジケータ名とサブウィンドウからIDを導き出していますが、この組み合わせはユニークかもしれません。しかし、最近Terminalの実装が不安定なので、サブウィンドウ番号に依存しないIDを探したいと思っています。
何かいい方法はないでしょうか?
もし、目に見えるジャンクを少なくしたいのであれば、排他的アクセスでファイル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); }
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索
チャート上のインジケータ同士が干渉しないように、インジケータコードで一意のIDを取得したいのですが、どうすればよいでしょうか。
元々、MathRand()関数を 使用していたのですが、残念ながら期待したようなユニークな数値は返されませんでした。おそらく、ランダム・ジェネレータはすべてのインジケータで独立して実行され、同じ初期シード(GetTickCountかも しれません)を取得するのですが、複数のインジケータが同じIDを取得するためです。
ということで、現在はインジケータ名とサブウィンドウからIDを導き出していますが、この組み合わせはユニークかもしれません。しかし、最近Terminalの実装が不安定なので、サブウィンドウ番号に依存しないIDを探したいと思っています。
何かいい方法はないでしょうか?