» Календарь |
« Май 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)- Читать Закрыть 31
функция OrderProfit.
Функция OrderProfit() возвращает прибыль для ордера, выделенного с помощью функции OrderSelect().
Предположим, что мы хотим подсчитать прибыль, которую мы получили по закрытым позициям.
int profit = 0;
int pos;
for ( pos = 0; pos<= OP_SELL) profit += OrderProfit();
}
else
Print("Ошибка ", GetLastError(), " при выделении ордера ", OrderTicket());
}
Print("Суммарный профит по закрытым позициям = ", profit);
- Читать Закрыть 32
функция OrderOpenTime.
С помощью функции OrderOpenTime() мы можем получить дату и время открытия ордера или позиции, выделенного предварительно с помощью функции OrderSelect().
datetime OrderOpenTime()
- В случае отложенного ордера функция OrderOpenTime() возвращает дату и время выставления ордера.
- В случае открытой или закрытой позиции функция возвращает дату и время открытия позиции.
Дляи:
- datetime CurTime() — время прихода последней котировки в виде количества секунд, прошедших после 00:00 1 января 1970 года;
- int TimeHour(datetime time) — возвращает порядковый номер часа для времени time;
- int TimeMinute(datetime time) — возвращает порядковый номер минуты для времени time;
- int TimeSeconds(datetime time) — возвращает количество секунд с начала минуты для времени time.
Например, для 02:16:05 функции TimeHour, TimeMinute и TimeSeconds вернут соответственно 2, 16 и 5.
Мы помним, что значение типа datetime представляет собой количество
секунд, прошедшее с 00:00 1 января 1970 года. Также мы помним, что в
часе 60×60 секунд, а в минуте 60 секунд. Поэтому, зная текущее время (мы
можем получить его с помощью CutTime), мы можем получить время текущего
дня на 00:00:00 часов:
int c_time = CurTime();
datetime day_start;
day_start=c_time-TimeHour(c_time)*60*60-TimeMinute(c_time)*60-TimeSeconds(c_time);
А полный код, который подсчитывает прибыль по всем закрытым позициям, которые открыты сегодня, будет таким:
//---- вычислим начало дня - переменная day_start
int c_time = CurTime();
datetime day_start;
day_start=c_time-TimeHour(c_time)*60*60-TimeMinute(c_time)*60-TimeSeconds(c_time);
//---- подсчитаем прибыль
int profit = 0;
int pos;
for ( pos = 0; pos<= OP_SELL)
{
// ордер был открыт сегодня?
if (OrderOpenTime()>=day_start) profit += OrderProfit();
}
}
else
Print("Ошибка ", GetLastError(), " при выделении ордера ", OrderTicket());
}
Print("Суммарный профит по закрытым позициям = ", profit);
- Читать Закрыть 33
функция OrderMagicNumber.
- Читать Закрыть 34
функция OrderSend.
Формат функции:
int OrderSend(string symbol, int cmd, double volume, double price, int slippage,
double stoploss, double takeprofit, string comment=NULL,
int magic=0, datetime expiration=0, color arrow_color=CLR_NONE)
Ф
- Читать Закрыть 35
функция OrderModify.
Функция OrderModify().
bool OrderModify(int ticket, double price, double stoploss, double takeprofit,
datetime expiration, color arrow_color=CLR_NONE)
Эта функция позволяет изменять параметры отложенных ордеров и открытых позиций. В случае успеха она возвращает true, а в случае неудачи — false. Код ошибки можно будет получить с помощью функции GetLastError().
Параметры функции:
- ticket — тикер отложенного ордера или открытой позиции;
- price — новый уровень отложенного ордера (для открытых позиций не может быть изменен);
- stoploss — новый уровень Stop Loss;
- takeprofit — новый уровень Take Profit;
- expiration — новые дата и время истечения
отложенного ордера (если к этой дате и времени отложенный ордер не
сработает, то он будет удален — см. выпуск «OrderExpiration() — дата
истечения отложенного ордера»);
- arrow_color — цвет открывающей стрелки на графике.
Если параметр отсутствует или его значение равно CLR_NONE, то
открывающая стрелка не отображается на графике.
В случае неправильных параметров функция возвращает следующие коды ошибок:
- 1 (ERR_NO_RESULT) — если ни один из параметров не был изменен;
- 147 (ERR_TRADE_EXPIRATION_DENIED) — если в настройках торгового
сервера запрещено выставлять дату эксперации ордера. В этом случае
параметр expiration всегда должен быть равен нулю).
В качестве практического примера применения этой функции рассмотрим установку и управление трейлинг стопом.
Напомню, что 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);
}
}
}
- Читать Закрыть 36
функция OrderDelete.
Мы уже знаем, как можно выставить отложенный ордер. Для этого надо
использовать функцию OrderSend(). Также мы умеем изменять параметры
отложенных ордеров с помощью функции OrderModify().
В этом выпуске расскажем о том, как можно удалить отложенный ордер. Это можно сделать с помощью функции OrderDelete().
bool OrderDelete(int ticket)
Эта функция удаляет отложенный ордер с тикером ticket. Функция возвращает true в случае успешного удаления и false — в случае возникновения ошибки. Код ошибки можно получить, вызвав функцию GetLastError().
Применение функции OrderDelete() рассмотрим на следующем примере:
Предположим, что наш эксперт по какой-то логике (не будем здесь
вдаваться в подробности) выставляет по одному инструменту сразу два
отложенных ордера — Buy Limit и Sell Limit. Наша задача — если один из
ордеров сработал, то удалить оставшийся отложенный ордер.
Предположим, что по данному инструменту работает только наш эксперт.
Пусть в момент выставления каждого отложенного ордера было задано
«магическое» число, одинаковое для каждого отложенного ордера.
Предположим, что это «магическое» число хранится в переменной MyMagicNumber.
// просмотрим все открытые позиции и выставленные ордера
int pos;
for(pos=0; pos<=OP_SELL))
{
// найти второй отложенный ордер
int i;
for(i=0; iOP_SELL))
{
// ордер найден - удалим его
if (OrderDelete(OrderTicket()))
{
Print("Ордер удален");
}
else
{
Print("Ошибка ", GetLastError(), " при удалении ордера");
}
}
}
}
// выйти из цикла
break;
}
}
}
- Читать Закрыть 37
функция OrderClose.
Пришло время рассказать о том, как закрыть открытую позицию с помощью функции 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 |
Максимальный размер лота |
- Читать Закрыть 38
функция OrderCloseBy.
Давайте перепишем нашего эксперта с учетом этого совета. В этом нам поможет функция 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().
- Читать Закрыть 39
Обработка ошибок.
Как я уже неоднократно упоминал в предыдущих выпусках, если какая-то
функция вернула ошибку, то код этой ошибки можно получить с помощью
функции GetLastError():
int GetLastError()
После вызова этой функции код последней ошибки обнуляется, поэтому если в промежутке между двумя вызовами функции GetLastError() не произошло новой ошибки, то второй раз функция вернет 0.
Функция GetLastError() возвращает числовой код ошибки. Если же Вы хотите получить словесное описание ошибки, то используйте функцию ErrorDescription(), описанную в файле stdlib.mqh:
string ErrorDescription(int error_code)
{
string error_string;
//----
switch(error_code)
{
//---- codes returned from trade server
case 0:
case 1: error_string="no error"; break;
case 2: error_string="common error"; break;
...
}
//----
return(error_string);
}
Коды ошибок, возвращаемые сервером:
Константа |
Значение |
Описание |
ERR_NO_ERROR |
0 |
Нет ошибки |
ERR_NO_RESULT |
1 |
Нет ошибки, но результат неизвестен |
ERR_COMMON_ERROR |
2 |
Общая ошибка |
ERR_INVALID_TRADE_PARAMETERS |
3 |
Неправильные параметры |
ERR_SERVER_BUSY |
4 |
Торговый сервер занят |
ERR_OLD_VERSION |
5 |
Старая версия клиентского терминала |
ERR_NO_CONNECTION |
6 |
Нет связи с торговым сервером |
ERR_NOT_ENOUGH_RIGHTS |
7 |
Недостаточно прав |
ERR_TOO_FREQUENT_REQUESTS |
8 |
Слишком частые запросы |
ERR_MALFUNCTIONAL_TRADE |
9 |
Недопустимая операция нарушающая функционирование сервера |
ERR_ACCOUNT_DISABLED |
64 |
Счет заблокирован |
ERR_INVALID_ACCOUNT |
65 |
Неправильный номер счета |
ERR_TRADE_TIMEOUT |
128 |
Истек срок ожидания совершения сделки |
ERR_INVALID_PRICE |
129 |
Неправильная цена |
ERR_INVALID_STOPS |
130 |
Неправильные стопы |
ERR_INVALID_TRADE_VOLUME |
131 |
Неправильный объем |
ERR_MARKET_CLOSED |
132 |
Рынок закрыт |
ERR_TRADE_DISABLED |
133 |
Торговля запрещена |
ERR_NOT_ENOUGH_MONEY |
134 |
Недостаточно денег для совершения операции |
ERR_PRICE_CHANGED |
135 |
Цена изменилась |
ERR_OFF_QUOTES |
136 |
Нет цен |
ERR_BROKER_BUSY |
137 |
Брокер занят |
ERR_REQUOTE |
138 |
Новые цены |
ERR_ORDER_LOCKED |
139 |
Ордер заблокирован и уже обрабатывается |
ERR_LONG_POSITIONS_ONLY_ALLOWED |
140 |
Разрешена только покупка |
ERR_TOO_MANY_REQUESTS |
141 |
Слишком много запросов |
ERR_TRADE_MODIFY_DENIED |
145 |
Модификация запрещена, так как ордер слишком близок к рынку |
ERR_TRADE_CONTEXT_BUSY |
146 |
Подсистема торговли занята |
ERR_TRADE_EXPIRATION_DENIED |
147 |
Использование даты истечения ордера запрещено брокером |
ERR_TRADE_TOO_MANY_ORDERS |
148 |
Количество открытых и отложенных ордеров достигло предела, установленного брокером |
Коды ошибок выполнения, генерируемые клиентским терминалом при выполнении советника:
Константа |
Значение |
Описание |
ERR_NO_MQLERROR |
4000 |
Нет ошибки |
ERR_WRONG_FUNCTION_POINTER |
4001 |
Неправильный указатель функции |
ERR_ARRAY_INDEX_OUT_OF_RANGE |
4002 |
Индекс массива — вне диапазона |
ERR_NO_MEMORY_FOR_FUNCTION_CALL_STACK |
4003 |
Нет памяти для стека функций |
ERR_RECURSIVE_STACK_OVERFLOW |
4004 |
Переполнение стека после рекурсивного вызова |
ERR_NOT_ENOUGH_STACK_FOR_PARAMETER |
4005 |
На стеке нет памяти для передачи параметров |
ERR_NO_MEMORY_FOR_PARAMETER_STRING |
4006 |
Нет памяти для строкового параметра |
ERR_NO_MEMORY_FOR_TEMP_STRING |
4007 |
Нет памяти для временной строки |
ERR_NOT_INITIALIZED_STRING |
4008 |
Неинициализированная строка |
ERR_NOT_INITIALIZED_ARRAYSTRING |
4009 |
Неинициализированная строка в массиве |
ERR_NO_MEMORY_FOR_ARRAYSTRING |
4010 |
Нет памяти для строкового массива |
ERR_TOO_LONG_STRING |
4011 |
Слишком длинная строка |
ERR_REMAINDER_FROM_ZERO_DIVIDE |
4012 |
Остаток от деления на ноль |
ERR_ZERO_DIVIDE |
4013 |
Деление на ноль |
ERR_UNKNOWN_COMMAND |
4014 |
Неизвестная команда |
ERR_WRONG_JUMP |
4015 |
Неправильный переход |
ERR_NOT_INITIALIZED_ARRAY |
4016 |
Неинициализированный массив |
ERR_DLL_CALLS_NOT_ALLOWED |
4017 |
Вызовы DLL не разрешены |
ERR_CANNOT_LOAD_LIBRARY |
4018 |
Невозможно загрузить библиотеку |
ERR_CANNOT_CALL_FUNCTION |
4019 |
Невозможно вызвать функцию |
ERR_EXTERNAL_EXPERT_CALLS_NOT_ALLOWED |
4020 |
Вызовы внешних библиотечных функций не разрешены |
ERR_NOT_ENOUGH_MEMORY_FOR_RETURNED_STRING |
4021 |
Недостаточно памяти для строки, возвращаемой из функции |
ERR_SYSTEM_BUSY |
4022 |
Система занята |
ERR_INVALID_FUNCTION_PARAMETERS_COUNT |
4050 |
Неправильное количество параметров функции |
ERR_INVALID_FUNCTION_PARAMETER_VALUE |
4051 |
Недопустимое значение параметра функции |
ERR_STRING_FUNCTION_INTERNAL_ERROR |
4052 |
Внутренняя ошибка строковой функции |
ERR_SOME_ARRAY_ERROR |
4053 |
Ошибка массива |
ERR_INCORRECT_SERIES_ARRAY_USING |
4054 |
Неправильное использование массива-таймсерии |
ERR_CUSTOM_INDICATOR_ERROR |
4055 |
Ошибка пользовательского индикатора |
ERR_INCOMPATIBLE_ARRAYS |
4056 |
Массивы несовместимы |
ERR_GLOBAL_VARIABLES_PROCESSING_ERROR |
4057 |
Ошибка обработки глобальныех переменных |
ERR_GLOBAL_VARIABLE_NOT_FOUND |
4058 |
Глобальная переменная не обнаружена |
ERR_FUNCTION_NOT_ALLOWED_IN_TESTING_MODE |
4059 |
Функция не разрешена в тестовом режиме |
ERR_FUNCTION_NOT_CONFIRMED |
4060 |
Функция не подтверждена |
ERR_SEND_MAIL_ERROR |
4061 |
Ошибка отправки почты |
ERR_STRING_PARAMETER_EXPECTED |
4062 |
Ожидается параметр типа string |
ERR_INTEGER_PARAMETER_EXPECTED |
4063 |
Ожидается параметр типа integer |
ERR_DOUBLE_PARAMETER_EXPECTED |
4064 |
Ожидается параметр типа double |
ERR_ARRAY_AS_PARAMETER_EXPECTED |
4065 |
В качестве параметра ожидается массив |
ERR_HISTORY_WILL_UPDATED |
4066 |
Запрошенные исторические данные в состоянии обновления |
ERR_TRADE_ERROR |
4067 |
Ошибка при выполнении торговой операции |
ERR_END_OF_FILE |
4099 |
Конец файла |
ERR_SOME_FILE_ERROR |
4100 |
Ошибка при работе с файлом |
ERR_WRONG_FILE_NAME |
4101 |
Неправильное имя файла |
ERR_TOO_MANY_OPENED_FILES |
4102 |
Слишком много открытых файлов |
ERR_CANNOT_OPEN_FILE |
4103 |
Невозможно открыть файл |
ERR_INCOMPATIBLE_ACCESS_TO_FILE |
4104 |
Несовместимый режим доступа к файлу |
ERR_NO_ORDER_SELECTED |
4105 |
Ни один ордер не выбран |
ERR_UNKNOWN_SYMBOL |
4106 |
Неизвестный символ |
ERR_INVALID_PRICE_PARAM |
4107 |
Неправильный параметр цены для торговой функции |
ERR_INVALID_TICKET |
4108 |
Неверный номер тикета |
ERR_TRADE_NOT_ALLOWED |
4109 |
Торговля не разрешена |
ERR_LONGS_NOT_ALLOWED |
4110 |
Длинные позиции не разрешены |
ERR_SHORTS_NOT_ALLOWED |
4111 |
Короткие позиции не разрешены |
ERR_OBJECT_ALREADY_EXISTS |
4200 |
Объект уже существует |
ERR_UNKNOWN_OBJECT_PROPERTY |
4201 |
Запрошено неизвестное свойство объекта |
ERR_OBJECT_DOES_NOT_EXIST |
4202 |
Объект не существует |
ERR_UNKNOWN_OBJECT_TYPE |
4203 |
Неизвестный тип объекта |
ERR_NO_OBJECT_NAME |
4204 |
Нет имени объекта |
ERR_OBJECT_COORDINATES_ERROR |
4205 |
Ошибка координат объекта |
ERR_NO_SPECIFIED_SUBWINDOW |
4206 |
Не найдено указанное подокно |
ERR_SOME_OBJECT_ERROR |
4207 |
Ошибка при работе с объектом |
- Читать Закрыть 40
Секреты правильной торговли.
Расскажем о трех функциях: IsExpertEnabled(), IsTradeContextBusy() и IsTradeAllowed().
Функция IsExpertEnabled()
bool IsExpertEnabled()
Функция IsExpertEnabled() возвращает true,
если экспертам разрешено совершать сделки и управлять ордерами. Дело в
том, что на уровне настроек клиентского терминала можно запретить ВСЕМ
экспертам торговать. Это можно сделать, например, с помощью команды
главного меню: Сервис -> Настройки. В появившемся окне выбираем вкладку «Советники», в которой ставим или убираем галочку напротив «Включить советники
».
Более простой способ отключать/включать советников — кнопка.
Если же на уровне настроек терминала работа экспертов запрещена, то функция IsExpertEnabled() вернет false.
Функция IsTradeContextBusy()
В каждый момент времени только один эксперт может торговать. Если в
этот момент второй эксперт попытается совершить торговую операцию, то
торговая функция вернет ошибку ERR_TRADE_CONTEXT_BUSY (146).
bool IsTradeContextBusy()
Функция IsTradeContextBusy() позволит Вам заблаговременно выявить ситуацию, когда другой эксперт уже пытается торговать (она вернет в этом случае значение true),
и избежать нерезультативного вызова торговой функции (которая все равно
завершиться с ошибкой). Обычно в таких случаях лучше подождать немного
до того момента, когда другой эксперт закончит торговать (тогда функция IsTradeContextBusy() вернет значение false) и только после этого вызывать Вашу торговую функцию.
Функция IsTradeAllowed()
Функция IsTradeAllowed() объединяет все обе предыдущие функции. Она вернет true
только в том случае, если торговля экспертов разрешена и торговый поток
свободен для торговли, т.е. никакой другой эксперт не совершает в
данный момент торговых операций.
bool IsTradeAllowed()
Как уже говорилось в каждый момент времени только один эксперт может
торговать. Если в этот момент второй эксперт попытается совершить
торговую операцию, то торговая функция вернет ошибку
ERR_TRADE_CONTEXT_BUSY (146).
Что же делать, если у Вас торгует одновременно несколько экспертов?
Напишем функцию, которая возвращает:
- 0, если торговый поток свободен;
- 1, если работа эксперта была остановлена (см. причины ниже);
- 2, если торговля экспертов запрещена на уровне настроек клиентского терминала.
Если в момент обращения к функции торговый поток был занят, то
функция ждет, пока он освободится. После этого она обновляет данные о
текущих котировках с помощью функции RefreshRates() и возвращает 0.
Напомню возможные причины остановки эксперта:
- завершение работы MetaTrader 4,
- закрытие графика,
- удаление эксперта с графика,
- изменение инструмента или периода графика,
- удачная перекомпиляции программы в MetaEditor,
- изменение параметров эксперта,
- переключение на другой счет.
Исходный код функции, которая решает поставленную задачу:
//+-------------------------------------------------------------------+
//| Функция WaitUntilTradingIsAllowed возвращает:|
//| 0 - если торговый поток свободен |
//| 1 - если работа эксперта была остановлена |
//| 2 - если торговля экспертов запрещена на |
//| уровне настроекклиентского терминала |
//+-------------------------------------------------------------------+
int WaitUntilTradingIsAllowed()
{
// Если торговля разрешена, то вернем 0 и выйдем
if (IsTradeAllowed()) return(0);
// В цикле проверяем, как изменилась ситуация
while (!IsStopped())
{
// Если торговля экспертов запрещена на уровне настроек
// клиентского терминала, то выйдем и вернем 2
if (!IsExpertEnabled()) return(2);
// Если торговый поток освободился, то обновим данные
// о текущих курсах и вернем 0
if (!IsTradeContextBusy())
{
RefreshRates();
return(0);
}
// Если дошли до момента, то ситуация не изменилась
// Поэтому делаем паузу в 0.1 секунду
Sleep(100);
}
// Т.к. вышли из цикла, то работа эксперта была остановлена
// Вернем 1
return(1);
}
Функция IsStopped().
bool IsStopped()
Функция возвращает true, если эксперт был «остановлен», и false — в противном случае.
Эксперт получает команду на завершение в следующих случаях:
- при завершении работы клиентского терминала,
- при закрытии графика, к которому прикреплен эксперт,
- при удалении эксперта с графика,
- при изменении инструмента или периода графика,
- после перекомпиляции эксперта в MetaEditor,
- после изменения параметров советника,
- при переключении на другой счет.
Чтобы не пытаться совершить сделку по старым котировкам и не получить
сообщение об ошибке, мы обновляем информацию о текущих котировках с
помощью функции RefreshRates().
bool RefreshRates()
Функция возвращает true, если информация была обновлена, и false, если данные не изменились и в обновлении нет нужды. Если данные были обновлены, то вызов функции RefreshRates() также обновит время последней котировки, которое возвращается функцией CurTime().
Считается хорошим тоном вызывать функцию RefreshRates()
перед вызовом торговой функции, если перед этим эксперт что-то очень
долго или пересчитывал. Или же если эксперт ждал, пока другой эксперт
закончит торговать и торговый поток освободиться.
Поскольку, наверняка, в своей торговле Вы будете использовать сразу
несколько экспертов или одного и того же эксперта, но на разных
временных промежутках или инструментах, то Ваши эксперты будут
периодически ожидать освобождения торгового потока и Вы будете
использовать функцию RefreshRates() практически всегда.
|
|
» Статистика |
Онлайн всего: 1 Гостей: 1 Пользователей: 0
|
|