» Календарь |
« Май 2024 » | Пн | Вт | Ср | Чт | Пт | Сб | Вс | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
|
|
Торговые советники (Expert Advisors)- Читать Закрыть 21
функция OrderStopLoss.
В этом примере была использована функция OrderStopLoss(). Из названия абсолютно понятно ее предназначение, но лучше все-таки остановиться на ней поподробнее.
Для того, чтобы изучение функции OrderStopLoss()
стало не просто скучным теоретическим описанием, попробуем слегка
изменить прошлый пример, чтобы получить максимум практической пользы.
Прошлый наш пример работал только в тех случаях, когда Stop Loss был сработан без проскальзывания. Изменим немного наш код:
//---- выбираем ордер/позицию с тикером 77777
if ( OrderSelect (77777, SELECT_BY_TICKET) == true)
{
// позиция выбрана успешно
if ( ((OrderClosePrice() <= OrderStopLoss()) && (OrderType() == OP_BUY)) ||
((OrderClosePrice() >= OrderStopLoss()) && (OrderType() == OP_SELL)) )
{
// позиция закрылась по Stop Loss
// ...
}
else
{
// позиция закрылась по Take Profit
// ...
}
}
else
Print("OrderSelect() вернул ошибку - ",GetLastError());
Этот пример базируется на том, что:
- Если позиция была на покупку (условие OrderType() == OP_BUY
истинно), то Stop Loss сработает или по цене ордера, или хуже, т.е.
ниже: (OrderClosePrice() <= OrderStopLoss()).
- Если позиция была на продажу (условие OrderType() == OP_SELL
истинно), то Stop Loss сработает или по цене ордера, или хуже, т.е.
выше: (OrderClosePrice() >= OrderStopLoss()).
- Читать Закрыть 22
функция OrderType.
Функция OrderType() возвращает значение, которое определяет тип
операции ордера, который предварительно выбран с помощью OrderSelect():
- OP_BUY — позиция на покупку,
- OP_SELL — позиция на продажу,
- OP_BUYLIMIT — отложенный ордер Buy Limit,
- OP_BUYSTOP — отложенный ордер Buy Stop,
- OP_SELLLIMIT — отложенный ордер Sell Limit,
- OP_SELLSTOP — отложенный ордер Sell Stop.
В предыдущем выпуске я поместил пример, которые определял, как была
закрыта позиция — по Stop Loss ордеру или по Take Profit. Вместе с тем в
этом примере есть небольшая ошибка: если выделенный ордер является
отложенным ордером, то этот кусочек кода будет ошибочно считать, что
позиция закрылась по Take Profit. Изменим наш пример, чтобы исключить
эту ошибку:
//---- выбираем ордер/позицию с тикером 77777
if ( OrderSelect (77777, SELECT_BY_TICKET) == true)
{
if ((OrderType() == OP_BUY) || (OrderType() == OP_SELL))
{
// позиция выбрана успешно
if ( ((OrderClosePrice() <= OrderStopLoss()) && (OrderType() == OP_BUY)) ||
((OrderClosePrice() >= OrderStopLoss()) && (OrderType() == OP_SELL)) )
{
// позиция закрылась по Stop Loss
// ...
}
else
{
// позиция закрылась по Take Profit
// ...
}
}
else
Print("Ошибка: это не закрытая позиция, а отложенный ордер");
}
else
Print("OrderSelect() вернул ошибку - ",GetLastError());
Путем добавления дополнительной проверки, нам удастся отделить закрытые позиции от отложенных ордеров:
if ((OrderType() == OP_BUY) || (OrderType() == OP_SELL))
- Читать Закрыть 23
функция OrderCloseTime.
Возможен случай, когда мы по ошибке выделили открытую позицию. Выявить этот случай нам поможет функция OrderCloseTime().
datetime OrderCloseTime()
Функцию можно вызвать после того, как ордер или позиция были предварительно выбраны с помощью функции OrderSelect().
Возвращает дату и время закрытия позиции или ордера:
- Если позиция открыта, то возвращает 0 (ноль).
- Если позиция закрыта, то возвращает дату и время закрытия позиции.
- Если отложенный ордер удален, то возвращает дату и время удаления ордера.
- Если отложенный ордер еще не удален, то возвращает 0 (ноль).
Исходя из этих правил нам надо проверить время закрытия выделенной
позиции. Если оно равно нулю, то это открытая позиция и нам надо
сообщить об ошибке:
//---- выбираем ордер/позицию с тикером 77777
if ( OrderSelect (77777, SELECT_BY_TICKET) == true)
{
// это позиция, а не отложеный ордер?
if ((OrderType() == OP_BUY) || (OrderType() == OP_SELL))
{
// это закрытая позиция, а не открытая?
if ( OrderCloseTime() != 0 )
{
if ( ((OrderClosePrice() <= OrderStopLoss()) && (OrderType() == OP_BUY)) ||
((OrderClosePrice() >= OrderStopLoss()) && (OrderType() == OP_SELL)) )
{
// позиция закрылась по Stop Loss
// ...
}
else
{
// позиция закрылась по Take Profit
// ...
}
}
else
Print("Ошибка: это не закрытая позиция, а открытая");
}
else
Print("Ошибка: это не закрытая позиция, а отложенный ордер");
}
else
Print("OrderSelect() вернул ошибку - ",GetLastError());
То, что это не может быть отложенный ордер, мы уже проверили (см. прошлый выпуск).
Теперь наш пример по определению типа ордера, по которому была
закрыта позиция, стал содержать на одну ошибку меньше, но по-прежнему
остается небезгрешным. Мы почему-то с первых строчек кода безусловно
верим в тот факт, что позиция закрыта именно по Stop Loss или Take
Profit ордера. А если нет?
- Читать Закрыть 24
функция OrderTakeProfit.
Изучим функцию OrderTakeProfit() и доработаем наш
пример. Мы почему-то с первых строчек кода безусловно верим в тот факт,
что позиция была закрыта именно по Stop Loss или Take Profit ордера. А
если нет? Это легко проверить.
- Если для позиции на покупку цена закрытия находится не ниже уровня Take Profit, то позиция закрыта по Take Profit.
- Если для позиции на продажу цена закрытия находится не выше уровня Take Profit, то позиция закрыта по Take Profit.
Мы знаем, что уровень Stop Loss ордера выделенной позиции или ордера
можно определить с помощью функции OrderStopLoss(). По аналогии уровень
Take Profit определяется с помощью функции OrderTakeProfit():
double OrderTakeProfit()
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Изменим наш пример, чтобы убедиться, что позиция закрыта по ордеру, а не с рынка:
//---- выбираем ордер/позицию с тикером 77777
if ( OrderSelect (77777, SELECT_BY_TICKET) == true)
{
// это позиция, а не отложеный ордер?
if ((OrderType() == OP_BUY) || (OrderType() == OP_SELL))
{
// это закрытая позиция, а не открытая?
if ( OrderCloseTime() != 0 )
{
if ( ((OrderClosePrice() <= OrderStopLoss()) && (OrderType() == OP_BUY)) ||
((OrderClosePrice() >= OrderStopLoss()) && (OrderType() == OP_SELL)) )
{
// позиция закрылась по Stop Loss
// ...
}
else
{
if ( ((OrderClosePrice() >= OrderTakeProfit()) && (OrderType() == OP_BUY)) ||
((OrderClosePrice() <= OrderTakeProfit()) && (OrderType() == OP_SELL)) )
{
// позиция закрылась по Take Profit
// ...
}
else
Print("Ошибка: позиция закрыта не по ордеру");
}
}
else
Print("Ошибка: это не закрытая позиция, а открытая");
}
else
Print("Ошибка: это не закрытая позиция, а отложенный ордер");
}
else
Print("OrderSelect() вернул ошибку - ",GetLastError());
- Читать Закрыть 25
функция OrderSymbol.
Очень часто перед трейдером стоит задача перебрать все открытые
позиции или отложенные ордера и что-то сделать с позициями или ордерами,
которые выставлены по инструменту, к которому прикреплен советник.
Предположим, что нас интересуют только отложенные ордера.
Используя функцию OrderSymbol(), мы можем получить информация о выделенном с помощью функции OrderSelect() ордере или позиции.
string OrderSymbol()
Напишем кусочек кода, который просматривает все наши неудаленные
отложенные ордера и производит какие-то действия с ордерами, которые
выставлены по инструменту, к которому прикреплен советник.
int pos;
for (pos=0; pos=OP_BUYLIMIT)
{
// ордер оказался отложенным; проверим инструмент
if (OrderSymbol()==Symbol())
{
// делаем что-то с ордером
// ...
}
}
}
else
Print("Ошибка ", GetLastError(), " при выборе ордера номер ", pos);
В этом коде Вам могут быть непонятны два момента.
Во-первых, я как-то странно на первый взгляд провожу определение типа
ордера: if (OrderType()>=OP_BUYLIMIT). На самом деле условие
OrderType()>=OP_BUYLIMIT будет истинно в тех случаях, когда выбран
ордер, и ложно в тех случаях, когда выбрана позиция. Дело в том, что
константы, определяющие тип ордера, имеют следующие числовые значения:
Константа |
Значение |
Описание |
OP_BUY |
0 |
Позиция на покупку |
OP_SELL |
1 |
Продажа |
OP_BUYLIMIT |
2 |
Отложенный ордер BUY LIMIT |
OP_SELLLIMIT |
3 |
Отложенный ордер SELL LIMIT |
OP_BUYSTOP |
4 |
Отложенный ордер BUY STOP |
OP_SELLSTOP |
5 |
Отложенный ордер SELL STOP |
Как мы видим, во всех случаях, когда выделен отложенный ордер,
значение функции OrderType() будет больше или равно OP_BUYLIMIT (т.е.
больше или равно 2).
Второй непонятный момент в коде — функция Symbol(). Эта функция возвращает текстовую строку с именем финансового инструмента, к которому прикреплен советник:
string Symbol()
- Читать Закрыть 26
функция OrderComment.
Существует еще один способ узнать была ли закрыта позиция по Stop
Loss или Take Profit ордеру. При этом данный способ будет более простым,
чем рассмотренные ранее.
В этом нам поможет функция OrderComment().
string OrderComment()
После того как ордер или позиция выбраны функцией OrderSelect() вызов функции OrderComment() вернет комментарии этого ордера/позиции в виде строки.
Очень часто сервер пишет в комментарий ордера или позиции полезные вещи:
- [sl] — если сработал Stop Loss;
- [tp] — если сработал Take Profit;
- cancelled — если отложенный ордер был отменен клиентом;
- deleted [no money] — если отложенный ордер должен был сработать, но был удален сервером из-за недостатка свободных средств на счете;
- partial close — если позиция была закрыта частично;
- close hedge by #тикер — если локированная позиция была закрыта полностью другой локированной позицией;
- [число%] — позиция была закрыта по Stop Out (т.е. сервер автоматически закрыл позицию, когда equity стало меньше 20% необходимой маржи);
- deleted [good for day] — удаленный отложенный ордер по CFD, который имел статус Day Order;
- expiration [YYYY.MM.DD HH:MM] — отложенный ордер, который был удален сервером при достижении даты эксперации YYYY.MM.DD HH:MM;
- split from #тикер — при закрытии одной позицией
другой с разными объемами появляется в рынке новая позиция с таким
комментарием; #тикер — номер тикера позиции с бОльшим объемом.
Может быть этот список неполон, но в данный момент нас это не должно
волновать. Нас интересуют те позиции и ордера, в комментарии которых
встречается подстрока [sl] (позиция закрыта по Stop Loss ордеру) или подстрока [tp] (позиция закрыта по Take Profit ордеру):
//---- выбираем ордер/позицию с тикером 77777
if ( OrderSelect (77777, SELECT_BY_TICKET) == true)
{
// это позиция, а не отложеный ордер?
if ((OrderType() == OP_BUY) || (OrderType() == OP_SELL))
{
// это закрытая позиция, а не открытая?
if ( OrderCloseTime() != 0 )
{
if ( StringFind(OrderComment(), "[sl]") != -1 )
{
// позиция закрылась по Stop Loss
// ...
}
else
{
if ( StringFind(OrderComment(), "[tp]") != -1 )
{
// позиция закрылась по Take Profit
// ...
}
else
Print("Ошибка: позиция закрыта не по ордеру");
}
}
else
Print("Ошибка: это не закрытая позиция, а открытая");
}
else
Print("Ошибка: это не закрытая позиция, а отложенный ордер");
}
else
Print("OrderSelect() вернул ошибку - ",GetLastError());
В этом примере есть неизвестная пока нам функция — StringFind():
int StringFind ( string text, string matched_text, int start=0 )
Эта функция ищет в строке text подстроку matched_text начиная с позиции start
(если третий параметр не указан, то поиск идет с нулевой позиции, т.е. с
первого элемента). Если подстрока не найдена, то функция возвращает -1;
если найдена — номер позиции в строке, с которой начинается искомая
подстрока.
- Читать Закрыть 27
функция OrderSwap.
В этом выпуске расскажем о функции OrderSwap().
Честно говоря, совершенно не понятно практического применения этой
функции в экспертах, но раз она присутствует, то лучше о ней рассказать.
double OrderSwap()
Функция OrderSwap() возвращает начисленный или
списанный сторидж (т.е. плату за перенос позиции на следующий день) по
ордеру или позиции, выделенных с помощью функции OrderSelect().
- Читать Закрыть 28
функция OrderCommission.
К сожалению, при всей моей достаточно буйной фантазии я так и не смог
придумать практического применения этих функций. Но раз эти функции
присутствуют, то лучше о них расcказать. Вдруг вам они все-таки
пригодятся.
double OrderCommission()
Функция OrderCommission() возвращает удержанную комиссию по ордеру, выделенному функцией OrderSelect().
- Читать Закрыть 29
функция OrderOpenPrice.
В этом выпуске я рассмотрю функцию OrderOpenPrice(). В качестве практического примера применения этой функции рассмотрим установку и управление трейлинг стопом.
Напоминаем, что Trailing Stop (трейлинг стоп) — это
алгоритм управления уровнем Stop Loss ордера. После выставления
трейлинг-стопа (например, на Х пипсов) происходит следующее:
- MetaTrader не предпринимает никаких действий до того момента, пока
по открытой позиции не образуется прибыль в Х пипсов. После этого
MetaTrader выставляет Stop Loss ордер на расстоянии Х пипсов от текущей
цены (в данном случае — на уровне безубыточности).
- После выполнения первого шага MetaTrader посылает команду на
изменение уровня Stop Loss ордера на расстояние Х пипсов от текущей
котировки каждый раз, когда расстояние между ней и старым уровнем ордера
превысит Х пипсов. В результате этого Stop Loss ордер «подтягивается» к
текущей цене.
Реализуем этот принцип на языке MetaQuotes Language 4. Будем
полагать, что открытая позиция уже выбрана и мы точно знаем, что эта
позиция открыта по инструменту, к которому прикреплен эксперт. Также
предположим, что значение трейлинг стопа в пипсах содержится в
переменной TrailingStop.
int err;
if (OrderType() == OP_BUY)
{
// позиция на покупку
if ((Bid-OrderOpenPrice())>=(TrailingStop*Point))
{
// выставляем Stop Loss
if (OrderModify(OrderTicket(), OrderOpenPrice(), Bid-TrailingStop*Point,
OrderTakeProfit(), 0))
Print("#", OrderTicket(),": trailing stop ", Bid-TrailingStop*Point);
else
{
err = GetLastError();
Print("#", OrderTicket(),": trailing stop error ", err);
}
}
}
else
{
// позиция на продажу
if ((OrderOpenPrice()-Ask)>=(TrailingStop*Point))
{
// выставляем Stop Loss
if (OrderModify(OrderTicket(), OrderOpenPrice(), Ask+TrailingStop*Point,
OrderTakeProfit(), 0))
Print("#", OrderTicket(),": trailing stop ", Ask+TrailingStop*Point);
else
{
err = GetLastError();
Print("#", OrderTicket(),": trailing stop error ", err);
}
}
}
Прежде всего нас интересует новая функция OrderOpenPrice():
double OrderOpenPrice()
Эта функция возвращает цену открытия для выбранного функцией OrderSelect() ордера или позиции.
В этом коде Вам могут быть непонятны еще несколько функций:
- OrderTicket() — возвращает тикер выделенного функцией OrderSelect() ордера или позиции;
- Bid — Bid последней котировки по инструменту, к которому прикреплен эксперт;
- Ask — Ask последней котировки по инструменту, к которому прикреплен советник;
- Point — размер пункта текущего инструмента в валюте котировки (для EURUSD это 0.0001, для USDJPY- 0.01 и т.д.).
- Читать Закрыть 30
функция OrderTicket.
|
|
» Статистика |
Онлайн всего: 1 Гостей: 1 Пользователей: 0
|
|