Numéro magique automatique - page 2

 
jjc

Il y a quelque chose qui m'échappe. Si j'ouvre deux graphiques, par exemple USDJPY H1, et que j'ajoute une instance de l'EA à chacun d'eux, les deux utilisent le nombre magique 9999033.

Oui, cette option n'a pas été intégrée car je n'en ai jamais eu l'utilité. La seule possibilité de distinguer deux graphiques identiques (à ma connaissance) serait de hacher la poignée de la fenêtre...

mais alors vous perdriez la persistance sur les redémarrages et les fermetures de graphiques, et donc des ordres orphelins peuvent être ou seront créés en conséquence.

 
BarrowBoy:

L'application de terminal MT est-elle un "conteneur", avec un seul hWnd pour "l'ensemble" ?

Oui. Il s'agit d'une application MDI assez typique. Il y a une fenêtre de niveau supérieur qui contient des choses comme des barres d'outils, des volets et la zone client MDI. Cette dernière contient ensuite chaque graphique, et chaque graphique consiste en fait en deux fenêtres : un conteneur avec la zone de dessin à l'intérieur. Chacun de ces éléments possède son propre handle hWnd. La fonction WindowHandle() renvoie le handle de la zone de dessin, et par conséquent, en utilisant trois fois l'appel API GetParent(), vous obtenez le hWnd de la fenêtre MT4 de niveau supérieur.

 

fwiw, j'utilise ci-dessous et je n'ai jamais eu de doublons. Même EA sur jusqu'à 10 graphiques [de n'importe quel type].

Je n'ai pas de réponse à la surcharge massive de données réelles transmises à la fonction de hachage. J'ai juste mis tout ce qu'il fallait, y compris l'évier de cuisine, c'est à dire que je ne suis pas un mathématicien..., j'ai juste martelé et ciselé jusqu'à ce que je n'ai jamais eu de répétitions - même au démarrage du terminal avec 10 profils de graphiques tous de la même EA...

Évidemment, j'aimerais avoir une méthode meilleure et plus descriptible/logique... alors commencez à la mettre en pièces :O)

#define EMPTYSTRING     ""
#define EAIDMIN         1
#define EAIDMAX         21473


  //+------------------------------------------------------------------+
//
int iMakeHash (string s1, string s2=EMPTYSTRING, string s3=EMPTYSTRING, string s4=EMPTYSTRING, string s5=EMPTYSTRING
              ,string s6=EMPTYSTRING, string s7=EMPTYSTRING, string s8=EMPTYSTRING, string s9=EMPTYSTRING, string s10=EMPTYSTRING)
{
  /*
  Produce 32bit string hash code from  a string composed of up to TEN concatenated input strings.
  WebRef: http://www.cse.yorku.ca/~oz/hash.html
  KeyWrd: "djb2"
  FirstParaOnPage:
  "  Hash Functions
    A comprehensive collection of hash functions, a hash visualiser and some test results [see Mckenzie
    et al. Selecting a Hashing Algorithm, SP&E 20(2):209-224, Feb 1990] will be available someday. If
    you just want to have a good hash function, and cannot wait, djb2 is one of the best string hash
    functions i know. it has excellent distribution and speed on many different sets of keys and table
    sizes. you are not likely to do better with one of the "well known" functions such as PJW, K&R[1],
    etc. Also see tpop pp. 126 for graphing hash functions.
  "

  NOTES:
  0. WARNING - mql4 strings maxlen=255 so... unless code changed to deal with up to 10 string parameters
     the total length of contactenated string must be <=255
  1. C source uses "unsigned [char|long]", not in MQL4 syntax
  //
  Downside?
    original code uses UNSIGNED - MQL4 not support this, presume could use type double and then cast back to type int.
  */
  string s = StringConcatenate(s1,s2,s3,s4,s5,s6,s7,s8,s9,s10);
  int iHash = 5381;
  int iLast = StringLen(s)-1;
  int iPos=0;

  while( iPos <= iLast )    //while (c = *str++)  [ consume str bytes until EOS hit {isn't C concise!} ]
  {
    //original C code: hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    iHash = ((iHash << 5) + iHash) + StringGetChar(s,iPos);    //StringGetChar() returns int
    iPos++;
  }
  return(MathAbs(iHash));
  
}//iMakeHash()




  //+------------------------------------------------------------------+
//
int iMakeExpertId ()
{
  int i1a,i2a,i1b,i2b;
  int iExpertId = EAIDMAX+1;
  while(iExpertId<EAIDMIN || iExpertId>EAIDMAX)
  {
    i1a=TimeLocal(); i2a=GetTickCount();
    Sleep(500);
    i1b=TimeLocal(); i2b=GetTickCount();
    MathSrand(iMakeHash(Symbol()
                        ,DoubleToStr(Period(),Digits)
                        ,DoubleToStr(i2a*WindowBarsPerChart()/Period(),Digits-1)
                        ,DoubleToStr(WindowTimeOnDropped()/i2b,Digits+1)
                        ,StringConcatenate(i2a/Period()
                                          ,Symbol()
                                          ,Period()
                                          ,i1a
                                          ,i2b*WindowBarsPerChart()/Period()
                                          ,i1b/WindowBarsPerChart()
                                          ,WindowTimeOnDropped()
                                          )
                        )
              );

    iExpertId = MathRand();  //here, on 2nd rand call, is even btr (tests seem to say this...)
  }

  return(iExpertId);

}//iMakeExpertId()

daaaaamn... these results are when had diff EAIDMAX! Anyway, just can't get the staff these days 0 lol
  /*test extract:
12:06:22 "EXPERT ID = "19736
12:06:21 "EXPERT ID = "16236
12:06:20 "EXPERT ID = "4633
12:06:19 "EXPERT ID = "26753
12:06:18 "EXPERT ID = "28286
12:06:16 "EXPERT ID = "23335
12:06:15 "EXPERT ID = "4036
12:06:14 "EXPERT ID = "12879
12:06:13 "EXPERT ID = "8095

12:06:08 "EXPERT ID = "7940
12:06:07 "EXPERT ID = "10700
12:06:06 "EXPERT ID = "24889
12:06:05 "EXPERT ID = "16055
12:06:04 "EXPERT ID = "12774
12:06:03 "EXPERT ID = "10058
12:06:02 "EXPERT ID = "29346
12:06:01 "EXPERT ID = "14624
12:06:00 "EXPERT ID = "18432
*/
 
fbj:

fwiw, j'utilise ci-dessous et je n'ai jamais eu de doublons. Même EA sur jusqu'à 10 graphiques [de n'importe quel type].

Je n'ai pas de réponse à la surcharge massive de données réelles transmises à la fonction de hachage. J'ai juste mis tout ce qu'il fallait, y compris l'évier de cuisine, c'est à dire que je ne suis pas un mathématicien..., j'ai juste martelé et ciselé jusqu'à ce que je n'ai jamais eu de répétitions - même au démarrage du terminal avec 10 profils de graphiques, tous de la même EA...

Évidemment, j'aimerais avoir une méthode meilleure et plus descriptible/logique... alors commencez à la mettre en pièces :O)

J'aime bien. En particulier le bon vieux djb2 hash.

 

Très impressionnant, les gars :)

Les conteneurs MDI me ramènent en arrière <soupir>.

Je persiste à dire que, IMHO, les Magic Numbers sont trop importants pour être appliqués au hasard !

Je suis sûr que CB confirmerait que la récupération prévisible au redémarrage est un élément extrêmement important dans un système robuste...

FWIW

-BB-

 

Avec ce code, un EA est capable de reconnaître ses propres ordres si la plateforme s'arrête. Il utilise des variables globales, donc si vous voulez rendre l'EA "inmune" à l'arrêt du PC, il pourrait être réécrit pour utiliser des fichiers au lieu des variables globales. J'ai également joint un exemple qui ouvre une position juste au moment de l'initialisation et la ferme dans la barre suivante, vous pouvez charger l'expert en 1M timeframe, arrêter metatrader et ensuite l'ouvrir à nouveau, attendez juste la prochaine barre pour voir comment l'EA ferme son ordre. Cela n'a pas été prouvé avec des graphiques multiples ni trompé avec des ordres multiples, mais qu'en pensez-vous ?

int MagicNumber;
 
int init()
{
   // Unique sting id.    
   string id = WindowExpertName() + Symbol() + Period();
    
    
   // If there isn't already a Global Variable with the id in wich search for the MagicNumber create it  
   if(!GlobalVariableCheck( id))
   {
      MagicNumber = WindowHandle(Symbol(),0);   
      GlobalVariableSet( id, MagicNumber);
   }
   else // Just get the MagicNumber for the unique id
   {
      MagicNumber = GlobalVariableGet( id);
   }
      
}
Dossiers :
 
jjc wrote >>

Je l'aime bien. En particulier le bon vieux hash djb2.

Merci - mais je me sens vraiment gêné d'avoir codé de manière aussi peu informée dans makeexpertid...

Il est encore tôt, mais peut-être que quelqu'un repérera le(s) défaut(s)... s'il(s) est(sont) présent(s)...

 
BarrowBoy wrote >>

Très impressionnant, les gars :)

Les conteneurs MDI me ramènent en arrière <soupir>.

Je persiste à dire que, IMHO, les Magic Numbers sont trop importants pour être appliqués au hasard !

Je suis sûr que CB confirmerait que la récupération prévisible au redémarrage est un élément extrêmement important dans un système robuste...


FWIW

-BB-

Je persiste à dire que, IMHO, les nombres magiques sont trop importants pour être appliqués au hasard !

Pour sûr BB, les données vip. J'ai passé beaucoup trop de temps à essayer de découvrir une donnée unique que de multiples instances d'un EA pourraient utiliser. Cette donnée devait être reproductible de telle sorte que tous les fichiers ouverts puissent être cartographiés lors de la récupération ou du redémarrage. Je voulais permettre à n'importe quel nombre d'instances de la même EA ccy+par graphique d'ouvrir "d'une manière ou d'une autre" un nom de fichier unique et, au redémarrage, de le rouvrir comme par magie...


Les données de la poignée de fenêtre pourraient être ce "facteur X" ?

 
fbj:

pour sûr BB, vip datums. J'ai passé beaucoup trop de temps à essayer de découvrir une donnée unique que plusieurs instances d'un EA pourraient utiliser. Cette donnée devait être reproductible de telle sorte que tous les fichiers ouverts puissent être cartographiés lors de la récupération ou du redémarrage. Je voulais permettre à n'importe quel nombre d'instances de la même EA ccy+par graphique d'ouvrir "d'une certaine manière" un nom de fichier unique et de le rouvrir par magie au redémarrage...

Je ne vois pas comment cela est possible sans que MT4 ou l'utilisateur n'attribue un ID à chaque EA. Ou, plus précisément, je ne vois rien qui n'implique pas quelque chose de très désagréable comme la génération d'un ID unique et la modification du fichier .chr de l'EA pour stocker l'ID dans les paramètres externes de l'EA.


Et, pour le divertissement général, ce qui suit ne fait pas vraiment avancer la discussion, mais remplace l'entrée du hachage djb2 par une valeur dont l'unicité est garantie (au prix d'appels de DLL). Je ne sais pas à quel point djb2 est censé être bon pour des choses comme les GUIDs, mais je viens d'essayer de générer 1.000.000 d'IDs sans aucune collision. Mais cela ne résout toujours pas le problème du redémarrage.


#import "ole32.dll"
   int CoCreateGuid(int & Bytes[]);
#import

int GenerateMagicNumber()
{
   // Generate a 16-byte GUID
   int Bytes[4];
   CoCreateGuid( Bytes);
   
   // Hash the GUID using djb2
   int iHash = 5381;
   for (int i = 0; i < 4; i++) {
      //original C code: hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
      iHash = (( iHash << 5) + iHash) + Bytes[ i];
   }
   return (MathAbs( iHash));
}
 
fbj wrote >>

Les données de la poignée de fenêtre pourraient être ce "facteur X" ?

Si vous ne fermiez pas partiellement des ordres, vous pourriez utiliser le commentaire de l'ordre pour stocker les informations sur la paire/le cadre temporel d'origine ?

Ainsi l'EA, au redémarrage, pourrait savoir s'il y avait des ordres antérieurs et quel numéro magique il était donc censé utiliser ?

NB

Gardez les commentaires à < 25 et vérifiez sur le LEFT(OrderComments(), 24) sinon les trucs [sl] ou [tp] pourraient affecter les choses.

Suppose que <tout l'historique> soit laissé disponible dans l'onglet Historique du compte !

FWIW

-BB-

Raison: