Any questions from newcomers on MQL4 and MQL5, help and discussion on algorithms and codes - page 1949

 
Александр #:

Thank you!

Why don't you like ENUM_TIMEFRAMES?

And you can put variables in input in the form of enumeration and select them as you like... Why should you make such a mess? And in mql4 this enumeration has been available for a long time...

Документация по MQL5: Константы, перечисления и структуры / Константы графиков / Периоды графиков
Документация по MQL5: Константы, перечисления и структуры / Константы графиков / Периоды графиков
  • www.mql5.com
Периоды графиков - Константы графиков - Константы, перечисления и структуры - Справочник MQL5 - Справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Alexey Viktorov #:

Why don't you like ENUM_TIMEFRAMES?

And you can put variables in input as an enumeration and select them as you like... Why do you have to go through all this trouble? And in mql4 this enumeration has been available for ages...

+

 
Alexey Viktorov #:

Why don't you like ENUM_TIMEFRAMES?

And you can put variables in input in the form of enumeration and select them as you like... Why should you make such a mess? And in mql4 this enumeration has also been available for a long time...

Thank you! I had no idea.

 

Colleagues, please advise the best algorithm to find the price of the previously placed limit order closest to the current price - respectively to the ascending sell limit, to the bid

the buy limit which is closest to the bottom.

This f-iio counts the quantity but I need the PRICE of the previously placed limit order to make the f-iio return...


So far, I'm using min price for sell limit and max price for buy limit....

int Price_of_orders(int Magic_) // цена ближайшего ордера к цене по магику
  {
//--- получим общее количество ордеров
   int ord = 0; // итоговое значение кол-ва ордеров
   int orders=OrdersTotal();
//--- пробежим по списку ордеров
   for(int i=0;i<orders;i++)
     {
      ResetLastError();
      //--- скопируем в кэш ордер по его номеру в списке
      ulong ticket=OrderGetTicket(i);
      if(ticket!=0)// если ордер успешно скопирован в кэш, работаем с ним
        {
         double price_open  =OrderGetDouble(ORDER_PRICE_OPEN);
         datetime time_setup=OrderGetInteger(ORDER_TIME_SETUP);
         string symbol      =OrderGetString(ORDER_SYMBOL);
         long magic_number  =OrderGetInteger(ORDER_MAGIC);
         if(magic_number==Magic_)
           {
            //  обработаем ордер с заданным ORDER_MAGIC - посчитаем
            ord++;
           }
         PrintFormat("Ордер #%d по %s был выставлен %s, ORDER_MAGIC=%d",ticket,symbol,TimeToString(time_setup),magic_number);
        }
      else         // вызов OrderGetTicket() завершился неудачно
        {
         PrintFormat("Ошибка при получении ордера из списка в кэш. Код ошибки: %d",GetLastError());
        }

     }
   return (ord);   
  }
 
Roman Shiredchenko #:

Colleagues, please advise the best algorithm to find the price of the previously placed limit order closest to the current price - respectively to the ascending sell limit, to the bid

the buy limit which is closest to the bottom.

This f-iio counts the quantity but I need the PRICE of the previously placed limit order to make the f-iio return...


So far I'm using min price for sell limit and max price for buy limit....

I want to save the required prices with tickets and maybe something else, for example time, in my structure or array and sort immediately after adding by price. By resources, if you search not often, it is the same or a little more expensive, and if often, it's better to remember. Of course, if you don't have 100500 orders) Then it may be too expensive. In general, sorting in a structure or multidimensional array problem is solved only for the first index unfortunately.

Sometimes I use several one-dimensional arrays with the same indexes, tickets, time, prices. And search by index of necessary property. For example, we get the index of a smaller time or a larger price and get the ticket of the necessary order. Of course, it is a crutch, but it works clearly.

 

A question has arisen, not found in the search. Is it possible to enable algotrading from the EA. Get the properties of the terminal, whether it is enabled or not.

And is it possible to run one EA in one terminal with algotrading enabled and another not.

 
Valeriy Yastremskiy #:

to store in its structure or array the required prices with tickets and maybe something else, e.g. time, and sort immediately after adding by price. By resources, if you do not look often, it is the same or a little more expensive, and if you often, it is better to remember. Of course, if you don't have 100500 orders) Then it may be too expensive. In general, sorting in a structure or multidimensional array is solved only for the first index unfortunately.

Sometimes I use several one-dimensional arrays with the same indexes, tickets, time, prices. And search by index of necessary property. For example, we get the index of a smaller time or a larger price and get the ticket of the necessary order. Of course, it is a crutch, but it works clearly.

Thanks - I'll have a look too...
 
Valeriy Yastremskiy #:

to store in its structure or array the desired prices with tickets and maybe something else, such as time, and sort immediately after adding by price. By resources, if you do not look often, it is the same or a little more expensive, and if you often, it is better to remember. Of course, if you don't have 100500 orders) Then it may be too expensive. In general, sorting in a structure or multidimensional array is solved only for the first index unfortunately.

Sometimes I use several one-dimensional arrays with the same indexes, tickets, time, prices. And search by index of necessary property. For example, if we get the index of a smaller time or a larger price, we obtain the ticket of the necessary order. Of course, it is a crutch, but it works very well.

I have done it this way:

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

The array is always sorted, a new order is inserted at the required point, with shifting of other orders, when an order is deleted there is a shift.

But this is in MT5

 
JRandomTrader #:

I have done it this way:

The array is always sorted, a new order is inserted at the right point, with a shift of other orders, when an order is deleted there is a shift.

But this is in MT5.

It would be nice to have code for shifting during writing, deleting and sorting. It's not a trivial task for me to sort the array structure by fields. Yes, and shifts too).

 
Valeriy Yastremskiy #:

Shift code for writing, deleting and sorting would be good. It's not a trivial task for me to sort an array structure by fields. And shifts, too).

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

And probably the most interesting part:

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