Давайте перепишем нашего эксперта с учетом этого совета. В этом нам поможет функция OrderCloseBy():
//+------------------------------------------------------------------+
//| Close everything on Friday.mq4 |
//| Copyright © 2006, Andrey Vedikhin |
//| http://www.vedikhin.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Andrey Vedikhin"
#property link "http://www.vedikhin.ru"
//---- input parameters
extern int MyHour=22;
extern int MyMinute=00;
// 5 - Friday
#define MyDay 5
datetime LastTradeTime;
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
// установим время последней торговой операции вчерашним днем
LastTradeTime = CurTime()-24*60*60;
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//----
// проверим, не закрывали ли мы все уже сегодня
// если да - выходим
if (TimeDayOfYear(CurTime())==TimeDayOfYear(LastTradeTime)) return(0);
// если не пятница - выходим
if (DayOfWeek()!=MyDay) return(0);
// проверим, не наступило ли время закрывать позиции
if (((TimeHour(CurTime())==MyHour)&&(TimeMinute(CurTime())>=MyMinute))
||(TimeHour(CurTime())>MyHour))
{
// закроем все позиции и удалим ордера
while (OrdersTotal()>0)
{
// выделим первую позицию или ордер в списке
if (!OrderSelect(0, SELECT_BY_POS))
// в случае неудачи выйти из цикла
break;
// если отложенный ордер, то удалить
if (OrderType()>OP_SELL)
{
if (!OrderDelete(OrderTicket()))
{
Print("Ошибка ", GetLastError()," при удалении отложенного ордера ",
OrderTicket());
break;
}
}
// если открытая позиция, то закрыть
else
{
// попробуем найти локированную позицию по этому же инструменту
int ticket0;
ticket0 = OrderTicket();
string symbol0;
symbol0 = OrderSymbol();
int ordertype0;
ordertype0 = OrderType();
int i;
for (i = 1; i
// заново выделим нулевую позицию
if (!OrderSelect(ticket0, SELECT_BY_TICKET))
// в случае неудачи выйти из цикла
break;
double price;
if (OrderType()==OP_SELL)
price = MarketInfo(OrderSymbol(), MODE_ASK);
else
price = MarketInfo(OrderSymbol(), MODE_BID);
if (!OrderClose(OrderTicket(), OrderLots(), price, 3))
{
Print("Ошибка ", GetLastError()," при закрытии позиции ",
OrderTicket());
break;
}
}
// пауза 10 секунд
Sleep(10000);
}
if (OrdersTotal()==0) LastTradeTime = CurTime();
}
//----
return(0);
}
//+------------------------------------------------------------------+
Вначале я расскажем о самой функции, потом разберем каждую новую строчку нашего эксперта.
bool OrderCloseBy(int ticket, int opposite, color сolor=CLR_NONE)
Функция OrderCloseBy() закрывает одну позицию другой позицией по тому же самому инструменту. В случае успеха она возвращает true, а в случае ошибки — false. Код ошибки можно в дальнейшем узнать с помощью функции GetLastError().
Параметры функции OrderCloseBy():
- ticket — тикер первой позиции;
- opposite — тикер второй позиции;
- сolor — цвет закрывающей стрелки на графике. Если параметр отсутствует или его значение равно CLR_NONE, то закрывающая стрелка не отображается на графике.
Разберем каждую новую строчку нашего эксперта:
// попробуем найти локированную позицию по этому же инструменту
int ticket0;
ticket0 = OrderTicket();
string symbol0;
symbol0 = OrderSymbol();
int ordertype0;
ordertype0 = OrderType();
int i;
for (i = 1; i
// заново выделим нулевую позицию
if (!OrderSelect(ticket0, SELECT_BY_TICKET))
// в случае неудачи выйти из цикла
break;
Вначале запомним номер тикера, инструмент и тип операции выделенной позиции (первой в списке открытых позиций и отложенных ордеров) в переменных ticket0, symbol0 и ordertype0 соответственно:
int ticket0;
ticket0 = OrderTicket();
string symbol0;
symbol0 = OrderSymbol();
int ordertype0;
ordertype0 = OrderType();
После этого в цикле переберем все оставшиеся позиции в поиске позиции, чтобы найти позицию по тому же инструменту, но открытую в другом направлении (OrderType()==((ordertype0+1)%2)):
int i;
for (i = 1; i
Если такую позицию мы нашли, то закроем ее и нашу первоначально выделенную позицию с помощью функции OrderCloseBy() и в случае успеха присвоим переменной i значение -2.
Далее мы проверяем были ли закрыты локированные позиции. Если «да», то делаем паузу и переходим к следующей итерации цикла while, т.е. смотрим следующую позицию/ордер — кандидатов на закрытие/удаление:
if (i==-2)
{
Sleep(10000);
continue;
}
Если же локированные позиции были не найдены, то вновь выделяем первую позицию в списке открытых позиций и отложенных ордеров:
if (!OrderSelect(ticket0, SELECT_BY_TICKET))
// в случае неудачи выйти из цикла
break;
Далее пытаемся закрыть эту позицию с помощью функции OrderClose().