Пришло время рассказать о том, как закрыть открытую позицию с помощью функции OrderClose().
bool OrderClose(int ticket, double lots, double price, int slippage,
color Color=CLR_NONE)
Параметры функции:
- ticket — тикер открытой позиции;
- lots — объем в лотах;
- price — цена закрытия позиции;
- slippage — максимально допустимое отклонение между price и ценой сервера, при котором позиция будет закрыта;
- arrow_color — цвет закрывающей стрелки на графике. Если параметр отсутствует или его значение равно CLR_NONE, то стрелка не отображается на графике.
Функция OrderClose() вернет true, если позиция закрыта успешно. Если же произошла какая-то ошибка, то функция вернет false и код ошибки можно будет получить с помощью функции GetLastError().
Практических примеров применения этой функции можно привести
бесчисленное количество, т.к. в большинстве экспертов существует
потребность закрывать позиции не только по Stop Loss или Take Profit
ордеру, но и по текущей цене.
Мы же в качестве примера применения функции OrderClose()
рассмотрим эксперт, который закрывает все открытые позиции и удаляет
все отложенные ордера в пятницу после 22:00 (по времени торговой
платформы).
//+------------------------------------------------------------------+
//| 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
{
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);
}
//+------------------------------------------------------------------+
Разоберем каждую строчку кода этого советника.
Прежде всего этот эксперт имеет несколько параметров:
extern int MyHour=22;
extern int MyMinute=00;
Эти параметры имеют следующих смысл:
MyHour и MyMinute — час и минута, когда эксперт закрывает открытые позиции и удаляет отложенные ордера.
Напомню, что о том, как описать в коде параметры эксперта, я рассказывал в выпуске «Внешние переменные».
Мы объявили глобальную переменную LastTradeTime:
datetime LastTradeTime;
С ее помощью мы сможем избежать «сработки» эксперта на каждом тике
после 22:00, если в этот день мы уже закрыли все открытые позиции и
удалили отложенные ордера.
При инициализации эксперта в функции init() мы присваиваем этой переменной значение вчерашнего дня:
int init()
{
//----
// установим время последней торговой операции вчерашним днем
LastTradeTime = CurTime()-24*60*60;
//----
return(0);
}
Напомню, что функция CurTime() возвращает текущее время в формате datetime.
На каждом тике вызывается функция start(), в которой мы сначала
проверяем, не закрывали ли мы уже сегодня открытые позиции и не удаляли
ли мы уже отложенные ордера:
if (TimeDayOfYear(CurTime())==TimeDayOfYear(LastTradeTime)) return(0);
Здесь используется функция TimeDayOfYear():
int TimeDayOfYear( datetime date )
Эта функция возвращает порядковый номер дня (с начала года): 1 — 1 января,
, 365 или 366 — 31 декабря.
Если же порядковый номер дня последней торговой операции —
TimeDayOfYear(LastTradeTime) — равен порядковому дню текущего времени —
TimeDayOfYear(CurTime()), — значит мы уже сегодня ордера удаляли и
позиции закрывали, поэтому выходим из эксперта: return(0).
Проверим, не пятница ли сегодня:
if (DayOfWeek()!=MyDay) return(0);
Функция DayOfWeek() возвращает порядковый номер дня
недели (воскресенье — 0, 1 — понедельник,
, 6 — суббота) последнего
известного времени сервера.
Теперь проверим, не наступило ли время закрывать позиции:
if (((TimeHour(CurTime())==MyHour)&&(TimeMinute(CurTime())>=MyMinute))
||(TimeHour(CurTime())>MyHour))
{
...
}
В этом кусочке кода я использовал две новые функции:
- int TimeHour(datetime time) — возвращает час для времени time: 0..23;
- int TimeMinute(datetime time) — возвращает минуту для времени time: 0..59.
Далее с помощью функции OrderSelect() мы начинаем выделять первую
позицию/ордер в списке, пытаться ее закрыть или удалить ордер, а потом с
помощью цикла while этот процесс повторяется вновь и вновь, пока есть
открытые позиции или отложенные ордера. Также цикл прерывается в случае
ошибки.
Обязательно между торговыми операциями мы выдерживаем паузу в 10 секунд:
Sleep(10000);
Функция Sleep(int milliseconds) делает паузу в работе эксперта на milliseconds милисекунд (1 секунда = 1000 милисекунд).
После того, как все позиции закрыты и все отложенные ордера удалены,
мы задаем время последней «сработки» советника текущим временем:
if (OrdersTotal()==0) LastTradeTime = CurTime();
В коде эксперта Вы видите еще одну незнакомую нам функцию — MarketInfo():
double MarketInfo(string symbol, int type)
С помощью этой функции можно получить различную информацию об инструменте symbol. Вид получаемой информации зависит от значения параметра type:
Константа |
Значение |
Описание |
MODE_LOW |
1 |
Минимальная цена за день |
MODE_HIGH |
2 |
Максимальная цена за день |
MODE_TIME |
5 |
Время поступления последней котировки |
MODE_BID |
9 |
Последний Bid |
MODE_ASK |
10 |
Последний Ask |
MODE_POINT |
11 |
Размер пункта в валюте котировки |
MODE_DIGITS |
12 |
Количество цифр после десятичного точки в цене инструмента |
MODE_SPREAD |
13 |
Спрэд в пунктах |
MODE_STOPLEVEL |
14 |
Минимально допустимый уровень стоп-лосса/тейк-профита в пунктах |
MODE_LOTSIZE |
15 |
Размер контракта в базовой валюте инструмента |
MODE_TICKVALUE |
16 |
Размер минимального изменения цены инструмента в валюте котировки |
MODE_TICKSIZE |
17 |
Минимальный шаг изменения цены инструмента в пунктах |
MODE_SWAPLONG |
18 |
Сторидж для длинных позиций |
MODE_SWAPSHORT |
19 |
Сторидж для коротких позиций |
MODE_STARTING |
20 |
Дата начала торгов по инструменту (для фьючерсов) |
MODE_EXPIRATION |
21 |
Дата окончания торгов по инструменту (для фьючерсов) |
MODE_TRADEALLOWED |
22 |
Флаг разрешения торгов по данному инструменту |
MODE_MINLOT |
23 |
Минимальный размер лота |
MODE_LOTSTEP |
24 |
Шаг изменения размера лота |
MODE_MAXLOT |
25 |
Максимальный размер лота |