sihirli sayı oluşturma

 
/**
* 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 :
[ ... Özet fonksiyonu ... ]

Kayıt için, fbj bir zamanlar iyi bilinen djb2 karma işlevini kullanarak benzer bir şey yaptı: https://www.mql5.com/en/forum/120034/page2

 
Başlangıçta bu http://www.cs.hmc.edu/~geoff/classes/hmc.cs070.200101/homework10/hashfuncs.html'den, özellikle de CRC varyantı olarak etiketlenenden (djb2'ye çok benzeyen) ilham aldım. . Tek başına bu karma, kolayca çarpışma üretemesem de, bana yeterince güven vermedi, bazen iki benzer dizenin karmaları arasında yalnızca çok az bit farklılık gösteriyordu. Bu yüzden, değişen h dönüşlü üç varyantını yarattım ve 3 alt karmanın hepsini bir araya ekledim. Bunlardan biri çarpışırsa, tamamen farklı bir şekilde hesaplanmış iki tane daha var. Şimdi girdi dizisindeki her değiştirilen bit, karmadaki tüm bitlerin yarısından fazlasını değiştirir ve tüm bitler tamamen rastgele görünür.


Yukarıdaki bağlantınızda bahsedilen djb2, etrafındaki yüzlerce satır olmadan basitçe şöyle yazılabilir:
 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 :
Yukarıdaki bağlantınızda bahsedilen djb2, etrafındaki yüzlerce satır olmadan basitçe şöyle yazılabilir: [...]

Özellikle djb2'yi bırakın, karma algoritmalar konusunda uzman değilim, ancak karma değerinin (sürümünüzdeki h değişkeni) 5381'e başlatılmasının önemli olarak kabul edildiğini hatırlıyorum, ancak kimse tam olarak neden olduğundan emin değil.

 
*    magic = makeMagicNumber(name+ Symbol() + Period());
Küçük düşürmek gibi olmasın ama bunu da kullanabilmelisin:
*    magic = makeMagicNumber(WindowExpertName() + Symbol() + Period());
Kodu (ve karma makaleyi!) gönderdiğiniz için teşekkür ederiz.

Soru - Aynı grafikte, aynı algoritmada vb. birden fazla siparişi açıp kapatmak için bir yöntem üzerinde çalışıyorum.

2 adımda yaklaşıyorum -

1) bir tamsayı olarak bir temel MN (yukarıdaki kodun yaptığı gibi) oluşturmak. Taban, her çizelge/sembol/zaman çerçevesi için her zaman aynı olacaktır.
2) her belirli sipariş gönderimi için ondalık nokta olarak ifade edilen belirli bir son ekin üretilmesi, bir son ek kullanılmadığında onu tekrar kullanılabilir hale getirmek

Dolayısıyla MN, XXXXXX.YYY olur, burada X taban ve Y özel sonektir. Son ekler .001 ile başlar ve her yeni gönderim için .001 ile artar. Her sipariş gönderiminde, şu anda kullanılmayan en düşük son eki atayacaktır. Bu şekilde, MN tabanını yeniden oluşturarak ve son ekler arasında dolaşarak MN'yi daha sonra alabilirim.

Biraz fazla karmaşık görünüyor. Bunu yapmanın daha iyi bir yolu var mı?

Bittiğinde elimdekileri yayınlıyorum.
 
Bir NuB olarak, neden 'şifreli' bir MagicNumber isteyip istemediğinizden emin değilim?
EA # sürümü için sadece ilk 5 rakamı ve işlem gördüğü dakika sayısı için son 4 rakamı kullanıyorum.
 
FourX :
Bir NuB olarak, neden 'şifreli' bir MagicNumber isteyip istemediğinizden emin değilim?
EA # sürümü için sadece ilk 5 rakamı ve işlem gördüğü dakika sayısı için son 4 rakamı kullanıyorum.

Örneğinizde Symbol() nasıl MN'nin bir parçası olur? Bir EA numaranız ve bir Zaman Çerçevesi numaranız var, peki ya sembol?

Siparişlerimi yalnızca MN ile tanımlarım, sipariş listesi üzerindeki döngülerim yalnızca OrderMagicNumber() ile karşılaştırır, sizinkilerin de sembol adını kontrol etmesi gerekir. Sipariş listesiyle bir şeyler yapan birkaç başka bağımsız komut dosyam var, örneğin, EA'ların hisse senedi arsalarını çizin veya alım satımları başka bir platforma kopyalayın, belirli bir Çiftte belirli bir EA'nın alım satımlarını tanımlamak için hepsinin yalnızca sihirli sayıya ihtiyacı var ve belirli bir Zaman Çerçevesi.

Farklı EA'larım için hiç seri numaraları kullanmıyorum, tüm EA'larım için 4 veya 5 harflik kısa adlar kullanıyorum. Örneğin, snowball.mq4 adlı bir EA "snow" adını alır. Bu, kodda sabittir ve asla değişmez. Bu kısa adı sipariş yorumları için de kullanıyorum.

Yani 3 şeyim var: kısa isim, Sembol ve zaman dilimi. Bunu bir MN'ye dönüştürmenin en uygun yolu bir karmadır. EA'larım için isimler yerine numaralar verebilirdim ama yine de sembol adını bir sayıya dönüştürmenin kolay bir yolu olmazdı. Bir Hash, tüm bu sorunları bir kerede çözer.

 
FourX :
Bir NuB olarak, neden 'şifreli' bir MagicNumber isteyip istemediğinizden emin değilim?
EA # sürümü için sadece ilk 5 rakamı ve işlem gördüğü dakika sayısı için son 4 rakamı kullanıyorum.

Bunu da görmelisiniz -> https://www.mql5.com/en/forum/120034


Tüm bu yaklaşımla ilgili sorunum, bazen aynı hesapta çalışan aynı uzman/sembol/zaman çerçevesine sahip olmam. Sonunda yine de bir şeyi manuel olarak değiştirmek zorunda kalacağım, bu yüzden sihrin kendisini manuel olarak ayarlamayı tercih ediyorum.

 
gordon :
Tüm bu yaklaşımla ilgili sorunum, bazen aynı hesapta çalışan aynı uzman/sembol/zaman çerçevesine sahip olmam. Sonunda yine de bir şeyi manuel olarak değiştirmek zorunda kalacağım, bu yüzden sihrin kendisini manuel olarak ayarlamayı tercih ediyorum.

Saniye kullanmaya ne dersiniz? TimeCurrent(), her zaman benzersiz olacak bir sayı döndürür - en azından bu saniye aralığının dışında.

- Uzmanınız için bir GlobalVariable Kimlik Numarası atayın. WindowExpertName() ile döndürün.

- Bu kimliği bir artış sayacıyla (aynı uzmanı eklemeniz gerekir) ve TimeCurrent () ile birleştirin

- TimeCurrent() tarafından döndürülen sayı izin verilen boyutu aşarsa. Ardından gün, saat, dakika ve saniye modülünü elde edene kadar yıl ve ay miktarını atın.

 
cameofx :

Saniye kullanmaya ne dersiniz? TimeCurrent(), her zaman benzersiz olacak bir sayı döndürür - en azından bu saniye aralığının dışında.

- Uzmanınız için bir Kimlik Numarası atayın. WindowExpertName() ile döndürün.

- Bu kimliği bir artış sayacı ve TimeCurrent () ile birleştirin

- TimeCurrent() tarafından döndürülen sayı izin verilen boyutu aşarsa. Ardından gün, saat, dakika ve saniye modülünü elde edene kadar yıl ve ay miktarını atın.

Çünkü o zaman o sihir için bir kalıcılık seviyesini korumanız gerekir. Terminaliniz yeniden başlatılırsa ne olur? Büyü farklı olurdu...

 
gordon :

Çünkü o zaman o sihir için bir kalıcılık seviyesini korumanız gerekir. Terminaliniz yeniden başlatılırsa ne olur? Büyü farklı olurdu...

Tanrım, düzenleme hızımı geçtin :)). editledim. Bir GlobalVariable olduğunu söylemeyi unuttum.