Cualquier pregunta de los recién llegados sobre MQL4 y MQL5, ayuda y discusión sobre algoritmos y códigos - página 1549

 
MakarFX:

Es bueno hablar cuando se sabe qué hacer...

ayúdame con consejos sobre cómo "sacar toda la información útil que puedas".

Lo he dicho todo muy claro. Bueno, para ti personalmente, déjame preguntar.

Aquí hay dos funciones y ambas pasan por órdenes históricas

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

Dos ciclos en los mismos pedidos. No se puede obtener todo lo que devuelven estas funciones en un solo ciclo, ¿verdad?

 

¡Hola!

Estoy tratando de añadir una inversión comercial al búho. Lo estoy haciendo como se describe en las instrucciones: https://www.mql5.com/ru/forum/128200

No tengo errores al compilar, pero flip no funciona en tester.

El registro da un error:

2021.07.29 20:06:34.316 2015.01.08 22:10:00 SMA con código flip through AUDUSD,M5: OrderSend error 130

2021.07.29 20:06:34.316 2015.01.08 22:05:45 SMA con inversión vía AUDUSD,M5: OrderSend error 4107

2021.07.29 20:06:34.316 2015.01.08 22:05:45 SMA con flip vía AUDUSD,M5: stoploss inválido para la función OrderSend

¿Podría decirme cuál es el problema aquí?

Yo mismo pienso que las variables especificadas en

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)

No están relacionados con el código principal.

Lo he probado en diferentes terminales, de 4 y 5 signos.

Aquí está el código completo:

//+-----------------------------------------------------------------------------------------------+
//|                                                                     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:

Ya lo he dicho claramente. Te haré una pregunta personal.

Aquí hay dos funciones y ambas recorren los pedidos históricos

Hay dos bucles en las mismas órdenes. No se puede obtener todo lo que devuelven estas funciones en un ciclo, ¿verdad?

Alexei, ya escribí, ¡sé que eres un buen programador!

Pero yo no soy programador, y lo que es "suficientemente claro" para ti no lo es tanto para mí...

En cuanto a los dos bucles, para mí"En un solo bucle obtener todo" no es posible, porque devuelven diferentes tipos de datos.

 
MakarFX:

Alexey, ya escribí, ¡sé que eres un buen programador!

Pero no soy programador y lo que para ti es "suficientemente claro" para mí es un bosque oscuro...

En cuanto a los dos bucles, para mí"obtener todo en un bucle" no es posible, porque devuelven diferentes tipos de datos.

Los tipos devueltos no tienen nada que ver. Si hay 2 bucles sobre los mismos datos con diferentes comprobaciones y filtros, siempre se puede poner todo en un solo bucle, pero el código no se leerá tan claro, pero debería funcionar más rápido) En la fase de depuración no hago todo en un solo bucle. Es más fácil encontrar errores en los diferentes.

 
MakarFX:

Alexey, ya escribí, ¡sé que eres un buen programador!

Pero no soy programador y lo que para ti es "suficientemente claro" para mí es un bosque oscuro...

En cuanto a los dos bucles, para mí"En un solo bucle para obtener todo" no es posible, porque devuelven diferentes tipos de datos.

Tengo dos variantes.

  1. Hacer variables a nivel global. Entonces estarán disponibles en todas las funciones.
  2. Pasar la variable local por referencia. Entonces, si cambias esta variable, se cambiará la variable local.
    /********************Script program start function*******************/
    void OnStart()
     {
      int a = 0;
      f_0(a);
      Print(a);
     }/******************************************************************/
    
    void f_0(int & b)
     {
      b = 100;
     }
    Y puede haber hasta 64 variables de este tipo, Dios me libre de mentir. Si me equivoco, alguien puede corregirme.
  3. Lea la documentación con más atención. Allí está escrito con gran detalle.
 
MakarFX:

Tengo un conflicto entre órdenes pendientes.

Por ejemplo, he colocado una orden pendiente para el EURUSD, el EA ha seguido el algoritmo (comprar en 1.18901, abrir la posición, el EA ha puesto el stop en 1.18751, tomar ganancias en 1.19051 y la orden de venta en 1.18751) todo está bien según los planes.

Pero ahora es el momento de abrir una operación en GBPUSD donde los precios son diferentes y el EA está haciendo todo bien, excepto por establecer una orden pendiente. Una orden de venta a 1,39393 se ha disparado y el EA ha intentado abrirla, poner un stop en 1,39633 y tomar 1,39153 pero la orden de compra a 1,39633 está totalmente duplicada en el EURUSD y una orden de venta a 1,18751)

Acabo de encontrar otro problema: en el EURUSD se abrió un stop en 1,18751 y una orden pendiente de venta en 1,18901 y toma 1,18595. El Asesor Experto no añadió el stop activado, que está en el historial.

Estos son los problemas.

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

¡Hola!

Estoy tratando de atornillar en una vuelta de los oficios a la lechuza.

¿Qué quieres decir? ¿Un determinado rango de precios a partir del cual se compra/vende?

 
SGarnov:

Buenas tardes. Ayuda con la EA. De acuerdo con la estrategia, si un stop se dispara, entonces el EA debería añadir (el número de puntos) a la siguiente toma establecida
del historial por ID, pero no lo hace por alguna razón.

¿Qué es lo que falla en el código?

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 señaló correctamente OrderMagicNumber(), pero entendió mal el error. Lea la documentación para la sintaxis de esta función... debe ser el índice en la lista de pedidos o el ticket de un determinado pedido, pero no un magik. Y OrderTicket() no ayudará aquí. No intentes ponerlo ahí.

 
SGarnov:

¿Qué quieres decir? ¿Un determinado rango de precios a partir del cual comprar/vender?

El autor del código, según tengo entendido, sugirió lo siguiente:

si owl abre una operación de compra con stop y take, entonces su pedazo de código abre una operación de venta al mismo tiempo en el mismo lugar (teniendo en cuenta el spread) también con stop y take en lugar de una operación de compra.

Por lo tanto, la lógica de búsqueda de un punto de entrada del EA no cambia, y sólo cambia la dirección con el spread tomado en cuenta.

esto es exactamente lo que necesito

 
MakarFX:

Describa en pocas palabras lo que quiere de este EA (la lógica de funcionamiento),

Creo que tienes muchas cosas innecesarias en tu código o no entiendo algo.

los búhos deben abrir operaciones según su propio algoritmo

si el stop, la siguiente operación con un Martin, y así sucesivamente hasta el número de multiplicaciones que especifiqué (función -OrdersClose = .....;).

Más adelante, si el búho está desactivado junto con el terminal, basta con pulsar el botón "auto-trade" con otro búho, entonces la siguiente operación comenzará con el lote inicial, no con el último incrementado por una martingala.

También estaría bien adjuntarle un horario, pero esta idea se me acaba de ocurrir.

Por ejemplo: se activó a las 10-00 del lunes con lote de salida, luego se apagó durante el día cuando se consiguió algún resultado, y el martes por la mañana se activó a las 10-00 y volvió a empezar con lote de salida.

Todo.

Razón de la queja: