Ошибка 4051

 
Здравствуйте, писал советник и столкнулся с ошибкой 4051, функция ontick, помогите пожалуйста!
OrderSelect(OrdersHistoryTotal(), SELECT_BY_POS, MODE_HISTORY) //ошибка происходит в этой функции, проверял
OrderSend(OrderSymbol(), OrderType(), OrderLots(), OrderOpenPrice(), 0, OrderStopLoss(), OrderTakeProfit(), OrderComment(), magic, OrderExpiration()) //эта функция ведь правильно написана?

В истории есть закрытые ордера.

Заранее спасибо!

 
arethelпомогите пожалуйста!

Выбирать ордер нужно в цикле (в общем случае)
Например так (МТ4) - 

double HistoryLastProfit()
{ 
   datetime LastTimeClose=0; 
   double LastProfit=0.0;  
   for (int i = OrdersHistoryTotal()-1; i>=0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)
      && LastTimeClose<OrderCloseTime() 
      && OrderSymbol()==Symbol() 
      && OrderMagicNumber()==Magic 
      && (OrderType()==OP_BUY || OrderType()==OP_SELL))
      {
         LastTimeClose=OrderCloseTime();
         LastProfit=OrderProfit()+OrderCommission()+OrderSwap();
      }        
   }  
   return(LastProfit);
}
 
Цикл вайл не подходит? Я выбирал ордер через цикл вайл.
 
arethel:
Цикл вайл не подходит? Я выбирал ордер через цикл вайл.

Дело не в том, какой цикл использовать (можно хоть for, хоть while), а в том, как он построен. В коде, который Вы привели, цикла нет вообще, выбирается ордер, которого заведомо нет в списке. Проверки успешности выбора ордера тоже нет.

Параметры в функции OrderSend вообще очень странные.

 
Ihor Herasko:

Дело не в том, какой цикл использовать (можно хоть for, хоть while), а в том, как он построен. В коде, который Вы привели, цикла нет вообще, выбирается ордер, которого заведомо нет в списке. Проверки успешности выбора ордера тоже нет.

Параметры в функции OrderSend вообще очень странные.

Мне надо открывать оредер, если он закрылся, вот, что мне надо делать, перед этим я проверяю, есть ли ордера в истории, затем если их кол-во увеличилось, то с проверкой по магику, всё новые закрытые ордера выставляю через цикл вайл, а там дальше эти функции идут. Номер тоже там определяется при проверке истории.
 
arethel:
Мне надо открывать оредер, если он закрылся, вот, что мне надо делать, перед этим я проверяю, есть ли ордера в истории, затем если их кол-во увеличилось, то с проверкой по магику, всё новые закрытые ордера выставляю через цикл вайл, а там дальше эти функции идут. Номер тоже там определяется при проверке истории.

Не нужно рассчитывать на историю счета. В МТ4 пользователь может изменить глубину отображения истории, чем собьет с толку любой алгоритм, ориентирующийся на нее. Лучше отслеживать наличие ордеров, открытых советником, в списке рабочих ордеров. И только тогда, когда ордер исчез из этого списка (был закрыт), открывать следующий ордер.

 
Ihor Herasko:

Не нужно рассчитывать на историю счета. В МТ4 пользователь может изменить глубину отображения истории, чем собьет с толку любой алгоритм, ориентирующийся на нее. Лучше отслеживать наличие ордеров, открытых советником, в списке рабочих ордеров. И только тогда, когда ордер исчез из этого списка (был закрыт), открывать следующий ордер.

Пн, можете тогда пожалуйста скинуть хотя бы примерный код отслеживания? Или как мне фиксировать все тикеты открытых оредров?
 
arethel:
Пн, можете тогда пожалуйста скинуть хотя бы примерный код отслеживания? Или как мне фиксировать все тикеты открытых оредров?

Эксперт работает не с одним ордером? Тогда все усложняется. При открытии каждого ордера нужно запомнить его тикет в собственном массиве. А потом на каждом тике проверять, существует ли этот ордер.

При открытии ордера:

#define ARRAY_RESERVE_SIZE            // Здесь придумать самому подходящее значение для резервного размера массива, исходя из логики стратегии
int g_arrnTickets[];                    // Массив тикетов. Объявляется на глобальном уровне 

int nTicket = OrderSend(...);
if (nTicket > 0)
{
   int nTotal = ArraySize(g_arrnTickets);
   if (ArrayResize(g_arrnTickets, nTotal +1, ARRAY_RESERVE_SIZE) != nTotal + 1)
   {
       Alert("Ошибка распределения памяти");
       return;
   }

   g_arrnTickets[nTotal] = nTicket;
}

Затем для проверки существования ордера:

for (int i = ArraySize(g_arrnTickets) - 1; i >= 0; --i)
   if (OrderSelect(g_arrnTickets[i], SELECT_BY_TICKET) && OrderCloseTime() > 0)
   {
      // Удалить тикет из массива отслеживаемых ордеров и произвести действия, нужные в стратегии
   }
Ну и кроме того нужно озаботиться сохранением накопленных данных (в файл, к примеру) для случаев прерывания работы советника.
 
Ihor Herasko:

Эксперт работает не с одним ордером? Тогда все усложняется. При открытии каждого ордера нужно запомнить его тикет в собственном массиве. А потом на каждом тике проверять, существует ли этот ордер.

При открытии ордера:

Затем для проверки существования ордера:

Ну и кроме того нужно озаботиться сохранением накопленных данных (в файл, к примеру) для случаев прерывания работы советника.
Большое спасибо, думаю дальше уже сам справлюсь, но сейчас нет времени протестить, если что, то буду писать в эту тему.
 
arethel:
Большое спасибо, думаю дальше уже сам справлюсь, но сейчас нет времени протестить, если что, то буду писать в эту тему.

Это всего лишь пример кода. Писалось даже без проверки синтаксиса. Смысл - показать направление. Поэтому могут быть какие-то мелкие ошибки.

 
Ihor Herasko:

Это всего лишь пример кода. Писалось даже без проверки синтаксиса. Смысл - показать направление. Поэтому могут быть какие-то мелкие ошибки.

Понял, спасибо
Причина обращения: