[Архив!] Любой вопрос новичка, чтоб не захламлять форум. Профи, не проходите мимо. Без вас никуда - 2. - страница 294

 
CreAndr:
У меня вопрос по тралу, кто может подскажите. Вроде правильный трал в безубыток, а не работает.

Здесь есть трал: https://www.mql5.com/ru/forum/131859

Чтобы вставить в текст код, нажмите кнопочку SRC, которая находится над полем ввода текста.

 
DhP:

Здесь есть трал: https://www.mql5.com/ru/forum/131859

Чтобы вставить в текст код, нажмите кнопочку SRC, которая находится над полем ввода текста.


Спасибо.
 
CreAndr:
У меня вопрос по тралу, кто может подскажите. Вроде правильный трал в безубыток, а не работает.


Перечисление причин по мере убывания значимости:

1. Не включен компьютер

2. Не включен Метатрейдер

3. Не установлен скрипт на график

4. Не разрешены советники

5. Нечего тралить.

6. Что-то в коде не так.

 
Roger:


Перечисление причин по мере убывания значимости:

1. Не включен компьютер

2. Не включен Метатрейдер

3. Не установлен скрипт на график

4. Не разрешены советники

5. Нечего тралить.

6. Что-то в коде не так.

Отличный ответ, Roger, но компьютер включен, метатрейдер тоже, советник прикреплен к графику, советники разрешены, сделки открываются и соответственно есть что тралить! А вот что в коде не так, в этом и заключался вопрос.
 
artmedia70:
Используйте OrderOpenTime()
Ибо - а нафига он нужен-то тогда?


Так то да, но по порядковому номеру у меня получилось довольно коротко а с OrderOpenTime я как-то не понимаю что делать, надо куда-то положить время открытия, сравнить со следующим ордером в списке, если время больше, переписать переменную итд. Не врубаюсь в алгоритм пока.


bool DeleteOrders()
{
   for(int i=0 ; i <=OrdersTotal() ; i++)
      {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
         {
         if(Symbol()==OrderSymbol())
            {
            if(OrderType()!= OP_SELL)
               {
               int ticket=OrderTicket();
               OrderDelete(ticket);
               return(true);
               }
            }
         }
      }
return(false);
} 
 
CreAndr:
Отличный ответ, Roger, но компьютер включен, метатрейдер тоже, советник прикреплен к графику, советники разрешены, сделки открываются и соответственно есть что тралить! А вот что в коде не так, в этом и заключался вопрос.


Сначала кода не было, Вы его потом прикрепили.

Наверное потому не работает, что Вы засунули трейлинг в функцию открытия ордера, т.е условия по открытию ордера таки наступают, ордер открывается, а уж дальше может и не попасть.

 
Pyro:

Так то да, но по порядковому номеру у меня получилось довольно коротко а с OrderOpenTime я как-то не понимаю что делать, надо куда-то положить время открытия, сравнить со следующим ордером в списке, если время больше, переписать переменную итд. Не врубаюсь в алгоритм пока.


По порядковому номеру ненадежно, в этой нумерации никто ничего не гарантирует, только для тестера. Парой страниц ранее писал код для поиска последнего закрытого ордера, для открытых аналогично. Все просто, перебрали, запомнили тикет, потом выбрали ордер или позу по тикету вот и все:

  int lastclosetime=-1;
  int lastcloseticket=-1;
  int lastdealtype=0;

  for (int i=0; i<OrdersHistoryTotal(); i++) 
  {
    if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue; 
    if (OrderSymbol()==symbol || OrderMagicNumber()==magic) 
    {
      if (lastclosetime<OrderCloseTime()) 
      {
        lastclosetime=OrderCloseTime();
        lastcloseticket=OrderTicket();
      }
    }
  }

  if (OrderSelect(lastcloseticket, SELECT_BY_TICKET, MODE_HISTORY)) 
  {
    if (OrderType()==OP_BUY) lastdealtype=1;
    if (OrderType()==OP_SELL) lastdealtype=-1;   
  }
 
Figar0:


По порядковому номеру ненадежно, в этой нумерации никто ничего не гарантирует, только для тестера. Парой страниц ранее писал код для поиска последнего закрытого ордера, для открытых аналогично. Все просто, перебрали, запомнили тикет, потом выбрали ордер или позу по тикету вот и все:

Спасибо, действительно все просто. Буду разбираться.
 
Roger:


Сначала кода не было, Вы его потом прикрепили.

Наверное потому не работает, что Вы засунули трейлинг в функцию открытия ордера, т.е условия по открытию ордера таки наступают, ордер открывается, а уж дальше может и не попасть.

Ясно, спасибо.
 
Figar0:


По порядковому номеру ненадежно, в этой нумерации никто ничего не гарантирует, только для тестера. Парой страниц ранее писал код для поиска последнего закрытого ордера, для открытых аналогично. Все просто, перебрали, запомнили тикет, потом выбрали ордер или позу по тикету вот и все:

Код неверный.

Во-первых вот это:

if (OrderSymbol()==symbol || OrderMagicNumber()==magic) 

Если символ ордера равен заданному символу в переменной symbol или магик ордера равен магику magic... Значит, если будет выбран любой ордер с символом symbol, а магик будет другой или отсутствовать, то условие будет выполнено. Потому что или то или то... Соответственно нужно ставить и вместо или, а лучше разнести проверки в отдельные строки - цикл быстрее будет, что значимо для оптимизации.

Далее... Выбор по тикету: параметр pool игнорируется, т.е. его и писать-то тут бессмысленно.

if (OrderSelect(lastcloseticket, SELECT_BY_TICKET, MODE_HISTORY)) 

после успешного выбора ордера по тикету, необходимо проверить из какого списка ордеров он был выбран - из рыночных или из закрытых. Для этого нужно проверить время закрытия ордера и, если оно больше нуля, то ордер однозначно был закрытым. У открытых позиций этот параметр всегда равен нулю. ИМХО, после выбора последнего ордера нужно сразу проверить его тип и вписать его в переменную.

Теперь функция примет такой вид:

int   GetTypeLastClosePos(int symbol, int magic)   // Функция возвращает 0 если последний закрытый Бай, 1 - если Селл и -1 при ошибке
{
int   i, lastclosetime=0, 
         lastdealtype=-1;

   for (i=0; i<OrdersHistoryTotal(); i++) {
      if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) { // Если выбрали ордер в истории
         if (OrderSymbol()!=symbol)          continue;   // Если его символ не равен переданному в функцию - идём к следующему
         if (OrderMagicNumber()!=magic)      continue;   // Если его магик не равен переданному в функцию - идём к следующему
         if (OrderType()>1)                  continue;   // Если ищем только Бай и Селл, значит если больше единицы - к следующему
         // ... теперь выбранный ордер соответствует критериям поиска по символу, магику и типу
         if (lastclosetime<OrderCloseTime()) {           // Посмотрим время его закрытия и если оно больше предыдущего, то...
            lastclosetime=OrderCloseTime();              // ... запишем его как предыдущее
            lastdealtype=OrderType();                    // Тип текущего закрытого ордера: 0 для Бай, 1 для Селл
            }
         }
      else if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) { // Иначе, если не удалось выбрать ордер в истории
         Print ("Func: GetTypeLastClosePos, Ошибка выбора ордера - ",GetLastError());  // Посмотрим номер ошибки
         break;                                                // Выходим из цикла перебора ордеров
         }
      }
   return(lastdealtype);
}

Теперь, чтобы проверить только Бай или Селл текущего графика и какой из них был последним закрытым, вызываем эту функцию таким образом:

int LastPoseType=GetTypeLastClosePos(Symbol(), Magic);
if (LastPoseType==OP_BUY) {
   // ... код, если последний закрытый Buy ...
   }
if (LastPoseType==OP_SELL) {
   // ... код, если последний закрытый Sell ...
   }
else {// ... код обработки ошибки ... }

Для обработки ошибки, в принципе, можно завести глобальную переменную, напр. int err; и в теле самой функции запоминать номер ошибки в этой переменной:

else if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) { // Иначе, если не удалось выбрать ордер в истории
         err=GetLastError();                                                     // Посмотрим номер ошибки
         Print ("Func: GetTypeLastClosePos, Ошибка выбора ордера - ",err);       // Сообщим об ошибке и в какой ф-ции она произошла
         break;                                                                  // Выходим из цикла перебора ордеров
         }

Тогда для обработки ошибки после вызова ф-ции ...

GetTypeLastClosePos(Symbol(), Magic);

... и возникновения ошибки, её номер будет находиться в переменной err и в блоке обработки этот номер обработать.

else {
   if (err==???) {
      // обработка этой ошибки
      }
   if (err==???) {
      // обработка этой ошибки
      }
// ... и т.д. ...
   }

А лучше использовать switch

Причина обращения: