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

 
SGarnov:

Pour faciliter les choses prenez mon code source, il a une logique qui fonctionne, sauf pour le problème que j'ai décrit, je ne le comprends pas bien, ma tête est en ébullition mais je n'arrive à rien.

Placez-vous un seul ordre en attente ou deux dans des directions différentes ?
 
SGarnov:
J'ai l'impression que le robot devient plus fort, je ne sais pas quoi en faire.

@MakarFX le fait déjà. Ne nous mettons pas en travers du chemin.

Ce que je voulais dire...Ecrivez tout de façon à ce que ce soit clair pour vous (personnellement/personnellement), ne tirez pas le code avec du copier-coller.

et un squelette de robot grandement simplifié ressemble à quelque chose comme ça :

int ticket=-1;             // тикет открытого ордера
bool inited=false;      // признак завершения инициализации

int OnInit()
{
   ticket=-1;
   inited=false;
   // ещё надо проверить параметры, но пока чёрт с ними
   // пробуем загрузить прежнее состояние
   if (LoadState()) {
      // из файла, базы или глоб.переменных загрузились
      if (!CheckState()) {
         // проверили, плохо всё..
         ClearState(); // удалить и поругаться
         Alert("Усё пропало, шеф !");
         return INIT_FAILED();
      }
   }
   return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
   if (inited) {
      // инициализация была проведена, стейт мог уже менятся во время работы
      SaveState(); // сохраняем куда-то там
   }
}

void OnTick()
{
   //// ЧТОБЫ БЫ БЫЛО ХОРОШО, 
   //// НЕ БОЛЕЕ 1-го ПРИКАЗА Open/Close/Modify на тик
   //// И ЗАВЕРШИТЬ ВСЁ ПО БЫСТРОМУ
   if (!inited) {
      // связь есть, тики идут
      // довести инициализацию до нужной кондиции
      if (!DoInit()) {
         // не довелась
         Alert("вот же блин...");
         ExpertRemove();
      } else {
         // в DoInit проставлен корректный ticket
         inited=true;
      }
      return;
   }
   // всё проиничено, ticket или -1 если нет нифига или реально тикет
   //// РАЗБОРЫ С ТИКЕТАМИ
   if (ticket<0) {
      // нет открытых ордеров
      // может открыть/переоткрыть ?
   } else {
      if (!OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) {
         // что-то не так с синхронизацией, просто пропустим тик
         return;
      }
      if (OrderCloseTime()!=0) {
         // ордер закрылся ручками или по стопам/тейкам (или стопаут, приплыли)
         OnCloseOrder();   // обработать, разобраться
         ticket=-1;        // нет у нас больше тикета..
         // в этот тик больше не успеть
         return;
      } else {
         if ((OrderStopLoss()==0 && SL!=0) || (OrderTakeProfit()==0 && TP!=0)) {
            // свежачок - надо ему выстаить Тейк и/или стоп
            
         } else {
            // для реала - проверять сработку Sl/Tp на ГЕПАХ, ЭТО ВАЖНО
         }
      }
   }
   //// РАЗБОРЫ с БАРАМИ
   CheckForOnBar();
   ///  и так далее...
}
void OnTimer()
{
   // тики завершаем быстро-быстро, поэтому открытия баров дополнительно проверяем по таймеру
   CheckForOnBar();
}

la bière fait des merveilles et rend les gens plus gentils :-)

 
MakarFX:
Placez-vous un seul ordre en attente ou deux dans des directions différentes ?
Je place toujours un ordre en attente
 
SGarnov:
Je mets toujours un seul en attente.

Essayez-le, demandez-le

//+------------------------------------------------------------------+
//|                                                   SGarnov.v2.mq4 |
//|                                           Copyright 2020, DrMak. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, DrMak."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
//--- input parameters
input int      T_Profit = 2;     // Коэффициент Take Profit
input int      S_Loss   = 200;   // Уровень Stop Loss
input double   O_Lots   = 0.01;  // Лоты
input int      SL_Count = 2;     // Количество убыточных ордеров
input int      Slippage = 30;    // Проскальзывание
input int      N_Magic  = 888;   // Magic

datetime T_Start;
double sl_price,tp_price,t_profit,s_loss;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- 
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   t_profit = S_Loss*T_Profit;
   tp_price = NormalizeDouble(t_profit * Point(), Digits)+GetPointLoss();
//---
   s_loss   = MathMax(S_Loss, MarketInfo(_Symbol, MODE_STOPLEVEL));
   sl_price = NormalizeDouble(s_loss * Point(), Digits);

   // Удаляем отложенный ордер после профита
   if(CountOrders(-1)==1) DeletePending();
   // Проверяем серию убыточных ордеров
   if(GetLossOrders()<=SL_Count)
     {
      // Устанавливаем отложенный ордер
      SendPending();
     }

   // Проверяем наличие ордеров BUY
   if(CountOrders(0)>0)
     {
      // Устанавливаем StopLoss/TakeProfit
      ModifyOrder();
     }

   // Проверяем наличие ордеров SELL
   if(CountOrders(1)>0)
     {
      // Устанавливаем StopLoss/TakeProfit
      ModifyOrder();
     }
  }
//+------------------------------------------------------------------+
//| Модификация ордера                                               |
//+------------------------------------------------------------------+
void ModifyOrder()
  {
   int ticket=0;
   for(int pos=OrdersTotal()-1;pos>=0;pos--)
     {
      if(OrderSelect(pos,SELECT_BY_POS)==true)
        {
         if(OrderSymbol()==_Symbol)
           {
            if(OrderStopLoss()==0)
              {
               if(OrderType()==OP_BUY)
                 {
                  if(OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()-sl_price, OrderOpenPrice()+tp_price, OrderExpiration()))
                    {Print("Ордер модифицирован");}
                  else
                    {Print("Ошибка модификации ордера:", GetLastError());}
                 }
               if(OrderType()==OP_SELL)
                 {
                  if(OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()+sl_price, OrderOpenPrice()-tp_price, OrderExpiration()))
                    {Print("Ордер модифицирован");}
                  else
                    {Print("Ошибка модификации ордера:", GetLastError());}
                 }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| Подсчет ордеров по типу                                          |
//+------------------------------------------------------------------+
//|  0 - ордера типа BUY          1 - ордера типа SELL               |
//|  2 - ордера типа BUYLIMIT     3 - ордера типа SELLLIMIT          |
//|  4 - ордера типа BUYSTOP      5 - ордера типа SELLSTOP           |
//|  6 - ордера типа Balance     -1 - Все типы ордеров               |
//+------------------------------------------------------------------+
int CountOrders(int or_ty=-1) 
  {
   int cnt=0;
   for(int pos=OrdersTotal()-1;pos>=0;pos--)
     {
      if(OrderSelect(pos,SELECT_BY_POS)==true)
        {
         if(OrderSymbol()==_Symbol)
           {
            if(or_ty<0 || or_ty==OrderType()) cnt++;
           }
        }
     }
   return(cnt);
  }
//+------------------------------------------------------------------+
//| Установка отложенного ордера                                     |
//+------------------------------------------------------------------+
void SendPending()
  {
   double op=0;
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(OrderSelect(i, SELECT_BY_POS)==true)
        {
         if(CountOrders(-1)==1)
           {
            if(OrderType()==OP_BUY)
              {
               if(OrderStopLoss() != 0)
                 {
                  op=OrderStopLoss();
                  if(OrderSend(_Symbol,OP_SELLSTOP,O_Lots,op,Slippage,0,0,NULL,N_Magic))
                    {Print("Отложенный ордер установлен");}
                  else
                    {Print("Ошибка установки отложеного одера: ", GetLastError());}
                 }
              }
            if(OrderType()==OP_SELL)
              {
               if(OrderStopLoss() != 0)
                 {
                  op=OrderStopLoss();
                  if(OrderSend(_Symbol,OP_BUYSTOP,O_Lots,op,Slippage,0,0,NULL,N_Magic))
                    {Print("Отложенный ордер установлен");}
                  else
                    {Print("Ошибка установки отложеного одера: ", GetLastError());}
                 }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| Удаление отложенного ордера                                      |
//+------------------------------------------------------------------+
void DeletePending()
  {
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(OrderSelect(i, SELECT_BY_POS)==true)
        {
         if(CountOrders(-1)==1)
           {
            if(OrderType()==OP_BUYSTOP || OrderType()==OP_SELLSTOP)
              {
               if(OrderMagicNumber() == N_Magic)
                 {
                  if(OrderDelete(OrderTicket()))
                    {Print("Отложенный ордер удален");}
                  else
                    {Print("Ошибка удаления отложеного одера: ", GetLastError());}
                 }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| Возвращает время начала цикла                                    |
//+------------------------------------------------------------------+
datetime TimeStart()
  {
   datetime ts=0;
   if(OrdersTotal()!=0)
     {
      for(int pos=OrdersTotal()-1;pos>=0;pos--)
        {
         if(OrderSelect(pos,SELECT_BY_POS)==true)
           {
            if(OrderSymbol()==_Symbol)
              {
               if(OrderMagicNumber()!=N_Magic)
                 {
                  ts=OrderOpenTime();
                 }
              }
           }
        }
     }
   else
   if(OrdersTotal()==0)
     {
      for(int pos=0; pos<OrdersHistoryTotal(); pos++)
        {
         if(OrderSelect(pos, SELECT_BY_POS, MODE_HISTORY))
           {
            if(OrderSymbol()==_Symbol)
              {
               if(OrderType()==OP_BUY || OrderType()==OP_SELL)
                 {
                  if(OrderProfit()>0)
                    {
                     if(ts<OrderCloseTime())
                       {
                        ts=OrderCloseTime();
                       }
                    }
                 }
              }
           }
        }
     }
   return(ts);
  }
//+------------------------------------------------------------------+
//|  Возвращает пункты убытка закрытых ордеров с начала цикла        |
//+------------------------------------------------------------------+
double GetPointLoss()
  {
   double result=0,b=0,s=0;;
   int i=OrdersHistoryTotal();
   for(int pos=0; pos<i; pos++)
     {
      if(OrderSelect(pos, SELECT_BY_POS, MODE_HISTORY))
        {
         if((OrderSymbol()==_Symbol))
           {
            if(OrderType()==OP_BUY || OrderType()==OP_SELL)
              {
               if(OrderProfit()<0)
                 {
                  if(OrderCloseTime()>TimeStart())
                    {
                     if(OrderType()==OP_BUY&&OrderProfit()<0)
                       {
                        b+=OrderOpenPrice()-OrderClosePrice();
                       }
                     if(OrderType()==OP_SELL&&OrderProfit()<0)
                       {
                        s+=OrderClosePrice()-OrderOpenPrice();
                       }
                    }
                 }
              }
           }
        }
     }
   return(b+s);
  }
//+------------------------------------------------------------------+
//|  Возвращает кол-во серии убыточных ордеров                       |
//+------------------------------------------------------------------+
int GetLossOrders()
  {
   int cnt=0;
   int i=OrdersHistoryTotal();
   for(int pos=0; pos<i; pos++)
     {
      if(OrderSelect(pos, SELECT_BY_POS, MODE_HISTORY))
        {
         if((OrderSymbol()==_Symbol))
           {
            if(OrderCloseTime()>TimeStart())
              {
               if(OrderProfit()<0) cnt++;
              }
           }
        }
     }
   return(cnt);
  }
//+------------------------------------------------------------------+
 
MakarFX:

Essayez-le, demandez-le

C'est en marche. Je vous tiens au courant. Merci pour votre aide.
 
SGarnov:
Je vous ferai savoir ce qui se passe. Merci pour votre aide.

Quelqu'un peut-il expliquer la raison de ce comportement ?

J'ouvre une commande

2021.07.29 18:53:57.436 '60744458': order was opened : #1639674290 sell 0.01 USDJPY at 109.519 sl: 0.000 tp: 0.000

alors le conseiller expert le modifie

2021.07.29 18:53:57.647 '60744458': modify order #1639674290 sell 0.01 USDJPY at 109.519 sl: 0.000 tp: 0.000 -> sl: 109.919 tp: 108.719

et ensuite cette merde arrive

2021.07.29 18:53:58.313 '60744458': order #1639674290 sell 0.01 USDJPY closing at 0.000 failed [Off quotes]
2021.07.29 18:53:57.647 '60744458': close order #1639674290 sell 0.01 USDJPY at 109.519 sl: 0.000 tp: 0.000 at price 0.000

La chose intéressante est que cela se produit sur l'USDJPY et ne se vend que sur les autres paires.

 
MakarFX:

Quelqu'un peut-il expliquer la raison de ce comportement ?

J'ouvre une commande

alors le conseiller expert le modifie

et puis cette merde arrive

La chose intéressante est que cela ne se produit que sur l'USDJPY et que tout va bien sur les autres.

Si vous voulez comprendre quelque chose, vous devez apprendre à obtenir le maximum d'informations utiles dans un minimum de cycles...

 
Alexey Viktorov:

Pour comprendre quelque chose, apprenez à extraire les informations les plus utiles en un minimum de cycles...

C'est bien de parler quand on sait ce qu'il faut faire...

aide avec des conseils sur la manière de "tirer le meilleur parti des informations utiles".

 
MakarFX:

Quelqu'un peut-il expliquer la raison de ce comportement ?

J'ouvre une commande

alors le conseiller expert le modifie

et puis cette merde arrive

La chose intéressante est que cela se produit sur l'USDJPY et ne se vend que sur les autres paires.

Est-ce ainsi que fonctionne le conseiller dont vous avez écrit le code ?
 
SGarnov:
Est-ce ainsi que fonctionne l'EA dont vous avez écrit le code ?
C'est bon, le problème était le terminal.