Какой рейтинг вас больше интересует?
|
Главная /
Каталог блоговCтраница блогера Форекс и я. Forex - это просто! Вся информация как заработать на/Записи в блоге |
Форекс и я. Forex - это просто! Вся информация как заработать на
Голосов: 1 Адрес блога: http://forexii.blogspot.com/ Добавлен: 2011-12-17 17:47:08 |
|
Пишем советник для Forex. Написания советника для рынка Форекс в MQL4
2012-05-10 19:45:00 (читать в оригинале)
В предыдущем посте мы рассмотрели как написать индикатор для рынка Форекс. Хоть он и не был полезен нам как трейдерам, он был весьма полезен нам как новичкам - программистам.
Индикаторы, в общем, очень важны для технического анализа рынков и попыток предсказания будущее двежение цены.
Но для того, чтобы использовать индикаторы необходимо сидеть перед монитором с широко открытыми глазами и вручную совершать сделки.
Если Вы вдруг устанете, решите выпить чашечку чая или взять небольшой отпуск, то Вам придётся рассмотреть одну из следующих опций:
Можно кого-нибудь нанять, чтобы он следил за терминалом и звонил Вам каждые 5 минут, чтобы рассказать, что происходит. Если этот человек профессионал, то Вы будете тратить на него всю свою прибыль. А если он новичок, то Вы потратете на него весь свой каптал.
Вторая опция — автоматизировать свою торговлю.
Именно для этого нужны советники - они же торговые эксперты - они же механические торговые системы (МТС).
Примечание: не путать с роботами - далее я объясню почему...
Можно сказать, что Советник — это программа, написанная на MQL4 (ведь мы изучаем MQL4, верно?), которая использует Ваши любимые индикаторы, торговые методы для автоматизации Ваших торгов.
Он покупает, продаёт и модифицирует ордера за Вас.
Сегодня я попробую подробно описать процесс написания советника для рынка Форекс в MQL4.
Первые два шага:
Если Вы ещё не открыли свой MetaEditor, то пора бы это сделать. Затем выберите Файл->Создать (или просто нажмите CTRL+N).
Появится помощник (как при создании индикатора).
На этот раз надо выбрать пункт «Советник».
Шаг 2:
После нажатия кнопки «Next», Вы окажетесь в окошке общих параметров советника.
Помощник позволяет Вам назначить свойства Вашего советника и задать внешние переменные, которые будут использоваться в нём.
На этом шаге можно задать следующие свойства:
1 — Имя. Название Вашего советника. Мы назовём его My_first_EA.
2 — Автор. Имя автора. Введите какое либо имя.
3 — Ссылка. Ссылка на Ваш сайт или e-mail.
4 — Параметры:
Это список внешних (extern) параметров. Это те параметры, которые пользователь сможет менять из окошка настроек советника.
Для добавления нового параметра нажмите кнопку «Добавить». Нажатие этой конпки приведёт к появлению новой записи в списке внешних переменных. Каждая переменная имеет три поля:
Имя: двойной щелчок по этому полю позволит Вам задать имя (идентификатор) переменной.
Тип: двойной щелчок по этому полю позволит Вам задать тип переменной.
Начальное значение: двойной щелчок по этому полю позволит Вам задать начальное значение переменной.
Последнее поле является опциональным, что означает, что его можно оставить пустым.
В нашем случае, мы добавим три переменные:
Рис. 2 — Помощник. 2й шаг.
Теперь нажмите кнопку «Finish». MetaEditor перенесёт Вас к коду, подготовленному помощником и сохранит его в файл My_first_EA.mq4 в папке MetaTrader4experts.Замечание: торговых советников надо класть в папку MetaTrader4 - experts, а индикаторы — в папку MetaTrader4 - experts - indicators, иначе они не будут работать.
Помощник подготовил следующий код:
Код:
//+------------------------------------------------------------------+
//| My_First_EA.mq4 |
//| Kirill |
//| StockProgrammer@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Kirill"
#property link "StockProgrammer@mail.ru"
//---- input parameters
extern double TakeProfit=350.0;
extern double Lots=0.1;
extern double TrailingStop=35.0;
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
Теперь добавим свой код:
Код:
//+------------------------------------------------------------------+
//| My_First_EA.mq4 |
//| Kirill |
//| StockProgrammer@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Kirill"
#property link "StockProgrammer@mail.ru"
//---- input parameters
extern double TakeProfit=350.0;
extern double Lots=0.1;
extern double TrailingStop=35.0;
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
int Crossed (double line1 , double line2)
{
static int last_direction = 0;
static int current_dirction = 0;
if(line1>line2)current_dirction = 1; //up
if(line1<line2)current_dirction = 2; //down
if(current_dirction != last_direction) //changed
{
last_direction = current_dirction;
return (last_direction);
}
else
{
return (0);
}
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//----
int cnt, ticket, total;
double shortEma, longEma;
if(Bars<100)
{
Print("bars less than 100");
return(0);
}
if(TakeProfit<10)
{
Print("TakeProfit less than 10");
return(0); // check TakeProfit
}
shortEma = iMA(NULL,0,8,0,MODE_EMA,PRICE_CLOSE,0);
longEma = iMA(NULL,0,13,0,MODE_EMA,PRICE_CLOSE,0);
int isCrossed = Crossed (shortEma,longEma);
total = OrdersTotal();
if(total < 1)
{
if(isCrossed == 1)
{
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point, "My EA",12345,0,Green);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("BUY order opened : ",OrderOpenPrice());
}
else Print("Error opening BUY order : ",GetLastError());
return(0);
}
if(isCrossed == 2)
{
ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,
Bid-TakeProfit*Point,"My EA",12345,0,Red);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("SELL order opened : ",OrderOpenPrice());
}
else Print("Error opening SELL order : ",GetLastError());
return(0);
}
return(0);
}
for(cnt=0;cnt<total;cnt++)
{
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(OrderType()<=OP_SELL && OrderSymbol()==Symbol())
{
if(OrderType()==OP_BUY) // long position is opened
{
// should it be closed?
if(isCrossed == 2)
{
OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position
return(0); // exit
}
// check for trailing stop
if(TrailingStop>0)
{
if(Bid-OrderOpenPrice()>Point*TrailingStop)
{
if(OrderStopLoss()<Bid-Point*TrailingStop)
{
OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green);
return(0);
}
}
}
}
else // go to short position
{
// should it be closed?
if(isCrossed == 1)
{
OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // close position
return(0); // exit
}
// check for trailing stop
if(TrailingStop>0)
{
if((OrderOpenPrice()-Ask)>(Point*TrailingStop))
{
if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0))
{
OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,OrderTakeProfit(),0,Red);
return(0);
}
}
}
}
}
}
return(0);
}
//+------------------------------------------------------------------+
Можно скопировать код прямо отсюда.
Скомпилируйте эксперта, например, нажав F5.
Напуганы?
Не бойтесь этих 170 строчек кода, что Вы видите выше. Скоро мы их разберём строчка-за-строчкой. Это очень просто.
Протестируйте МТС:
Прежде, чем разбирать код, проверим прибыльна ли созданная МТС.
Замечание: эта МТС предназначена для работы с EUR/USD на ТФ H4.
Протестировать советника можно двумя способами:
1 — Online-торговля
При online-торговле результаты теста точнее, но надо потратить дни или даже месяцы, чтобы выяснить прибыльна или нет данная МТС.
Для начала, необходимо разрешить советнику автоматизировать Вашу торговлю.
В MetaTrader4 выберите Сервис -> Настройки (или просто нажмите CTRL+O).
Во вкладке Советники разрешите следующие опции:
Включить советники
Разрешить советнику торговать
И нажмите кнопку «OK».
Рис.3 — Разрешаем автоторговлю.
Теперь найдите своего эксперта в Навигаторе в разделе Советники и перетащите его на график EUR/USD H4.Рис.4 — Советник включён.
2 — тестер стратегийВторой метод тестирования советника — это тестер стратегий. Он менее аккуратен, но зато занимает намного меньше времени. Об этом методе мы подробно поговорим позже, сейчас мы не об этом....
Сейчас просто вызовем его окошко, нажав F6.
Выберете параметры как на рисунке:
Рис.5 — Настройки тестера.
Нажмите кнопку Старт.Далее Вас интересует вкладка отчёт.
Вникайте!
Изучаем основной материал:
Ваш первый советник.
Теперь мы разберем полученную программу строчку за строчкой.
Если Вы готовы? Начнём!
Замечание: Наш советник предназначен для обучения и не будет (не нацелен на) извлекать прибыль.
Код, который у нас уже есть:
Код:
//+------------------------------------------------------------------+
//| My_First_EA.mq4 |
//| Kirill |
//| StockProgrammer@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Kirill"
#property link "StockProgrammer@mail.ru"
//---- input parameters
extern double TakeProfit=350.0;
extern double Lots=0.1;
extern double TrailingStop=35.0;
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
int Crossed (double line1 , double line2)
{
static int last_direction = 0;
static int current_dirction = 0;
if(line1>line2)current_dirction = 1; //up
if(line1<line2)current_dirction = 2; //down
if(current_dirction != last_direction) //changed
{
last_direction = current_dirction;
return (last_direction);
}
else
{
return (0);
}
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//----
int cnt, ticket, total;
double shortEma, longEma;
if(Bars<100)
{
Print("bars less than 100");
return(0);
}
if(TakeProfit<10)
{
Print("TakeProfit less than 10");
return(0); // check TakeProfit
}
shortEma = iMA(NULL,0,8,0,MODE_EMA,PRICE_CLOSE,0);
longEma = iMA(NULL,0,13,0,MODE_EMA,PRICE_CLOSE,0);
int isCrossed = Crossed (shortEma,longEma);
total = OrdersTotal();
if(total < 1)
{
if(isCrossed == 1)
{
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point, "My EA",12345,0,Green);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("BUY order opened : ",OrderOpenPrice());
}
else Print("Error opening BUY order : ",GetLastError());
return(0);
}
if(isCrossed == 2)
{
ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,
Bid-TakeProfit*Point,"My EA",12345,0,Red);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("SELL order opened : ",OrderOpenPrice());
}
else Print("Error opening SELL order : ",GetLastError());
return(0);
}
return(0);
}
for(cnt=0;cnt<total;cnt++)
{
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
if(OrderType()<=OP_SELL && OrderSymbol()==Symbol())
{
if(OrderType()==OP_BUY) // long position is opened
{
// should it be closed?
if(isCrossed == 2)
{
OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position
return(0); // exit
}
// check for trailing stop
if(TrailingStop>0)
{
if(Bid-OrderOpenPrice()>Point*TrailingStop)
{
if(OrderStopLoss()<Bid-Point*TrailingStop)
{
OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green);
return(0);
}
}
}
}
else // go to short position
{
// should it be closed?
if(isCrossed == 1)
{
OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // close position
return(0); // exit
}
// check for trailing stop
if(TrailingStop>0)
{
if((OrderOpenPrice()-Ask)>(Point*TrailingStop))
{
if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0))
{
OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,OrderTakeProfit(),0,Red);
return(0);
}
}
}
}
}
}
return(0);
}
//+------------------------------------------------------------------+
Идея ТС нашего эксперта.
Прежде чем, разбирать код, рассмотрим, как устроена ТС, на которой основан наш эксперт. Любой советник должен решать, когда входить в рынок, и когда из него выходить. Основная идея при написании советников — определить каковы условия входов и выходов.
Наш советник прост и проста его идея. Рассмотрим её.
Используются две средние типа EMA (Exponential Moving Average): EMA 8 (быстрая) и EMA 13 (медленная).
Открытие позиций:
Наш советник будет открывать позиции при пересечении средних. Причём направление пересечения определяет в какую сторону будет открыта позиция.
Если быстрая EMA после пересечения окажется выше медленной EMA, то откроется сделка BUY (long).
Если быстрая EMA после пересечения окажется ниже медленной EMA, то откроется сделка SELL (short).
Одновременно может быть открыта только одна сделка.
Закрытие позиций:
Наш советник будет закрывать позиции при обратном пересечении средних.
Также позиция будет закрываться автоматически при достижении уровня стоп-лосс или тейк-профит.
Модификация позиций:
помимо открытия и закрытия позиций эксперт имеет возможность модификации уже открытых позиций. Эту возможность мы будем использовать для реализации треилинг-стопа. Про треилинг-стоп мы поговорим позже в данном посте, а сейчас продолжим разбор:
Код:
//---- input parameters
extern double TakeProfit=350.0;
extern double Lots=0.1;
extern double TrailingStop=35.0;
В приведённых строчках помощник объявил три внешние переменные, как мы его и попросили. Эти переменные пользователь может изменять в окошке настроек эксперта. Также они проинициализированы значениями по умолчанию.
Код:
int Crossed (double line1 , double line2)
{
static int last_direction = 0;
static int current_dirction = 0;
if(line1>line2)current_dirction = 1; //up
if(line1<line2)current_dirction = 2; //down
if(current_dirction != last_direction) //changed
{
last_direction = current_dirction;
return (last_direction);
}
else
{
return (0);
}
}
Как я уже говорил, идея советника заключается в слежении за двумя средними и их пересечениями. Для достижения этой цели мы создаем функцию Crossed.
Функция Crossed принимает на вход две переменные типа double и возвращает переменную типа integer. Первый параметр — это тек. значение первой линии (в нашем случае — быстрой EMA). Второй параметр — это тек. значение второй линии (в нашем случае — медленной EMA).
При каждом вызове функция сохраняет информацию о взаиморасположении этих линий в статических переменных (cтатические переменные хранятся в постоянной области памяти программы, их значения не теряются при выходе из функции). При этом функция сравнивает тек. взаиморасположение линий с их взаиморасположением при предыдущем вызове.
- Функция возвращает 0, если взаиморасположение линий не изменилось.
- Функция возвращает 1, если взаиморасположение линий изменилось, и первая линия оказалась над второй.
- Функция возвращает 2, если месторасположение линий изменилось, и первая линия оказалась под второй.
Замечание: Вы можете использовать эту функцию в своих последующих советниках для слежения за пересечениями любых двух линий.
Посмотрим — как мы написали эту функцию?
Код:
int Crossed (double line1 , double line2)
Это объявление функции. Оно означает, что мы хотим создать функцию с именем Crossed, которая принимает на вход два параметра типа double и возвращает integer. Когда Вы будете вызывать эту функцию, ей надо быдет передавать два параметра типа double, а возвращать Вам она будет integer. Функцию необходимо объявлять перед её использованием (вызовом).
Расположение кода функции значения не имеет. Я его поставил гад функцией start(), Вы можете поставить его где угодно.
Код:
static int last_direction = 0;
static int current_dirction = 0;
Здесь мы объявляем две статические переменные типа static для хранения информации о тек. и предыдущем расположении линий (ещё раз: они статические, потому не теряют своего значения при выходе из функции). Они нам нужны, чтобы проверить изменилось ли взаиморасположение линий. Мы их проинициализировали нулями, т.к. не хотим, чтобы они сработали при самом первом вызове функции (в противном случае советник сразу бы открыл ордера
Код:
if(current_dirction != last_direction) //changed
В этой строчке мы сравниваем две статические переменные. Если current_dirction не равен last_direction, это значит, что взаиморасположение претерпело изменение.
Код:
last_direction = current_dirction;
return (last_direction);
В случае, если направление изменилось, нам надо изменить значение переменной last_direction для будущего использования. После чего мы возвращаем значение last_direction, которое равно 1, если первая линия выше второй, и 2— если наоборот.
Код:
else
{
return (0);
}
В противном случае (взаиморасположение линий не изменилось) необходимо вернуть 0.
Наша программа будет вызывать эту функцию из функции start(), чтобы выполнять правильные действия.
Теперь узнаем, как это реализовано, и познакомимся с очень важными торговыми функциями.
Торговые функции
Рассмотрим 25 торговых функций, часть из которых необходимы нам для продолжения написания советника для рынка Форекс в MQL4.
Для начала мы разберём самую главную функцию — SenOrderd(). А затем — все остальные в алфавитном порядке.
Готовы? Поехали!
1 — 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)
Описание:
Основная функция, используемая для открытия позиции или установки отложенного ордера.
Возвращает номер тикета, который назначен ордеру торговым сервером или -1 в случае неудачи. Чтобы получить дополнительную информацию об ошибке, необходимо вызвать функцию GetLastError().
Замечания.
При открытии рыночного ордера (OP_SELL или OP_BUY) в качестве цены открытия могут использоваться только самые последние цены Bid (для продажи) или Ask (для покупки). Если операция проводится по финансовому инструменту, отличному от текущего, то для получения последних котировок по этому инструменту необходимо воспользоваться функцией MarketInfo() с параметром MODE_BID или MODE_ASK. Нельзя использовать расчетную либо ненормализованную цену. Если запрашиваемой цены открытия не было в ценовом потоке либо запрашиваемая цена не нормализована в соответствии с количеством знаков после десятичной точки, то будет сгенерирована ошибка 129 (ERR_INVALID_PRICE). Если запрашиваемая цена открытия сильно устарела, то независимо от значения параметра slippage будет сгенерирована ошибка 138 (ERR_REQUOTE). Если же запрашиваемая цена устарела, но ещё присутствует в ценовом потоке, то позиция открывается по текущей цене и только в том случае, если текущая цена попадает в диапазон price+-slippage.
Цены StopLoss и TakeProfit не могут располагаться слишком близко к рынку. Минимальное расстояние стопов в пунктах можно получить, используя функцию MarketInfo() с параметром MODE_STOPLEVEL. В случае ошибочных, а также ненормализованных стопов генерируется ошибка 130 (ERR_INVALID_STOPS).
При установке отложенного ордера цена открытия не может быть слишком близкой к рынку. Минимальное расстояние отложенной цены от текущей рыночной цены в пунктах также можно получить, используя функцию MarketInfo() с параметром MODE_STOPLEVEL. В случае неправильной цены открытия отложенного ордера будет сгенерирована ошибка 130 (ERR_INVALID_STOPS).
На некоторых торговых серверах может быть установлен запрет на применение срока истечения отложенных ордеров. В этом случае при попытке задать ненулевое значение в параметре expiration будет сгенерирована ошибка 147 (ERR_TRADE_EXPIRATION_DENIED).
На некоторых торговых серверах может быть установлен лимит на общее количество открытых и отложенных ордеров. При превышении этого лимита новая позиция открыта не будет (отложенный ордер не будет установлен), и торговый сервер вернет ошибку 148 (ERR_TRADE_TOO_MANY_ORDERS).
Параметры:
symbol - Наименование финансового инструмента, с которым проводится торговая операция.
cmd - Торговая операция. Может быть любым из значений торговых операций.
volume - Количество лотов.
price - Цена открытия.
slippage - Максимально допустимое отклонение цены для рыночных ордеров (ордеров на покупку или продажу).
stoploss - Цена закрытия позиции при достижении уровня убыточности (0 в случае отсутствия уровня убыточности).
takeprofit - Цена закрытия позиции при достижении уровня прибыльности (0 в случае отсутствия уровня прибыльности).
comment - Текст комментария ордера. Последняя часть комментария может быть изменена торговым сервером.
magic - Магическое число ордера. Может использоваться как определяемый пользователем идентификатор.
expiration - Срок истечения отложенного ордера.
arrow_color - Цвет открывающей стрелки на графике. Если параметр отсутствует или его значение равно CLR_NONE, то открывающая стрелка не отображается на графике.
Торговые операции:
2 — OrderClose()
Синтаксис:
bool OrderClose( int ticket, double lots, double price, int slippage, color Color=CLR_NONE)
Описание:
Закрытие позиции. Возвращает TRUE при успешном завершении функции. Возвращает FALSE при неудачном завершении функции. Чтобы получить информацию об ошибке, необходимо вызвать функцию GetLastError().
Параметры:
ticket — Уникальный порядковый номер ордера.
lots — Количество лотов для закрытия.
price — Цена закрытия.
slippage — Значение максимального проскальзывания в пунктах.
Color — Цвет стрелки закрытия на графике. Если параметр отсутствует или его значение равно CLR_NONE, то стрелка на графике не отображается.
3 — OrderCloseBy()
Синтаксис:
bool OrderCloseBy( int ticket, int opposite, color Color=CLR_NONE)
Описание:
Закрытие одной открытой позиции другой позицией, открытой по тому же самому инструменту, но в противоположном направлении. Возвращает TRUE при успешном завершении функции. Возвращает FALSE при неудачном завершении функции. Чтобы получить информацию об ошибке, необходимо вызвать функцию GetLastError().
Параметры:
ticket — Уникальный порядковый номер закрываемого ордера.
opposite — Уникальный порядковый номер противоположного ордера.
Color — Цвет стрелки закрытия на графике. Если параметр отсутствует или его значение равно CLR_NONE, то стрелка на графике не отображается.
4 — OrderClosePrice()
Синтаксис:
double OrderClosePrice( )
Описание:
Возвращает цену закрытия выбранного ордера.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
5 — OrderCloseTime()
Синтаксис:
datetime OrderCloseTime( )
Описание:
Возвращает время закрытия для выбранного ордера. Только закрытые ордера имеют время закрытия, не равное 0. Открытые или отложенные ордера имеют время закрытия, равное 0.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
6 — OrderComment()
Синтаксис:
string OrderComment( )
Описание:
Возвращает комментарий для выбранного ордера.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
7 — OrderCommission()
Синтаксис:
double OrderCommission( )
Описание:
Возвращает значение рассчитанной комиссии для выбранного ордера.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
8 — OrderDelete()
Синтаксис:
bool OrderDelete( int ticket, color arrow_color=CLR_NONE)
Описание:
Удаляет ранее установленный отложенный ордер. Возвращает TRUE при успешном завершении функции. Возвращает FALSE при неудачном завершении функции. Чтобы получить информацию об ошибке, необходимо вызвать функцию GetLastError().
Параметры:
ticket — Уникальный порядковый номер ордера.
arrow_color — Цвет стрелки на графике. Если параметр отсутствует или его значение равно CLR_NONE, то стрелка на графике не отображаются.
9 — OrderExpiration()
Синтаксис:
datetime OrderExpiration( )
Описание:
Возвращает дату истечения для выбранного отложенного ордера.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
10 — OrderLots()
Синтаксис:
double OrderLots( )
Описание:
Возвращает количество лотов для выбранного ордера.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
11 — OrderMagicNumber()
Синтаксис:
int OrderMagicNumber( )
Описание:
Возвращает идентификационное («магическое») число для выбранного ордера.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
12 — OrderModify()
Синтаксис:
bool OrderModify( int ticket, double price, double stoploss, double takeprofit, datetime expiration, color arrow_color=CLR_NONE)
Описание:
Изменяет параметры ранее открытых позиций или отложенных ордеров. Возвращает TRUE при успешном завершении функции. Возвращает FALSE при неудачном завершении функции. Чтобы получить информацию об ошибке, необходимо вызвать функцию GetLastError().
Замечания: цену открытия и время истечения можно изменять только у отложенных ордеров.
Если в качестве параметров функции передать неизмененные значения, то в этом случае будет сгенерирована ошибка 1 (ERR_NO_RESULT).
На некоторых торговых серверах может быть установлен запрет на применение срока истечения отложенных ордеров. В этом случае при попытке задать ненулевое значение в параметре expiration будет сгенерирована ошибка 147 (ERR_TRADE_EXPIRATION_DENIED).
Параметры:
ticket — Уникальный порядковый номер ордера.
price — Новая цена открытия отложенного ордера.
stoploss — Новое значение StopLoss.
takeprofit — Новое значение TakeProfit.
expiration — Время истечения отложенного ордера.
arrow_color — Цвет стрелок модификации StopLoss и/или TakeProfit на графике. Если параметр отсутствует или его значение равно CLR_NONE, то стрелки на графике не отображаются.
13 — OrderOpenPrice()
Синтаксис:
double OrderOpenPrice( )
Описание:
Возвращает цену открытия для выбранного ордера.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
14 — OrderOpenTime()
Синтаксис:
datetime OrderOpenTime( )
Описание:
Возвращает время открытия выбранного ордера.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
15 — OrderPrint()
Синтаксис:
void OrderPrint( )
Описание:
Выводит данные ордера в журнал в виде строки следующего формата:
номер тикета; время открытия; торговая операция; количество лотов; цена открытия; стоп лосс; тейк профит; время закрытия; цена закрытия; комиссия; своп; прибыль; комментарий; магическое число; дата истечения отложенного ордера.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
16 — OrderProfit()
Синтаксис:
double OrderProfit( )
Описание:
Возвращает значение чистой прибыли (без учёта свопов и комиссий) для выбранного ордера. Для открытых позиций это — текущая нереализованная прибыль. Для закрытых ордеров — зафиксированная прибыль.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
17 — OrderSelect()
Синтаксис:
bool OrderSelect( int index, int select, int pool=MODE_TRADES)
Описание:
Функция выбирает ордер для дальнейшей работы с ним. Возвращает TRUE при успешном завершении функции. Возвращает FALSE при неудачном завершении функции. Чтобы получить информацию об ошибке, необходимо вызвать функцию GetLastError().
Параметр pool игнорируется, если ордер выбирается по номеру тикета. Номер тикета является уникальным идентификатором ордера. Чтобы определить, из какого списка выбран ордер, необходимо проанализировать его время закрытия. Если время закрытия ордера равно 0, то ордер является открытым или отложенным и взят из списка открытых позиций терминала. Отличить открытую позицию от отложенного ордера можно по типу ордера. Если время закрытия ордера не равно 0, то ордер является закрытым или удаленным отложенным и был выбран из истории терминала. Отличить закрытый ордер от удаленного отложенного также можно по типу ордера.
Параметры:
index — Позиция ордера или номер ордера в зависимости от второго параметра.
select — Флаг способа выбора. Mожет быть одним из следующих величин:
SELECT_BY_POS — в параметре index передается порядковый номер позиции в списке,
SELECT_BY_TICKET — в параметре index передается номер тикета.
pool — Источник данных для выбора. Используется, когда параметр select равен SELECT_BY_POS. Mожет быть одной из следующих величин:
MODE_TRADES (по умолчанию) — ордер выбирается среди открытых и отложенных ордеров,
MODE_HISTORY — ордер выбирается среди закрытых и удаленных ордеров.
18 — OrderHistoryTotal()
Синтаксис:
int OrdersHistoryTotal( )
Описание:
Возвращает количество закрытых позиций и удаленных ордеров в истории текущего счета, загруженной в клиентском терминале. Размер списка истории зависит от текущих настроек вкладки «История счета» терминала.
Параметры:
- отсутствуют -
19 — OrderStopLoss()
Синтаксис:
double OrderStopLoss( )
Описание:
Возвращает значение цены закрытия позиции при достижении уровня убыточности (stop loss) для текущего выбранного ордера.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
20 — OrdersTotal()
Синтаксис:
int OrdersTotal( )
Описание:
Возвращает общее количество открытых и отложенных ордеров.
Параметры:
- отсутствуют -
21 — OrderSwap()
Синтаксис:
double OrderSwap( )
Описание:
Возвращает значение свопа для текущего выбранного ордера.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
22 — OrderSymbol()
Синтаксис:
string OrderSymbol( )
Описание:
Возвращает наименование финансового инструмента для текущего выбранного ордера.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
23 — OrderTakeProfit()
Синтаксис:
double OrderTakeProfit( )
Описание:
Возвращает значение цены закрытия позиции при достижении уровня прибыльности (take profit) для текущего выбранного ордера
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
24 — OrderTicket()
Синтаксис:
int OrderTicket( )
Описание:
Возвращает номер тикета для текущего выбранного ордера.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
25 — OrderType()
Синтаксис:
int OrderType( )
Описание:
Возвращает тип операции текущего выбранного ордера. Mожет быть одной из следующих величин:
OP_BUY — позиция на покупку,
OP_SELL — позиция на продажу,
OP_BUYLIMIT — отложенный ордер на покупку по достижении заданного уровня, текущая цена выше уровня,
OP_BUYSTOP — отложенный ордер на покупку по достижении заданного уровня, текущая цена ниже уровня,
OP_SELLLIMIT — отложенный ордер на продажу по достижении заданного уровня, текущая цена ниже уровня,
OP_SELLSTOP — отложенный ордер на продажу по достижении заданного уровня, текущая цена выше уровня.
Ордер должен быть предварительно выбран с помощью функции OrderSelect().
Параметры:
- отсутствуют -
Замечания
Хотел бы, чтобы Вы обратили внимание на наиболее важные торговые функции:
OrderSend()
OrderModify()
OrderSelect()
OrderClose()
OrderDelete()
А на закуску мы рассмотрим ошибки исполнения:
Любая торговая операция (функции OrderSend(), OrderClose, OrderCloseBy, OrderDelete или OrderModify) по ряду причин может завершиться неудачей и вернуть либо отрицательный номер тикета, либо FALSE. Причину неудачи можно выяснить, вызвав функцию GetLastError(). Каждая ошибка должна быть обработана по-своему. Ниже в таблице приведены общие рекомендации.
Коды ошибок, возвращаемые торговым сервером:
Надеюсь, Вам хватило времени познакомиться с торговыми функциями MQL4, потому что сегодня они нам пригодятся.
В предыдущем описании данного поста мы познакомились с нашим первым советником и поняли, какая идея за ним скрывается. Тепер
Пишем индикатор для Forex.
2012-05-09 00:42:00 (читать в оригинале)
Добро пожаловать в мир практических курсов MQL4; добро пожаловать в пост где я попробую подробно описать процесс написания индикатора для рынка Форекс в MQL4.
Уверен, этот и последующие несколько постов по программированию на языке MQL4 будут интересны не только теоретикам, но и практикам.
Важно: рекомендую проситать предыдущие посты очень внимательно, прежде, чем переходить к этому и последующим постам. Мы будем очень обширно пользоваться вышеописанном материалом.
Теперь мы создадим простой индикатор, который будет значить немного для нашей торговли, но будет значить очень много для нашего понимания программирования на MQL4.
Он будет просто-напросто рассчитывать разницу High [] – Low []. Не торопитесь, скоро Вы всё поймёте.
Поехали!
Это название той встроенной в MetaTrader 4 программы, которая позволяет Вам писать программы, читать помощь по MQL4, компилировать программы и многое другое.
У меня на рабочем столе есть ярлык MetaEditor, чтобы проще его запускать.
2 — Пуск -> Программы -> /Группа MetaTrader 4/ -> MetaEditor .
3 — Зайти в папку установки MT4 (например: C:Program FilesMetaTrader 4), найти MetaEditor.exe и запустить (рекомедую сделать ярлык на рабочем столе).
2 — Окно инструментария. Содержит четыре вкладки:
3 — Окно навигатора. Содержит три вкладки:
Советую ознакомиться с окнами MetaEditor.
Заметка: пользовательский индикатор — это программа, которая позволяет Вам использовать функции технического анализа, но не может автоматизировать Ваши сделки.
В дальнейшем Вы научитесь пропускать эти три скучные шага, но пока мы будем их выполнять.
Шаг 1: Нажмите Файл -> Создать (или просто Ctrl + N)
Появится такое окошко:
Шаг 2:
Появится такое окошко:
2 — Автор программы.
3 — Ссылка на Ваш сайт или e-mail.
4 — Параметры — список внешних (extern) переменных. Это те переменные, которые пользователь сможет изменять в окошке настроек индикатора (см. урок про переменные).
В нашем примере нам не потребуются внешние переменные. Заполните первые три поля и нажмите Next.
Шаг 3:
Появится такое окошко:
1 — Индикатор в отдельном окне. Думаю, понятно, что эта опция делает.
2 — Минимум. Если индикатор рисуется в отдельном окне, эта опция устанавливает нижнюю границу для этого окна.
3 — Максимум. Если индикатор рисуется в отдельном окне, эта опция устанавливает верхнюю границу для этого окна.
4 — Список индексов. Сюда Вы добавляете линии индикатора и ставите их цвет-по-умолчанию.
Далее мы более подробно разберём эти опции, поэтому не спешите.
А сейчас сделайте всё, как на рис. 5.
Когда Вы нажмёте кнопку Finish, начнётся волшебство. Окошко помощника исчезнет, Вы опять окажетесь в MetaEditor и… Угадайте….
Вы получили шаблон для своего первого индикатора.
Примерно такой код Вы получите:
Код:
//+------------------------------------------------------------------+
//| MyFirstIndicator.mq4 |
//| Kirill |
//| StockProgrammer@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Kirill"
#property link "StockProgrammer@mail.ru"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red
//---- buffers
double ExtMapBuffer1[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,ExtMapBuffer1);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int counted_bars=IndicatorCounted();
//----
//----
return(0);
}
//+------------------------------------------------------------------+
Как Вы видите, помощник написал достаточно много кода за Вас.
Теперь мы добавим пару строк в уже имеющийся код, чтобы программа стала более полезной.
После этого мы разберём весь код строчку за строчкой.
Начнём кодить!
Я выделил жирным код, который нужно добавить.
Цитата:
//+——————————————————————+
//| MyFirstIndicator.mq4 |
//| Kirill |
//| StockProgrammer@mail.ru |
//+——————————————————————+
#property copyright «Kirill»
#property link «StockProgrammer@mail.ru»#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red
//—- buffers
double ExtMapBuffer1[];
//+——————————————————————+
//| Custom indicator initialization function |
//+——————————————————————+
int init()
{
//—- indicators
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,ExtMapBuffer1); string short_name = «Your first indicator is running!»;
IndicatorShortName(short_name);//—-
return(0);
}
//+——————————————————————+
//| Custom indicator deinitialization function |
//+——————————————————————+
int deinit()
{
//—-//—-
return(0);
}
//+——————————————————————+
//| Custom indicator iteration function |
//+——————————————————————+
int start()
{
int counted_bars=IndicatorCounted();//—- check for possible errors
if (counted_bars<0) return(-1);
//—- last counted bar will be recounted
if (counted_bars>0) counted_bars—;
int pos=Bars-counted_bars;
double dHigh , dLow , dResult;
Comment(«Hi! I’m here on the main chart window!»);
//—- main calculation loop
while(pos>=0)
{
dHigh = High[pos];
dLow = Low[pos];
dResult = dHigh — dLow;
ExtMapBuffer1[pos]= dResult ;
pos—;
}
//—-
return(0);
}
//+——————————————————————+
//+------------------------------------------------------------------+
//| MyFirstIndicator.mq4 |
//| Kirill |
//| StockProgrammer@mail.ru |
//+------------------------------------------------------------------+
Комментарии
Первые пять строчек (выделены серым цветом у Вас в редакторе) — это комментарии.
Напомню, что комментарии мы используем для того, чтобы вставлять в код строчки, которые компилятор должен игнорировать.
Есть много причин, по которым могут потребоваться комментарии:
- Сделать код более красивым.
- Задокументировать такие моменты, как право собственности, дату создания и т.д.
- Сделать код понятнее.
- Объяснить, как код работает.
Комментарии бывают однострочные и многострочные (см. предыдущий пост).
В нашей программе помощник собрал введённую нами информацию о названии программы, её авторе и ссылке в самом верху.
Код:
#property copyright "Kirill"
#property link "StockProgrammer@mail.ru"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red
Директива property . (см. предыдущий пост)
#property copyright — здесь хранится имя автора программы. Вы ввели его на втором шаге помощника. Тип данных — string.
#property link — ссылка на Вашу домашнюю страницу или Ваш e-mail. Эти данные Вы также ввели на втором шаге помощника. Тип данных — string.
#property indicator_separate_window — таким образом мы говорим препроцессору, что мы хотим, чтобы наш индикатор рисовался в отдельном окне. Тип данных — void (нет принимаемого значения).
* #property indicator_chart_window — алтернатива — индикатор рисуется в окне графика. Обе опции использовать одновременно нельзя.
#property indicator_buffers 1 — с помощью indicator_buffers мы устанавливаем количество массивов, выделяемых под линии нашего индикатора. В кажлом индикаторе разрешается не больше 8 линий. В нашем случае мы рисуем только одну линию.
#property indicator_color1 Red — indicator_colorN устанавливает цвет линии номер N. Пользователь может изменить этот цвет в настройках индикатора. Тип данных — color.
Код:
//---- buffers
double ExtMapBuffer1[];
Разбор:
Массивы (Arrays)
В жизни мы часто группируем похожие объекты. В программировании тоже очень удобно группировать данные одного типа. Для достижения этой цели используются массивы.
Массив — это упорядоченное множество элементов одного типа. Нумерация в массиве начинается с нуля.
Объявление массива:
Код:
int my_array[50];
Здесь мы объявили массив, в котором может содержатся до 50 (включительно) элементов типа integer.
Доступ к элементу происходит по его индексу.
Например, доступ к 0-вому элементу массива и присваивания ему значения 16 выглядит так:
Код:
my_array[0] = 16;
Массив можно инициализировать в строчке его объявления. Делается это так:
Код:
int my_array[5] = {16,24,15,8901,17}
В нашей программе используется такой код:
Код:
double ExtMapBuffer1[];
Таким образом мы объявили массив типа double. Этот массив мы будем использовать для подсчёта значений, которые необходимо рисовать на графике индикатора.
Код:
Код:
int init()
Разбор:
В MQL4 есть три спец. функции: init(), start(), deinit(). Подробнее — см. пост — Функции.
Код:
Код:
//---- indicators
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,ExtMapBuffer1);
string short_name = "Your first indicator is running!"; IndicatorShortName(short_name);
//----
Разбор:
Я не могу дать Вам описания всех функций индикаторов в этом посте, но те, которые мы использовали, мы обсудим.
SetIndexStyle():
void SetIndexStyle( int index, int type, int style=EMPTY, int width=EMPTY, color clr=CLR_NONE)
- Устанавливает новый тип, стиль, ширину и цвет для указанной линии индикатора.
index — Порядковый номер линии. Должен быть от 0 до 7. Это потому что у нас может быть всего 8 линий, а нумерация в массиве, где они хранятся начинается с нуля.
type — Стиль отрисовки линии индикатора. Может быть одним из перечисленных стилей отрисовки линии:
DRAW_LINE — Простая линия
DRAW_SECTION — Отрезки между непустыми значениями линии
DRAW_HISTOGRAM — Гистограмма
DRAW_ARROW — Стрелки (символы)
DRAW_ZIGZAG — Отрезки между непустыми значениями чётной и нечётной линий (зигзаг)
DRAW_NONE — Отсутствие какого-либо рисования
style — Стиль линии. Используется для линий толщиной в 1 пиксель. Может быть одним из перечисленных стилей линии. Пустое значение (EMPTY) указывает, что стиль не будет изменен.
DRAW_LINE — Простая линия
DRAW_SECTION — Отрезки между непустыми значениями линии
DRAW_HISTOGRAM — Гистограмма
DRAW_ARROW — Стрелки (символы)
DRAW_ZIGZAG — Отрезки между непустыми значениями чётной и нечётной линий (зигзаг)
DRAW_NONE — Отсутствие какого-либо рисования
width — Ширина линии. Допустимые значения — 1,2,3,4,5. Пустое значение (EMPTY) указывает, что ширина не будет изменена.
clr — Цвет линии. Отсутствие параметра означает, что цвет не будет изменен.
В нашем коде:
Код:
SetIndexStyle(0,DRAW_LINE);
index = 0 — это означает, что мы будем работать с первой (и единственной) нашей линией.
type = DRAW_LINE — это означает, что мы хотим рисовать линию.
Остальные параметры мы оставили по умолчанию.
SetIndexBuffer()
bool SetIndexBuffer(int index, double array[])
- Связывает переменную-массив, объявленный на глобальном уровне, с предопределенным буфером пользовательского индикатора. Количество буферов, необходимых для расчета индикатора, задается с помощью функции IndicatorBuffers() и не может быть больше 8. В случае успешного связывания возвращается TRUE, иначе FALSE. Чтобы получить расширенные сведения об ошибке, следует вызвать функцию GetLastError().
Как мы уже замечали ранее, расчитанные данные для отрисовки на график в нашей программе будут храниться в массиве ExtMapBuffer1[]. Его мы и связываем с нашей единственной линией, имеющей индекс 0.
IndicatorShortName();
void IndicatorShortName(string name)
- Установка «короткого» имени пользовательского индикатора для отображения в подокне индикатора и в окне DataWindow.
Мы в нашей программе завели переменную short_name типа string, которой присвоили значение «Your first indicator is running!». Затем мы передали эту переменную в функцию IndicatorShortName(); .
Код:
Код:
return (0);
Разбор:
Функция init() возвращает 0 и завершает свою работу. Управление переходит функции start().
Код:
Код:
int deinit()
{
//----
//----
return(0);
}
Разбор:
Ничего нового про функцию deinit() сказать не могу.
Выше мы разбирали код нашего индикатора строчку за строчкой и дошли до функции start().
Очень надеюсь, что Вы прекрасно понимаете.
Теперь мы изучим функцию start() и её содержимое, и, наконец-то, мы скомпилируем и запустим наш первый индикатор.
Давайте разберём оставшийся код!
Наш код:
Цитата:
//+——————————————————————+
//| MyFirstIndicator.mq4 |
//| Kirill |
//| StockProgrammer@mail.ru |
//+——————————————————————+
#property copyright «Kirill»
#property link «StockProgrammer@mail.ru»#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red
//—- buffers
double ExtMapBuffer1[];
//+——————————————————————+
//| Custom indicator initialization function |
//+——————————————————————+
int init()
{
//—- indicators
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,ExtMapBuffer1);string short_name = «Your first indicator is running!»;
IndicatorShortName(short_name);//—-
return(0);
}
//+——————————————————————+
//| Custom indicator deinitialization function |
//+——————————————————————+
int deinit()
{
//—-//—-
return(0);
}
//+——————————————————————+
//| Custom indicator iteration function |
//+——————————————————————+
int start()
{
int counted_bars=IndicatorCounted();//—- check for possible errors
if (counted_bars<0) return(-1);
//—- last counted bar will be recounted
if (counted_bars>0) counted_bars—;
int pos=Bars-counted_bars;
double dHigh , dLow , dResult;
Comment(«Hi! I’m here on the main chart windows!»);
//—- main calculation loop
while(pos>=0)
{
dHigh = High[pos];
dLow = Low[pos];
dResult = dHigh — dLow;
ExtMapBuffer1[pos]= dResult ;
pos—;
}
//—-
return(0);
}
//+——————————————————————+
Код:
Код:
int start()
{
}
Разбор:
Как я Вам уже говорил, мы будем проводить 90% нашей программистской жизни внутри фигурных скобок тела функцииstart(). Это так, потому что она самая важная из всех трёх спец. функций MQL4. В отличии от функций init() и deinit()функция start() не будет вызвана (клиентским терминалом) только единожды. Она будет вызываться при каждом поступление новых котировок. Функция start() возвращает значение типа integer, как и все остальные спец. функции языка MQL4. 0 означает, что функция отработала без ошибок, а любое другое число означает, что произошла ошибка.
Код:
Код:
int counted_bars=IndicatorCounted();
Разбор:
Здесь мы объявили переменную counted_bars типа integer и инициализировали её значением, возвращаемым функцией IndicatorCounted(); .
- Функция возвращает количество баров, не измененных после последнего вызова индикатора. Большинство подсчитанных баров не нуждается в пересчете. Функция используется для оптимизации вычислений.
Замечание: самый последний бар не считается посчитанным, и в большинстве случаев необходимо пересчитывать только его. Однако бывают пограничные случаи, когда вызов пользовательского индикатора производится из эксперта на первом тике нового бара. Возможна ситуация, что последний тик предыдущего бара не обработан (по той причине, что в момент прихода этого последнего тика обрабатывался предпоследний тик), и пользовательский индикатор не был вызван и поэтому не был рассчитан. Чтобы избежать в такой ситуации ошибок расчета индикатора, функция IndicatorCounted() возвращает реально посчитанное количество баров минус один.
ОЧЕНЬ ВАЖНО: на будущее запомните, что в MQL4 бары нумеруются задом-наперёд. Нулевой бар — это текущий бар, следующий (более старый — левее на графике) — это первый бар, за ним — второй и т.д. При появлении нового бара они все перенумеровываются, и текущий опять становится нулевым.
Код:
Код:
//---- check for possible errors
if (counted_bars<0) return(-1);
Разбор:
Очевидно, что число баров, не измененных после последнего вызова индикатора должно быть = 0 или > 0. Если же оно < 0, значит произошла ошибка. Мы терминируем функцию start() и сообщаем об ошибке, возвращая не 0.
Код:
Код:
//---- last counted bar will be recounted
if (counted_bars>0) counted_bars--;
Разбор:
Притворяемся, что посчитано на один бар меньше, чтобы пересчитать последний бар. На самом деле, это перестраховка, т.к. функция IndicatorCounted( ) и так возвращает число на 1 меньше. Но ничего страшного в том, что мы пересчитаем ещё один лишний бар нет. PS: надеюсь, вы помните, что —; — это оператор декремента — уменьшение на единицу.
Код:
Код:
int pos=Bars-counted_bars;
Разбор:
Здесь мы объявляем переменную pos, которая указывает, сколько раз должен сработать наш счётный цикл (про цикл while см. далее). ‘Функция’ Bars возвращает количество уже имеющихся на графике баров. Чтобы вычислить pos мы из общего количества баров графика вычитаем количество уже посчитанных баров.
Кстати, хороший момент обсудить ‘функцию’ Bars и её братьев.
Предопределённые переменные языка MQL4:
Ask, Bid, Bars, Close, Open, High, Low, Time и Volume — являются функциями, хотя в MQL4 они называются предопределёнными переменными и после них не надо ставить круглые скобки.
И я докажу Вам, что они скорее функции, чем переменные.
Переменная — означает область в памяти + тип данных, который Вы указываете.
Функция — означает сделать что-то и вернуть какое-то значение. Например, Bars считает и возвращает количество баров на графике. Так что же? Это переменная?
Если ввести следующий код:
Bars = 1;
Вы получите ошибку: ‘Bars’ — unexpected token
Это потому что они не переменные, и Вы не можете присваивать им значения.
Итак, обсудим эти функции.
int Bars
Эта функция возвращает значение типа integer, в котором содержится информация о количестве имеющихся на текущем графике барах.
double Ask
Эта функция, используемая преимущественно в советниках, возвращает значение типа double, в котором содержится информация о цене покупки базовой валюты в данной валютной паре.
double Bid
Эта функция, используемая преимущественно в советниках, возвращает значение типа double, в котором содержится информация о цене продажи базовой валюты в данной валютной паре.
Замечание: Например, USD/JPY = 105.11/105.14 — здесь левая цена — это bid (цена, по которой Вы продаёте), правая цена — это ask (цена, по которой Вы покупаете).
double Open[]
Эта функция возвращает значение типа double, в котором содержится информация о цене открытия (далее — везде ‘цена’ — это bid) для указанного бара.
Например: Open[0] вернёт цену открытия текущего бара.
double Close[]
Эта функция возвращает значение типа double, в котором содержится информация о цене закрытия для указанного бара.
Замечание: Т.к. цена закрытия текущего бара ещё никому не известна, Close[0] возвращает текущую цену bid.
double High[]
Эта функция возвращает значение типа double, в котором содержится информация о самой высокой цене (цене high) для указанного бара.
double High[]
Эта функция возвращает значение типа double, в котором содержится информация о самой низкой цене (цене low) для указанного бара.
double Volume[]
Эта функция возвращает значение типа double, в котором содержится информация ( для forex объёмы не контролируются, поэтому: ) о количестве изменений котировки для указанного бара.
int Digits
Эта функция возвращает значение типа integer, в котором содержится информация о количестве знаков после запятой для котировки данной валюты. Обычно 4.
int Point
Эта функция возвращает значение типа double равное одному пункту для данной валютной пары. Обычно 0.0001 .
datetime Time[]
Эта функция возвращает значение типа datetime, в котором содержится информация о времени открытия указанного бара.
Код:
Код:
double dHigh , dLow , dResult;
Разбор:
Мы объявили три переменные типа double, которые мы используем позже. Заметьте, как мы объявили все три в одной строчке, разделив их запятыми.
Код:
Код:
Comment("Hi! I'm here on the main chart window!");
Разбор:
В этой строчке мы используем функцию Comment, чтобы распечатать текст «Hi! I’m here on the main chart window!» в левом верхнем углу основного графика.
Всего таких информирующих функции три:
void Comment()
- Функция выводит комментарий, определенный пользователем, в левый верхний угол графика. Параметры могут иметь любой тип. Количество параметров не может превышать 64.
void Print( …)
- Печатает некоторое сообщение в журнал экспертов. Параметры могут иметь любой тип. Количество параметров не может превышать 64.
void Alert( …)
- Отображает диалоговое окно, содержащие пользовательские данные. Параметры могут быть любого типа. Количество параметров не может превышать 64.
Код:
Код:
//---- main calculation loop
while(pos>=0)
{
dHigh = High[pos];
dLow = Low[pos];
dResult = dHigh - dLow;
ExtMapBuffer1[pos]= dResult ;
pos--;
}
ОЧЕНЬ ВАЖНО: когда мы связываем массив с линией, массив приобретает ещё одно спец. свойство. При появлении нового бара на графике, все элементы массива сдвигаются влево на один, т.е. N-й становится N+1-ым, … , 1-й становится 2-м, 0-й становится 1-м. Таким образом, высвобождается место для нового нулевого элемента. Это сделано для того,чтобы при пересчёте только новых баров графика, информация о значении индикатора на старых барах сохранялась в элементах масива, индексируемых теми же числами, что и сами бары.
Переменной цикла (она регулирует число его прохождений) у нас является переменная pos. Мы её используем для обращения к неподсчитанным барам. Например High[pos] вернёт максимальное значение цены на баре с индексом pos.
В теле цикла мы присваиваем переменной dHigh значение цены high на баре pos.
Аналогично, мы присваиваем переменной dLow значение цены low на баре pos.
Разницу dHigh — dLow мы присваиваем переменной dResult.
Затем Мы используем dResult для отрисовки линии индикатора, присваивая его значение соответствующему элементу массива ExtMapBuffer1[] (элементу с индексом pos).
Последняя строчка цикла — мы применяем оператор декремента к переменной цикла pos. Когда, pos станет = -1, цикл завершит свою работу.
Нажмите F5 или нажмите кнопку Компилировать.
В результате сгенерируется исполняемый файл «MyFirstIndicator.ex4″, который Вы можете запустить в своём терминале.
Чтобы это сделать нажмите F4 или вручную откройте терминал. В окне навигатора в терминале выберите раздел «Пользовательские Индикаторы«, найдите MyFirstIndicator и перетащите его на график цены.
Замечание: Ваш индикатор показывает волатильность рынка.
Уверен, этот и последующие несколько постов по программированию на языке MQL4 будут интересны не только теоретикам, но и практикам.
Важно: рекомендую проситать предыдущие посты очень внимательно, прежде, чем переходить к этому и последующим постам. Мы будем очень обширно пользоваться вышеописанном материалом.
Теперь мы создадим простой индикатор, который будет значить немного для нашей торговли, но будет значить очень много для нашего понимания программирования на MQL4.
Он будет просто-напросто рассчитывать разницу High [] – Low []. Не торопитесь, скоро Вы всё поймёте.
Поехали!
MetaEditor
У меня на рабочем столе есть ярлык MetaEditor, чтобы проще его запускать.
Запуск MetaEditor — у Вас есть три возможности:
1 — Запустите MT4, затем либо нажмите F4, либо выберите MetaEditor из вкладки «сервис», либо нажмите на значок MetaEditor (см. рис. 1).2 — Пуск -> Программы -> /Группа MetaTrader 4/ -> MetaEditor .
3 — Зайти в папку установки MT4 (например: C:Program FilesMetaTrader 4), найти MetaEditor.exe и запустить (рекомедую сделать ярлык на рабочем столе).
Рис. 1 — Стандартные кнопки MT4.
В любом случае Вы попадаете в программу MetaEditor 4.Рис. 2 — Окна MetaEditor.
1 — Окно редактора. Здесь Вы пишите свою программу.2 — Окно инструментария. Содержит четыре вкладки:
- Ошибки. Здесь Вам покажут возникшие при компиляции ошибки.
- Поиск в файлах. Здесь Вы можете просматривать файлы, найденные с помощью соотетствующей комманды из вкладки правка (Ctrl+Shift+F).
- Библиотека. Online — библиотека.
- Справка. Выделяете в коде нужное слово и жмёте F1. Появится справка.
3 — Окно навигатора. Содержит три вкладки:
- Файлы. Для простого доступа к файлам, сохранённым в папке MT4.
- Словарь. Доступ к справке по MQL4.
- Поиск. Поиск в справке MQL4.
Советую ознакомиться с окнами MetaEditor.
А теперь приступим к созданию нашего первого индикатора.
Заметка: пользовательский индикатор — это программа, которая позволяет Вам использовать функции технического анализа, но не может автоматизировать Ваши сделки.
Первые три шага
В дальнейшем Вы научитесь пропускать эти три скучные шага, но пока мы будем их выполнять.
Шаг 1: Нажмите Файл -> Создать (или просто Ctrl + N)
Появится такое окошко:
Рис. 3 — окошко нового проекта.
Выберите пункт «пользовательский индикатор» и нажмите Next.Шаг 2:
Появится такое окошко:
Рис. 4 — окошко свойств проекта.
1 — Имя Вашей программы.2 — Автор программы.
3 — Ссылка на Ваш сайт или e-mail.
4 — Параметры — список внешних (extern) переменных. Это те переменные, которые пользователь сможет изменять в окошке настроек индикатора (см. урок про переменные).
В нашем примере нам не потребуются внешние переменные. Заполните первые три поля и нажмите Next.
Шаг 3:
Появится такое окошко:
Рис. 5 — окошко свойств отображения индикатора.
В этом окошке Вы можете устанавливать свойства рисования Вашего индикатора, например: сколько у него будет линий, их цвета, где рисовать Ваш индикатор (на графике цены или в отдельном окне).1 — Индикатор в отдельном окне. Думаю, понятно, что эта опция делает.
2 — Минимум. Если индикатор рисуется в отдельном окне, эта опция устанавливает нижнюю границу для этого окна.
3 — Максимум. Если индикатор рисуется в отдельном окне, эта опция устанавливает верхнюю границу для этого окна.
4 — Список индексов. Сюда Вы добавляете линии индикатора и ставите их цвет-по-умолчанию.
Далее мы более подробно разберём эти опции, поэтому не спешите.
А сейчас сделайте всё, как на рис. 5.
Когда Вы нажмёте кнопку Finish, начнётся волшебство. Окошко помощника исчезнет, Вы опять окажетесь в MetaEditor и… Угадайте….
Вы получили шаблон для своего первого индикатора.
Примерно такой код Вы получите:
Код:
//+------------------------------------------------------------------+
//| MyFirstIndicator.mq4 |
//| Kirill |
//| StockProgrammer@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Kirill"
#property link "StockProgrammer@mail.ru"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red
//---- buffers
double ExtMapBuffer1[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,ExtMapBuffer1);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int counted_bars=IndicatorCounted();
//----
//----
return(0);
}
//+------------------------------------------------------------------+
Как Вы видите, помощник написал достаточно много кода за Вас.
Изучаем основной материал:
Пишем первый индикатор
Теперь мы добавим пару строк в уже имеющийся код, чтобы программа стала более полезной.
После этого мы разберём весь код строчку за строчкой.
Начнём кодить!
Я выделил жирным код, который нужно добавить.
Цитата:
//+——————————————————————+
//| MyFirstIndicator.mq4 |
//| Kirill |
//| StockProgrammer@mail.ru |
//+——————————————————————+
#property copyright «Kirill»
#property link «StockProgrammer@mail.ru»#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red
//—- buffers
double ExtMapBuffer1[];
//+——————————————————————+
//| Custom indicator initialization function |
//+——————————————————————+
int init()
{
//—- indicators
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,ExtMapBuffer1); string short_name = «Your first indicator is running!»;
IndicatorShortName(short_name);//—-
return(0);
}
//+——————————————————————+
//| Custom indicator deinitialization function |
//+——————————————————————+
int deinit()
{
//—-//—-
return(0);
}
//+——————————————————————+
//| Custom indicator iteration function |
//+——————————————————————+
int start()
{
int counted_bars=IndicatorCounted();//—- check for possible errors
if (counted_bars<0) return(-1);
//—- last counted bar will be recounted
if (counted_bars>0) counted_bars—;
int pos=Bars-counted_bars;
double dHigh , dLow , dResult;
Comment(«Hi! I’m here on the main chart window!»);
//—- main calculation loop
while(pos>=0)
{
dHigh = High[pos];
dLow = Low[pos];
dResult = dHigh — dLow;
ExtMapBuffer1[pos]= dResult ;
pos—;
}
//—-
return(0);
}
//+——————————————————————+
Как он будет работать?
Код://+------------------------------------------------------------------+
//| MyFirstIndicator.mq4 |
//| Kirill |
//| StockProgrammer@mail.ru |
//+------------------------------------------------------------------+
Разбор:
Комментарии
Первые пять строчек (выделены серым цветом у Вас в редакторе) — это комментарии.
Напомню, что комментарии мы используем для того, чтобы вставлять в код строчки, которые компилятор должен игнорировать.
Есть много причин, по которым могут потребоваться комментарии:
- Сделать код более красивым.
- Задокументировать такие моменты, как право собственности, дату создания и т.д.
- Сделать код понятнее.
- Объяснить, как код работает.
Комментарии бывают однострочные и многострочные (см. предыдущий пост).
В нашей программе помощник собрал введённую нами информацию о названии программы, её авторе и ссылке в самом верху.
Код:
#property copyright "Kirill"
#property link "StockProgrammer@mail.ru"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red
Разбор:
Директива property . (см. предыдущий пост)
#property copyright — здесь хранится имя автора программы. Вы ввели его на втором шаге помощника. Тип данных — string.
#property link — ссылка на Вашу домашнюю страницу или Ваш e-mail. Эти данные Вы также ввели на втором шаге помощника. Тип данных — string.
#property indicator_separate_window — таким образом мы говорим препроцессору, что мы хотим, чтобы наш индикатор рисовался в отдельном окне. Тип данных — void (нет принимаемого значения).
* #property indicator_chart_window — алтернатива — индикатор рисуется в окне графика. Обе опции использовать одновременно нельзя.
#property indicator_buffers 1 — с помощью indicator_buffers мы устанавливаем количество массивов, выделяемых под линии нашего индикатора. В кажлом индикаторе разрешается не больше 8 линий. В нашем случае мы рисуем только одну линию.
#property indicator_color1 Red — indicator_colorN устанавливает цвет линии номер N. Пользователь может изменить этот цвет в настройках индикатора. Тип данных — color.
Код:
//---- buffers
double ExtMapBuffer1[];
Разбор:
Массивы (Arrays)
В жизни мы часто группируем похожие объекты. В программировании тоже очень удобно группировать данные одного типа. Для достижения этой цели используются массивы.
Массив — это упорядоченное множество элементов одного типа. Нумерация в массиве начинается с нуля.
Объявление массива:
Код:
int my_array[50];
Здесь мы объявили массив, в котором может содержатся до 50 (включительно) элементов типа integer.
Доступ к элементу происходит по его индексу.
Например, доступ к 0-вому элементу массива и присваивания ему значения 16 выглядит так:
Код:
my_array[0] = 16;
Массив можно инициализировать в строчке его объявления. Делается это так:
Код:
int my_array[5] = {16,24,15,8901,17}
В нашей программе используется такой код:
Код:
double ExtMapBuffer1[];
Таким образом мы объявили массив типа double. Этот массив мы будем использовать для подсчёта значений, которые необходимо рисовать на графике индикатора.
Код:
Код:
int init()
Разбор:
В MQL4 есть три спец. функции: init(), start(), deinit(). Подробнее — см. пост — Функции.
Код:
Код:
//---- indicators
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,ExtMapBuffer1);
string short_name = "Your first indicator is running!"; IndicatorShortName(short_name);
//----
Разбор:
Функции пользовательских индикаторов.
Я не могу дать Вам описания всех функций индикаторов в этом посте, но те, которые мы использовали, мы обсудим.
SetIndexStyle():
void SetIndexStyle( int index, int type, int style=EMPTY, int width=EMPTY, color clr=CLR_NONE)
- Устанавливает новый тип, стиль, ширину и цвет для указанной линии индикатора.
index — Порядковый номер линии. Должен быть от 0 до 7. Это потому что у нас может быть всего 8 линий, а нумерация в массиве, где они хранятся начинается с нуля.
type — Стиль отрисовки линии индикатора. Может быть одним из перечисленных стилей отрисовки линии:
DRAW_LINE — Простая линия
DRAW_SECTION — Отрезки между непустыми значениями линии
DRAW_HISTOGRAM — Гистограмма
DRAW_ARROW — Стрелки (символы)
DRAW_ZIGZAG — Отрезки между непустыми значениями чётной и нечётной линий (зигзаг)
DRAW_NONE — Отсутствие какого-либо рисования
style — Стиль линии. Используется для линий толщиной в 1 пиксель. Может быть одним из перечисленных стилей линии. Пустое значение (EMPTY) указывает, что стиль не будет изменен.
DRAW_LINE — Простая линия
DRAW_SECTION — Отрезки между непустыми значениями линии
DRAW_HISTOGRAM — Гистограмма
DRAW_ARROW — Стрелки (символы)
DRAW_ZIGZAG — Отрезки между непустыми значениями чётной и нечётной линий (зигзаг)
DRAW_NONE — Отсутствие какого-либо рисования
width — Ширина линии. Допустимые значения — 1,2,3,4,5. Пустое значение (EMPTY) указывает, что ширина не будет изменена.
clr — Цвет линии. Отсутствие параметра означает, что цвет не будет изменен.
В нашем коде:
Код:
SetIndexStyle(0,DRAW_LINE);
index = 0 — это означает, что мы будем работать с первой (и единственной) нашей линией.
type = DRAW_LINE — это означает, что мы хотим рисовать линию.
Остальные параметры мы оставили по умолчанию.
SetIndexBuffer()
bool SetIndexBuffer(int index, double array[])
- Связывает переменную-массив, объявленный на глобальном уровне, с предопределенным буфером пользовательского индикатора. Количество буферов, необходимых для расчета индикатора, задается с помощью функции IndicatorBuffers() и не может быть больше 8. В случае успешного связывания возвращается TRUE, иначе FALSE. Чтобы получить расширенные сведения об ошибке, следует вызвать функцию GetLastError().
Как мы уже замечали ранее, расчитанные данные для отрисовки на график в нашей программе будут храниться в массиве ExtMapBuffer1[]. Его мы и связываем с нашей единственной линией, имеющей индекс 0.
IndicatorShortName();
void IndicatorShortName(string name)
- Установка «короткого» имени пользовательского индикатора для отображения в подокне индикатора и в окне DataWindow.
Мы в нашей программе завели переменную short_name типа string, которой присвоили значение «Your first indicator is running!». Затем мы передали эту переменную в функцию IndicatorShortName(); .
Код:
Код:
return (0);
Разбор:
Функция init() возвращает 0 и завершает свою работу. Управление переходит функции start().
Код:
Код:
int deinit()
{
//----
//----
return(0);
}
Разбор:
Ничего нового про функцию deinit() сказать не могу.
Теперь продолжим разбирать код
Выше мы разбирали код нашего индикатора строчку за строчкой и дошли до функции start().
Очень надеюсь, что Вы прекрасно понимаете.
Теперь мы изучим функцию start() и её содержимое, и, наконец-то, мы скомпилируем и запустим наш первый индикатор.
Давайте разберём оставшийся код!
Наш код:
Цитата:
//+——————————————————————+
//| MyFirstIndicator.mq4 |
//| Kirill |
//| StockProgrammer@mail.ru |
//+——————————————————————+
#property copyright «Kirill»
#property link «StockProgrammer@mail.ru»#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red
//—- buffers
double ExtMapBuffer1[];
//+——————————————————————+
//| Custom indicator initialization function |
//+——————————————————————+
int init()
{
//—- indicators
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0,ExtMapBuffer1);string short_name = «Your first indicator is running!»;
IndicatorShortName(short_name);//—-
return(0);
}
//+——————————————————————+
//| Custom indicator deinitialization function |
//+——————————————————————+
int deinit()
{
//—-//—-
return(0);
}
//+——————————————————————+
//| Custom indicator iteration function |
//+——————————————————————+
int start()
{
int counted_bars=IndicatorCounted();//—- check for possible errors
if (counted_bars<0) return(-1);
//—- last counted bar will be recounted
if (counted_bars>0) counted_bars—;
int pos=Bars-counted_bars;
double dHigh , dLow , dResult;
Comment(«Hi! I’m here on the main chart windows!»);
//—- main calculation loop
while(pos>=0)
{
dHigh = High[pos];
dLow = Low[pos];
dResult = dHigh — dLow;
ExtMapBuffer1[pos]= dResult ;
pos—;
}
//—-
return(0);
}
//+——————————————————————+
Код:
Код:
int start()
{
}
Разбор:
Как я Вам уже говорил, мы будем проводить 90% нашей программистской жизни внутри фигурных скобок тела функцииstart(). Это так, потому что она самая важная из всех трёх спец. функций MQL4. В отличии от функций init() и deinit()функция start() не будет вызвана (клиентским терминалом) только единожды. Она будет вызываться при каждом поступление новых котировок. Функция start() возвращает значение типа integer, как и все остальные спец. функции языка MQL4. 0 означает, что функция отработала без ошибок, а любое другое число означает, что произошла ошибка.
Код:
Код:
int counted_bars=IndicatorCounted();
Разбор:
Здесь мы объявили переменную counted_bars типа integer и инициализировали её значением, возвращаемым функцией IndicatorCounted(); .
int IndicatorCounted( )
- Функция возвращает количество баров, не измененных после последнего вызова индикатора. Большинство подсчитанных баров не нуждается в пересчете. Функция используется для оптимизации вычислений.
Замечание: самый последний бар не считается посчитанным, и в большинстве случаев необходимо пересчитывать только его. Однако бывают пограничные случаи, когда вызов пользовательского индикатора производится из эксперта на первом тике нового бара. Возможна ситуация, что последний тик предыдущего бара не обработан (по той причине, что в момент прихода этого последнего тика обрабатывался предпоследний тик), и пользовательский индикатор не был вызван и поэтому не был рассчитан. Чтобы избежать в такой ситуации ошибок расчета индикатора, функция IndicatorCounted() возвращает реально посчитанное количество баров минус один.
ОЧЕНЬ ВАЖНО: на будущее запомните, что в MQL4 бары нумеруются задом-наперёд. Нулевой бар — это текущий бар, следующий (более старый — левее на графике) — это первый бар, за ним — второй и т.д. При появлении нового бара они все перенумеровываются, и текущий опять становится нулевым.
Код:
Код:
//---- check for possible errors
if (counted_bars<0) return(-1);
Разбор:
Очевидно, что число баров, не измененных после последнего вызова индикатора должно быть = 0 или > 0. Если же оно < 0, значит произошла ошибка. Мы терминируем функцию start() и сообщаем об ошибке, возвращая не 0.
Код:
Код:
//---- last counted bar will be recounted
if (counted_bars>0) counted_bars--;
Разбор:
Притворяемся, что посчитано на один бар меньше, чтобы пересчитать последний бар. На самом деле, это перестраховка, т.к. функция IndicatorCounted( ) и так возвращает число на 1 меньше. Но ничего страшного в том, что мы пересчитаем ещё один лишний бар нет. PS: надеюсь, вы помните, что —; — это оператор декремента — уменьшение на единицу.
Код:
Код:
int pos=Bars-counted_bars;
Разбор:
Здесь мы объявляем переменную pos, которая указывает, сколько раз должен сработать наш счётный цикл (про цикл while см. далее). ‘Функция’ Bars возвращает количество уже имеющихся на графике баров. Чтобы вычислить pos мы из общего количества баров графика вычитаем количество уже посчитанных баров.
Кстати, хороший момент обсудить ‘функцию’ Bars и её братьев.
Предопределённые переменные языка MQL4:
Ask, Bid, Bars, Close, Open, High, Low, Time и Volume — являются функциями, хотя в MQL4 они называются предопределёнными переменными и после них не надо ставить круглые скобки.
И я докажу Вам, что они скорее функции, чем переменные.
Переменная — означает область в памяти + тип данных, который Вы указываете.
Функция — означает сделать что-то и вернуть какое-то значение. Например, Bars считает и возвращает количество баров на графике. Так что же? Это переменная?
Если ввести следующий код:
Bars = 1;
Вы получите ошибку: ‘Bars’ — unexpected token
Это потому что они не переменные, и Вы не можете присваивать им значения.
Итак, обсудим эти функции.
int Bars
Эта функция возвращает значение типа integer, в котором содержится информация о количестве имеющихся на текущем графике барах.
double Ask
Эта функция, используемая преимущественно в советниках, возвращает значение типа double, в котором содержится информация о цене покупки базовой валюты в данной валютной паре.
double Bid
Эта функция, используемая преимущественно в советниках, возвращает значение типа double, в котором содержится информация о цене продажи базовой валюты в данной валютной паре.
Замечание: Например, USD/JPY = 105.11/105.14 — здесь левая цена — это bid (цена, по которой Вы продаёте), правая цена — это ask (цена, по которой Вы покупаете).
double Open[]
Эта функция возвращает значение типа double, в котором содержится информация о цене открытия (далее — везде ‘цена’ — это bid) для указанного бара.
Например: Open[0] вернёт цену открытия текущего бара.
double Close[]
Эта функция возвращает значение типа double, в котором содержится информация о цене закрытия для указанного бара.
Замечание: Т.к. цена закрытия текущего бара ещё никому не известна, Close[0] возвращает текущую цену bid.
double High[]
Эта функция возвращает значение типа double, в котором содержится информация о самой высокой цене (цене high) для указанного бара.
double High[]
Эта функция возвращает значение типа double, в котором содержится информация о самой низкой цене (цене low) для указанного бара.
double Volume[]
Эта функция возвращает значение типа double, в котором содержится информация ( для forex объёмы не контролируются, поэтому: ) о количестве изменений котировки для указанного бара.
int Digits
Эта функция возвращает значение типа integer, в котором содержится информация о количестве знаков после запятой для котировки данной валюты. Обычно 4.
int Point
Эта функция возвращает значение типа double равное одному пункту для данной валютной пары. Обычно 0.0001 .
datetime Time[]
Эта функция возвращает значение типа datetime, в котором содержится информация о времени открытия указанного бара.
Код:
Код:
double dHigh , dLow , dResult;
Разбор:
Мы объявили три переменные типа double, которые мы используем позже. Заметьте, как мы объявили все три в одной строчке, разделив их запятыми.
Код:
Код:
Comment("Hi! I'm here on the main chart window!");
Разбор:
В этой строчке мы используем функцию Comment, чтобы распечатать текст «Hi! I’m here on the main chart window!» в левом верхнем углу основного графика.
Всего таких информирующих функции три:
void Comment()
- Функция выводит комментарий, определенный пользователем, в левый верхний угол графика. Параметры могут иметь любой тип. Количество параметров не может превышать 64.
void Print( …)
- Печатает некоторое сообщение в журнал экспертов. Параметры могут иметь любой тип. Количество параметров не может превышать 64.
void Alert( …)
- Отображает диалоговое окно, содержащие пользовательские данные. Параметры могут быть любого типа. Количество параметров не может превышать 64.
Код:
Код:
//---- main calculation loop
while(pos>=0)
{
dHigh = High[pos];
dLow = Low[pos];
dResult = dHigh - dLow;
ExtMapBuffer1[pos]= dResult ;
pos--;
}
Разбор:
Пришло время войти в цикл расчёта отображаемых нашим индикатором точек. Любое значение, которое мы положим в массив ExtMapBuffer1[] будет отображено на графике (потому что, используя функцию SetIndexBuffer(), мы связали этот массив с линией, индексируемой нулём).ОЧЕНЬ ВАЖНО: когда мы связываем массив с линией, массив приобретает ещё одно спец. свойство. При появлении нового бара на графике, все элементы массива сдвигаются влево на один, т.е. N-й становится N+1-ым, … , 1-й становится 2-м, 0-й становится 1-м. Таким образом, высвобождается место для нового нулевого элемента. Это сделано для того,чтобы при пересчёте только новых баров графика, информация о значении индикатора на старых барах сохранялась в элементах масива, индексируемых теми же числами, что и сами бары.
Переменной цикла (она регулирует число его прохождений) у нас является переменная pos. Мы её используем для обращения к неподсчитанным барам. Например High[pos] вернёт максимальное значение цены на баре с индексом pos.
В теле цикла мы присваиваем переменной dHigh значение цены high на баре pos.
Аналогично, мы присваиваем переменной dLow значение цены low на баре pos.
Разницу dHigh — dLow мы присваиваем переменной dResult.
Затем Мы используем dResult для отрисовки линии индикатора, присваивая его значение соответствующему элементу массива ExtMapBuffer1[] (элементу с индексом pos).
Последняя строчка цикла — мы применяем оператор декремента к переменной цикла pos. Когда, pos станет = -1, цикл завершит свою работу.
Наконец-то мы можем скомпилировать наш индикатор!
Нажмите F5 или нажмите кнопку Компилировать.
В результате сгенерируется исполняемый файл «MyFirstIndicator.ex4″, который Вы можете запустить в своём терминале.
Чтобы это сделать нажмите F4 или вручную откройте терминал. В окне навигатора в терминале выберите раздел «Пользовательские Индикаторы«, найдите MyFirstIndicator и перетащите его на график цены.
Замечание: Ваш индикатор показывает волатильность рынка.
Надеюсь, Вам понравился Ваш только, что созданный первый индикатор и материал был усвоен.
Препроцессор — Учимся программировать на языке MQL4
2012-05-08 23:41:00 (читать в оригинале)
Препроцессор. Что такое препроцессор?
Препроцессор — это программа, обеспечивающая предварительную обработку кода для его подготовки к компиляции.Например, если Вы используете директиву #include
Например:
Код:
#define my_constant 100
Как Вы можете заметить в приведённом примере нет символа присваивания «=», а есть только пробел между именем константы (my_constant) и её значением (100).И также Вы должны были заметить, что строчка не закончилась точкой с звпятой — она закончилась символом перехода на новую строку.
Имена констант подчиняются тем же правилам, что и имена переменных (см. предыдущий пост), например нельзя начинать имя константы с цифры, и его длина не должна превышать 31 символ.
Значение константы может быть любым.
Препроцессор просто заменит Вашу константу на её значение везде, где повстречает её в коде. Да именно так —заменит одни символы (имя константы) на другие (её значение). И всё это произойдёт до компиляции, поэтому компилятор даже не заметит, что у Вас была какая-то константа.
Так что, Вашу константу можно применить, например так:
Код:
um = constant1 * 10;
2 — директива propertyВ MQL4 существуют заранее подготовленные переменные, называемые «Управляющие Компляцией», значения которых можно изменять для своей программы.
Для этого используется директива property — она говорит препроцессору, как настроить Ваш исполняемый файл *.ex4 .
Пример:
Код:
#property link "http://www.MYSITE.com"
#property copyright "FreeWare"
Список предопределённых переменных MQL4:
Использование директивы include равносильно копированию всего содержимого подключаемого файла к себе в программу, в то место, где стоит эта директива. Ctrl+C -> Ctrl+V — только за Вас это делает препроцессор.
Пример:
Код:
#include
Внимание: Есть два различных способа указания пути к файлу.
- Можно указать имя файла в угольных скобках
- Можно указать имя файла в кавычках «win32.h» — тогда препроцессор будет искать этот файл в текущей директории — в той, где будет лежать Ваш код. Если Ваш код и искомый файл лежат в разных местах, то можно указать полный путь к файлу — это тоже делается с помощью кавычек: «F:My_folderMy_include_filesHello.h» .
Директиву include можно вставить в любую часть кода, но обычно это делается в самом начале.
Подсказка: Хорошей практикой является размещение часто употребляемого Вами кода в отдельном файле, для его дальнейшего подключения в свои программы.
(просто совет).
4 — директива import
Это как директива include, но есть различия.
Директива import используется только для подключения исполняемых файлов MQL4 (*.ex4) и динамических библиотек (*.dll), чтобы импортировать их функции в Вашу программу.
Например:
Код:
#import "user32.dll"
int MessageBoxA(int hWnd,string lpText,string lpCaption,
int uType);
int MessageBoxExA(int hWnd,string lpText,string lpCaption,
int uType,int wLanguageId);
#import "melib.ex4"
#import "gdi32.dll"
int GetDC(int hWnd);
int ReleaseDC(int hWnd,int hDC);
#import
Когда Вы импортируете функции из файла *.ex4 нет необходимости их объявлять.Когда Вы импортируете функции из файла *.dll необходимо объявлять функции, чтобы они были готовы к использованию.
Пример объявления функции:
Код:
int MessageBoxA(int hWnd,string lpText,string lpCaption, int uType);
Импорт функций начинается со строчки #include «имя файла» (или в угольных скобках).Импорт йункций заканчивается строчкой #include .
Как говорит один знакомый информатик: «препроцессор помогает избежать работы обезьянкой». Этим всё сказано!!!
Циклы и Условия, Функции, Переменные в MQL4
2012-05-08 23:15:00 (читать в оригинале)
Циклы и Условия
Оператор — это строчка кода, которая говорит компьютеру что-либо сделать.
Например:
Код:
Print("Hello World");
return 0;
Точка с запятой является очень важной частью оператора, но обычно очень легко забывается, потому является причиной 90% всех ошибок.Принцип выполнение кода сверху вниз имеет исключения — это циклы и условия.
Программа, которую Вы пишите, может, как человек, принимать решения в ответ на изменение обстоятельств. В таких случаях управление перепрыгивает из одной части программы в другую её часть.
Операторы, которые вызывают такие прыжки называются Операторами Контроля (контроллерами).
Контроллеры состоят из циклов и условий.
Циклы
Циклы заставляют раздел программы выполнятся определённое число раз.
Такое повторение продолжается пока какое-то условие явлется истинным (true) и прекращается как только условие становится ложным (false).
Когда цикл завершается контроль переходит следующему за циклом оператору.
В MQL4 существует два вида циклов:
1 — цикл for
Цикл for считается самым простым циклом, поскольку все его параметры собраны в одном месте.
Цикл for выполняет определённый раздел кода фиксированное число раз.
Например:
Код:
int j;
for(j=0; j<15; j++)
Print(j);
Как это работает?Оператор состоит из ключевого слова for, за этим следуют круглые скобки, в которых указаны 3 выражения, разделённые точками с запятыми:
for(j=0; j<15; j++)
Эти три выражения — это: выражение инициализации, выражение проверки и выражение инкремента.
j = 0 — выражение инициализации
j < 15 — выражение проверки
j++ — выражение инкремента
Тело цикла — это код, который будет выполняться:
Print(j); — тело цикла.
В нашем примере тело цикла выполняется 15 раз.
Замечание: сразу после выражения for(…;…;…) точка с запятой НЕ ставится, т.к. это выражение + идущее после него тело цикла считаются единым оператором.
Кстати, в этом заключается очень распространённая ошибка — оператор ; (просто точка с запятой) называется пустым оператором (он не говорит компьютеру что-либо делать), поэтому цикл for(…;…;…); имеет пустое тело. В основном это не то, чего мы хотим.
Выражение инициализации
Вы можете объявить переменную цикла вне самого цикла, как в нашем примере:
Код:
int j;
for(j=0; j<15; j++)
Или Вы можете объявить её прямо внутри скобок цикла:Код:
for(int j=0; j<15; j++)
Две предыдущие строчки кода эквиваленты за тем исключением, что области видимости (об этом в уроке про переменные) переменной цикла в обоих случаях разные. Во втором случае переменная считается объявленной только внутри самого цикла.В цикл for можно вставить больше одного выражения инициализации, разделив их запятой:
Код:
int i;
int j;
for(i=0 ,j=0;i<15;i++)
Print(i);
Выражение проверки
Проверка истинности выражения происходит после каждого прохождения цикла. Цикл продолжается, если выражение истинно, цикл завершается, если выражение ложно.
В нашем примере тело цикла будет продолжать печатать i ( Print(i); ), пока условие j<15 верно. j пробежит значения 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14, затем j станет = 15 и цикл остановится. Контроль перейдёт оператору, следующему за циклом.
Выражение инкремента
Выражение инкремента только так называется. Его задача — изменять переменную цикла. В нашем случае оно увеличивает j на 1.
Например, в следующем примере распечатаются числа 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1:
Код:
int i;
for(i=15;i>0,i<;i--)
Print(i);
Выражение инкремента выполняется самым последним в списке шагов цикла.Схема 1. Цикл for.
Как и в выражении инициализации, в выражении инкремента можно использовать более одного выражения, разделив их запятой:Код:
int i;
int j;
for(i=0 ,j=0;i<15,i<;i++,j++)
Print(i);
Но выражение проверки может быть только одно.Тело цикла
Во всех предыдущих примерах в качестве тела цикла мы использовали толко один оператор. В большенстве случаев этого недостаточно.
В тело цикла можно записывать много операторов, если их все взять в фигурные скобки:
Код:
for(int i=1;i<=15;i++)
{
Print(i);
PlaySound("alert.wav");
}
В этом коде в теле цикла содержится два оператора. Программа будет выполнять 1й оператор, а за ним 2й при каждом прохождении цикла.Не забывайте ставить точку с запятой в конце каждого оператора.
Оператор Break
Если при выполнении цикла for (или цикла while, или оператора switch) встречается оператор break;, то цикл терминируется, а контроль переходит оператору, следующему за циклом. PS: break — это ключевое слово.
Например:
Код:
for(int i=0;i<15;i++)
{
if((i==10)
break;
Print(i);
}
В этом примере цикл будет нормально выполняться пока i не достигнет значения 10. Как только это произойдёт, операторbreak; остановит цикл. В результате, на экран распечатаются: 0,1,2,3,4,5,6,7,8,9.Оператор Continue
Оператор break; останавливает цикл, а оператор continue; переводит цикл на следующий шаг, игнорируя оставшиеся операторы тела цикла.
Например:
Код:
for(int i=0;i<15; i++)
{
if(i==10) continue;
Print(i)
}
В этом примере цикл будет нормально выполняться пока i не достигнет значения 10. Как только это произойдёт, операторcontinue; переведёт цикл на следующий шаг, и i=10 НЕ распечатается. В результате, на экран распечатаются: 0,1,2,3,4,5,6,7,8,9,11,12,13,14.Важно!
Часть или даже все управляющие выражения цикла for можно опускать.
Например:
Код:
for(;;)
Этот цикл равносилен циклу while, в котором выражение проверки всегда истинно.Мы Вам представим цикл while прямо сейчас:
2 — цикл while
Цикл for обычно используется, когда Вы знаете, сколько раз цикл должен быть пройден. А что делать, если это не так?
Для этого есть цикл while.
В цикле while, как и в цыкле for есть выражение проверки, но в нём нет выражений инициализации и инкремента.
Пример:
Код:
int i=0;
while(i<15)
{
Print(i);
i++;
}
- Переменная цикла была объявлена и про инициализирована ДО цикла. В отличии от цикла for, внутри скобок этого делать нельзя.
- Формально i++ НЕ является выражением инкремента, но нам нужно чтобы что-то в цикле менялось, чтобы мы когда-нибудь из него выбрались.
Как же приведённый пример работает?
Оператор while содержит только выражение проверки, и он его проверяет после каждого прохождения цикла. Если оно истинно, цикл продолжится. Если оно ложно, цикл завершится и контроль перейдёт оператору, следующему за циклом.
В приведённом примере цикл будет выполняться пока i не станет равным 16. Как только это произойдёт, проверка условия i<15 вернёт false, и цикл завершится.
Схема 2. Цикл while.
Я уже говорил, что цикл while похож на цикл for. Вот их сходства:1. В обоих можно использовать операторы break; и continue; .
2. В обоих тело цикла может быть одиночным или составным. Во вотром случае операторы тела цикла нужно брать в фигурные скобки.
3. Аналогом for(;;) является while(true).
Изучаем основной материал:
Циклы и Условия (часть 2)
Мы уже поговорили про циклы. Теперь Вы знаете, что циклы — это один из двух способов изменить обычный порядок выполнения программы сверху вниз. Второй способ — это условия.
Условия могут провоцировать однократный прыжок в другую часть программы, в зависимости от значаения некоторого выражения.
1 — Оператор if
Оператор if является самым простым среди операторов условия.
Пример:
Код:
if( x < 100 )
Print("hi");
После if идут круглые скобки, в которых записывается выражение проверки (в данном случае x < 100). Если результат выражение проверки является истиной (true), то тело оператора if будет выполнено. В данном случае тело состоит из одного оператора — Print(«hi»); . А если результат выажения проверки является ложью (false), то тело оператора if НЕ выполняется, а контроль переходит оператору, следующему за телом if.Схема 1. Оператор if.
Несколько операторов в теле ifТочно, как и в циклах, тело оператора if может состоять из нескольких операторов, взятых в фигурные скобки.
Пример:
Код:
if(current_price==stop_loss)
{
Print("you have to close the order");
PlaySound("warning.wav");
}
Обратите внимание на сумбол == и выражении проверки. Это одна из операций сравнения, которые Вы изучали в уроке 4 «Операции и Выражения».Отсюда происходит очень много ошибок — когда Вы забываете символ ==, и вместо него используете символ операции присваивания =.
Вложенные циклы и условия
Циклы и условия можно вкладывать друг в друга.
Пример:
Код:
for(int i=2; i<10; i++)
if(i%2==0)
{
Print("It's definetly not a prime number");
PlaySound("warning.wav");
}
Заметьте, что тело цикла в данном примере НЕ нужно заключать в фигурные скобки, потому что оператор if и все операторы внутри его тела считаются как один оператор.2 — Оператор if … else
Оператор if позволяет что-то сделать, если определённое условие выполняется. Допустим, мы хотим сделать что-то другое, если это условие не выполнено. Для этого есть оператор if … else. Он состоит из оператора if и его тела, после чего идёт ключевое слово else и его тело.
Пример:
Код:
if(current_price>stop_loss)
Print("It’s not too late to stop, please stop!");
else
Print("you're playing well today!");
Схема 2. Оператор if … else.
Вложенные операторы if…elseОператоры if … else и оператор if можно как угодно вкладывать друг в друга.
Пример:
Код:
if(current_price>stop_loss)
Print("It’s not too late to stop, please stop!");
if(current_price==stop_loss)
Print("It’s time to stop!");
else
Print("you're playing well today!");
Есть опастность, связанная с вложенными операторами if … else. По невнимательности Вы можете случайно связать какой-то else не с тем if.Чтобы избежать подобных ошибок, можно сделать одно из двух:
1 — всегда брать пары if … else в фигурные скобки.
Вот так:
Код:
if(current_price>stop_loss)
{
Print("It’s not too late to stop, please stop!");
if(current_price==stop_loss)
Print("It’s time to stop!");
else
Print("you're playing well today!");
}
2 — Если Вам не подходит 1й вариант (слишком много этих if … else, или Вам просто лень), то просто следуйте правилусвязывать else с ближайшим if.3 — Оператор switch
Если у Вас есть большое дерево условий, и все условия зависят от одного параметра, то можно применить оператор switch.
Пример:
Код:
switch(x)
{
case 'A':
Print("CASE A");
break;
case 'B':
case 'C':
Print("CASE B or C");
break;
default:
Print("NOT A, B or C");
break;
}
После ключевого слова switch идут круглые скобки. Внутри этих скобок находится switch-константа. Внктри фигурных собок находятся case-константы — это проверямые условия switch-константы. Они записываются в виде case <значение>: <что делать>. <Значение> может быть integer, character или неизменным выражением. Неизменность выражения означает, что оно не зависит от переменных. Например, выражение X+Y не является неизменным.Как же работает указанный пример?
Оператор switch сравнивает switch-константу поочерёдно со всеми case-константами.
В случае x==’A’ программа напечает «CASE A» и оператор break; прервёт оператор switch. Контроль передастся за пределы блока switch.
В случае x==’B’ или x==’C’, программа напечатает «CASE B or C». Это потому что нет оператора break; в case ‘B’: .
В случае x!= ни одной из case-констант, оператор switch выполнит блок default: и напечатает «NOT A, B jr C».
Схема 3. Оператор switch.
Изучаем основной материал:
Функции
Работа с функциями в любом языке состоит из двух этапов:
- изучение функций, что, порой, очень скучное занятие
- использование функций, что всегда является спасательной шлюпкой.
В чём смысл функций ?
Функция очень похожа на мясорубку — вы кладёте в неё мясо, лук, специи и получаете фарш.
Мясо, лук и специи называются параметрами функции (входными параметрами функции), фарш — возвращаемое значение. А механизм мясорубки — тело функции.
Есть только одно различие между функциями и Вашей мясорубкой: некоторые функции возвращают НИЧЕГО (в MQL4 ничего называется словом void).
Пример:
Код:
double // тип фарша - возвращаемое значение
my_func (double a, double b, double c) // название функции и список параметров (мясо, лук и специи)
{
}
Как Вы видите выше, функция начинается с типа возвращаемого значения «double», за ним следует имя функции, после которого идут круглые скобки.
Внутрь скобок Вы кладёте мясо, лук и специи, точнее параметры функции.
В данном случае — три параметра: double a, double b, double c.
Затем идёт тело функции, которое заключено в фигурные скобки.
В данном примере, тело функции выполнит операцию (a*b + c).
Ключевое слово return ответственно за возвращение итого результата.
Ключевое слово return
Оператор return (); завершает работу функции (как break; завершает работу цикла), и передаёт контоль в точку вызова функции (об этом скоро).
Оператор return (); может содержать выражение в своих скобках, как в нашем примере. Это означает, что надо завершить работу функции и вернуть результат вычисление этого выражения.
Или оператор return (); может не содержать выражения в своих скобках. Тогда его единственная задача — завершить работу функции.
Внимание: не все функции используют оператор return (); Особенно, если возвращаемого значения нет, как в следующем примере:
Код:
void // void означает, что фарша не будет – возвращаемое значение
my_func (string s) // function name and parameters list (meat & spices)
{
Print(s);
}
Эта функция не вернёт никакого значения, но она напечатает параметр s, который Вы ей предоставите. Чтобы показать, что функция ничего не возвращает, используется «void» в качестве её возвращаемого значения.В некоторых языках программирования такие функции называются «методам», но в MQL4 они всё равно функции.
Вызов функции
Теперь, я надеюсь, мы понимаем, что такое функция. Как же использовать функции в Вашей программе?
Есть ещё один шаг, который нужно для этого сделать.
Этот шаг называется вызовом функции (её использованием).
Допустим, у Вас есть функция, котороая возвращает сумму двух integer.
Вот она:
Код:
int collect (int first_number, int second_number)
{
return(first_number+ second_number);
}
Вы хотите ей воспользоваться в своей программе.Делается это так:
Код:
int a = 10;
int b = 15;
int sum = collect(a,b);
Print (sum);
В этом примере на экран распечатается 25. Магия! Но как компьютер узнал, что печатать?Магической является строчка int sum = collect(a,B); Здесь Вы объявили переменную sum, чтобы в неё положить возвращаемое значение, а затем дали функции на вход два параметра (a,b).
Вы просто-напросто вызвали функцию.
Когда MQL4 видит имя функции в Вашей программе, он берёт Ваши параметры и идёт к функции, после чего он возвращается с результатом и кладёт его на то же место.
На самом деле, происходит следующее: в процессе компиляции MQL4 заменяет строчку с вызовом функции в вашей программе целиком телом самой функции (с учётом Ваших параметров). Причём вместо оператора return(); MQL4 производит присваивание возвращаемого им значения в родготовленную Вами переменную.
Вложение функций друг в друга
В тело одной функции можно вкладывать другие функции. Это потому что строчка вызова обрабатывается, как оператор (это и есть оператор).
Пример:
Код:
void print_collection (int first_number, int second_number)
{
int sum = collect(first_number, second_number);
Print(sum);
}
В этом примере мы вызвали функцию collect внутри функции print_collection и распечатали результат. void означает, что возвращаемого значения нет (ещё помните?).Спец. функции MQL4: init(), deinit(), start().
В MQL4 любая программа начинает своё выполнение с функции «init()» (initialize) и она срабатывает, когда Вы перетаскиваете программу (советника или индикатор) на график MetaTrader или если Вы поменяете валюту или период графика. Задача этой функции заключается в инициализации основных переменных, необходимых для работы Вашей программы. (Больще об инициализации переменных Вы узнаете далее).
Когда Ваша программа заканчивает свою работу, или Вы закрываете окно графика, или меняете валюту или период графика, или закрываете терминал, срабатывает функция «deinit()» (de-initialize).
Третья функция (самая важная) «start()» срабатывает каждый раз, когда приходят новые котировки. 90% своей программистской жизни Вы проводите внутри этой функции.
Мы больше узнаем об этих функциях, когда будем писать советник или индикатор
Изучаем основной материал:
Переменные в MQL4
Зачем нужны переменные?
Как я уже говорил ранее, переменные — это всего лишь имена, которые привязаны к кускам памяти, где храняться соответствующие данные.
Чтобы было легче понимать, что происходит, представьте себе, что память — это набор коробок различных размеров. Размер коробки — это эквивалент количества бит, требуемого для хранения данного типа.
- Чтобы использовать коробку для хранения данных, необходимо присвоить ей имя. Этот процесс называется объявлением.
- В процессе объявления Вы используете слово, чтобы объяснить компьютеру какого размера коробка Вам нужна. Это слово называется ключевым.
- Лучше дать имя коробке такое, чтобы потом было легко понять, что в ней лежит.
- Данные кладутся в коробку путём присвоения данных коробке.
- Если объявление и присвоение данных происходит в одной строчке, то такой процесс называется инициализацией.
Когда мы создаём переменную, мы говорим компьютеру, что мы хотим, чтобы он присвоил часть памяти определённого размера (в битах) нашей переменной. Поскольку хранение числа, буквы или большого числа занимает разный объём памяти, компьютер спросит, что Вы хотите хранить в этой памяти, и каков размер данных. Для этого и нужны типы данных.
Например, если мы дадим компьютеру следующую строчку кода:
Код:
int MyVaraible=0;
то мы говорим компьютеру, что хотим, чтобы он выделил блок памяти длиной 4 байта под нащу переменную «MyVariable».В этом примере:
int — это ключевоу слово
int — тип данных integer
int — объявление
MyVariable — имя переменной
=0 — инициализация
О переменных мы узнаем больше далее.
В MQL4 присутствубт следующие типы данных:
- Integer (int)
- Boolean (bool)
- Character (Char)
- String (String)
- Floating-point number (double)
- Color (color)
- Datetime (datetime)
Я скопировал для Вас предыдущие строки из поста про типы данных. Теперь Вы вспомнили, что такое переменные в MQL4 — давайте посмотрим, как их надо объявлять:
Объявление:
Объявить переменную означает представить её миру и указать её тип. Для этого используются ключевые слова, которые мы упоминали в посте про типы данных (int, double, char, bool, string, color и datetime) и имя, которое Вы выбрали для своей переменной.
Например:
Код:
int MyVaraible;
Здесь Вы объявили переменную под именем MyVariable, которая имеет тип integer. До строчки объявления ‘слово’MyVariable в коде использовать нельзя. Если Вы попробуете это сделать, то компилятор MQL4 будет жаловаться и выдаст такую ощибку: ‘MyVaraible’ — variable not defined. 1 error(s), 0 warning(s).Инициализация (присвоение)
А можно объявить переменную в одном месте, а инициализацию производить совершенно в другом:
Код:
int MyVaraible;
…
…
MyVaraible=5;
Но помните, что объявление всегда идёт ДО инициализации.Зоны видимости переменных
1 — Локальная зона видимости
Локальные переменные не видны вне того мира, где они были объявлены. Границы ‘мира’ определяются ближайшей парой фигурных скобок {}. Сверху мир ограничен скобкой {, а снизу — скобкой }. Например, переменные, объявленные внутри функции, локальны для тела этой функции. Переменные, объявленные внутри цикла или услови локальны для этого цикла или условия, и они НЕ видны и НЕ могут быть использованы вне этого цикла или условия.
Например:
Код:
double my_func (double a, double b, double c)
{
int d;
return (a*b + c);
}
В приведённом примере переменные a,b,c и d являются локальными и могут быть использованы только внутри тела этой функции.2 — Глобальная зона видимости
Глобальные переменные — это переменные, объявленные вне всех фигурных скобок. Они видны и могут быть использованы в любой части Вашей программы.
Например:
Код:
int Global_Variable;
double my_func (double a, double b, double c)
{
return (a*b + c + Global_Variable);
}
Здесь глобальная переменная Global_Variable объявлена вне функции (на уровне обявления функций), поэтому она видна всем функциям Вашей программы.Глобальные переменные автоматически выставляются на нуль, если Вы их не проинициализировали при объявлении.
Внешние переменные
Ключевое слово «extern» используется для объявления переменных специального вида (не типа, а вида). Переменные такого вида используются для хранения входных данных программы, которые Вы можете ввести в окошке настроек Вашего советника или индикатора.
Например:
Код:
extern color Indicator_color = C'0x00,0x00,0xFF'; // blue
int init()
{
...
}
В этом примере переменная Indicator_color была объявлена, как extern, которую Вы увидите, когда прикрепите индикатор к графику в терминале, и которую можно менять в окошке настроек.Рис. 1. Окошко настроек индикатора MA.
Здесь переменные Period, Shift, MA_method, Apply_to и Style — переменные, объявленные с использованием ключевого слова «extern«. Поэтому они появляются в окошке настроек.Если Вы хотите, чтобы пользователь мог изменять какую-либо переменную, сделайте её extern-переменной
Что нужно для того что бы начать торговать на рынке форекс. Пошаговая инструкция для Форекс начинающих.
2012-01-27 18:23:00 (читать в оригинале)Что нужно для того что бы начать?
Что нужно для того что бы начать торговать на рынке форекс?
Что нужно для того что бы начать прибыльно торговать на рынке форекс?
Итак! Для начала здравствуйте уважаемый посетитель.
Посмею себе предположить, что что Вы хотите начать торговать на Форекс, но не знаете как, не знаете с чего начать, что Вам для этого нужно и чему ещё надо научится.
Откровенно говоря когда я только задумал создать блог я даже не думал и не мог себе представить, что огромное количество людей желают познакомится с форексом, но боятся сделать даже первые шаги в этом направлении из за неуверенности в собственных силах. А сколько людей под воздействием призывных рекламных лозунгов влезло сломя голову в это действие и бездумно потеряло свои кровные просто трудно себе представить. Поэтому как в принципе я и обещал на странице “О чём блог” я начинаю серию постов с пошаговым обучением для Форекс начинающих.
Что нужно чтоб начать?
1. Ваше драгоценнейшее желание!!!
2. Цель – чётко мотивированная цель - куда Вы хотите дойти и чего добиться с помощью трейдинга и рынка форекс.
Для начала определяемся с целью, с реально достижимой целью или вернее его назвать бизнес планом, как уже неоднократно сказано: “деньги любят счёт”, а счёт подразумевает планомерность. Поставьте себе конкретную цель – к примеру, увеличить депозит на 10% - понимаете, как я ставлю вопрос! Затем будут новые цели и новые горизонты, но начинайте всегда с малого. Но главное ни за что не ставьте себе неопределённые цели - достичь финансовой независимости, обеспечить свою жизнь, стать безбедным, стать богатым и т.д. - всё это является утопией, цель должна иметь законченный смысл.
3. Деньги – И именно СВОБОДНЫЕ ДЕНЬГИ.
У кого - то это 10 долларов у кого то 10000 зелёных у кого и более, но именно свободные деньги. Форекс как не странно для сильных духом людей, которые не сдадутся при первых же неудачах, для тех у кого не стоит вопрос, что нет денег на еду, для тех кто действует от богатства, а не от бедности.
Да, без денег Вы можете учиться, тренироваться и начать можно без депозита, но, сколько Вы будете играть в этой песочнице и как долго будете решаться стать, кем – то, будет большим вопросом, у многих этот процесс занимает целую жизнь.
Определитесь с суммой, с которой будете работать и именно работать и приумножать – что будет Вашим начальным депозитом.
4. Чёткое понимание “Куда Вы лезете!!!”, готовность учиться, развиваться, тренироваться и само совершенствоваться.
Как не странно многие не понимают, что такое Форекс, возводя зачастую его в ранги халявных видов заработка и под воздействием рекламных призывов, в способы ежеминутного обогащения. Forex – это рынок, здесь работают банки и им подобные. Фактически рынок Форекс и был создан для банков и для тех чей капитал примерно сопоставим с банкам, поэтому нужно немало усилий, воли и желания, чтобы систематически зарабатывать на нём.
5. Начальное знание компьютера и пользователя Интернета – думаю, это у Вас есть – Вы ведь читаете данный пост.
6. Компьютер – судя по тому, что вы прочитали пункт №5, думаю, это у Вас есть тоже.
7. Интернет. Желательно безлимитный.
Вот в принципе и всё, что Вам минимум нужно и если Вы решили что у Вас все это есть – добро пожаловать.
Что же теперь?
1. Для начала четко уясним, что рынок – это абстрактное понятие – фактические это природное явление, которое в природе не существует. Бред! Но это так!
Сам рынок – это абстрактное понятие взаимоотношений людей, интересов и факторов, а приобретает свою форму он на торговых площадках. Если кто-то представил себе кучу людей машущих руками и непрерывно что-то покупающих и продающих, то спешу Вас разочаровать – это в прошлом. На данный момент биржа представляет собой ничто, иное как большое скопище мощных компьютеров, которые в единицу времени обрабатывают потоком огромное количество информации. Однако, чтобы не отклоняться от темы, с этими компьютерами-серверами Вас кто-то должен связать или иными словами кто-то должен вывести Ваши деньги на рынок. Эту функцию Выполняют брокеры, как их называют брокерские дома или маркет-мейкер – это компании, профессиональные участники финансового рынка, непосредственно участвующие в торговых операциях.
Брокеры forex — это ключевая фигура на валютном рынке. Именно брокеры forex помогают частным трейдерам торговать на Форексе. Во-первых, брокеры форекс предоставляет своим клиентам торговую платформу, с помощью которой трейдеры могут выходить на рынок и заключать сделки. Во-вторых, торговлю на валютном рынке не начнешь с тысячей долларов. Более того, даже $100 000 будет маловато. Им неинтересно разовое предложение, и даже миллионеру, вышедшему «в рынок» с разовой сделкой, будут предложены крайне невыгодные условия.
Брокерские дома и компании, подобно банкам, не только производят операции купли/продажи валюты по ценам, выставляемым другими активными участниками, но и сами выставляют собственные цены. Соответственно, они оказывают активное влияние на жизнь рынка в общем и процесс ценообразования в частности, поэтому они называются маркет-мэйкерами (market makers).
В задачу брокерских фирм входит посредническая деятельность по сведению продавца и покупателя иностранной валюты и проведение между ними конверсионной операции. За свое посредничество брокерские фирмы взимают брокерскую комиссию. На Форекс комиссия в виде заранее оговорённой определенной суммы или процента от суммы сделки, как правило, отсутствует. Обычно дилеры брокерских фирм котируют валюту со спрэдом, который уже содержит их комиссионные.
Брокерская фирма, которая располагает информацией о запрашиваемых курсах — это место, где образуется фактический валютный курс по уже совершенным сделкам. Коммерческие банки получают от брокерских фирм сведения о текущем курсе.
Наиболее известные на международных рынках брокерские компании: Harlow Butler, Lasser Marshall, Coutts, Tullett and Tokio, Tradition и ряд других.
Так как брокерские дома оперирую огромными суммами напрямую с Вами они работать не будут, но существуют компании, которые готовы работать с каждым и с любыми капиталами – их в свою очередь называют Дилинговыми центрами или ДЦ.
ДЦ есть разные и работают они по-разному в первую очередь это связано с методом их взаимоотношения с тем или иным брокерским домом ичастным лицом. Так как это достаточно обширные темы на этом остановимся и подытожим.
Для того чтобы Ваши деньги вышли на рынок – Вам необходимо Выбрать себе представителя. Будет это банк или ДЦ решать Вам. Свои наработки я представил на странице “Лучшие брокеры”
2. Определится как Вы будете вводить и выводить деньги со своего счёта. Это может быть банковские, почтовые или как достаточно удобно электронные платежи.
И для начала этого уже достаточно. Теперь переходим к регистрации торгового счёта к примеру как я рекомендую в компании Forex4you, скачиваем терминал через который будем осуществлять торговлю и пополняем счёт.
Категория «Истории»
Взлеты Топ 5
+1920 |
1940 |
Дрочливый_Драчун |
+1899 |
1946 |
Коптящий_Небо |
+1891 |
1957 |
Da_Queen_of_Da_World |
+1873 |
1964 |
Splash_Phantom |
+1754 |
1777 |
jolly_M |
Падения Топ 5
-1 |
1180 |
Вкусное меню |
-1 |
1270 |
Выдающиеся женщины |
-1 |
829 |
Работа в интернете |
-2 |
84 |
xpyctal |
-2 |
1062 |
TradeIP |
Популярные за сутки
Загрузка...
BlogRider.ru не имеет отношения к публикуемым в записях блогов материалам. Все записи
взяты из открытых общедоступных источников и являются собственностью их авторов.
взяты из открытых общедоступных источников и являются собственностью их авторов.