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

 
Valeriy Yastremskiy #:

para almacenar en su estructura o array los precios deseados con los tickets y quizás algo más, como el tiempo, y ordenar inmediatamente después de añadir por precio. Por recursos, si no buscas a menudo, es igual o un poco más caro, y si lo haces a menudo, es mejor recordarlo. Por supuesto, si no tiene 100500 pedidos) Entonces puede ser demasiado caro. En general, la ordenación en una estructura o matriz multidimensional se resuelve sólo para el primer índice, lamentablemente.

A veces utilizo varias matrices unidimensionales con los mismos índices, entradas, tiempo, precios. Y buscar por índice de propiedad necesaria. Por supuesto, es una muleta, pero funciona claramente.

Gracias, yo también echaré un vistazo...
 
Valeriy Yastremskiy #:

para almacenar en su estructura o array los precios deseados con los tickets y quizás algo más, como el tiempo, y ordenar inmediatamente después de añadir por precio. Por recursos, si no buscas a menudo, es igual o un poco más caro, y si lo haces a menudo, es mejor recordarlo. Por supuesto, si no tiene 100500 pedidos) Entonces puede ser demasiado caro. En general, la ordenación en una estructura o matriz multidimensional se resuelve sólo para el primer índice, lamentablemente.

A veces utilizo varias matrices unidimensionales con los mismos índices, entradas, tiempo, precios. Y buscar por índice de propiedad necesaria. Por supuesto, es una muleta, pero funciona muy bien.

Yo lo he hecho así:

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[]; // С начала массива - ордера на покупку, по убыванию цены,
                      // С конца - на продажу, по возрастанию

El array está siempre ordenado, se inserta una nueva orden en el punto requerido, con desplazamiento de otras órdenes, cuando se borra una orden hay un desplazamiento.

Pero esto es en MT5

 
JRandomTrader #:

Yo lo he hecho así:

El array está siempre ordenado, la nueva orden se inserta en el punto correcto, con un desplazamiento de otras órdenes, cuando se elimina una orden hay un desplazamiento.

Pero esto es en MT5.

Sería bueno tener un código para el desplazamiento durante la escritura, el borrado y la ordenación. No es una tarea trivial para mí ordenar la estructura del array por campos. Sí, y los turnos también).

 
Valeriy Yastremskiy #:

Estaría bien un código de desplazamiento para escribir, borrar y ordenar. No es una tarea trivial para mí ordenar una estructura de array por campos. Y también los turnos).

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;
}

Y probablemente la parte más interesante:

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 #:

Gracias.

No está mal. No me gusta arrays)))), y nunca funciona la primera vez sin depurar en arrays. ))) Especialmente los turnos, la copia, la clasificación no regular))
 
Valeriy Yastremskiy #:

Gracias.

No está mal. No me gusta arrays)))), y nunca funciona la primera vez sin depurar en arrays. ))) Especialmente los turnos, la copia, la clasificación no regular))

Cada herramienta es buena por sí misma.

Pero, insidioso error de comprobación y re-control ))

 

Eso es lo que significa una nueva mirada a su antiguo código.

Veo dos defectos idénticos, vestigios de la versión anterior.

Una sub-optimidad obvia.

Y un diseño obsoleto.

 
Hola. Si me equivoco de lugar, por favor, indíqueme dónde escribir, gracias.

Buscando un Asesor Experto gratuito para MT5 que cierre posiciones TODAS cuando se alcance una ganancia o pérdida, especificada en la configuración, y abra nuevas posiciones inmediatamente en la dirección especificada en la configuración. ¿Puede alguien darme un enlace al hilo?
O tal vez conozcas un EA que solo abre 1 posición en el mercado si ve que no hay posiciones abiertas y no cierra.
 

MT4 1353

¿Qué tipo de error se muestra en el registro?

El código funciona correctamente


 
Vitaly Muzichenko #:

MT4 1353

¿Qué tipo de error se muestra en el registro?

El código funciona correctamente.


Parece que algunos objetos creados mediante "new" no se destruyen al salir.