Useful features from KimIV - page 2

 
How about this:
if (err==146)
{
while (IsTradeContextBusy())
{
if (IsTradeAllowed()) break;
else
Sleep(1000*1,1);
}}
I think this is a faster solution. Please share your comments.
Thank you.
 
Red.Line писал (а): Thanks for the useful topic, although I'm about burnt pies, but still maybe someone has faced the problem of stockpiling and sampling from large data sets in µl. µl and databases? Has anyone thought in that direction?
Certainly a simple solution, but something. https://forum.mql4.com/ru/9377
 
zhuki:
How would you feel about this variant:
if (err==146)
{
  while (IsTradeContextBusy())
  {
    if (IsTradeAllowed()) break;
    else 
    Sleep(1000*1,1);
  }
}
This seems to me to be a faster solution.I work this way . Comment.
Thank you.

I'll be fine with it. With understanding. The pause is less, it works faster... But there is some unjustified redundancy in your version.

The IsTradeContextBusy function returns the flag of trade thread occupancy. There was no such function before the 195th build at all. So we used the IsTradeAllowed function that returns a sign that the EA is allowed to trade and the trade flow is free.

We allow the EA to trade by checking "Allow EA to trade" box in the EA properties dialog box (F7 key).

The error 146 (Trade Stream is busy) has nothing to do with allowing the Expert Advisor to trade. Therefore, let us have a look at the properties of the IsTradeAllowed function as far as they relate to the trade thread only.

So, the trade thread is free and the IsTradeAllowed function returns True. The trade thread is busy, the IsTradeAllowed function returns False. Now let's take a look at the values returned by the IsTradeContextBusy function. The trade thread is free, the IsTradeContextBusy function returns False. The trade thread is busy, the IsTradeContextBusy function returns True. We can see that for the same trade flow states, the values of the IsTradeAllowed and IsTradeContextBusy functions are opposite. Moreover, these functions duplicate each other rather than complementing each other with respect to the trade flow states. Therefore, one of them can be excluded. Which one? The IsTradeAllowed function, as I have already mentioned above, apart from the trade flow state flag, also returns the flag allowing the EA to trade which in this situation, i.e. when handling error 146 (Trade Flow is busy), is not necessary to us. Therefore, it will be necessary and sufficient to use only one function IsTradeContextBusy. If you carry out the above abbreviations, your code will be reduced to mine:

if (err==146) while (IsTradeContextBusy()) Sleep(1000*1,1);
with the only difference being the size of the pause. But this is a matter of taste, personal preference, trading style and so on. You could put a pause of 0.1 second. It's not a big deal... I just prefer 11 seconds.
 
But for accuracy I still prefer to make a pause between all types of trading operations from 5 seconds to the release of the thread. Thank you.
 

Two errors were found in the SetOrder function:

  1. Incorrect use of the MarketInfo function. It should have been called AFTER checking the sy parameter, not BEFORE.
  2. Correction of order setting levels worked incorrectly. In addition to that, price levels of stops and takeovers were not corrected. Now it is fixed and works perfectly. I have been testing this thing for a long time using the test script which I will show a bit later.

Attention! The post with SetOrder function for online trading has been corrected. The function is a bit longer. It didn't fit into the whole post, so it had to be moved to the trailer.

 

In this post I decided to give the main points explaining how the SetOrder function works. I do not work with orders myself, i.e. I am in someone else's territory here. Perhaps someone who knows how the SetOrder function works will suggest improvements or find errors.

1. In the first lines of code, local variables are declared and some of them are initialized. For example, in lsComm, the name of the EA and the name of the timeframe returned by the GetNameTF function are written. By the way, I am not going to dwell on such functions as GetNameOP, GetNameTF, Message, etc., only if someone has questions about them.

string   lsComm=WindowExpertName()+" "+GetNameTF(Period());

2. Checking received parameters. If sy is empty, it is initialized with the name of the current tool. The variable for the colour of the icon on the chart is initialised by the type of the operation. If the non-zero expiry time of the order is less than the current time, it is reset to zero.

if (sy=="" || sy=="0") sy=Symbol();
msl=MarketInfo(sy, MODE_STOPLEVEL);
if (op==OP_BUYLIMIT || op==OP_BUYSTOP) clOpen=clOpenBuy; else clOpen=clOpenSell;
if (ex>0 && ex<TimeCurrent()) ex=0;

3. the body of the cycle of trading attempts, the number of which is limited by the value of the global variable NumberOfTry. The operations performed inside the main loop of the SetOrder function go further.

for (it=1; it<=NumberOfTry; it++)

4. If the SetOrder function is not executed in the tester, we have the opportunity to terminate its operation. Waiting for the trade flow release cycle is performed here. Market environment variables are updated and current time is recorded.

if (!IsTesting() && (!IsExpertEnabled() || IsStopped())) {
  Print("SetOrder(): Остановка работы функции");
  break;
}
while (!IsTradeAllowed()) Sleep(5000);
RefreshRates();
ot=TimeCurrent();

5. Sending a request to a trade server. If the ticket is positive, the SetOrder function is terminated.

ticket=OrderSend(sy, op, ll, pp, Slippage, sl, tp, lsComm, mn, ex, clOpen);
if (ticket>0) {
  if (UseSound) PlaySound(NameFileSound); break;
 

6. If the ticket is negative, the processing of execution errors is performed.
7. In the case of errors 128 (Waiting time has expired for deal execution), 142 (Order has been queued up) and 143 (Order accepted by dealer for execution) we pause for 66 seconds. After the pause, using the ExistOrders function (which we will describe later) we check if the order has already been set in the time interval between the server's request and the current moment. If the order has been set, exit the function.

err=GetLastError();
if (err==128 || err==142 || err==143) {
  Sleep(1000*66);
  if (ExistOrders(sy, op, mn, ot)) {
    if (UseSound) PlaySound(NameFileSound); break;
  }
  Print("Error(",err,") set order: ",ErrorDescription(err),", try ",it);
  continue;
}

8. The item size and the Bid and Ask prices are stored in the local variables.

mp=MarketInfo(sy, MODE_POINT);
pa=MarketInfo(sy, MODE_ASK);
pb=MarketInfo(sy, MODE_BID);

9. In case of error 130 (Incorrect stops) the price levels of the order, stop and take out are corrected if possible.

// Неправильные стопы
if (err==130) {
  switch (op) {
    case OP_BUYLIMIT:
      if (pp>pa-msl*mp) pp=pa-msl*mp;
      if (sl>pp-(msl+1)*mp) sl=pp-(msl+1)*mp;
      if (tp>0 && tp<pp+(msl+1)*mp) tp=pp+(msl+1)*mp;
      break;
    case OP_BUYSTOP:
      if (pp<pa+(msl+1)*mp) pp=pa+(msl+1)*mp;
      if (sl>pp-(msl+1)*mp) sl=pp-(msl+1)*mp;
      if (tp>0 && tp<pp+(msl+1)*mp) tp=pp+(msl+1)*mp;
      break;
    case OP_SELLLIMIT:
      if (pp<pb+msl*mp) pp=pb+msl*mp;
      if (sl>0 && sl<pp+(msl+1)*mp) sl=pp+(msl+1)*mp;
      if (tp>pp-(msl+1)*mp) tp=pp-(msl+1)*mp;
      break;
    case OP_SELLSTOP:
      if (pp>pb-msl*mp) pp=pb-msl*mp;
      if (sl>0 && sl<pp+(msl+1)*mp) sl=pp+(msl+1)*mp;
      if (tp>pp-(msl+1)*mp) tp=pp-(msl+1)*mp;
      break;
  }
  Print("SetOrder(): Скорректированы ценовые уровни");
}

10. The information which can help to solve the problem or find the error later is displayed in the report.

Print("Error(",err,") set order: ",ErrorDescription(err),", try ",it);
Print("Ask=",pa,"  Bid=",pb,"  sy=",sy,"  ll=",ll,"  op=",GetNameOP(op),
      "  pp=",pp,"  sl=",sl,"  tp=",tp,"  mn=",mn);
if (pa==0 && pb==0) Message("SetOrder(): Проверьте в обзоре рынка наличие символа "+sy);

At the end we process other errors. Some of them show a long pause (5 minutes), others block the Expert Advisor, others allow further attempts to trade, etc.

That's it! End of description!

 

The ExistOrders() function.

Returns a flag for the existence of an order. Answers the question if the order is set or not. You can use this function to request any order, as well as more specific ones. The request filter is configured using the function parameters:

  • sy - Imposes a restriction on the name of the instrument. The default parameter is "" - no restriction, i.e. any instrument. If you pass NULL, the order selection will be limited by the current symbol.
  • op - places a restriction on the order type. No constraint by default, i.e. any order type is checked. Valid values for this parameter are -1, OP_BUYLIMIT, OP_BUYSTOP, OP_SELLLIMIT and OP_SELLSTOP.
  • mn - places a limit on the identification ("magic") number of the order. No constraint by default, i.e. the order with any magic number is checked.
  • ot - places a limit on the order setting time. It is checked to make sure that the order was set later than the value of this parameter. By default there is no limit, i.e. an order with any setting time is checked.
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 12.03.2008                                                     |
//|  Описание : Возвращает флаг существования ордеров.                         |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    sy - наименование инструмента   (""   - любой символ,                   |
//|                                     NULL - текущий символ)                 |
//|    op - операция                   (-1   - любой ордер)                    |
//|    mn - MagicNumber                (-1   - любой магик)                    |
//|    ot - время открытия             ( 0   - любое время установки)          |
//+----------------------------------------------------------------------------+
bool ExistOrders(string sy="", int op=-1, int mn=-1, datetime ot=0) {
  int i, k=OrdersTotal(), ty;
 
  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      ty=OrderType();
      if (ty>1 && ty<6) {
        if ((OrderSymbol()==sy || sy=="") && (op<0 || ty==op)) {
          if (mn<0 || OrderMagicNumber()==mn) {
            if (ot<=OrderOpenTime()) return(True);
          }
        }
      }
    }
  }
  return(False);
}
 

Examples of how to use the ExistOrders() function.

1. Check availability of any order

ExistOrders();

2. Check availability of any order for any instrument on the current chart

ExistOrders(NULL);

3. Check presence of BuyLimit order on any instrument

ExistOrders("", OP_BUYLIMIT);

4. Check if there is a SellStop order with magic number 123456 on EURUSD

ExistOrders("EURUSD", OP_SELLSTOP, 123456);

5. Check the availability of any order with a setup time of 2 hours or less

ExistOrders("", -1, -1, TimeCurrent()-2*60*60);
In the trailer there is a script to test the ExistOrders function. The first 4 examples in the script are commented out.

Files:
 

Warning! In the post of 12.03.2008 07:24 I have replaced the SetOrder.mq4 attachment

Reason: