В прошлом выпуске мы рассказали о том, как можно закрыть открытую позицию с помощью функции OrderClose(). Практических примеров применения этой функции можно привести бесчисленное количество, т.к. в большинстве экспертов существует потребность закрывать позиции не только по 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;
Эти параметры имеют следующих смысл:
Напомню, что о том, как описать в коде параметры эксперта, я рассказывал в выпуске "Внешние переменные".
Мы объявили глобальную переменную 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)) { ... }
В этом кусочке кода я использовал две новые функции:
Далее с помощью функции 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 | Максимальный размер лота |
В следующй статье мы познакомимся с функцией OrderCloseBy().
Есть что сказать? Не стесняйтесь!
Последние статьи:
Видео по теме:
УГОЛОК АДМИНИСТРАТОРА