マジックナンバーの作成

 
/**
* create a positive integer for the use as a magic number.
*
* The function takes a string as argument and calculates
* an 31 bit hash value from it. The hash does certainly not 
* have the strength of a real cryptographic hash function 
* but it should be more than sufficient for generating a
* unique ID from a string and collissions should not occur.
*
* use it in your init() function like this: 
*    magic = makeMagicNumber(WindowExpertName() + Symbol() + Period());
*
* where name would be the name of your EA. Your EA will then
* get a unique magic number for each instrument and timeframe
* and this number will always be the same, whenever you put
* the same EA onto the same chart.
*
* Numbers generated during testing mode will differ from those
* numbers generated on a live chart.
*/
int makeMagicNumber(string key){
   int i, k;
   int h = 0;
   
   if (IsTesting()){
      key = "_" + key;
   }
   
   for (i=0; i<StringLen(key); i++){
      k = StringGetChar(key, i);
      h = h + k;
      h = bitRotate(h, 5); // rotate 5 bits
   }
   
   for (i=0; i<StringLen(key); i++){
      k = StringGetChar(key, i);
      h = h + k;
      // rotate depending on character value
      h = bitRotate(h, k & 0x0000000F);
   }
   
   // now we go backwards in our string
   for (i=StringLen(key); i>0; i--){   
      k = StringGetChar(key, i - 1);
      h = h + k;
      // rotate depending on the last 4 bits of h
      h = bitRotate(h, h & 0x0000000F); 
   }
   
   return(h & 0x7fffffff);
}

/**
* Rotate a 32 bit integer value bit-wise 
* the specified number of bits to the right.
* This function is needed for calculations
* in the hash function makeMacicNumber()
*/
int bitRotate(int value, int count){
   int i, tmp, mask;
   mask = (0x00000001 << count) - 1;
   tmp = value & mask;
   value = value >> count;
   value = value | (tmp << (32 - count));
   return(value);
}
 
7bit:
[ ... ハッシュ関数 ... ]。

ちなみに、fbjは以前、よく知られたdjb2ハッシュ関数を使って似たようなことをやっていました: https://www.mql5.com/en/forum/120034/page2

 
私は最初、この http://www.cs.hmc.edu/~geoff/classes/hmc.cs070.200101/homework10/hashfuncs.html 、特に CRC variant (これは djb2 に非常に似ています) としてラベル付けされたものからインスピレーションを得ました。このハッシュだけでは、衝突を簡単に発生させることはできませんでしたが、十分な信頼性を得ることができず、時には2つの似たような文字列のハッシュ間でごくわずかなビットが異なるだけでした。そこで、hの回転を変えた3種類のハッシュを作成し、3つのサブハッシュを足し合わせてみた。そのうちの1つが衝突しても、他の2つは全く異なる方法で計算されます。これで、入力文字列のビットが変わるたびに、ハッシュの全ビットの半分以上が変わり、全ビットが完全にランダムに見えるようになりました。


上のリンクにあるdjb2は、その周りの何百行もない、単純にこう書くことができます。
int djb2(string key){
   int i, h, k;
   for (i=0; i<StringLen(key); i++){
      k = StringGetChar(key, i);
      h = (h << 5) + h + k;
   }
   return(h);
}
 
7bit:
上のリンクにあるdjb2は、その周りの何百行もない、単純な書き方で書くことができます。[...]

私はハッシュアルゴリズムの専門家ではありませんし、特にdjb2の専門家でもありません。しかし、ハッシュ値(あなたのバージョンではh変数)を5381に初期化することは重要だと考えられているように記憶していますが、その理由は誰もはっきりとは知りません。

 
*    magic = makeMagicNumber(name+ Symbol() + Period());
細かいことを言うつもりはありませんが、これも使えるはずです。
*    magic = makeMagicNumber(WindowExpertName() + Symbol() + Period());
コード(とハッシュ記事!)を投稿していただきありがとうございます。

質問 - 私は、同じチャート、同じアルゴリズムなどで、複数の注文を開始および終了するための方法を研究しています。

私は2つのステップでそれをアプローチしています。

1) ベースとなるMN(上記のコードが行うように見えるもの)を整数として生成する。ベースは各チャート/シンボル/タイムフレームで常に同じになります。
2) 各オーダーエンドに対応する小数点以下のサフィックスを生成し、サフィックスが未使用になると、再び使用可能にする。

つまり、MNはXXXXXX.YYYとなり、Xはベース、Yは特定のサフィックスとなります。サフィックスは.001から始まり、新しい送信ごとに.001ずつ増加します。各オーダーエンドで、それは現在使用されていない最も低い接尾辞を割り当てます。この方法では、私はベースMNを再生成し、接尾辞を循環させることによって、後でMNを取得することができます。

少し複雑すぎるような気がします。何か良い方法はないでしょうか?

完成したらアップします。
 
NuBとして、なぜ「暗号化された」MagicNumberが必要なのか、よく分かりませんが?
私は、最初の5つの数字をEAのバージョンに、最後の4つの数字を取引されている分数に使っているだけです。
 
FourX:
NuBとして、なぜ「暗号化された」MagicNumberが必要なのか、よくわかりませんね?
私は、最初の5つの数字をEAのバージョンに、最後の4つの数字を取引されている分数に使っているだけです。

あなたの例では、Symbol()はどのようにMNの一部になるのでしょうか?EA番号とTimeframe番号がありますが、Symbolはどうするのでしょうか?

私はMNによってのみ注文を識別し、注文リスト上の私のループはOrderMagicNumber()のみを比較し、あなた方はシンボル名もチェックしなければならないでしょう。私は注文リストで何かをする独立したスクリプトをいくつか持っています。例えば、EAの株式プロットや他のプラットフォームへの取引のコピーなどです。これらはすべて、特定のペアと特定のタイムフレームで特定のEAの取引を識別するためのマジックナンバーだけを必要とします。

私は自分のEAにシリアルナンバーを一切使わず、すべてのEAに4文字か5文字の短い名前を使っています。例えばsnowball.mq4というEAは "snow "という名前になります。これはコードに組み込まれていて、決して変更されることはありません。この短い名前は、注文コメントにも使って います。

つまり、ショートネーム、Symbol、Timeframeの3つがありますね。これをMNに変換するのに一番便利なのはハッシュです。EAに名前の代わりに数字を与えることもできますが、それでもシンボル名を数字に変換する簡単な方法はありません。ハッシュはこれらの問題を一挙に解決してくれます。

 
FourX:
NuBとして、なぜあなたが「暗号化された」MagicNumberを必要とするのか、よく分かりませんが?
私は、最初の5つの数字をEAのバージョンに、最後の4つの数字を取引されている分数に使っているだけです。

また、このように表示されるはずです→https://www.mql5.com/en/forum/120034


このアプローチ全体の問題は、私は時々同じアカウントで実行されている同一のエキスパート/シンボル/タイムフレームを持っているということです。そのため、最終的には手動で何かを変更する必要があり、それがマジック自体を手動で設定することを好む理由です。

 
gordon:
この方法の問題点は、同じ口座で同じエキスパート、シンボル、タイムフレームを実行することがあることです。だから、最終的に私はまだ手動で何かを変更する必要があります、私はちょうど手動でマジック自体を設定することを好む理由です。

秒を使うのはどうでしょうか?TimeCurrent() は、常に一意である数値を返します - 少なくとも、その秒数の範囲外では。

- エキスパートに GlobalVariable ID 番号を割り当てます。WindowExpertName()でそれを返します。

- そのIDを増分カウンタ(同じエキスパートを添付する場合)とTimeCurrent()で連結する。

- TimeCurrent()が返す数値が許容サイズを超える場合。そして、日、時間、分、秒のモジュールができるまで、年、月の量を破棄します。

 
cameofx:

秒を使うのはどうでしょうか?TimeCurrent() は、常に一意である数字を返します - 少なくともその秒数の範囲外では。

- エキスパートに ID 番号を割り当てる。WindowExpertName()でそれを返します。

- そのIDをインクリメント・カウンターとTimeCurrent()で連結する。

- TimeCurrent()で返された数字が許容サイズを超えたら、年数や月数を破棄する。日、時間、分、秒のモジュールが得られるまで、年および月の数を破棄します。

なぜなら、そのマジックのためにパーシステンスレベルを維持しなければならないからです。ターミナルが再起動したらどうなる?魔法は違うものになる...

 
gordon:

なぜなら、そのマジックのためにパーシステンスレベルを維持しなければならないからです。ターミナルが再起動したらどうなる?魔法は違うものになる...

やれやれ、私の編集スピードに負けましたね :)) 。編集しておきました。書き忘れました It's a GlobalVariable.