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

 
PolarSeaman:

What a twist!)))

Order 1 (from# no, to#2) -- > Order2 (from#1, to#3) -- >Order3 (from#2, to# no)

From this you can find the whole chain.

We look at the open comment and if there is from#XXX, it means that it was previously closed partially - look for ticket XXX from the comment and look for it in the history. Look there comment - if there is from#YYY - it means it was partially closed earlier too - look ticket YYY from comment and search it in the history. Look at the comment - if there is from#ZZZZ - it means that it was partially closed earlier too - repeat the search. If there is no from#..., then it is the first of the whole chain.

 
Artyom Trishkin:

Order 1 (from# no, to#2) -- > Order2 (from#1, to#3) -- > Order3 (from#2, to# no)

From this you can find the whole chain.

We look at the open comment and if there is from#XXX, it means that it was previously closed partially - look for ticket XXX from the comment and look for it in the history. Look there comment - if there is from#YYY - it means it was partially closed earlier too - look ticket YYY from comment and search it in the history. Look at the comment - if there is from#ZZZZ - it means that it was partially closed earlier too - repeat the search. If there is no from#..., then it is the very first of the whole chain.

Thank you, there may be an order in the opposite direction, which I will also chop. I'm afraid of getting confused. I think it would be easier to use the Profit order of a certain date, of course, if we are able to find out when the position was opened, because the date changes when the position is partially closed

 
Artyom Trishkin:

Order 1 (from# no, to#2) -- > Order2 (from#1, to#3) -- > Order3 (from#2, to# no)

From this you can find the whole chain.

Watch open comment and if there is from#XXX, it means that it was partially closed earlier - look for ticket XXX from comment and look for it in history. View comment there - if there is from#YYY - so it was partially closed earlier too - view ticket YYY from comment and look for it in history. Look at the comment - if there is from#ZZZZ - it means that it was partially closed earlier too - repeat the search. If there is no from#..., then it is the very first of the whole chain.

Artem you know that this is not always the case. And in order not to trace a chain not to interrogate the terminal three times - history all the same is driven in own arrays and structures. It is no different from maintaining your own database, except for the extra steps

The terminal and its API is the lowest possible level. And to implement robot's logic, it is logical to do accounting in its terms (trade, chain, group, transaction - everyone calls it differently). It's just sensible to keep it separate and not try to reconstruct it at every sneeze (tick/bar).

 
Maxim Kuznetsov:

You know that's not always the case, Artyom. And so you don't have to ask the terminal three times when tracking the chain - the story is still driven into its own arrays and structures. It's no different from maintaining your own database, except for the extra steps

The terminal and its API is the lowest possible level. And for the robot logic realisation, it is logical to keep accounts in its terms (trade, chain, group, transaction - everyone calls it differently). It's just sensible to keep it separate and not try to reconstruct it at every sneeze (tick/bar).

I've had it all done for a long time - I don't read the history every time - but it's always up to date, and I can easily and very quickly find everything I need there. But to advise someone to do the same, I need at least a couple of articles. And so I've written the logic of finding the whole chain.

 
PolarSeaman:

Thank you, there may be an order in the opposite direction which I will also shred. I'm afraid of getting confused. I think it would be easier to use the Profit function to close a position from a certain date, of course if you can find out when the position was opened, because in a partial close the date changes

To search for a chain, it is sufficient to know the ticket of the order, the entire chain of which you want to know - pass the ticket as a parameter to the search function, and the output - a filled array or array of structures with all of the data of each order of the entire chain.

 
Artyom Trishkin:

A filled array or an array of structures with all the data of each order of the whole chain.

I don't even know approximately what you just said.

At least show me an example of how it should be.

 
PolarSeaman:

I don't even know approximately what you just said.

At least give me an example of how it should be.

I solve the problem in the following way: I look for chains by history. Well, for the history to be unambiguously available, I use two variants:

  1. If without DLL, then in program description in 24 bold )))) I specify that account history must always be loaded in full (Account History tab of Terminal window, context menu - All History).
  2. With DLL - Expert Advisor keeps the "Account history" tab up to date, regardless of any user actions.

Functions to determine the parent order, if the current order is not the primary one:

int GetSignOfPartialOrCloseByClose()
{
   string comment = OrderComment();
   if (comment == "")
      return 0;
   
   // Ордер образовался вследствии частичного закрытия
   int fromStart = StringFind(comment, "from #");
   if (fromStart >= 0)
      return GetTicketByPartialClose(comment, fromStart, OrderType(), OrderOpenTime());
   
   // Ордер образовался вследствии встречного закрытия
   if (StringFind(comment, "partial close") >= 0)
   {
      datetime openTime = OrderOpenTime();
      int type = OrderType();
      for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
      {
         if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
            continue;
            
         if (OrderOpenTime() != openTime)
            continue;
            
         if (OrderType() != type)
            continue;
            
         if (StringFind(OrderComment(), "partial close") < 0)
            continue;
            
         return OrderTicket();
      }
   }
   
   return 0;
}


int GetTicketByPartialClose(string comment, int fromStart, int orderType, datetime openTime)
{
   string sTicket = StringSubstr(comment, fromStart + 6);
   int iTicket = (int)StringToInteger(sTicket);
   int type = OrderType();
   if (!OrderSelect(iTicket, SELECT_BY_TICKET))
      return 0;
      
   if (OrderType() == type)                                                                        // Дочерний ордер указывает на родителя - уходим
      return iTicket;
      
   // Дочерний ордер указывает на противоположный ордер. Необходимо искать родительский
   for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
   {
      if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
         continue;
         
      if (OrderType() != orderType || OrderOpenTime() != openTime)
         continue;
         
      int iFind = StringFind(OrderComment(), "close hedge by #");
      if (iFind < 0)
         continue;
         
      sTicket = StringSubstr(OrderComment(), iFind + 16);
      int iNewTicket = (int)StringToInteger(sTicket);
      if (iNewTicket != iTicket)
         continue;
         
      return OrderTicket();
   }
   
   return 0;
}

Easy to use:

   for (int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if (!OrderSelect(i, SELECT_BY_POS))
         continue;

      ....         

      int nFromTicket = GetSignOfPartialOrCloseByClose();                // Обязательно последней строкой в теле цикла, т. к. может измениться текущий выбранный ордер
   }


 
Ihor Herasko:

The roughest error here is specifying value 100 instead of ticket in OrderDelete() argument.

The next error is not so rough, but it is related to the fact that the calculated value of Stop Loss is checked, not its actual value.

The order type is also not checked. What if we have chosen a market order? How to delete it? The order symbol has not been checked.

Taking into consideration these errors, we get the code of deleting the pending order when the price reaches its Stop Loss:

Also, in your code, the Stop Loss is checked immediately after the order is opened. It seems that after opening a pending order, this code is no longer executed. That is, you need to separate the execution branches. One is responsible for setting the order, and the second is responsible for its accompaniment.

Thank you for your detailed reply!

Following your advice, I have separated branches and everything works.

Then I have faced with issue with simultaneous opening of 10-15 pending orders, I have solved this problem by adding it after your code:

if (OrdersTotal ()>0) return;

I am sure there is a better way.

By your code, could you please explain what 1; i >=0; --i means?

for (int i = OrdersTotal() - 1; i >= 0; --i)
 

Please help me to understand how to write an indicator. I drew such a dummy, how to make a lenght of indicator to be drawn at size points above current Bid, starting from the moment, when indicator is placed on the chart? Maybe the error is that I am shifting this array in the wrong direction?

I know it's "canonical", without any prev_calculated etc., but I need it like this


#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
//---- plot 
#property indicator_label1  "myInd"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Blue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

double buff[], Bid;
input int lenght = 50, size = 5;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping

   ArrayResize(buff, 50);
   ArrayInitialize(buff, 0);
   SetIndexBuffer(0, buff, INDICATOR_DATA);
   //--- установим метку для отображения в DataWindow
   PlotIndexSetString(0,PLOT_LABEL,"myInd");   
//--- установим имя для показа в отдельном подокне и во всплывающей подсказке
   IndicatorSetString(INDICATOR_SHORTNAME,"myInd");
//--- укажем точность отображения значений индикатора
   IndicatorSetInteger(INDICATOR_DIGITS, _Point);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   for(int i = lenght-1; i>0; i--){
      buff[i] = buff[i-1];
   }
   buff[0] = Bid+size;
   


   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 
Roman Sharanov:

Please help me to understand how to write an indicator. I drew such a dummy, how to make a lenght of indicator to be drawn at size points above current Bid, starting from the moment, when indicator is placed on the chart? Maybe the error is that I am shifting this array in the wrong direction?

I know it's "canonical", without prev_calculated and stuff like that.


What's the canon? There is an official doc - it is exactly like yours.

1. you should set serialization of all used arrays inside of OnCalculate.

2. Before entering the loop, put buff[length]=Bid+size; - you will get approximately what you want. A curved line and at the end a "visor" at Bid+size

3. Watch the array bounds. Of course, rates_total is hardly < length, but you can't go wrong :-)

4.
buff[i] = buff[i+1]; // если тайм-серия (а вы подразумеваете их) то +