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

 
MakarFX:

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

aidez-moi avec des conseils sur la façon de "faire sortir autant d'informations utiles que possible".

J'ai tout dit très clairement. Eh bien, pour vous personnellement, laissez-moi vous demander.

Voici deux fonctions et toutes deux passent par des commandes historiques

//+------------------------------------------------------------------+
//|  Возвращает пункты убытка закрытых ордеров с начала цикла        |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|  Возвращает кол-во серии убыточных ордеров                       |
//+------------------------------------------------------------------+

Deux cycles sur les mêmes commandes. Vous ne pouvez pas obtenir tout ce que ces fonctions renvoient en un seul cycle, n'est-ce pas ?

 

Bonjour !

J'essaie d'ajouter une inversion de transaction à la chouette. Je le fais comme décrit dans les instructions :https://www.mql5.com/ru/forum/128200

Je n'ai aucune erreur lors de la compilation, mais flip ne fonctionne pas dans le testeur.

Le journal donne une erreur :

2021.07.29 20:06:34.316 2015.01.08 22:10:00 SMA avec code flip through AUDUSD,M5 : Erreur OrderSend 130

2021.07.29 20:06:34.316 2015.01.08 22:05:45 SMA avec retournement via AUDUSD,M5 : erreur OrderSend 4107

2021.07.29 20:06:34.316 2015.01.08 22:05:45 SMA avec flip via AUDUSD,M5 : stoploss invalide pour la fonction OrderSend

Pouvez-vous me dire quel est le problème ici ?

Pour ma part, je pense que les variables spécifiées dans

int ReversOrderSend (string symbol,int cmd,double volume,double price,int slippage,double stoploss,double takeprofit,string comment,int magic=0,datetime expiration=0,color arrow_color=CLR_NONE)

Ne sont pas liés au code principal.

Je l'ai essayé dans différents terminaux, 4 et 5 signes.

Voici le code complet :

//+-----------------------------------------------------------------------------------------------+
//|                                                                     Simple Moving Average.mq4 |
//|                                                                 Copyright 2016, Andrey Minaev |
//|                                                     https://www.mql5.com/ru/users/id.scorpion |
//+-----------------------------------------------------------------------------------------------+
#property copyright "Copyright 2016, Andrey Minaev"
#property link      "https://www.mql5.com/ru/users/id.scorpion"
#property version   "1.00"
#property strict

// Параметры советника
extern string sParametersEA = "";     // Параметры советника
extern double dLots         = 0.01;   // Количество лотов
extern int    iStopLoss     = 30;     // Уровень убытка (в пунктах)
extern int    iTakeProfit   = 30;     // Уровень прибыли (в пунктах)
extern int    iSlippage     = 3;      // Проскальзование (в пунктах)
extern int    iMagic        = 1;      // Индентификатор советника
extern double K_Martin     = 2.0;
extern int    OrdersClose  = 5;
extern int    DigitsLot    = 2;
extern int    ReversOrder  = 0;             // Переворот сделок 1-да; 0-нет;
// Параметры индикатора
extern string sParametersMA = "";     // Параметры индикатора
extern int    iPeriodMA     = 14;     // Период усреднения
// Глобальные переменные
double dMA;
//+-----------------------------------------------------------------------------------------------+
int OnInit()
  {
// Если брокер использует 3 или 5 знаков после запятой, то умножаем на 10
   if(Digits == 3 || Digits == 5)
     {
      iStopLoss   *= 10;
      iTakeProfit *= 10;
      iSlippage   *= 10;
     }

   return(INIT_SUCCEEDED);
  }
//+-----------------------------------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

  }
//+-----------------------------------------------------------------------------------------------+
void OnTick()
  {
// Получим значение индикатора
   dMA = iMA(Symbol(), 0, iPeriodMA, 0, MODE_SMA, PRICE_CLOSE, 0);

// Если нет открытых ордеров, то входим в условие
   if(bCheckOrders() == true)
     {
      // Если появился сигнал на покупку, то откроем ордер на покупку
      if(bSignalBuy() == true)
         vOrderOpenBuy();

      // Если появился сигнал на продажу, то откроем ордер на продажу
      if(bSignalSell() == true)
         vOrderOpenSell();
     }
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                             Функция проверки открытых оредров |
//+-----------------------------------------------------------------------------------------------+
bool bCheckOrders()
  {
// Переберем в цикле ордера, для проверки открытых ордеров данным советником
   for(int i = 0; i <= OrdersTotal(); i++)
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == iMagic)
            return(false);

   return(true);
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                             Функция поиска сигнала на покупку |
//+-----------------------------------------------------------------------------------------------+
bool bSignalBuy()
  {
   if(dMA > Open[1] && dMA < Close[1])
      return(true);

   return(false);
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                             Функция поиска сигнала на продажу |
//+-----------------------------------------------------------------------------------------------+
bool bSignalSell()
  {
   if(dMA < Open[1] && dMA > Close[1])
      return(true);

   return(false);
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                            Функция открытия ордера на покупку |
//+-----------------------------------------------------------------------------------------------+
void vOrderOpenBuy()
  {
   int iOTi = 0;   // Тикет ордера

   iOTi = ReversOrderSend(Symbol(), OP_BUY, LOT(), Ask, iSlippage, 0, 0, "", iMagic, 0, clrNONE);

// Проверим открылся ли ордер
   if(iOTi > 0)
      // Есди да, то выставим уровни убытка и прибыли
      vOrderModify(iOTi);
   else
      // Если нет, то получим ошибку
      vError(GetLastError());
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                            Функция открытия ордера на продажу |
//+-----------------------------------------------------------------------------------------------+
void vOrderOpenSell()
  {
   int iOTi = 0;   // Тикет ордера

   iOTi = ReversOrderSend(Symbol(), OP_SELL, LOT(), Bid, iSlippage, 0, 0, "", iMagic, 0, clrNONE);

// Проверим открылся ли ордер
   if(iOTi > 0)
      // Есди да, то выставим уровни убытка и прибыли
      vOrderModify(iOTi);
   else
      // Если нет, то получим ошибку
      vError(GetLastError());
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                                    Функция модификации ордера |
//+-----------------------------------------------------------------------------------------------+
void vOrderModify(int iOTi)
  {
   int    iOTy = -1;   // Тип ордера
   double dOOP = 0;    // Цена открытия ордера
   double dOSL = 0;    // Стоп Лосс
   int    iMag = 0;    // Идентификатор советника

   double dSL = 0;     // Уровень убытка
   double dTP = 0;     // Уровень прибыли

// Выберем по тикету открытый ордер, получим некоторые значения
   if(OrderSelect(iOTi, SELECT_BY_TICKET, MODE_TRADES))
     {
      iOTy = OrderType();
      dOOP = OrderOpenPrice();
      dOSL = OrderStopLoss();
      iMag = OrderMagicNumber();
     }

// Если ордер открыл данный советник, то входим в условие
   if(OrderSymbol() == Symbol() && OrderMagicNumber() == iMag)
     {
      // Если Стоп Лосс текущего ордера равен нулю, то модифицируем ордер
      if(dOSL == 0)
        {
         if(iOTy == OP_BUY)
           {
            dSL = NormalizeDouble(dOOP - iStopLoss * Point, Digits);
            dTP = NormalizeDouble(dOOP + iTakeProfit * Point, Digits);

            bool bOM = OrderModify(iOTi, dOOP, dSL, dTP, 0, clrNONE);
           }

         if(iOTy == OP_SELL)
           {
            dSL = NormalizeDouble(dOOP + iStopLoss * Point, Digits);
            dTP = NormalizeDouble(dOOP - iTakeProfit * Point, Digits);

            bool bOM = OrderModify(iOTi, dOOP, dSL, dTP, 0, clrNONE);
           }
        }
     }
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                                      Функция обработки ошибок |
//+-----------------------------------------------------------------------------------------------+
void vError(int iErr)
  {
   switch(iErr)
     {
      case 129:   // Неправильная цена
      case 135:   // Цена изменилась
      case 136:   // Нет цен
      case 138:   // Новые цены
         Sleep(1000);
         RefreshRates();
         break;

      case 137:   // Брокер занят
      case 146:   // Подсистема торговли занята
         Sleep(3000);
         RefreshRates();
         break;
     }
  }
//+-----------------------------------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double LOT()
  {
   int n=0;
   double OL=dLots;
   for(int j = OrdersHistoryTotal()-1; j >= 0; j--)
     {
      if(OrderSelect(j, SELECT_BY_POS,MODE_HISTORY))
        {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == iMagic)
           {
            if(OrderProfit()<0)
              {
               if(n==0)
                  OL=NormalizeDouble(OrderLots()*K_Martin,DigitsLot);
               n++;
               if(n>=OrdersClose)
                 {
                  Comment("1");
                  return(dLots);
                 }
              }
            else
              {
               if(n==0)
                 {
                  Comment("2");
                  return(dLots);
                 }
               else
                 {
                  Comment("3");
                  return(OL);
                 }
              }
           }
        }
     }
   return(OL);
  }
//------------------------------------------------------------------
int ReversOrderSend (string symbol,int cmd,double volume,double price,int slippage,double stoploss,double takeprofit,string comment,int magic=0,datetime expiration=0,color arrow_color=CLR_NONE)
{
int Ret=0;
double sprd=MarketInfo(symbol,MODE_SPREAD)*Point;
//Print ("----------------------------",sprd);
if (ReversOrder==0) // Открываем ордера без разворота
{
Ret=OrderSend (symbol,cmd,volume,price,slippage,stoploss,takeprofit,comment,magic,expiration,arrow_color);
}
if (ReversOrder==1)
{
///////////////
if (cmd==OP_SELLSTOP) // Переворачиваем ордера OP_SELLSTOP
{
Ret=OrderSend (symbol,OP_BUYLIMIT,volume,price+sprd,slippage,takeprofit-sprd,stoploss-sprd,comment,magic,expiration,arrow_color);
}
if (cmd==OP_BUYSTOP) // Переворачиваем ордера OP_BUYSTOP
{
Ret=OrderSend (symbol,OP_SELLLIMIT,volume,price-sprd,slippage,takeprofit+sprd,stoploss+sprd,comment,magic,expiration,arrow_color);
}
///////////////
if (cmd==OP_SELL) // Переворачиваем ордера OP_SELL
{
Ret=OrderSend (symbol,OP_BUY,volume,price+sprd,slippage,takeprofit-sprd,stoploss-sprd,comment,magic,expiration,arrow_color);
}
if (cmd==OP_BUY) // Переворачиваем ордера OP_BUY
{
Ret=OrderSend (symbol,OP_SELL,volume,price-sprd,slippage,takeprofit+sprd,stoploss+sprd,comment,magic,expiration,arrow_color);
}
//////////////
if (cmd==OP_SELLLIMIT) // Переворачиваем ордера OP_SELLLIMIT
{
Ret=OrderSend (symbol,OP_BUYSTOP,volume,price+sprd,slippage,takeprofit-sprd,stoploss-sprd,comment,magic,expiration,arrow_color);
}
if (cmd==OP_BUYLIMIT) // Переворачиваем ордера OP_BUYLIMIT
{
Ret=OrderSend (symbol,OP_SELLSTOP,volume,price-sprd,slippage,takeprofit+sprd,stoploss+sprd,comment,magic,expiration,arrow_color);
}
}
return (Ret);
}
Предлагаю функцию реверса ордеров, для сливающих советников.
Предлагаю функцию реверса ордеров, для сливающих советников.
  • 2010.08.24
  • www.mql5.com
Помню, поначалу сталкивался с вопросом, как грамотно "перевернуть" ордера с покупки на продажу и наоборот...
 
Alexey Viktorov:

Je l'ai déjà dit assez clairement. Je vais vous poser une question personnelle.

Voici deux fonctions qui parcourent toutes deux les commandes historiques.

Il y a deux boucles sur les mêmes ordres. Vous ne pouvez pas obtenir tout ce que ces fonctions renvoient en un seul cycle, n'est-ce pas ?

Alexei, j'ai déjà écrit, je sais que tu es un bon programmeur !

Mais je ne suis pas un programmeur, et ce qui est "suffisamment clair" pour vous ne l'est pas pour moi...

En ce qui concerne les deux boucles, pour moi"Dans une boucle, tout récupérer" n'est pas possible, car elles renvoient des types de données différents.

 
MakarFX:

Alexey, j'ai déjà écrit, je sais que tu es un bon programmeur !

Mais je ne suis pas un programmeur et ce qui est "suffisamment clair" pour vous est une forêt obscure pour moi...

Quant aux deux boucles, pour moi,"tout récupérer en une seule boucle" n'est pas possible, car elles renvoient des types de données différents.

Les types de retour n'ont rien à voir avec cela. S'il y a deux boucles sur les mêmes données avec des contrôles et des filtres différents, vous pouvez toujours tout mettre dans une seule boucle, mais le code ne sera pas aussi clair, mais il devrait fonctionner plus rapidement. Il est plus facile de rechercher les bogues dans les différentes.

 
MakarFX:

Alexey, j'ai déjà écrit, je sais que tu es un bon programmeur !

Mais je ne suis pas un programmeur et ce qui est "suffisamment clair" pour vous est une forêt obscure pour moi...

En ce qui concerne les deux boucles, pour moi"Dans une seule boucle pour tout récupérer" n'est pas possible, car elles retournent des types de données différents.

J'ai deux options.

  1. Faire des variables au niveau global. Ils seront alors disponibles dans toutes les fonctions.
  2. Passer la variable locale par référence. Ensuite, si vous modifiez cette variable, la variable locale sera modifiée.
    /********************Script program start function*******************/
    void OnStart()
     {
      int a = 0;
      f_0(a);
      Print(a);
     }/******************************************************************/
    
    void f_0(int & b)
     {
      b = 100;
     }
    Et il peut y avoir jusqu'à 64 variables de ce type, Dieu me garde de mentir. Si je me trompe, quelqu'un peut me corriger.
  3. Lisez plus attentivement la documentation. C'est écrit là dans les moindres détails.
 
MakarFX:

J'ai un conflit entre les ordres en attente.

Premier résultat. Il y a un conflit entre les paires de devises et l'EA a un conflit sur le placement des ordres en attente. Par exemple, j'ai placé un ordre en attente pour EURUSD, l'EA a suivi l'algorithme (acheter à 1.18901, ouvrir la position, l'EA a fixé le stop à 1.18751, prendre le profit à 1.19051 et l'ordre de vente à 1.18751) tout est ok comme prévu.

Mais maintenant, il est temps d'ouvrir une transaction sur la paire GBPUSD où les prix sont différents et où l'EA fait tout ce qu'il faut, à l'exception de la définition d'un ordre en attente. Un ordre de vente à 1.39393 s'est déclenché et l'EA a essayé de l'ouvrir, de fixer un stop à 1.39633 et de prendre 1.39153 mais l'ordre d'achat à 1.39633 est entièrement dupliqué en EURUSD et un ordre de vente à 1.18751)

Je viens de trouver un autre problème : un stop à 1.18751 et un ordre de vente en suspens à 1.18901 et un take à 1.18595 déclenchés sur un trade ouvert EURUSD. Le conseiller expert n'a pas ajouté le stop déclenché, qui se trouve dans l'historique.

Ce sont les problèmes.

 
законопослушный гражданин:

Bonjour !

J'essaie d'intégrer un retournement de situation pour le hibou.

Qu'est-ce que tu veux dire ? Une certaine fourchette de prix à partir de laquelle vous achetez/vendez ?

 
SGarnov:

Bon après-midi. Aide pour l'EA. Selon la stratégie, si un stop s'est déclenché, alors l'EA devrait ajouter (le nombre de points) à la prochaine prise en charge
de l'historique par ID, mais il ne le fait pas pour une raison quelconque.

Qu'est-ce qui ne va pas dans ce code ?

if(isLimitOn && OrderSelect(OrderMagicNumber(), SELECT_BY_TICKET, MODE_HISTORY)){
            tpc += stop_loss;
            if(OrderSelect(lastMagic, SELECT_BY_TICKET)){
               if(OrderType() == OP_BUY) {
                  double tp_price = NormalizeDouble((OrderOpenPrice() + Point() * (tp + tpc)), Digits);
                  if(!OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), tp_price, OrderExpiration()))
                     Print("Ошибка модификации ордера:", GetLastError());
               }else if(OrderType() == OP_SELL){
                  double tp_price = NormalizeDouble((OrderOpenPrice() - Point() * (tp + tpc)), Digits);
                  if(!OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), tp_price, OrderExpiration()))
                     Print("Ошибка модификации ордера:", GetLastError());
               }
            }
               
            isLimitOn = false;
         }

Makar a correctement indiqué OrderMagicNumber(), mais a mal compris l'erreur. Lisez la documentation pour la syntaxe de cette fonction... ce devrait être soit l'index dans la liste des commandes, soit le ticket d'une certaine commande, mais pas une magik. Et OrderTicket() ne sera d'aucune utilité ici. N'essayez pas de l'y mettre.

 
SGarnov:

Qu'est-ce que tu veux dire ? Une certaine fourchette de prix dans laquelle vous achetez/vendez ?

L'auteur du code, tel que je le comprends, a suggéré ce qui suit :

si owl ouvre une transaction d'achat avec stop and take, alors son morceau de code ouvre une transaction de vente au même moment au même endroit (en prenant en compte le spread) également avec stop and take au lieu d'une transaction d'achat.

Ainsi la logique de recherche d'un point d'entrée de l'EA ne change pas, et seule la direction avec prise en compte du spread change.

c'est exactement ce dont j'ai besoin

 
MakarFX:

Décrivez en quelques mots ce que vous attendez de cette EA (la logique de fonctionnement),

Je pense que vous avez beaucoup de choses inutiles dans votre code ou je ne comprends pas quelque chose.

les hiboux devraient ouvrir des transactions selon leur propre algorithme

si le stop, le prochain trade avec un Martin, et ainsi de suite jusqu'au nombre de multiplications que j'ai spécifié (fonction -OrdersClose = ..... ;).

De plus, si le hibou est désactivé en même temps que le terminal, il suffit d'appuyer sur le bouton "auto-trade" avec un autre hibou, alors le prochain trade commencera avec le lot de départ, et non avec le dernier augmenté par une martingale.

Il serait également agréable d'y associer un calendrier, mais cette idée vient juste de me venir à l'esprit.

Par exemple, il a été activé à 10h00 le lundi avec le lot de départ, puis il a été désactivé au cours de la journée lorsque certains résultats ont été obtenus, et le mardi matin, il a été activé à 10h00 et a recommencé avec le lot de départ.

Tout.