Quelqu'un sait-il comment développer un indicateur multi-devises ? - page 3

 
4x_Gypsy:

Le gros indice était "Mais je ne sais pas comment faire ça.".

L'absence de toute réponse de la part du PO indique que quelque chose ne va pas. Je pense que le PO a été frustré par le manque de compréhension et a abandonné le fil. Il y a des années, j'ai fait la même chose. J'ai plus appris sur différents sites/forums que sur celui-ci parce que personne ne prenait le temps de réaliser à quel point j'étais nouveau et ne cessait de poster des exemples et d'avoir des discussions qui dépassaient complètement ma compréhension à ce moment-là.

De votre point de vue, vous avez peut-être raison, mais d'un autre côté, j'ai vu de nombreuses questions auxquelles il était possible de répondre en jetant un coup d'œil rapide dans les documentations et vous avez vraiment l'impression d'être un idiot en répondant à ces questions encore et encore.

De plus, il y a Google et une option de recherche ici. Si je ne sais pas comment faire quelque chose, c'est l'étape suivante pour essayer de résoudre le problème par moi-même.

Dans le cas du sujet de ce fil de discussion, je ne sais pas comment coder un système multi-devises, j'aurais répondu à Google ou cherché ici un code déjà existant.

 
gooly:

De votre point de vue, vous avez peut-être raison, mais d'un autre côté, j'ai vu de nombreuses questions auxquelles il a été répondu simplement en jetant un coup d'œil rapide dans les documentations et vous avez vraiment l'impression d'être un imbécile en répondant à ces questions encore et encore.

De plus, il y a Google et une option de recherche ici. Si je ne sais pas comment faire quelque chose, c'est l'étape suivante pour essayer de résoudre le problème par moi-même.

Dans le cas du sujet de ce fil, je ne sais pas comment coder un système multi-devises, j'aurais répondu à Google ou cherché ici un code déjà existant.

Merci pour le feedback, et content qu'il soit positif. lol

Je suis désolé pour ceux qui sont concernés par la façon dont je suis apparu dans cette situation. Je suis vraiment une personne pacifique, sans drame, qui ignore généralement la plupart des choses avec lesquelles je ne suis pas d'accord.

 

Salut les gars,

Désolé pour la longue période sans activité ici. J'étais en voyage pour le travail et également occupé avec certains projets et a dû laisser le projet de côté pendant un certain temps ....

Après avoir lu les mises à jour du post, j'ai quelques points à clarifier :

  1. Je ne veux pas que quelqu'un code toutes les choses pour moi, il suffit de me montrer la bonne direction et je fais le reste. Bon... je vais tester la solution WHRoeder maintenant et faire mes trucs et plus tard je posterai le résultat ici. Suggestion de WHRoeder: https://www.mql5.com/en/forum/158938
  2. Avant de créer ce sujet, j'ai fait une recherche de messages similaires, mais je n'ai rien trouvé... alors je l'ai créé.
  3. Je suis désolé de prendre beaucoup de temps pour répondre, mais j'ai vraiment été surchargé de travail, mais maintenant je continue à travailler avec l'indicateur.
  4. Désolé pour mon mauvais anglais ! ma langue est le portugais et quand je poste anglais, besoin d'utiliser google translator et il n'est pas parfait.


 
Voici mon test.

Il suffit de permettre aux utilisateurs d'informer leurs actifs, et après, montrer les valeurs High/Low de toutes les paires.

Si, l'une des paires sélectionnées est la même que la fenêtre active, ses taux sont mis à jour correctement. Mais les autres paires ne montrent que les taux quand l'indicateur a été ajouté... et ne sont plus mis à jour...

Comme vous pouvez le voir sur l'image ci-dessous, l'indicateur a été ajouté dans la fenêtre GBPUSD... et les taux GBPUSD ont été mis à jour tick par tick. Mais l'EURUSD ne se met pas à jour et reste avec la même valeur.

Taux copié


Ci-dessous, le code de l'indicateur :

//+------------------------------------------------------------------+
//|                                                MultiCurrency.mq4 |
//|                         Copyright 2016, Wemerson Couto Guimarães |
//|                  https://www.mql5.com/pt/users/wemersonrv/seller |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Wemerson Couto Guimarães"
#property link      "https://www.mql5.com/pt/users/wemersonrv/seller"
#property version   "1.00"
#property strict
#property indicator_separate_window

input string UsePairs="EURUSD,GBPUSD"; // Pares separados por vírgula.

struct pair_struct{
   string symbol;
   MqlRates rates[];
};
pair_struct pairs[];
bool initial;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){
   int i=0, j=0, c;
   string _pairs[], msg="";
   bool pairok=false;
   initial = true;
   ENUM_INIT_RETCODE result = INIT_SUCCEEDED;
   
   StringSplit(UsePairs, StringGetCharacter(",",0), _pairs);
   
   for( i=0; i< ArraySize(_pairs); i++){
      pairok=false;
      
      for( j=0; j<SymbolsTotal(true); j++){
         if( SymbolName(j, true) == _pairs[i]){
            pairok=true;
            break;
         }
      }
      if( pairok ){
         c=ArraySize(pairs);
         ArrayResize(pairs, c+1);
         pairs[c].symbol = _pairs[i];
      }else{
         msg += _pairs[i] + ", ";
      }
   }
   if( msg != "" ){
      string invalids = ArraySize(pairs)== 1?"Invalid Pair: ": "Invalid Pairs: ";
      msg = invalids +  StringSubstr(msg,0,StringLen(msg)-2) + ". Please Check!";
      Alert(msg);
      result = INIT_PARAMETERS_INCORRECT;
   }else{
      for(i=0; i<ArraySize(pairs); i++){
         ArrayCopyRates( pairs[i].rates, pairs[i].symbol, PERIOD_CURRENT );
      }
   }   
   
   return(result);

}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
   
   Comment("");
   
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {

   int i=0;
   if( initial ){
      for( i=0; i<ArraySize(pairs); i++){
         if(pairs[i].rates[0].time == 0) return(rates_total);
      }
      initial=false;
   }
   
   string log="";
   
   for(i=0; i<ArraySize(pairs); i++){
      log += "\nPair: " + pairs[i].symbol + 
             " - High: "+ DoubleToStr(pairs[i].rates[0].high, Digits()) + 
             " - Low: "+ DoubleToStr(pairs[i].rates[0].low, Digits());
   }

   Comment( "\n\n*** Pair Rates***\n" + log );
   return(rates_total);
   
}
//+------------------------------------------------------------------+

 
J'essaie d'utiliser RefreshRates() mais toujours avec le même résultat... seule la paire de la même fenêtre fonctionne, les autres paires ne sont pas mises à jour.
 
wemersonrv:
J'essaie d'utiliser RefreshRates() mais toujours avec le même résultat... seule la paire à la même fenêtre fonctionne, les autres paires ne sont pas mises à jour.

RefreshRates() n'a rien à voir avec les données MqlRates. L'exemple de code de WHRoeder n'est valable que pour les builds Pre-600. Pour la dernière version, vous devez vérifier les différents points mentionnés dans mon post, comme le test des codes de retour de ArrayCopyRates(), ainsi que les codes d'erreur, la taille du tableau de taux et, comme une précaution supplémentaire signalée par WHRoeder, la validité de l'attribut de temps.

PS ! Si vous avez des difficultés avec l'anglais, envoyez-moi un PM. Je suis portugais (Portugal)

 

Salut les gars.

En testant, j'ai inclus une "recopie" des taux dans la fonction OnCalculate... en ajoutant une boucle qui libère d'abord le tableau de la paire dans toutes les itérations, puis recopie les taux. Il semble que cela fonctionne et ne renvoie pas d'erreur.

Je ne sais pas si c'est la meilleure façon de faire ce dont j'ai besoin, mais apparemment cela fonctionne et sans erreur.


   int i=0;
   if( initial ){
      for( i=0; i<ArraySize(pairs); i++){
         if(pairs[i].rates[0].time == 0) return(rates_total);
      }
      initial=false;
   }

   // My change to recopy rates every tick by adding a loop at starting of OnCalculate() to do this
   // AS FMIC says, ArrayCopyRates needs the array without content, 
   // then before recopy, free the array.
   for(i=0; i<ArraySize(pairs); i++){
      ArrayFree(pairs[i].rates);
      ArrayCopyRates(pairs[i].rates, pairs[i].symbol, PERIOD_CURRENT);
   }
 
wemersonrv: En testant, j'ai inclus une "recopie" des taux dans la fonction OnCalculate... en ajoutant une boucle qui libère d'abord le tableau de paires dans toutes les itérations, puis recopie les taux. Il semble que cela fonctionne et ne renvoie pas d'erreur.
  1. Comme indiqué dans la documentation.
    Si l'on demande des données (le nom du symbole et/ou la période de temps diffèrent de ceux actuels) à partir d'un autre graphique, il est possible que le graphique correspondant n'ait pas été ouvert dans le terminal client et que les données nécessaires doivent être demandées au serveur. Dans ce cas, l'erreur ERR_HISTORY_WILL_UPDATED (4066 - les données de l'historique demandées sont en cours de mise à jour) sera placée dans la variable last_error, et il faudra redemander
    Et vérifié ici
    ArrayCopyRates retournera une erreur s'il n'y a pas d'historique du tout (ERR_NO_HISTORY_DATA = 4073.) Les appels répétés échouent également jusqu'à ce que le téléchargement soit complet. Quand il y a de l'historique mais pas à jour, ArrayCopyRates retourne un code valide ET met aussi `_LastError` à ERR_HISTORY_WILL_UPDATED (= 4066.)
  2. Testez votre code de retour, mettez en veille et réessayez si nécessaire. Quelles sont les valeurs de retour des fonctions ? Comment les utiliser ? - MQL4 forum and Common Errors in MQL4 Programs and How to Avoid Them - MQL4 Articles
 

Une mise à jour pour ceux qui suivent ce fil !

J'ai aidé l'OP via PM à corriger son code car il a des difficultés en anglais et nous parlons tous les deux portugais. Lors de nos tests, nous sommes tombés sur un autre phénomène "étrange" qui se produit avec la fonction"ArrayCopyRates()". Lorsque l'on utilise un tableau MqlRates avec"ArrayCopyRates()" dans un EA, le tableau de données est un tableau virtuel qui rapporte toujours l'état actuel des choses, donc les données sont toujours fraîches.

Cependant, dans un Indicateur, cela ne semble pas être le cas. Le tableau n'est pas une copie virtuelle mais plutôt une copie statique fixée dans le temps au moment où"ArrayCopyRates()" a été appelé. Les données ne sont pas mises à jour lorsque le symbole est différent du symbole du graphique. Lorsqu'il s'agit du même symbole que le graphique, les données du tableau sont "vivantes" et se mettent à jour comme prévu, mais lorsqu'il s'agit d'un autre symbole, il s'agit d'une copie statique.

Donc, pour que cela fonctionne dans un indicateur, il faut appeler la fonction "ArrayCopyRates()" à chaque appel à l'événement OnCalculate() si des données fraîches sont nécessaires.

 

Bonjour à tous.

  • FMIC, merci pour votre soutien !
  • WHRoeder, merci aussi... Vous êtes toujours là pour nous tous !
  • Merci à tous les membres du forum pour vos considérations et même merci pour tout le débat qui a été généré dans ce fil. C'était très intéressant!

C'est (presque) la même chose que je fais plus tard, mais la différence est que je lance un ArrayFree avant ArrayCopyRates... et je ne fais pas les validations que vous m'avez aidées.

Voici le code final que FMIC m'a aidé. Il fonctionne normalement maintenant dans un code indicateur.. :

input string UsePairs="NZDCAD,EURUSD,GBPUSD,USDJPY"; // pairs separated by commas
struct pair_struct{
   string symbol;
   MqlRates rates[];
   bool valid;
};
pair_struct pairs[];
bool initial;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){
   
   int i=0, j=0, c;
   string _pairs[], msg="";
   bool pairok=false;
   initial = true;
   ENUM_INIT_RETCODE result = INIT_SUCCEEDED;
   
   StringSplit(UsePairs, StringGetCharacter(",",0), _pairs);
   
   for( i=0; i< ArraySize(_pairs); i++){
      pairok=false;
      
      for( j=0; j<SymbolsTotal(true); j++){
         if( SymbolName(j, true) == _pairs[i] ){
            pairok=true;
            break;
         }
      }
      if( pairok ){
         c=ArraySize(pairs);
         ArrayResize(pairs, c+1);
         pairs[c].symbol = _pairs[i];
         pairs[c].valid = false;
      }else{
         msg += _pairs[i] + ", ";
      }
   }
   if( msg != "" ){
      string invalids = ArraySize(pairs)== 1?"Invalid Pair: ": "Invalid Pairs: ";
      msg = invalids +  StringSubstr(msg,0,StringLen(msg)-2) + ". Please Check!";
      Alert(msg);
      result = INIT_PARAMETERS_INCORRECT;
   }
   return(result);

}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
   
   Comment("");
   
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {

   InitializeRates();
   
   int i=0;
   string log="";
   for(i=0; i<ArraySize(pairs); i++){
      log += "\nPar: " + pairs[i].symbol;
      if( pairs[i].valid ){
         log += " - Time: "+ TimeToString( pairs[i].rates[0].time ) + 
                " - Open: "+ DoubleToString( pairs[i].rates[0].open, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) ) +
                " - Close: "+ DoubleToString( pairs[i].rates[0].close, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) ) +
                " - High: "+ DoubleToString( pairs[i].rates[0].high, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) ) +
                " - Low: "+ DoubleToString( pairs[i].rates[0].low, (int)MarketInfo( pairs[i].symbol, MODE_DIGITS ) );
      }else{
         log += " - Currently not valid!";
      }
   }

   Comment( "\n\n*** Pair Rates***\n" + log );
   return(rates_total);
   
}
//+------------------------------------------------------------------+

void InitializeRates(){
 
   for( int i=0; i<ArraySize( pairs ); i++ ){
      pairs[i].valid = false;
      ResetLastError();
      if( ArrayCopyRates(pairs[i].rates, pairs[i].symbol, PERIOD_CURRENT) > 0 ){
         if( _LastError == 0 ){
            if( ArraySize(pairs[i].rates) > 0 ){
               if( pairs[i].rates[0].time > 0 )
                  pairs[i].valid = true;
            }
         }
      }
   }

}