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

 
Valeriy Yastremskiy #:

pour stocker dans sa structure ou son tableau les prix requis avec les billets et peut-être autre chose, par exemple l'heure, et trier immédiatement après l'ajout par prix. Par ressources, si vous ne regardez pas souvent, c'est la même chose ou un peu plus cher, et si vous regardez souvent, c'est mieux de s'en souvenir. Bien sûr, si vous n'avez pas 100500 commandes) Alors cela peut être trop cher. En général, le tri dans une structure ou un tableau multidimensionnel n'est résolu que pour le premier indice malheureusement.

Parfois, j'utilise plusieurs tableaux unidimensionnels avec les mêmes index, billets, heure, prix. Et recherche par index des biens nécessaires. Par exemple, nous obtenons l'indice d'un temps plus court ou d'un prix plus élevé et nous obtenons le ticket de l'ordre nécessaire. Bien sûr, c'est une béquille, mais cela fonctionne clairement.

Merci - Je vais aussi jeter un coup d'oeil...
 
Valeriy Yastremskiy #:

pour stocker dans sa structure ou son tableau les prix souhaités avec les billets et peut-être autre chose, comme l'heure, et trier immédiatement après l'ajout par prix. Par ressources, si vous ne regardez pas souvent, c'est la même chose ou un peu plus cher, et si vous regardez souvent, c'est mieux de s'en souvenir. Bien sûr, si vous n'avez pas 100500 commandes) Alors cela peut être trop cher. En général, le tri dans une structure ou un tableau multidimensionnel n'est résolu que pour le premier indice malheureusement.

Parfois, j'utilise plusieurs tableaux unidimensionnels avec les mêmes index, billets, heure, prix. Et recherche par index des biens nécessaires. Par exemple, si nous obtenons l'indice d'un temps plus court ou d'un prix plus élevé, nous obtenons le ticket de l'ordre nécessaire. Bien sûr, c'est une béquille, mais cela fonctionne très bien.

Je l'ai fait de cette façon :

enum MT_ORD_STATE
  {
   ORD_NA,  // Not available
   ORD_SENT,
   ORD_ACTIVE,
   ORD_CHANGE_SENT,
   ORD_DEL_SENT
  };

struct MTOrder
  {
   ulong id;
   ulong Ticket;
   datetime Time;
   datetime TimeNotFound;
   double   Price;
   double   Vol;
   double   VolInit;
   uint     request_id;
   ENUM_ORDER_TYPE   Type;
   ENUM_ORDER_STATE State;
   MT_ORD_STATE MTState;
   int      Reserved;
   bool     Idf; // Identified
  };

...

   MTOrder  Orders[]; // С начала массива - ордера на покупку, по убыванию цены,
                      // С конца - на продажу, по возрастанию

Le tableau est toujours trié, un nouvel ordre est inséré à l'endroit voulu, avec décalage des autres ordres, lorsqu'un ordre est supprimé, il y a un décalage.

Mais ceci est dans MT5

 
JRandomTrader #:

Je l'ai fait de cette façon :

Le tableau est toujours trié, un nouvel ordre est inséré au bon endroit, avec un décalage des autres ordres, lorsqu'un ordre est supprimé, il y a un décalage.

Mais ceci est dans MT5.

Il serait bien d'avoir du code pour le décalage pendant l'écriture, la suppression et le tri. Ce n'est pas une tâche triviale pour moi de trier la structure du tableau par champs. Oui, et aussi des quarts de travail).

 
Valeriy Yastremskiy #:

Un code de décalage pour l'écriture, la suppression et le tri serait bien. Ce n'est pas une tâche triviale pour moi de trier une structure de tableau par champs. Et les quarts, aussi).

bool Tr2MT::InsertOrder(MTOrder &ord_tmp) // Из AddOrder (2 варианта), единственное место добавления ордеров в массив
{
 int i=0,n=0;
 string str="";
 ord_tmp.id=++st.LastOrdID;

 switch(ord_tmp.Type)
   {
    case ORDER_TYPE_BUY:
    case ORDER_TYPE_BUY_LIMIT:
      for(i=0,n=-1;i<ArraySize(Orders);i++)
        {
         if(Orders[i].id==0)
           {
            n=i; break;
           }
        }
      if(n<0) break;
      for(i=n;i>=0;i--)
        {
         if(i==0 || Orders[i-1].Price>=ord_tmp.Price)
           {
            Orders[i]=ord_tmp;
            SaveState();
            //str=OrdString();
            //Log(str);
            return true; //добавили
           }
         else
           {
            Orders[i]=Orders[i-1];
           }
        }
      break;
    case ORDER_TYPE_SELL:
    case ORDER_TYPE_SELL_LIMIT:
      for(i=ArraySize(Orders)-1,n=-1;i>=0;i--)
        {
         if(Orders[i].id==0)
           {
            n=i;
            break;
           }
        }
      if(n<0) break;
      for(i=n;i<ArraySize(Orders);i++)
        {
         if(i==ArraySize(Orders)-1 || Orders[i+1].Price<=ord_tmp.Price)
           {
            Orders[i]=ord_tmp;
            SaveState();
            //str=OrdString();
            //Log(str);
            return true; //добавили
           }
         else
           {
            Orders[i]=Orders[i+1];
           }
        }
      break;
    default:
      return false;
      break;
   }
 str="Can't add order - out of array!";
 ErrLog(str);
 return false; //не нашли места для ордера
}
bool Tr2MT::DelOrder(int n)
{
 int i;
 MTOrder ord_tmp={};

      switch(Orders[n].Type)
         {
          case ORDER_TYPE_BUY:
          case ORDER_TYPE_BUY_LIMIT:
            for(i=n;i<ArraySize(Orders);i++)
              {
               if(i==ArraySize(Orders)-1 || Orders[i+1].id==0 || Orders[i+1].Price>Orders[i].Price)
                 {
                  Orders[i]=ord_tmp; // Обнуляем
                  break;
                 }
               else
                 {
                  Orders[i]=Orders[i+1];
                 }
              }
            break;
          case ORDER_TYPE_SELL:
          case ORDER_TYPE_SELL_LIMIT:
            for(i=n;i>=0;i--)
              {
               if(i==0 || Orders[i-1].id==0 || Orders[i-1].Price<Orders[i].Price)
                 {
                  Orders[i]=ord_tmp; // Обнуляем
                  break;
                 }
               else
                 {
                  Orders[i]=Orders[i-1];
                 }
              }
            break;
          default:
            return false;
            break;
         }
 return true;
}

Et probablement la partie la plus intéressante :

bool Tr2MT::UpdOrder(int n) // Только если есть тикет или угадываем
{
 string str;
 int i;
 bool flag=false;
 MTOrder ord_tmp={0};
 ulong ticket=Orders[n].Ticket;

 if(ticket==0)
   {
    if(!GuessOrdTicket(n))return false; // Если угадываем - он будет в Orders[n].Ticket
    else ticket=Orders[n].Ticket;
   }

 switch(FindOrder(ticket,Orders[n].Time+100000))
   {
    case ORD_FOUND: //изменён или просто проверка
      //update (sync) order
      if(Orders[n].Price==OrderGetDouble(ORDER_PRICE_OPEN)) // Цена не изменилась
        {
         if(Orders[n].State==(ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)&&Orders[n].MTState!=ORD_NA)
           {
            if(Orders[n].Vol==OrderGetDouble(ORDER_VOLUME_CURRENT))
               return true; // Не нужно сохранять состояние, можно сразу выйти
            else
               Orders[n].Vol=OrderGetDouble(ORDER_VOLUME_CURRENT);
           }
         else
           {
            //Orders[n].State=(ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE);
            SetOrdState(Orders[n],(ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE)); // Обнулит и TimeNotFound
            if(Orders[n].Vol!=OrderGetDouble(ORDER_VOLUME_CURRENT))
               Orders[n].Vol=OrderGetDouble(ORDER_VOLUME_CURRENT);
           }
        }
      else // Цена изменилась
        {
         ord_tmp=Orders[n];
         //ord_tmp.State=(ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE);
         SetOrdState(ord_tmp,(ENUM_ORDER_STATE)OrderGetInteger(ORDER_STATE));
         ord_tmp.Price=OrderGetDouble(ORDER_PRICE_OPEN);
         ord_tmp.Vol=OrderGetDouble(ORDER_VOLUME_CURRENT);
         switch(Orders[n].Type)
           {
            case ORDER_TYPE_BUY:
            case ORDER_TYPE_BUY_LIMIT:
               if(ord_tmp.Price>Orders[n].Price) // Цена ордера увеличилась, перемещаем вверх (по массиву - вниз)
                 {
                  for(i=n;i>=0;i--)
                    {
                     if(i==0 // Конец массива ордеров
                        || ord_tmp.Price<=Orders[i-1].Price) // Следующий - по большей цене, вставляем перед ним
                       {
                        Orders[i]=ord_tmp;
                        break;
                       }
                     else
                       {
                        Orders[i]=Orders[i-1]; // Сдвигаем следующий элемент
                       }
                    }
                 }
               else // Цена ордера умньшилась, перемещаем вниз (по массиву - вверх)
                 {
                  for(i=n;i<ArraySize(Orders);i++)
                    {
                     if(i==ArraySize(Orders)-1 // Конец массива ордеров
                        || Orders[i+1].Ticket==0 // Следующий элемент пустой
                        || ord_tmp.Price>Orders[i+1].Price // Следующий - по меньшей цене, вставляем перед ним
                        || Orders[i+1].Price>Orders[i].Price) // Следующий - ордер уже на продажу
                       {
                        Orders[i]=ord_tmp;
                        break;
                       }
                     else
                       {
                        Orders[i]=Orders[i+1]; // Сдвигаем следующий элемент
                       }
                    }
                 }
               break;
            case ORDER_TYPE_SELL:
            case ORDER_TYPE_SELL_LIMIT:
               if(ord_tmp.Price>Orders[n].Price) // Цена ордера увеличилась, перемещаем вверх (по массиву - вниз)
                 {
                  for(i=n;i>=0;i--)
                    {
                     if(i==0 // Конец массива ордеров
                        || Orders[i-1].Ticket==0 // Следующий элемент пустой
                        || ord_tmp.Price<Orders[i-1].Price // Следующий - по большей цене, вставляем перед ним
                        || Orders[i-1].Price<Orders[i].Price) // Следующий - ордер уже на покупку
                       {
                        Orders[i]=ord_tmp;
                        break;
                       }
                     else
                       {
                        Orders[i]=Orders[i-1]; // Сдвигаем следующий элемент
                       }
                    }
                 }
               else // Цена ордера умньшилась, перемещаем вниз (по массиву - вверх)
                 {
                  for(i=n;i<ArraySize(Orders);i++)
                    {
                     if(i==ArraySize(Orders)-1 // Конец массива ордеров
                        || ord_tmp.Price>Orders[i+1].Price) // Следующий - по меньшей цене, вставляем перед ним
                       {
                        Orders[i]=ord_tmp;
                        break;
                       }
                     else
                       {
                        Orders[i]=Orders[i+1]; // Сдвигаем следующий элемент
                       }
                    }
                 }
               break;
            default:
               return false;
               break;
           }
        }
      SaveState();
      //str=OrdString();
      //Log(str);
      break;
    case ORD_HIST_FOUND: //исполнен || снят
      //delete order
      if(!DelOrder(n))
         return false;
      SaveState();
      str=OrdHistString(ticket); // Уточнить
      Log(str);
      break;
    case ORD_NOT_FOUND: //отправлен в историю?
      if(Orders[n].MTState!=ORD_NA)
        {
         Orders[n].MTState=ORD_NA;
         Orders[n].TimeNotFound=TimeCurrent();
         SaveState();
         printf(__FUNCTION__, "Order not found, ticket:",IntegerToString(Orders[n].Ticket)," TimeNF:",TimeToString(Orders[n].TimeNotFound,TIME_SECONDS));
        }
      else
        {
         if(TimeCurrent()-Orders[n].TimeNotFound>60) // > 60 секунд не найден
           {
            if(!DelOrder(n))
              return false;
            SaveState();
            str="Order not found >60s "+IntegerToString(ticket)+"\n";
            Log(str);
           }
        }
       break;
    default:
      return false; //не тот ордер
      break;
   }
 return true;
}
 
JRandomTrader #:

Merci.

Pas mal. Je n'aime pas les tableaux)))), et ça ne marche jamais du premier coup sans déboguer dans les tableaux. ))) Surtout les quarts, les copies, les tris non réguliers)))
 
Valeriy Yastremskiy #:

Merci.

Pas mal. Je n'aime pas les tableaux)))), et ça ne marche jamais du premier coup sans déboguer dans les tableaux. ))) Surtout les quarts, les copies, les tris non réguliers)))

Chaque outil est bon en soi.

Mais, erreur insidieuse de vérification et de re-vérification au coup par coup ;))

 

C'est ce que signifie un regard neuf sur votre ancien code !

Je vois deux défauts identiques, vestiges de la version précédente.

Une sous-optimalité évidente.

Et une conception obsolète.

 
Bonjour. Si je ne suis pas au bon endroit, veuillez m'indiquer où écrire, merci.

Vous recherchez un conseiller expert MT5 gratuit qui fermera TOUTES les positions lorsqu'un profit ou une perte est atteint, spécifié dans les paramètres, et ouvrira de nouvelles positions immédiatement dans la direction spécifiée dans les paramètres. Quelqu'un peut-il me donner un lien vers le fil de discussion ?
Ou peut-être connaissez-vous un EA qui ouvre juste une position sur le marché s'il voit qu'il n'y a pas de positions ouvertes et ne ferme pas.
 

MT4 1353

Quel type d'erreur est affiché dans le journal ?

Le code fonctionne correctement


 
Vitaly Muzichenko #:

MT4 1353

Quel type d'erreur est affiché dans le journal ?

Le code fonctionne correctement.


Il semble que certains objets créés via "new" ne soient pas détruits à la sortie.

Raison: