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

 
MakarFX:
Avez-vous un EA qui supporte les ordres placés manuellement ?
Oui. Je place les ordres en attente manuellement ou j'ouvre simplement une transaction, puis le conseiller expert fonctionne.
 
SGarnov:
J'ai essayé de l'insérer, ça ne compile pas. Le code entier, si nécessaire, je mettrai une capture d'écran de la compilation. Je pense qu'il peut y avoir un autre problème, mon TP est fixé par rapport au STOP par un coefficient (variable externe), peut-être que cela peut être changé en réglage manuel et il sera plus facile pour EA d'ajouter ?

La fonction

  double GetPointLastLoss(){
            datetime t=0;
            double result=0,p=0,tp=0;
            int i=OrdersHistoryTotal(),magic=0;
         for(int pos=0; pos<i; pos++)
         {
          if(OrderSelect(pos, SELECT_BY_POS, MODE_HISTORY))
         {
          if((OrderSymbol()==_Symbol) && (OrderMagicNumber()==magic))
           {
            if(OrderType()==OP_BUY || OrderType()==OP_SELL)
              {
               if(t<OrderCloseTime())
                 {t=OrderCloseTime(); p=OrderProfit(); tp=OrderType();
                  if(tp==OP_BUY&&p<0)
                    {
                     result=OrderOpenPrice()-OrderClosePrice();
                    } else {result=0;}
                  if(tp==OP_SELL&&p<0)
                    {
                     result=OrderClosePrice()-OrderOpenPrice();
                    } else {result=0;}
                 }
              }
           }
        }
     }
   return(result);
  }

de la portée globale. magic=0 pour la compilation.

magic=0

	          
 
Galim_V:

La fonction

de la portée globale, enlever magic=0 pour la compilation.

Supprimé, aucune erreur de compilation, seulement 1 avertissement apparaît dans la troisième ligne de fonction dans la colonne tp=0 avec audition sur la variable externe int tp=0. Je ne comprends pas bien ce que le programmeur n'aime pas. Tout code attaché, si vous n'êtes pas difficile à corriger, la vérité est quelque part proche.

input int takeProfitC = 2;// Коэффициент Take Profit
input int stop_loss = 100;//Уровень Stop Loss
input int stop_count = 2;//Количество Stop Loss
input double lots = 0.01;//Лоты
input int slippage = 30;//Проскальзывание
input int datePeriod = 48;// Время удержания при SL


int tp = 0;
int tpc = 0;
double tp_price_old = 777;
int stopLossCount = 0;
datetime startOrder = 0;
int pending_ticket = 0;
int lastMagic = 0;
bool isLimitOn = false;
bool isStart = True;
datetime startTime = 0;
bool isFinal = false;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit() {
//
   //OrderSend(Symbol(), OP_SELL, 0.01, 0.76228, 300, 0, 0);
   //OrderSend(Symbol(), OP_SELLSTOP, 0.01, 0.77057, 300, 0, 0);
   //OrderSend(Symbol(), OP_BUYSTOP, 0.01, 0.76928, 300, 0, 0);
   tp = stop_loss * takeProfitC;
//---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
//--

}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick() {
//---
//Comment("StopCount: " + stopLossCount + "\n" + "CurrentStopC: " + stop_count);
   for(int i = OrdersTotal() - 1; i >= 0; i--) {
      if(OrderSelect(i, SELECT_BY_POS)) {
         if(OrderSymbol() == Symbol()) {
         int magic = OrderMagicNumber();
            if((OrderType() == OP_BUY || OrderType() == OP_SELL) && OrderOpenTime()) {
               int ticket = OrderTicket();
               if(!findPending(ticket)) {
                  if(OrderSelect(ticket, SELECT_BY_TICKET) && (((TimeCurrent() <= (startTime + datePeriod * 3600))) || isStart)) {
                     if(OrderType() == OP_BUY) {
                        double sl_price = NormalizeDouble(OrderOpenPrice() - Point() * MathMax(stop_loss, MarketInfo(Symbol(), MODE_STOPLEVEL)), Digits);
                        double tp_price = NormalizeDouble((OrderOpenPrice() + Point() * (tp)), Digits);
                        if(!OrderModify(OrderTicket(), OrderOpenPrice(), sl_price, tp_price, OrderExpiration())) {
                           Print("Ошибка модификации ордера:", GetLastError());
                        } else {
                           if(stopLossCount < stop_count && tp_price != tp_price_old){
                              pending_ticket = OrderSend(Symbol(), OP_SELLSTOP, lots, sl_price, slippage, 0, 0, NULL, OrderTicket());
                              lastMagic = ticket;
                              isLimitOn = true;
                              if(isStart){
                                 startTime = TimeCurrent();
                                 isStart = false;
                              }
                              tp_price_old = tp_price;
                              stopLossCount++;                         
                           }
                        }
                     } else if(OrderType() == OP_SELL) {
                        double sl_price = NormalizeDouble(OrderOpenPrice() + Point() * MathMax(stop_loss, MarketInfo(Symbol(), MODE_STOPLEVEL)), Digits);
                        double tp_price = NormalizeDouble((OrderOpenPrice() - Point() * (tp)), Digits);
                        if(!OrderModify(OrderTicket(), OrderOpenPrice(), sl_price, tp_price, OrderExpiration())) {
                           Print("Ошибка модификации ордера:", GetLastError());
                        } else {
                          if(stopLossCount < stop_count && tp_price != tp_price_old){
                              pending_ticket = OrderSend(Symbol(), OP_BUYSTOP, lots, sl_price, slippage, 0, 0, NULL, OrderTicket());
                              lastMagic = ticket;
                              isLimitOn = true;
                              if(isStart){
                                 startTime = TimeCurrent();
                                 isStart = false;
                              }
                              stopLossCount++;
                              tp_price_old = tp_price;  
                          }
                        }
                     }
                  }
               }
         }
         if(startTime > 0 && (TimeCurrent() >= (startTime + datePeriod * 3600))){
            deletePending(lastMagic);
            isFinal = true;
         }
            
         if(lastMagic != 0 && !IsSell() && !IsBuy() && magic == lastMagic) {
            tpc = 0;
            startTime = 0;
            stopLossCount = 0;
            deletePending(lastMagic);
            isStart = true;
            }
         }
     }
   }
   if((startTime > 0 || isFinal) && !IsSell() && !IsBuy()){
            tpc = 0;
            startTime = 0;
            stopLossCount = 0;
            isStart = true;
            isFinal = false;
   }
}
//+----------------------------------------------------------------------------+
//|  Возвращает пункты убытка последнего закрытого ордера в пунктах            |
//+----------------------------------------------------------------------------+
double GetPointLastLoss(){
            datetime t=0;
            double result=0,p=0,tp=0;
            int i=OrdersHistoryTotal(),magic=0;
         for(int pos=0; pos<i; pos++)
         {
          if(OrderSelect(pos, SELECT_BY_POS, MODE_HISTORY))
         {
          if((OrderSymbol()==_Symbol) && (OrderMagicNumber()==magic))
           {
            if(OrderType()==OP_BUY || OrderType()==OP_SELL)
              {
               if(t<OrderCloseTime())
                 {t=OrderCloseTime(); p=OrderProfit(); tp=OrderType();
                  if(tp==OP_BUY&&p<0)
                    {
                     result=OrderOpenPrice()-OrderClosePrice();
                    } else {result=0;}
                  if(tp==OP_SELL&&p<0)
                    {
                     result=OrderClosePrice()-OrderOpenPrice();
                    } else {result=0;}
                 }
              }
           }
        }
     }
   return(result);
  }                                                                
//+------------------------------------------------------------------+
bool findPending(int ticket) {
   for(int i = OrdersTotal() - 1; i >= 0; i--) {
      if(OrderSelect(i, SELECT_BY_POS)) {
         if(OrderMagicNumber() == ticket) {
            return true;
         }
      }
   }

   for(int i = OrdersHistoryTotal() - 1; i >= 0; i--) {
      if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) {
         if(OrderMagicNumber() == ticket) {
            return true;
         }
      }
   }
   return false;
}
//+------------------------------------------------------------------+
void deletePending(int magic) {
   for(int i = OrdersTotal() - 1; i >= 0; i--) {
      if(OrderSelect(i, SELECT_BY_POS)) {
         if(OrderMagicNumber() == magic) {
            if(OrderType() != OP_BUY && OrderType() != OP_SELL) {
               if(!OrderDelete(OrderTicket())) {
                  Print("Ошибка удаления отложеного одера: ", GetLastError());
               }
            }
            break;
         }
      }
   }
}
//+------------------------------------------------------------------+
bool IsSell()
{
   int count = 0;
   for (int trade = OrdersTotal () -1; trade >= 0; trade--)
   {
      if (OrderSelect (trade, SELECT_BY_POS, MODE_TRADES) 
          && OrderSymbol() == Symbol()
          && OrderType() == OP_SELL)
      {
         count++;
      }
      
   }
   if (count == 0)
      return false;
   else
      return true;
}
//+------------------------------------------------------------------+
bool IsBuy()
{
   int count = 0;
   for (int trade = OrdersTotal () -1; trade >= 0; trade--)
   {
      if (OrderSelect (trade, SELECT_BY_POS, MODE_TRADES) 
          && OrderSymbol() == Symbol()
          && OrderType() == OP_BUY)
      {
         count++;
      }
      
   }
   if (count == 0)
      return false;
   else
      return true;
}
 
SGarnov:

Supprimé, pas d'erreurs de compilation, seulement 1 avertissement s'affiche dans la troisième ligne de la fonction dans la colonne tp=0 avec audition sur la variable externe int tp=0. Je ne comprends pas bien ce que le programmeur n'aime pas. Tout code attaché, si vous n'êtes pas difficile à corriger, la vérité est quelque part à proximité.

Cela ressemble à ceci

//+------------------------------------------------------------------+
//|                                                   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   = 100;   // Уровень Stop Loss
input double   O_Lots   = 0.01;  //Лоты
input int      Input4;
input int      Input5;
input int      Input6;

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;
   s_loss   = MathMax(S_Loss, MarketInfo(Symbol(), MODE_STOPLEVEL));
   // Проверяем наличие ордеров BUY
   if(CountOrders(_Symbol, 0)>0)
     {
      // Проверяем последний закрытый ордер SELL на наличие убытка в пунктах
      if(GetPointLastLoss(1)>0)
        {
         // Если убыток есть, то добавляем пункты убытка
         sl_price = NormalizeDouble(Point() * s_loss, Digits);
         tp_price = NormalizeDouble(GetPointLastLoss(1)+Point() * t_profit, Digits);
         ModifyOrder(_Symbol, sl_price, tp_price);
        }
      else
        {
         // Если убытка нет
         sl_price = NormalizeDouble(Point() * s_loss, Digits);
         tp_price = NormalizeDouble(Point() * t_profit, Digits);
         ModifyOrder(_Symbol, sl_price, tp_price);
        }
     }
   // Проверяем наличие ордеров SELL
   if(CountOrders(_Symbol, 1)>0)
     {
      // Проверяем последний закрытый ордер BUY на наличие убытка в пунктах
      if(GetPointLastLoss(0)>0)
        {
         // Если убыток есть, то добавляем пункты убытка
         sl_price = NormalizeDouble(Point() * s_loss, Digits);
         tp_price = NormalizeDouble(GetPointLastLoss(0)+Point() * t_profit, Digits);
         ModifyOrder(_Symbol, sl_price, tp_price);
        }
      else
        {
         // Если убытка нет
         sl_price = NormalizeDouble(Point() * s_loss, Digits);
         tp_price = NormalizeDouble(Point() * t_profit, Digits);
         ModifyOrder(_Symbol, sl_price, tp_price);
        }
     }
  }
//+--------------------------------------------------------------------------------------------------------------------+
//| Подсчет ордеров по типу                                                                                            |
//+--------------------------------------------------------------------------------------------------------------------+
//|  0 - ордера типа BUY          1 - ордера типа SELL                                                                 |
//|  2 - ордера типа BUYLIMIT     3 - ордера типа SELLLIMIT                                                            |
//|  4 - ордера типа BUYSTOP      5 - ордера типа SELLSTOP                                                             |
//|  6 - ордера типа Balance     -1 - Все типы ордеров                                                                 |
//+--------------------------------------------------------------------------------------------------------------------+
int CountOrders(string symb="", int or_ty=-1) 
  {
   int cnt=0;
   if(symb=="0") symb=_Symbol;
   for(int pos=OrdersTotal()-1;pos>=0;pos--)
     {
      if(OrderSelect(pos,SELECT_BY_POS)==true)
        {
         if(OrderSymbol()==symb || symb=="")
           {
            if(or_ty<0 || or_ty==OrderType()) cnt++;
           }
        }
     }
   return(cnt);
  }
//+----------------------------------------------------------------------------+
//| Модификация ордера                                                         |
//+----------------------------------------------------------------------------+
//|    sl - ценовой уровень стопа                                              |
//|    tp - ценовой уровень тейка                                              |
//+----------------------------------------------------------------------------+
void ModifyOrder(string symb="", double sl=0, double tp=0)
  {
   if(symb=="0") symb=_Symbol;
   for(int pos=OrdersTotal()-1;pos>=0;pos--)
     {
      if(OrderSelect(pos,SELECT_BY_POS)==true)
        {
         if(OrderSymbol()==symb || symb=="")
           {
            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                                                  |
//+----------------------------------------------------------------------------+
double GetPointLastLoss( int or_ty=-1)
  {
   datetime t=0;
   double result=0,p=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(t<OrderCloseTime())
                 {t=OrderCloseTime(); p=OrderProfit(); or_ty=OrderType();
                  if(or_ty==OP_BUY&&p<0)
                    {
                     result=OrderOpenPrice()-OrderClosePrice();
                    } else {result=0;}
                  if(or_ty==OP_SELL&&p<0)
                    {
                     result=OrderClosePrice()-OrderOpenPrice();
                    } else {result=0;}
                 }
              }
           }
        }
     }
   return(result);
  }
//+------------------------------------------------------------------+

Vous n'avez pas du tout besoin de magie dans votre cas.

 
MakarFX:

C'est à peu près ça.

Dans votre cas, la magie n'est pas du tout nécessaire.

Merci, je vais le tester, je vous en ferai part. J'espère qu'il fonctionne comme le mien, mais ajoute un stop (s'il est déclenché) à la nouvelle prise.

A quoi servent les paramètres externes Input4 ; 5 ; 6 ?

 
SGarnov:
Merci, je vais le tester et faire un rapport. J'espère qu'il fonctionne comme le mien, mais ajoute un arrêt (s'il s'est déclenché) à une nouvelle prise.

Il n'y a que des modifications ici. Il n'y a pas de suppression ou d'annulation d'ordre.

Si vous décrivez ce que l'EA doit faire, j'essaierai de vous aider.

 
SGarnov:

A quoi servent les paramètres externes Input4 ; 5 ; 6 ?

J'ai oublié de supprimer
 
MakarFX:

Si vous décrivez ce que l'EA doit faire, j'essaierai de vous aider.

Je place un ordre d'achat en attente - l'EA fonctionne - l'ordre en attente se déclenche - l'EA "voit" cela et place un stop loss sur cet ordre ouvert :

stop loss (le paramètre externe est défini dans les paramètres) ;

Prise de profit (le paramètre externe est réglé dans les paramètres en utilisant le rapport de 1 à 2, par exemple);

ordre de vente en attente au niveau du stop loss.

Scénarios possibles.

Variante 1.

A) Si le prix atteint Takei - le conseiller expert supprime le Stop Loss et un ordre de vente en attente ;

Variante 2.

B) Si le stop loss est déclenché et que l'EA est "passé à l'histoire", alors :

Un ordre de vente est ouvert et le conseiller expert repositionne cet ordre :

stop loss (le paramètre externe est défini dans les paramètres)

Take Profit + un Stop Loss déclenché à partir de l'historique ;

un ordre d'achat en attente au niveau du stop loss.

Si le prix atteint le take - le conseiller expert supprime le stop loss et l'ordre d'achat en attente.

Et vice versa, si le travail commence par un ordre de vente en attente.

Et ainsi le conseiller travaille jusqu'à ce qu'il arrête son travail avec le paramètre externe numéro de Stop Loss (dans mon cas c'est 2, cela signifie que la variante 2 sera répétée 3 fois et le conseiller arrêtera de travailler dans le futur et supprimera tous les ordres en attente, le premier stop n'est pas pris en compte).

Si takei n'est pas atteint et que la variante 2 est répétée, alors 2 stops sont ajoutés à takei et ainsi de suite, cela dépend du paramètre externe"Stop Loss count".


Le code que j'ai mis en place fonctionne comme il le devrait, à l'exception du problème que j'ai décrit (ne voit pas dans l'historique de 1 arrêt ou 2 arrêts, qui devraient s'ajouter à la prise).

Comme ça.

 
SGarnov:

Je place un ordre d'achat en attente - l'EA fonctionne - l'ordre en attente se déclenche - l'EA "voit" cela et place un stop loss sur cet ordre ouvert :

stop loss (le paramètre externe est défini dans les paramètres) ;

Prise de bénéfice (le paramètre externe est réglé dans les paramètres en utilisant le rapport de 1 à 2, par exemple);

ordre de vente en attente au niveau du stop loss.

Scénarios possibles.

Variante 1.

A) Si le prix atteint Takei - le conseiller expert supprime le Stop Loss et un ordre de vente en attente ;

Variante 2.

B) Si le stop loss est déclenché et que l'EA est "passé à l'histoire", alors :

Un ordre de vente est ouvert et le conseiller expert repositionne cet ordre :

stop loss (le paramètre externe est défini dans les paramètres);

Take Profit + un Stop Loss déclenché à partir de l'historique ;

un ordre d'achat en attente au niveau du stop loss.

Si le prix atteint le take - le conseiller expert supprime le stop loss et l'ordre d'achat en attente.

Et vice versa, si le travail commence par un ordre de vente en attente.

Et ainsi le conseiller travaille jusqu'à ce qu'il arrête son travail avec le paramètre externe numéro de Stop Loss (dans mon cas c'est 2, cela signifie que la variante 2 sera répétée 3 fois et le conseiller arrêtera de travailler dans le futur et supprimera tous les ordres en attente, le premier stop n'est pas pris en compte).

Si takei n'est pas atteint et que la variante 2 est répétée, alors 2 stops sont ajoutés à takei et ainsi de suite, cela dépend du paramètre externe"Stop Loss count".


Le code que j'ai mis en place fonctionne comme il le devrait, à l'exception du problème que j'ai décrit (ne voit pas dans l'historique de 1 arrêt ou 2 arrêts, qui devraient s'ajouter à la prise).

C'est comme ça.

"Nombre de Stop Loss" - à la suite ou pour la journée en cours ?

 
MakarFX:

"Nombre de Stop Loss" - à la suite ou pour la journée en cours ?

Le nombre de stops consécutifs sur une paire de devises.

Afin d'analyser l'historique, le conseiller expert étiquette initialement les ordres avec leurs ID, mais ne les trouve pas dans l'historique, je pensais que OrderMagikNumber() les rechercherait. Peut-être à cause du fait que dans l'historique des arrêts de différentes paires de devises, l'EA ne les "voit" plus ?

mettre la source à nouveau ? Tout ce qu'il doit faire, c'est corriger "rechercher les transactions stop à partir de l'historique et les faire ajouter à la prise nouvellement placée".
Raison: