Toute question des nouveaux arrivants sur MQL4 et MQL5, aide et discussion sur les algorithmes et les codes. - page 522

 
PolarSeaman:

Quel rebondissement !)))

Ordre 1 (de# no, à#2) -- > Ordre2 (de#1, à#3) -- >Ordre3 (de#2, à# no)

A partir de là, vous pouvez trouver toute la chaîne.

Nous regardons le commentaire ouvert et s'il y a le numéro XXX, cela signifie qu'il a été précédemment fermé partiellement - cherchez le ticket XXX du commentaire et cherchez-le dans l'historique. Regardez le commentaire - s'il est de#YYY - cela signifie qu'il a été partiellement fermé auparavant aussi - cherchez le ticket YYY du commentaire et recherchez-le dans l'historique. Regardez le commentaire - s'il y a du#ZZZZ - cela signifie qu'il a été partiellement fermé plus tôt aussi - répétez la recherche. S'il n'y a pas de from#..., alors c'est le tout premier de toute la chaîne.

 
Artyom Trishkin:

Ordre 1 (de# no, à#2) -- > Ordre 2 (de#1, à#3) -- > Ordre 3 (de#2, à# no)

A partir de là, vous pouvez trouver toute la chaîne.

Nous regardons le commentaire ouvert et s'il y a le numéro XXX, cela signifie qu'il a été précédemment fermé partiellement - cherchez le ticket XXX du commentaire et cherchez-le dans l'historique. Regardez le commentaire - s'il est de#YYY - cela signifie qu'il a été partiellement fermé auparavant aussi - cherchez le ticket YYY du commentaire et recherchez-le dans l'historique. Regardez le commentaire - s'il y a du#ZZZZ - cela signifie qu'il a été partiellement fermé plus tôt aussi - répétez la recherche. S'il n'y a pas de from#..., alors c'est le tout premier de toute la chaîne.

Merci, il se peut qu'il y ait une commande en sens inverse, que je vais également hacher. J'ai peur de m'embrouiller. Je pense qu'il serait plus facile d'utiliser l'ordre Profit d'une certaine date, bien sûr, si nous sommes en mesure de savoir quand la position a été ouverte, car la date change lorsque la position est partiellement fermée.

 
Artyom Trishkin:

Ordre 1 (de# no, à#2) -- > Ordre 2 (de#1, à#3) -- > Ordre 3 (de#2, à# no)

A partir de là, vous pouvez trouver toute la chaîne.

Surveillez le commentaire ouvert et s'il y a un from#XXX, cela signifie qu'il a été partiellement fermé auparavant - cherchez le ticket XXX du commentaire et cherchez-le dans l'historique. Regardez le commentaire - s'il est de#YYY - donc il a été partiellement fermé plus tôt aussi - regardez le ticket YYY du commentaire et cherchez-le dans l'historique. Regardez le commentaire - s'il y a du#ZZZZ - cela signifie qu'il a été partiellement fermé plus tôt aussi - répétez la recherche. S'il n'y a pas de from#..., alors c'est le premier de toute la chaîne.

Artyom vous savez que ce n'est pas toujours le cas. Et pour ne pas tracer une chaîne, ne pas interroger le terminal trois fois - l'histoire est tout de même conduite dans des tableaux et des structures propres. Ce n'est pas différent de la gestion de votre propre base de données, à l'exception des étapes supplémentaires.

Le terminal et son API constituent le niveau le plus bas possible. Et pour mettre en œuvre la logique du robot, il est logique de faire de la comptabilité dans ses termes (commerce, chaîne, groupe, transaction - chacun l'appelle différemment). Il est simplement judicieux de les garder séparés et de ne pas essayer de les restaurer à chaque éternuement (tic/bar).

 
Maxim Kuznetsov:

Tu sais que ce n'est pas toujours le cas, Artyom. Ainsi, il n'est pas nécessaire de poser trois fois la question au terminal lors du suivi de la chaîne - l'histoire est toujours conduite dans ses propres tableaux et structures. Ce n'est pas différent de la gestion de votre propre base de données, à l'exception des étapes supplémentaires.

Le terminal et son API constituent le niveau le plus bas possible. Et pour la réalisation de la logique du robot, il est logique de tenir une comptabilité dans ses termes (commerce, chaîne, groupe, transaction - chacun l'appelle différemment). Il est simplement judicieux de le garder séparé et de ne pas essayer de le reconstruire à chaque éternuement (tic/bar).

J'ai tout fait depuis longtemps - je ne lis pas l'historique à chaque fois - mais il est toujours à jour, et je peux facilement et très rapidement y trouver tout ce dont j'ai besoin. Mais pour conseiller quelqu'un à faire de même, il me faut au moins quelques articles. Et donc j'ai écrit la logique pour trouver la chaîne entière.

 
PolarSeaman:

Merci, il se peut qu'il y ait une commande en sens inverse que je vais également déchiqueter. J'ai peur de m'embrouiller. Je pense qu'il serait plus facile d'utiliser la fonction Profit pour clôturer une position à partir d'une certaine date, bien sûr si vous pouvez savoir quand la position a été ouverte, car dans une clôture partielle, la date change.

Pour rechercher une chaîne, il suffit de connaître le ticket de la commande, la chaîne entière dont vous voulez connaître - passez le ticket comme paramètre à la fonction de recherche, et la sortie - un tableau rempli ou un tableau de structures avec toutes les données de chaque commande de la chaîne entière.

 
Artyom Trishkin:

Un tableau rempli ou un tableau de structures contenant toutes les données de chaque ordre de la chaîne entière.

Je ne sais même pas approximativement ce que tu viens de dire.

Montrez-moi au moins un exemple de ce que cela devrait être.

 
PolarSeaman:

Je ne sais même pas approximativement ce que tu viens de dire.

Donnez-moi au moins un exemple de ce que cela devrait être.

Je résous le problème de la manière suivante : je cherche des chaînes par l'histoire. Pour que l'historique soit disponible sans ambiguïté, j'utilise deux variantes :

  1. S'il n'y a pas de DLL, alors dans la description du programme, en 24 caractères gras )))), je précise que l'historique du compte doit toujours être chargé dans son intégralité (onglet Historique du compte de la fenêtre du terminal, menu contextuel - Tout l'historique).
  2. Avec DLL - Expert Advisor maintient à jour l'onglet "Historique du compte", indépendamment de toute action de l'utilisateur.

Fonctions permettant de déterminer l'ordre parent, si l'ordre actuel n'est pas le principal :

int GetSignOfPartialOrCloseByClose()
{
   string comment = OrderComment();
   if (comment == "")
      return 0;
   
   // Ордер образовался вследствии частичного закрытия
   int fromStart = StringFind(comment, "from #");
   if (fromStart >= 0)
      return GetTicketByPartialClose(comment, fromStart, OrderType(), OrderOpenTime());
   
   // Ордер образовался вследствии встречного закрытия
   if (StringFind(comment, "partial close") >= 0)
   {
      datetime openTime = OrderOpenTime();
      int type = OrderType();
      for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
      {
         if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
            continue;
            
         if (OrderOpenTime() != openTime)
            continue;
            
         if (OrderType() != type)
            continue;
            
         if (StringFind(OrderComment(), "partial close") < 0)
            continue;
            
         return OrderTicket();
      }
   }
   
   return 0;
}


int GetTicketByPartialClose(string comment, int fromStart, int orderType, datetime openTime)
{
   string sTicket = StringSubstr(comment, fromStart + 6);
   int iTicket = (int)StringToInteger(sTicket);
   int type = OrderType();
   if (!OrderSelect(iTicket, SELECT_BY_TICKET))
      return 0;
      
   if (OrderType() == type)                                                                        // Дочерний ордер указывает на родителя - уходим
      return iTicket;
      
   // Дочерний ордер указывает на противоположный ордер. Необходимо искать родительский
   for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
   {
      if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
         continue;
         
      if (OrderType() != orderType || OrderOpenTime() != openTime)
         continue;
         
      int iFind = StringFind(OrderComment(), "close hedge by #");
      if (iFind < 0)
         continue;
         
      sTicket = StringSubstr(OrderComment(), iFind + 16);
      int iNewTicket = (int)StringToInteger(sTicket);
      if (iNewTicket != iTicket)
         continue;
         
      return OrderTicket();
   }
   
   return 0;
}

Facile à utiliser :

   for (int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if (!OrderSelect(i, SELECT_BY_POS))
         continue;

      ....         

      int nFromTicket = GetSignOfPartialOrCloseByClose();                // Обязательно последней строкой в теле цикла, т. к. может измениться текущий выбранный ордер
   }


 
Ihor Herasko:

L'erreur la plus grossière ici est de spécifier la valeur 100 au lieu de ticket dans l'argument OrderDelete().

L'erreur suivante n'est pas aussi grossière, mais elle est liée au fait que la valeur calculée du Stop Loss est vérifiée, et non sa valeur réelle.

Le type de commande n'est pas non plus vérifié. Que faire si nous avons choisi un ordre au marché ? Comment le supprimer ? Le symbole de l'ordre n'a pas été vérifié.

En tenant compte de ces erreurs, nous obtenons le code de suppression de l'ordre en attente lorsque le prix atteint son Stop Loss :

De plus, dans votre code, le Stop Loss est vérifié immédiatement après l'ouverture de l'ordre. Il semble qu'après l'ouverture d'un ordre en attente, ce code ne soit plus exécuté. C'est-à-dire que vous devez séparer les branches d'exécution. L'un est chargé de fixer l'ordre et le second est responsable de son accompagnement.

Merci pour votre réponse détaillée !

En suivant vos conseils, j'ai séparé les branches et tout fonctionne.

Ensuite, j'ai été confronté à un problème d'ouverture simultanée de 10-15 ordres en attente, j'ai résolu ce problème en l'ajoutant après votre code :

if (OrdersTotal ()>0) return;

Je suis sûr qu'il y a un meilleur moyen.

Par votre code, pouvez-vous expliquer ce que signifie 1 ; i >=0 ; --i ?

for (int i = OrdersTotal() - 1; i >= 0; --i)
 

Veuillez m'aider à comprendre comment écrire un indicateur. J'ai dessiné un tel mannequin, comment faire une longueur d'indicateur à dessiner à des points de taille au-dessus de l'offre actuelle, à partir du moment, où l'indicateur est placé sur le graphique ? Peut-être que l'erreur est que je déplace ce tableau dans la mauvaise direction ?

Je sais que c'est "canonique", sans prev_calculé etc., mais j'en ai besoin comme ceci


#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
//---- plot 
#property indicator_label1  "myInd"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Blue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

double buff[], Bid;
input int lenght = 50, size = 5;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping

   ArrayResize(buff, 50);
   ArrayInitialize(buff, 0);
   SetIndexBuffer(0, buff, INDICATOR_DATA);
   //--- установим метку для отображения в DataWindow
   PlotIndexSetString(0,PLOT_LABEL,"myInd");   
//--- установим имя для показа в отдельном подокне и во всплывающей подсказке
   IndicatorSetString(INDICATOR_SHORTNAME,"myInd");
//--- укажем точность отображения значений индикатора
   IndicatorSetInteger(INDICATOR_DIGITS, _Point);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   for(int i = lenght-1; i>0; i--){
      buff[i] = buff[i-1];
   }
   buff[0] = Bid+size;
   


   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 
Roman Sharanov:

Veuillez m'aider à comprendre comment écrire un indicateur. J'ai dessiné un tel mannequin, comment faire une longueur d'indicateur à dessiner à des points de taille au-dessus de l'offre actuelle, à partir du moment, où l'indicateur est placé sur le graphique ? Peut-être que l'erreur est que je déplace ce tableau dans la mauvaise direction ?

Je sais que c'est "canonique", sans prev_calculé et autres trucs du genre.


Quel est le canon ? Il y a un document officiel - c'est exactement comme le vôtre.

1. Vous devez définir la sérialisation de tous les tableaux utilisés dans OnCalculate.

2. avant d'entrer dans la boucle, mettez buff[length]=Bid+size ; - vous obtiendrez approximativement ce que vous voulez. Une ligne courbe et à la fin une "visière" à Bid+size

3. observez les limites du tableau. Bien sûr, rates_total est à peine < longueur, mais vous ne pouvez pas vous tromper :-)

4.
buff[i] = buff[i+1]; // если тайм-серия (а вы подразумеваете их) то +
Raison: