Discussion de l'article "L’implémentation d'un mode multi-devises dans MetaTrader 5" - page 5

 
Lazarev:

Dites-moi,

1. si je n'ai besoin que du Bid et du Ask des autres devises, est-il juste d'utiliser des "espions" ?

2. c'est juste une idée, n'y a-t-il pas la possibilité dans la fonction onChartEvent de vérifier les événements d'autres devises et pas seulement de la devise actuelle ?

3. est-il possible de fixer la valeur du timer à moins de un dans l'événement onTimer, de sorte que la valeur des cotations soit téléchargée beaucoup plus souvent et que l'heure du dernier tick soit retardée d'un temps minimum ?

4. ou est-il possible d'utiliser "CHARTEVENT_CUSTOM+n" pour vérifier, dans mon cas, le croisement des mashes sur d'autres graphiques ?

1. Utilisation.

2. Il existe une option. L'événement d'une autre devise doit être envoyé au graphique où l'EA avec OnChartEvent() est défini.

3. non. un est le minimum.

4. Peut.

 

J'ai créé un simple "indicateur espion" SendEvent.mq5, qui envoie un événement lorsqu'une nouvelle cotation arrive :

#property indicator_chart_window
#property indicator_plots 0
int OnInit()
  {
   return(0);
  }

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
   EventChartCustom(0,1,0,0,_Symbol);
   return(rates_total);
  }

J'ai créé un conseiller expert simple qui reçoit des événements de cet indicateur et tente d'effectuer une opération de trading (voici une partie, le texte complet se trouve dans le fichier joint) :

void OnChartEvent(const int id, // Gestionnaire d'événements ChartEvent
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)            // sparam contient le nom de l'instrument
  {
      // demande Digit,Point,Ask,Bid pour l'instrument pour lequel l'événement s'est produit
      if(!SymbolInfoInteger(sparam,SYMBOL_DIGITS,dig)) Print("SymbolInfoInteger(SYMBOL_DIGITS) ERROR!");
      if(!SymbolInfoDouble(sparam,SYMBOL_POINT,p)) Print("SymbolInfoDouble(SYMBOL_POINT) ERROR!");
      if(!SymbolInfoDouble(sparam,SYMBOL_BID,Bid)) Print("SymbolInfoDouble(SYMBOL_BID) ERROR!");
      if(!SymbolInfoDouble(sparam,SYMBOL_ASK,Ask)) Print("SymbolInfoDouble(SYMBOL_ASK) ERROR!");
      d=(int)dig;
      if(1>0) // nous achetons toujours
        {
         q.action=TRADE_ACTION_DEAL; // remplir la structure MqlTradeRequest et essayer d'effectuer une opération commerciale
         q.symbol=sparam; // sparam contient le nom de l'outil
         q.volume=Lot;
         q.price=NormalizeDouble(Ask,d);
         q.sl=NormalizeDouble(Ask-p*StopLoss,d);
         q.tp=NormalizeDouble(Ask+p*TakeProfit,d);
         q.deviation=0;
         q.type=ORDER_TYPE_BUY;
         q.type_filling=ORDER_FILLING_FOK;
         // vérifier les propriétés de l'outil actuel
         Print("Bid=",DoubleToString(Bid,8),", Ask=",DoubleToString(Ask,8),", Digits=",d,", Points=",DoubleToString(p,8));
         // vérifier la structure de la demande d'échange que nous allons envoyer
         Print("q.action=",q.action,", q.symbol=",q.symbol,", q.volume=",q.volume,", q.price=",DoubleToString(q.price,d),", q.sl=",DoubleToString(q.sl,d),", q.tp=",DoubleToString(q.tp,d),", q.deviation=",q.deviation,", q.type=",q.type,", q.type_filling=",q.type_filling);
         Print(OrderCheck(q,ch));                                  // vérifier si une opération commerciale peut être effectuée
         Print("ch.retcode=",ch.retcode,", ch.comment=",ch.comment); // résultat
         Print("OrderSend:",OrderSend(q,s));                        // tenter d'effectuer une opération commerciale
         Print("s.retcode=",s.retcode,", s.comment=",s.comment);     // résultat
        }
      if(0>0) // si la condition est corrigée, nous vendrons
        {
         // аналогично для продажи
        }
     }
  }

Le conseiller expert reçoit des événements de l'indicateur, mais dans le testeur (à la fois avec et sans visualisation) ne peut pas effectuer une opération commerciale - l'erreur "Invalid Request" est renvoyée, code de retour 10013. En temps réel, il fonctionne normalement. Si l'opération commerciale dans le conseiller expert est effectuée à partir de OnTick() au lieu de OnChartEvent(), elle fonctionne également correctement.

J'ai inséré l'envoi d'une demande de transaction dans le modèle de conseiller expert proposé par l'auteur de l'article dans CodeBase - les opérations de transaction ne fonctionnent pas non plus (même erreur).

Quelqu'un peut-il me dire quelle en est la raison ? J'ai lu dans ce fil que OnChartEvent() n' est pas traité dans le testeur, mais dans ce cas les événements envoyés par l'indicateur sont traités dans le testeur, mais il est impossible d'exécuter une opération commerciale à partir de OnChartEvent() dans le testeur.

Dossiers :
ea.mq5  4 kb
SendEvent.mq5  1 kb
[Supprimé]  
zdd:

J'ai créé un simple "indicateur-espion" SendEvent.mq5, qui envoie un événement lorsqu'une nouvelle cotation arrive :

J'ai créé un Conseiller Expert simple qui reçoit des événements de cet indicateur et essaie de faire une opération de trading (je donne une partie du texte, le texte complet est dans le fichier joint) :

Le conseiller expert reçoit des événements de l'indicateur, mais dans le testeur (avec et sans visualisation) ne peut pas effectuer une opération commerciale - l'erreur "Invalid Request" est renvoyée, code de retour 10013. En temps réel, il fonctionne normalement. Si une opération commerciale dans le conseiller expert est effectuée à partir de OnTick() au lieu de OnChartEvent() - cela fonctionne également bien.

J'ai inséré l'envoi d'une demande d'opération dans le modèle de conseiller expert proposé par l'auteur de l'article dans CodeBase - les opérations commerciales ne fonctionnent pas non plus (même erreur).

Quelqu'un peut-il me dire quelle en est la raison ? J'ai lu dans ce fil que OnChartEvent() n' est pas traité dans le testeur, mais dans ce cas les événements envoyés par l'indicateur sont traités dans le testeur, mais il est impossible d'exécuter une opération commerciale à partir de OnChartEvent() dans le testeur.

Essayez de ramener mon poisson à mon esprit. Bien sûr, la logique n'est pas complète et très bête, mais elle semble être très similaire à ce dont vous avez besoin.

Au moins les positions du marché s'ouvrent à la fois dans le testeur et sur la démo.

Je ne sais pas pourquoi (je suis trop paresseux pour le découvrir), mais votre exemple m'a donné 10013 dans n'importe quelle situation.

PS

Il est préférable de lier des objets standards (tels que CAccountInfo et CTrade). Mais si vous avez la patience de tout écrire vous-même, j'en serai ravi.

D'ailleurs, pour l'implémentation de l'espion lui-même, il vaut mieux s'inspirer de l'article, ou en faire une copie modifiable (je suggère par exemple de remplacer cette année "(long)_Period" par la date d'envoi de l'événement ou d'autres informations utiles). Votre variante est en quelque sorte assez "brute".

Dossiers :
DemoEA.mq5  20 kb
 
Interesting:

Essayez de faire fonctionner mon poisson. La logique est incomplète et très obtuse, mais elle semble très proche de ce dont vous avez besoin.

Merci, j'ai compris. Si vous déclarez les structures MqlTradeRequest et MqlTradeResult au niveau global, cela fonctionne !
 
Merci beaucoup pour cet article !
 

J'essaie d'obtenir les prix pour trois paires EURUSD, EURGBP, GBPUSD. Tout fonctionne bien lorsque je sélectionne "Tous les ticks" ou "Prix ouverts uniquement" dans le testeur de stratégie. Mais si je choisis "Every tick based on real ticks", alors pour une raison quelconque, plusieurs événements "New Bar" peuvent se produire en une minute pour un instrument.

Pour répéter, vous pouvez sélectionner un intervalle, par exemple de 2016.07.15 à 2016.07.19. Voici un exemple de journal, observez la 7ème minute, la 9ème minute :

2016.07.15 00:05:00 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.8333

2016.07.15 00:05:00 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.1119

2016.07.15 00:05:00 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33399

2016.07.15 00:06:00 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.8334

2016.07.15 00:06:00 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.1119

2016.07.15 00:06:00 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33394

2016.07.15 00:07:19 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.8333700000000001

2016.07.15 00:07:19 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11174

2016.07.15 00:07:19 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33382

2016.07.15 00:07:19 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.8333700000000001

2016.07.15 00:07:19 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11174

2016.07.15 00:07:19 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33381

2016.07.15 00:07:19 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.8333700000000001

2016.07.15 00:07:19 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11174

2016.07.15 00:07:19 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33384

2016.07.15 00:08:00 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.83329

2016.07.15 00:08:00 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11167

2016.07.15 00:08:00 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33394

2016.07.15 00:09:00 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.83327

2016.07.15 00:09:00 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11166

2016.07.15 00:09:00 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33396

2016.07.15 00:09:00 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.83327

2016.07.15 00:09:00 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11166

Quelle est la raison de ce comportement lorsque l'on sélectionne le mode "All ticks based on real ticks" ?
 
ooparadise:

J'essaie d'obtenir les prix pour trois paires EURUSD, EURGBP, GBPUSD. Tout fonctionne bien lorsque je sélectionne "Tous les ticks" ou "Prix ouverts uniquement" dans le testeur de stratégie. Mais si je choisis "Every tick based on real ticks", alors pour une raison quelconque, plusieurs événements "New Bar" peuvent se produire en une minute pour un instrument.

Pour répéter, vous pouvez sélectionner un intervalle, par exemple de 2016.07.15 à 2016.07.19. Voici un exemple de journal, observez la 7ème minute, la 9ème minute :

Quelle est la raison de ce comportement lorsque l'on sélectionne le mode "All ticks based on real ticks" ?

Comment attraper l'événement "New bar" ? Dans la version 1375, la précision de l'arrivée des ticks a été améliorée en millisecondes :

Testeur : Ajout d'un support pour le temps à la précision de la milliseconde. Auparavant, dans le testeur de stratégie, le quantum de temps était d'une seconde.

  • Les fonctions EventSetMillisecondTimer et Sleep fonctionnent désormais avec plus de précision dans le testeur de stratégie.
  • La précision de la soumission des ticks lors du test des Expert Advisors multidevises a été améliorée. Auparavant, si plusieurs ticks étaient placés en une seconde (le volume de ticks d'une barre de minutes est supérieur à 60), ils étaient tous assignés à la même heure. Lorsque l'on teste des conseillers experts mono-monnaie, cela n'a pas beaucoup d'importance, car les ticks sont simplement transmis au conseiller expert de manière séquentielle. Cependant, lors de tests sur plusieurs paires, il est important de savoir quel tic-tac de la paire est arrivé en premier. Auparavant, les ticks de chaque symbole étaient transmis au conseiller expert de manière séquentielle : d'abord tous les ticks d'un symbole pendant une seconde, puis tous les ticks d'un autre symbole. Désormais, ils sont transmis en tenant compte des millisecondes.

    Lors des tests sur des ticks réels, les millisecondes sont extraites des données du tick original. Lors de la génération de ticks, les millisecondes sont épelées en fonction du volume du tick. Par exemple, s'il y a 3 ticks en une seconde, les temps 000, 333 et 666 millisecondes leur seront attribués.
 

J'attrape unenouvelle barre de la manière décrite dans l'article. C'est à dire que l'indicateur envoie l'évènement "New Bar" de cette manière (par rapport au temps précédent minutes, heures, jours, mois) :

   double price_current=price[rates_total-1];

   TimeCurrent(time);

   if(prev_calculated==0)

     {

      EventCustom(CHARTEVENT_INIT,price_current);

      prev_time=time; 

      return(rates_total);

     }

//--- new tick

   if((flag_event & CHARTEVENT_TICK)!=0) EventCustom(CHARTEVENT_TICK,price_current);       


//--- check change time

   if(time.min==prev_time.min && 

      time.hour==prev_time.hour && 

      time.day==prev_time.day &&

      time.mon==prev_time.mon) return(rates_total);


//--- new minute

   if((flag_event & CHARTEVENT_NEWBAR_M1)!=0) EventCustom(CHARTEVENT_NEWBAR_M1,price_current); 

MISE A JOUR : Le problème a disparu lors de l'installation de la build 1375.

 

Merci pour cet article très complet. Je n'avais jamais entendu parler de EventChartCustom. J'ai essayé d'autres événements graphiques, mais ils ne prenaient en compte que les événements causés par l'action humaine. Cela résout beaucoup de choses.

D'ailleurs, je travaille sur MQL4, c'était à 98% la même chose.

Merci beaucoup.

 

Merci beaucoup, c'est très utile. C'est un excellent travail !