Навигация
Главная
Как стать клиентом
Скачать книги
Статьи
Контакты
Поиск
Ссылки
Статистика
Рейтинг Сайтов YandeG
 
Главная arrow Статьи arrow Статьи по MQL4
Статьи по MQL4

После установки MetaTrader4 в нужный терминал, вызвать MetaEditor можно одной кнопкой F4. по умолчанию, язык интерфейса и справочная система на английском языке. Для того, чтобы переключится на русский язык, выбираем меню «View»-«Languages»-«Russian». Язык сразу на русский не сменится, для этого необходимо закрыть MetaEditor и запустить его заново. Объясняется это тем, что при запуске MetaEditor проверяет установку языка и стартует с необходимым языковым файлом интерфейса.

Самый простой способ изучения языка для меня заключался в том, что я открывал какой-нибудь пользовательский индикатор (алгоритм которого я понимал очень хорошо) , идущий в составе дистрибутива, и пытался понять написанный код. Дополнительным источником знаний, как я уже говорил, служит форум разработчиков. Откроем для примера пользовательский индикатор Alligator.mq4, который находится в папке c:Program FilesMetaTrader 4expertsindicators (если ставить MetaTrader4 в папку по умолчанию). Это индикатор, наверное, знают или слышали все новички в трейдинге. Если мы подведем и установим курсор на строчку 70 на слово iMa и нажмем сочетание кнопок Ctrl+F1, то вызовется контекстная справка по данной функции. Эта функция представляет собой вызов значения встроенного технического индикатора Moving Average — скользящее среднее, пожалуй, наиболее известный и популярный технический индикатор .

Далее, нажав кнопку «Синхронизировать» ( при наведении всплывает подсказка «Синхронизировать словарь») мы откроем панель «Навигатора», в котором в списке технических индикаторов активизируется именно строчка Moving Average. Другой способ вызвать панель справку — нажать Ctrl+T. Чтобы вызвать панель «Навигатора» нужно нажать Ctrl+D (Dictionary).

 
MetaEditor
MetaEditor

 

В MQL-4 очень трудно программировать, не имея представления об объектно-ориентированном программировании (ООП). Языки ООП являются языками высокого уровня, и именно по этой причине многие трейдеры, писавшие индикаторы и советники на MQL-2 столкнулись с трудностями. На самом деле принципиальных сложностей здесь нет. Сам терминал MetaTrader4 дает много примеров объектов, которые помогают понять эту концепцию. Объект — это структура языка программирования, имеющая определенные свойства. При этом одни объекты могут содержать в себе другие объекты. Например, если в терминале выбрать меню «Окно»-«Окна», появится диалоговое окно , в котором будет список графиков. Этот список отражает открытые инструменты с указанными тайм-фреймами. Первым идет окно с графиком AUDUSD на 4-х часовом тайм-фрейме. То есть, сами окна графиков являются объектами.

 
 

Если выбрать первое окно и нажать кнопку F8 («Свойства»), то появится следующее окно, в котором указаны свойства графика (объекта). В нем указаны свойства-атрибуты графика-объекта. Мы видим каким цветом отражается фон, текст, сетка, линейный график, раскраска баров и свечей. Хотя средствами MQL-4 нельзя получить доступ к этим свойствам графика, тем не менее, мы имеем перед собой типичный пример объектного программирования. Но есть много других объектов, доступ к которым можно получить и в терминале и из индикаторов и советников (а также скриптов) на MQL-4. К ним относятся трендовые линии, вертикальные и горизонтальные линии, значки, текстовые метки, текст, фигуры и многое другое. Все эти объекты имеют как минимум одно свойство — цвет, которым они отображаются на графике.

 
 

Кроме того, примером объекта являются стандартные (встроенные) индикаторы и пользовательские индикаторы. Если на графике, содержащем индикаторы, нажать комбинацию Ctrl+I, то появится список индикаторов, прикрепленных к этому графику, то есть график-объект содержит индикаторы-объекты.

 
 

Эти индикаторы могут располагаться либо в главном окне графика (на графике цен) либо в своем собственном отдельном окне, если значения индикатора не укладываются в масштаб цен. Выбор расположения индикатора (в главном окне или дополнительном собственном окне) также задается свойствами данного индикатора-объекта. Опять-таки, если выбрать из списка (двойным щелчком мыши) какой-нибудь конкретный индикатор, то появится окно свойств этого индикатора.

 
 

С помощью закладок мы можем перемещаться по свойствам индикатора и задавать входные параметры индикатора (от них зависит значение индикатора на каждом баре), цвет которым отображается каждая линия индикатора, уровни индикатора и указать — на каких тайм-фреймах дозволено отображаться индикатору. Все эти свойства можно изменять не только из терминала, но и управлять поведением индикатора из программ, написанных на MQL-4. Поэтому одним из первых вопросов, которые появляются с изучением языка программирования, является следующий — Как написать свой индикатор и получить из кода индикатора доступ к свойствам объектов, которые размещены на графике пользователем или созданы самим кодом индикатора.

В MQL-4 существуют три вида самостоятельно исполняемых файлов, каждый из которых выполняет собственную задачу. По этой же причине, каждый их этих видов располагается в своей директории, скрипты хранятся в папке …MetaTrader 4expertsscripts , индикаторы в папке …MetaTrader 4expertsindicators, а советники в папке …MetaTrader 4experts , которая содержит и папки …scripts и …indicators. Сделано это для того, чтобы уже по месту нахождения файла можно было определить тип файла, так как расширение у них одинаковое — *.mq4.

 
 

Каждый из этих типов файлов выполняет только свои функции. Так, отражать на графике различные кривые наиболее простым и экономичным способом можно только из индикаторов, а проводить торговые операции на счету можно только скриптами и советниками. Тут можно сделать маленькое отступление: утверждение о невозможности рисования из скриптов и советников можно, вроде бы, опровергнуть — создавать и наносить графические объекты (линии вертикальные, горизонтальные и трендовые (в виде луча), значки разных стилей и цветов) можно и из скриптов и советников. Но попробуйте переключить тайм-фрейм графика — и все придется делать заново, потому что графические объекты имеют привязку по времени и цене, и на другом тайм-фрейме нужно будет удалять все объекты и рисовать новые.

Индикаторы, скрипты и советники также являются объектами. На график можно повесить советника, который будет в своем коде обращаться к одному или нескольким индикаторам, скрипт также не ограничен в вызовах индикаторов (пользовательских или стандартных). Можно также повесить индикатор, который строится на значениях другого индикатора, а тот в свою очередь вызывает для расчета третий индикатор. Все это в терминах ООП (объектно-ориентированного программирования) можно охарактеризовать так. Объект-график содержит в себе объект-советник, который содержит в себе объекты-индикаторы. Отобразим это представление двумя способами, стандартным и в виде диаграммы. Откроем график EURUSD, тайм-фрейм H1. Повесим на график советник MACD Sample из стандартной поставки MetaTrader4, разрешим ему торговать. Также набросим стандартный индикатор Stochastic Oscillator(5,5,5) , стандартный индикатор Fractals и пользовательский индикатор Zigzag (тоже из стандартной поставки MetaTrader4) . Получим такую картину:

 
 

Имеем три индикатора (два стандартных и один пользовательский), каждый из которых работает независимо от остальных. Кроме того, исполняется советник. Работа каждого из них требует машинного времени (ресурсов процессора) и размещения в оперативной памяти (ресурсов памяти). А теперь рассмотрим это под другим ракурсом: График EURUSD , H1 представляет из себя объект-окно графика, в который помещено еще три объекта-индикатора и один объект-эксперт (эти объекты называют дочерними). Объект-график получает ресурсы компьютера и распределяет его между своими дочерними объектами. Если заглянуть в код эксперта, то можно увидеть, что там содержится вызов стандартного индикатора MACD со значениями параметров 12, 26, 9. Обращение из советника к индикатору создает в самом эксперте еще один индикатор MACD(12,29,9), который мы не видим на графике, но, тем не менее, этот индикатор-объект также существует. Кроме того, существуют индикаторы, которые также обращаются в своих расчетах к значениям других индикаторов (стандартные или пользовательские — не имеет значения). То есть, кроме объектов, которые мы видим на графике, могут существовать и другие объекты — невидимые для нас. Но эти объекты также требуют ресурсов компьютера (процессора и оперативной памяти). Таким образом, на самом деле мы имеем не четыре объекта (три индикатора и один советник), а пять — три индикатора и один советник, содержащий один индикатор. Я это изобразил так:

 
 

На деле, часто на график набрасывают значительно больше трех индикаторов, и используют советники, использующие вызовы более одного индикатора, и все эти объекты используют ресурсы, отводимые терминалу (программе MetaTrader4). Кроме того, при тестировании индикаторов и советников в одном терминале часто открывают до 10 и более графиков, каждый из которых содержит индикаторы и советник. Поэтому правильное написание исполняемых файлов и экономный алгоритм работы советников, скриптов и индикаторов имеет первостепенное значение. Напоследок приведу скриншот моего терминала в выходные (рынок не работает и котировки не поступают). Открыто 19 окон-графиков, каждый из которых содержит до 4 индикаторов.

 
 

Ресурсы процессора (ЦП) практически не используются, а вот память задействовала более 70 мегабайт под работу терминала.


Все эти индикаторы, советники и скрипты пишутся для того, чтобы их присоединять к графикам. Поэтому необходимо сразу получить правильное представление о графиках, то есть о том, что они из себя представляют на самом деле и что скрывается за ними. Возьмем график EURUSD с тайм-фреймом D1. То есть, мы имеем график по инструменту EURUSD, каждый бар которого отражает поведение этой валютной пары за день (D1). Получить название инструмент в MQL-4 можно функцией Symbol()), а значение тайм-фрейма с помощью Period().

 

Эти функции можно использовать в любом файле MQL-4. Получить сведения по ним можно из встроенной справки в MetaEditor. Функция Period() возвращает значение периода в минутах, которое может быть одним из заданных констант: 1 минута, 5 минут, 15 минут, 30 минут и так далее. Вот как это описано в справке:
Перечисление периодов графика
Период графика. Mожет быть любой из следующих величин:
Константа Значение Описание
PERIOD_M1 1 1 минута.
PERIOD_M5 5 5 минут.
PERIOD_M15 15 15 минут.
PERIOD_M30 30 30 минут.
PERIOD_H1 60 1 час.
PERIOD_H4 240 4 часа.
PERIOD_D1 1440 Дни.
PERIOD_W1 10080 Недели.
PERIOD_MN1 43200 Месяцы.

 

На самом деле, даже если на графике нет ни одного индикатора, мы уже имеем перед собой как минимум один индикатор, так как даже представление цен в окне графика возможно в МТ4 тремя способами — свечи, бары и линии.

 

Таким образом, важно не то как изображен график, а то, на основании чего он изображен. На этом рисунке мы видим представление графика в виде баров. В отличие от первого рисунка (свечи) , здесь нет тел белого или черного цвета, с помощью которых было легко визуально отличить бычью свечу от медвежьей. Представление графиков в виде линии, построенной по ценам закрытий, оставляет еще меньше визуальной информации для человека. Хотя в самом терминале вся эта дополнительная информация никуда не теряется, она просто не отображается.

 

Если мы в терминале МТ4 нажмем комбинацию Ctrl+S (пункт меню «Сохранить как»), то появится диалоговое окно сохранения истории EURUSD D1 в формате *.csv (формат с разделителями).

 

Сохраним файл с именем, предлагаемым по умолчанию — EURUSD1440.csv . Как можно догадаться, имя файла по умолчанию содержит в себе имя инструмента (которое можно получить функцией Symbol()) и период 1440 минут (значение функции Period() для дневного тайм-фрейма равно 1440). Далее откроем полученный файл в Excel.
Последние пять строчек выглядят так:
2005.12.19,00:00,1.2029,1.2037,1.1973,1.1999,5166
2005.12.20,00:00,1.2002,1.2011,1.1839,1.1861,6679
2005.12.21,00:00,1.1859,1.1910,1.1800,1.1832,6787
2005.12.22,00:00,1.1830,1.1895,1.1808,1.1871,5284
2005.12.23,00:00,1.1870,1.1883,1.1827,1.1864,4686

 

Рассмотрим последнюю строчку, все остальные строчки аналогичны. Сначала идет запись 2005.12.23 — это дата 23 декабря 2005 года, Далее через запятую 00:00 — это 00 часов 00 минут. Все вместе означает начало дня 23.12.2005 — время открытия дневной свечи(Time). Далее числа 1.1870 ( цена открытия — Open ), 1.1883 ( максимальная цена за период — High ), 1827 ( минимальная цена за период — Low), 1.1864 (цена закрытия — Close) и 4686( объем за период — Volume). Если мы подведем мышку к последней свече на графике, то всплывет подсказка. Таким образом, можно сделать вывод, что график любого инструмента на любом тайм-фрейме можно представить в виде шести массивов: Time[], Open[], Low[], High[], Close[] и Volume[]. Все индикаторы и советники используют в своей работе только эти данные и более ничего. Первый из них содержит данные типа datetime, следующие четыре массива содержат данные типа double и последний — тип int. Cправка по всем типам содержится в MetaEditor. Доступ к элементам массива производится по индексу, индексы всегда имеют целочисленный тип. Самый последний бар (свеча) по времени всегда имеет нулевой индекс. Выражение Open[0] означает цену открытия нулевого бара (последнего), Time[1] означает дату и время открытия предпоследнего бара, Low[3] — минимальная цена за период на три периода назад и так далее. Важно запомнить, при увеличении индекса мы перемещаемся вглубь истории вплоть до самого раннего бара. Чтобы узнать количество баров, отображаемых на графике по данному инструменту, необходимо обратиться к параметру Bars. Этот параметр всегда содержит количество баров, которые можно увидеть на графике и автоматически обновляется при работе терминала в режиме реального времени. Самый первый бар на графике (дальше всех отстоящий от нас по ремени) будет иметь индекс Bars-1, так как индексация начинается с нуля, об этом не стоит забывать.

 

И напоследок хочу предупредить, что предопределенная переменная Bars напрямую связана с настройкой «Макс. баров в окне» (то есть обычно не больше этого значения) и не означает «Макс. баров в истории» (на рисунке 250000). Чем больше значения параметра «Макс. баров в окне» (на рисунке 15000), тем больше памяти потребляет терминал. Изменение этого параметра вступает в силу только после перезапуска МТ4.

 

Мы уже имеем необходимый минимум знаний, чтобы написать простейшую программу на MQL-4. Для этого я выбрал скрипт, а не индикатор или советник, так как в них было бы слишком много новой информации. Сделаем скрипт, который выполняет ту же функцию, что и строка меню терминала «Файл»-«Сохранить как» (Ctrl+S). Для этого начинаем в MetaEditor стандартную процедуру — меню «Файл» — «Создать» (Ctrl+N), появляется диалоговое окно, ставим галочку напротив поля «Пользовательский скрипт»:

 
 

Идем «Далее», открывается новое диалоговое окно. Заполняем поля «Имя», «Автор» и «Ссылка». Поля «Автор» и «Ссылка» MetaEditor в дальнейшем запомнит и будет подставлять их значения при создании каждого нового исполняемого файла. Жмем кнопку «Готово» и скрипт создан.

 
 

Получили простейший код, сгенерированный «Мастером создания советника».

 
 

Код состоит из трех частей:
1. Шапка
2. Директивы компилятору
3. Функция start().
Шапка

 
 

кодом не является, так как представляет 5 строк комментариев. Комментарий — любая строка, которая начинается с двойной косой черты, компилятор игнорирует комментарии, ему нет дела до того, есть ли там ошибки или нет. Но комментарии упрощают понимание программ, в них можно делать пояснения о назначении тех или иных функций или переменных. Экономить на них нецелесообразно, так как спустя какое-то время вы и сами не всегда сможете вспомнить все нюансы, заложенные в программе. Мы видим, что автоматом были вставлены как комментарии значения полей «Имя», «Автор» и «Ссылка». При опубликовании кода это будет удобно видеть.

Директивы компилятору

 
 

фактически тоже не влияют на работу нашего скрипта, но только эти, есть другие директивы, которые могут изменить алгоритм кода очень сильно. Справка по «Управлению компиляцией» приводит «Список предопределенных идентификаторов».

 
 

Функция start()

 
 

Самая важная часть, именно здесь мы задаем тот алгоритм, который и должен выполняться. Любая программа на MQL-4 должна иметь как минимум одну функцию, по умолчанию эта функция называется start(). Первые три строчки — это опять таки комментарии, для любой функции необходимо писать минимальный комментарий, объясняющий назначение функции, лучше сразу себя приучить к этому. Времени для написания требует пару минут, а в последствии может сэкономить часы, и не только для вас, но и для тех, с кем вы поделитесь кодом. Не зря говорят, что иногда проще написать самому, чем разбираться в чужом коде. Мы видим, что функция выделена визуально как блок, что позволяет легко видеть, где заканчивается одна и начинается другая функция. Сама функция может быть разделена на две части:

 
 

содержит имя функции и тип возвращаемого значения данной функцией, а

 
 

само тело функции.
Тело функции всегда заключено в фигурные скобки, и в конце функции (перед закрывающей фигурной скобкой) практически всегда стоит оператор возврата. Справка по оператору:

 
 

В данном случае мы видим, что функция start() возвращает значение 0 (ноль). Это значение мы использовать в данном случае не будем, поэтому можем спокойно закомментировать эту строчку. Наша задача: вывести значения Open, Close, Low, High, Time и Volume для каждого бара(свечи) на графике. Доступ к каждому бару мы можем получить по индексу, таким образом нам необходимо сделать пробег по барам от самого последнего бара до нулевого. Для этого существует оператор цикла for(). Из справки:

 
 

На открытом графике обычно присутствует не более Bars баров. Нам необходимо опросить их все, начиная с самого первого по истории, имеющего индекс Bars-1, и заканчивая последним, имеющим нулевой индекс. Объявим переменную целого типа, назовем ее index и напишем оператор цикла:
for (int index=Bars-1; index>=0; index-) { // Выведем High, Low, Open, Close для бара с индексом index }
Разберем цикл:
int index=Bars-1 объявили переменную index и задали для нее начальное значение Bars-1, то есть мы пойдем от самого первого бара на графике
index>=0 задали условие, при котором тело цикла выполняется. Таким образом, пока индекс больше или равно нулю, тело цикла выполняется
index- равносильно записи index= index-1 . Уменьшение значения на 1 называют декрементом, а увеличение инкрементом. Если индекс больше или равен нулю, выполняется тело цикла, после чего индекс уменьшается на единицу. Таким образом, когда-нибудь наступит момент, при котором index будет меньше нуля, в этот момент цикл и прервется.
{ // Выведем High, Low, Open, Close для бара с индексом index } Тело оператора цикла, вместо комментария нам необходимо вставить настоящие операторы вывода значений. Для этого существует оператор Print()

 
 

Добавим в тело цикла оператор Print(High[index],««,Low[index],» «,Open[index],» «,Close[index],» бар=»,index); Он выводит в Журнал советников и индикаторов значения High, Low и так далее. Скрипт готов, жмем F5 (Компилировать) — если ошибок нет, то скрипт готов к использованию.

 
 

Возвращаемся в терминал, открываем папку «Скрипты» и набрасываем наш скрипт на график EURUSD D1. Открываем окно «Терминал» (Ctrl+T), переходим на закладку «Эксперты» и видим результат работы скрипта. После завершения работы скрипт удаляется с графика : 2006.01.07 23:35:31 OutPrint EURUSD,Daily: removed В журнал экспертов можно выводить любую информацию с помощью оператора Print, при это выводится информация в два столбца. Первый столбец содержит дату и время вывода, а второй столбец содержит название скрипта, название инструмента, тайм-фрейм и двоеточие, после которого выводится результат работы скрипта. В этом простейшем скрипте мы использовали две, пожалуй самые нужные, функции в языке MQL-4, for() и Print(). Если for() используется для выполнения однообразных операций (работа в цикле), то Print() самая удобная функция для протоколирования работы советников и индикаторов, а также для отладки кода. Если код программы не работает, или работает не так, как ожидалось, то самое простое — это использовать вывод в лог переменных программы для анализа ее работы. Обычно этого достаточно для нахождения ошибки в своем коде.

 
 

И напоследок, лог журнала закладки «Эксперты» содержат результат работы нашего скрипта и любого другого советника или индикатора. Если нажмем на любой строке правую кнопку мышки, то появится контекстное меню.

Выберем пункт «Открыть», появится диалоговое окно выбора :

 
 

Логи экспертов (и индикаторов) хранятся в папке Program FilesMetaTrader 4expertslogs, каждый день создается новый файл. Наш лог (в котором находятся результаты работы скрипта) самый последний по времени и дате. Откроем его:

 
 

Таким образом, мы зафиксировали работу нашего скрипта, поэтому Print() очень удобно использовать для отладки кода в онлайне. Сам скрипт можно взять здесь

MetaTrader4 дает большие возможности для анализа финансовых инструментов, многие трейдеры считают эту платформой самой лучшей для технического анализа. Но не стоит отказываться и от других возможностей. Запись данных в логфайл МТ4 не всегда удобен, MQL-4 содержит функции работы с файловой системой. Сохраним скрипт OutPrint с новым именем WriteFile. Необходимо изменить алгоритм совсем немного, перед оператором цикла for() вставим функцию открытия файла FileOpen(), после цикла вставим функцию закрытия файла FileClose(), а оператор Print() заменим на оператор записи в файл FileWrite(). Для манипуляций с файлом необходимо предварительно создать ссылку (handle – читается хэндл) объект-файл. Хэндл файла имеет тип int, для этого FileOpen() нужно передать параметр – имя файла, имя файла имеет тип string. Файлы, открываемые в MQL-4 всегда находятся только в папке C:Program FilesMetaTrader 4expertsfiles (кроме файлов, используемых в тестере) в целях безопасности, в другие директории запись запрещена( невозможна). Записывать будем в формате CSV, который хорошо понимает Microsoft Excel. Открытый файл необходимо всегда закрыть в конце работы скрипта, иначе к нему не смогут получить полный доступ другие программы. Попробуем проверить простую идею – о неслучайном поведении цен в разные дни недели. Для этого будем записывать разницу между ценой закрытия и ценой открытия в пунктах – (Close[i]-Open[i])/Point. Point – предопределенная переменная, которая содержит значение пункта(минимально допустимого изменения цены) для текущего инструмента. Кроме того, нам необходимо записать день недели текущего дневного бара TimeDayofWeek(Time[i]). Добавим также год – TimeYear(Time[i]) . Предположим, что на открытии дня мы покупаем, а на закрытии дня закрываем сделку. Так как цены в МТ4 строятся по Bid (цена продажи), а покупки делаются по Ask (цена покупки), то нам необходимо учесть спред по данному инструменту. Спред по символу можно получить функцией MarketInfo(Symbol(),MODE_SPREAD). Напомню, что в операторе for() исполнение идет следующим образом:

 

 
Рис. 1
Рис. 1

 

Сначала выполняется инициализация цикла – задается начальное значение счетчика index, я отметил этот блок значком S. Этот блок выполняется только один раз в начале. Далее выполняется проверка условия – блок 1. Если условие выполнилось, происходит выполнение тела цикла - блок 2. И только после выполнения тела цикла происходит изменение счетчика в блоке 3 – index--. Прохождение трех блоков составляет один такт цикла for(). Далее по кругу – 1,2,3 до тех пор, пока выполняется условие блока 1. Как только это условие будет нарушено (в нашем случае счетчик index станет меньше нуля) – цикл завершится и управление будет передано операторам, следующим сразу за циклом for().
Наша задача будет записать в файл все значения с 2001 года по 2005 год включительно (для примера). Но цикл for() в нашем скрипте проходит по всем барам с начала истории и по сегодняшний день. То есть, нам нужно не записывать бары, относящиеся к годам меньше 2001 и больше 2005. Для этих целей есть операторы continue и break. Немного видоизменим скрипт таким образом.

 

 
Рис. 2
Рис. 2

 

Добавим оператор условный оператор if() , в котором и будем проверять значение года для каждого бара. Справку по нему, как и по операторам continue и break можно получить в MetaEditor, наш скрипт только помогает понять логику применения этих операторов.
Теперь тело цикла выполняется немного по другому, перед оператором Print() мы поставили две проверки , первая , в случае если год бара меньше 2001, заканчивает работу с текущим индексом и возвращает работу в блок 1 цикла (все следующие операторы тела цикла не выполняются), а второй полностью завершает работу цикла (если год бара с текущим индексом больше 2005).
Осталось добавить блоки открытия и закрытия файла, и преобразовать вывод в лог на запись в файл. Видно, что наш скрипт сейчас состоит из трех операций/блоков.

 

 
Рис. 3
Рис. 3

 

В операторе FileWrite() выводимые значения будут разделены точкой с запятой потому, что мы указали «;» в качестве разделителя при открытии файла. Это позволит открыть файл в Microsoft Excel, где каждое значение, разделенное точкой с запятой, будет помещено в свой столбец. Это, конечно, удобно, но остался последний штрих – нам не помешали бы названия столбцов, чтобы лучше понимать цифры. Для этого в блоке открытия файла добавим запись «шапки» выводимой таблицы. И не забудем вывести значения года, дня недели для каждого бара, значение спреда и разницы между ценой открытия и закрытияв пунктах.

 

 
Рис. 4
Рис. 4

 

На этом работа в MetaEditor закончена, компилируем и исполняем скрипт на графике EURUSD D1. Запускаем Excel и открываем наш файл.

 

 
Рис. 5
Рис. 5

 

Немного поправим границы столбцов и получим такое расположение данных.

 

 
Рис. 6
Рис. 6

 

Теперь мы можем использовать простейшие возможности Excel. Включим автофильтр.

 

 
Рис. 7
Рис. 7

 

Заголовки столбцов получат возможность фильтровать данные по этим столбцам.

 

 
Рис. 8
Рис. 8

 

Для примера, я хочу взять только те дни, которые соответствуют пятнице, то есть, таблица будет отображать те строки, которые приходятся на пятницу за 5 лет с 2001 по 2005 года. Сделаем так:

 

 
Рис. 9
Рис. 9

 

То есть, в столбце «День недели» мы выставили условие – равно 5 (5 – пятница в МТ4). Теперь мы можем посчитать все пятницы, сложить значения Close-Open по всем пятницам, для этого активизируем самую нижнюю ячейку в столбце «Close-Open» и нажмем на панели инструментов зачок «Сумма».

 

 
Рис. 10
Рис. 10

 

Значения для автосуммирования заполняются автоматически, жмем Enter и получаем сумму в пунктах. То же самое проделываем со столбцом «Спред».

 

 
Рис. 11
Рис. 11

 

Мы получили результат: если бы мы покупали бы EURUSD каждую пятницу на открытии все эти пять лет, а на закрытии дня закрывали бы сделку, то после вычета спреда в 783 пункта за эти дни мы получили бы прибыль в 652 пункта (1435-783). Данные условные, так как мы не учли возможность проскальзывания. Можно проверить таким же образом другие дни недели, можно дополнительно включить фильтр по годам

 

 
Рис. 12
Рис. 12

 

И напоследок, мы еще можем построить на наших данных цен Open, High, Low, Close диаграмму. Для этого выделим данные за нужный период (я взял небольшую часть 2003 года), нажмем кнопку «Мастер диаграмм», выберем тип «Биржевая».

 

 
Рис. 13
Рис. 13

 

Получим примерно такую диаграмму, как не бился , а в МТ4 графики лучше.

 

 
Рис. 14
Рис. 14
Сам скрипт можно взять здесь

Работа эксперта или скрипта, использующего торговые функции, требует получения текущей информации об открытых и отложенных ордерах – уровень открытия, значения Stop Loss и Take Profit, текущей прибыли(или убытка) для конкретного ордера, количество открытых ордеров. Иногда пишутся системы автоматической торговли, где важным является время удержания открытой позиции, в этих случаях также необходимо знать время открытия конкретной позиции. Для целей диверсификации создают системы, которые торгуют по схожим алгоритмам, но на разных инструментах, в таких случаях важно знать – по какому инструменту открыт данный ордер. Или на одном инструменте работают две или более механические торговые системы (МТС), которые еще называют торговыми роботами. В таком случае необходимо как-то различать ордера, открытые разными МТС на одном и том же инструменте. Бывают МТС, в которых приходят сигналы на открытие разной силы значимости(и поэтому открываются ордера большего или меньшего размера позиции) или требующие открытия нескольких ордеров в одном направлении по нескольким отличающимся друг от друга условиям, например, на пробой уровня сопротивления и на отскок от уровня поддержки. Ордера, открытые в одной МТС, но при разных ситуациях также необходимо как-то различать, добавлять к ним строчные комментарии. Кроме того, бывают системы, в которых отложенные ордера, не сработавшие в течение определенного периода времени после установки, необходимо удалять, так как считается, что условия их существования (ордеров) больше не соответствуют уже текущей ситуации. Например, мы выставляем отложенный ордер в день, когда ожидается выход сильных новостей, и необходимо его удалить, если он не сработал в первые минуты после выхода этих новостей. В общем, причин для открытия, закрытия, удаления и удержания ордеров может быть очень много, и практически все эти варианты реализуются в терминале МТ4. В терминале вызовем закладку «Терминал» (Ctrl+T) и выберем закладку «Торговля». На рисунке представлено типичное состояние терминала по торговому счету, на котором одновременно работают несколько МТС.

 

 
Рис. 1
Рис. 1

 

Первый столбец содержит номера тикета каждого ордера, далее столбец времени открытия ордера, затем следует столбец типа ордера (buy или sell), за ним столбец размера открытой позиции, цена открытия, уровень Stop Loss, уровень Take Profit, текущая рыночная цена, по которой можно закрыть ордер в данный момент(Ask или Bid в зависимости от типа ордера), накопленные свопы по данному ордеру (с плюсом или минусом), текущая прибыль по данному ордеру, и последний столбец – комментарии к ордеру. Ниже строки, содержащей информацию о текущем Балансе, Эквити (Средства), Марже (Залог), свободной марже (Свободно) находится строчка с информацией об единственном отложенном ордере с тикетом 3313320. Для отложенных ордеров отсутствуют данные о свопе и текущей прибыли, остальные параметры тоже известны. Кроме того, в таблице не показан MagicNumber каждого ордера. MagicNumber – это обычно уникальное целое число, которое выставляется советником при открытии ордера, чтобы этот советник мог отличать свои ордера от ордеров, открытых другими советниками или открытых вручную (для них MagicNumber=0). Чтобы увидеть MagicNumber конкретного ордера, достаточно подвести указатель мыши на нужный ордер, и тогда всплывет подсказка, содержащая номер тикета, номер MN (id 1005 на рисунке) и комментарий к ордеру.

 
Рис. 2
Рис. 2

То есть, у ордера с тикетом 3313336 MagicNumber равен 1005 и указан комментарий «sell stop». Создадим скрипт, который выводит в файл *.csv и в лог журнала все атрибуты ордеров по текущему торговому счету (account). Чтобы это сделать, нам необходимо пройти по все ордерам и запросить эти атрибуты. Сделаем это опять с помощью цикла for(), операторов Print() и FileWrite(). На рисунке из терминала мы видим, что ордера в МТ4 можно представить в виде списка. Мы видим, что количество ордеров равно 13 (12 открытых ордеров + 1 отложенный ордер). Информацию об общем количестве ордеров возвращает функция OrdersTotal(). Действительно, список ордеров хранится в терминале, при этом нужно помнить, что номер позиции в списке начинается с нуля и заканчивается на OrdersTotal()-1. В приведенном рисунке последний ордер в списке будет иметь номер позиции равным 12, но не 13. Для того, чтобы обратиться к ордеру его необходимо предварительно выбрать функцией OrderSelect(). При удачной попытке выбора функция возвращает значение true (истина), иначе false(ложь).

 

 

 
Рис. 3
Рис. 3

Я запустил скрипт на демо-счете и можно сравнить расположение ордеров в терминале (то, что мы видим) и расположение ордеров в памяти терминала (результат работы скрипта).

 

 

 
Рис. 4
Рис. 4

Видно, что ордера в памяти терминала расположены совсем не так, как мы видим. Но при правильном написании кода это не имеет значения. Я добавил отложенный ордер по USDCAD 0.1 Buy Stop 1.1490 и запустил на терминале доработанный скрипт. Обратите внимание, что имя файла состоит из номера счета, на котором выполнялся скрипт, а после окончания его работы выводятся в лог журнала функцией Print() значения баланса, эквити, маржи и свободных средств на счету. Также подсчитываются количество открытых ордеров в покупку, продажу и четырех видов отложенных ордеров. Сделать вывод на печать этих подсчитанных значений можно аналогично.

 

 

 
Рис. 5
Рис. 5

Получилась такая таблица в Microsoft Excel. Ордер, выставленный вручную (USDCAD), имеет MagicNumber равный нулю. Видно, что на одном символе(EURUSD) открыты ордера с разными MagicNumber(1002, 1003, 1005, 1006, 1007), а также то, что на двух разных символах (EURJPY и GBPJPY) имеются ордера с одинаковыми MagicNumber(1009). МТ4 позволяет тестировать на одном торговом счете множество МТС, при этом каждая МТС отличает свои ордера от ордеров других МТС, и от ордеров, выставленных вручную или на другом символе.

 

<#IMG6>
Напоследок хочу напомнить самую распространенную ошибку при работе со списком ордеров – обычно ошибочно начинают обработку не с нулевой позиции списка, а с первой, и заканчивают, соответственно, за пределом списка ордеров. В итоге, это дает двойную ошибку – не обрабатывается ордер с нулевой позицией и делается попытка обработать несуществующий ордер на позиции OrdersTotal().

Сам скрипт можно взять OrderList здесь

Теперь мы можем рассмотреть механизм удаления и закрытия рыночных ордеров в МТ4. Мы знаем, что функцией OrderSelect(номер_в_списке, SELECT_BY_POS) мы выбираем ордер, для которого потом получаем параметры. Функции OrderClose() и OrderDelete() требуют обязательный параметр — номер тикета ордера, который мы получим с помощью OrderTicket(). Предположим, что нам необходимо быстро закрыть все открытые ордера и удалить все отложенные. Создадим для этого новый скрипт StopTrade. mq4 . Самый простой способ будет опять таки пройти в цикле for() по списку ордеров и в зависимости от типа ордера закрыть или удалить каждый из них. Тип ордера мы получим функцией OrderType(). Если для удаления отложенного ордера достаточно знать номер тикета, то закрытие ордера требует указания правильной цены, по которой мы будем закрывать ордера типа OP_BUY или OP_SELL. Так как в терминале может быть открыто множество ордеров по разным инструментам, а исполняться скрипт будет на графике одного из них, то нам нужна возможность получения значений Ask и Bid для любого символа. Для этого служит функция MarketInfo() . Выражение MarketInfo(«GBPUSD», MODE_ASK) означает цену Ask для символа GBPUSD. Значение символа получаем из OrderSymbol(). Для подсказки я сделал таблицу списка ордеров, где выделенная строка для ордера на 8-ой позиции в списке ордеров (подсвечена желтым фоном) означает выбор этого ордера функцией OrderSelect(), а снизу разместил названия функций, с помощью которых можно получить необходимые параметры ордера. На рисунке выделена функция OrderTicket() для получения номера тикета для выбранного ордера.

 
 

Мы имеем все необходимые данные для написания скрипта. Но самой первой операцией в нашем скрипте будет проверка типа счета, на котором он исполняется. Мы пишем этот скрипт как учебный, и поэтому необходимо защититься от случайного использования его на реальном счете. Для проверки типа счета используем функцию isDemo(), которая возвращает true для демо-счета, в противном случае false.

 
 

Восклицательный знак (!) применяется для логических выражений и производит «переворот» : выражение ! true превращается в false, а ! false превращается в true. Выражение ! isDemo() на демосчете вернет значение false ( true превратится в false), а на реальном счету выдаст true. В этом случае скрипт досрочно завершит работу, предварительно выдав предупреждение «На реальном счете работа запрещена». Желательно всегда использовать такую защиту во всех скриптах(совершающих торговые операции) и советниках, чтобы избежать неприятных сюрпризов.
В цикле при переборе ордеров нам нужно будет проверять тип ордера, всего бывает 6 типов ордеров — 2 открытых (Buy или Sell) и 4 отложенных. Buy мы будем закрывать по цене Bid, а Sell по цене Ask для того символа, по которому открыт ордер. Оставшиеся 4 типа отложенных ордера хотелось бы удалять одинаковым способом, не разбирая — buylimit или sellstop ордер перед нами. Если мы посмотрим справку, то увидим что константы 0 и 1 означают открытые ордера, а отложенные ордера имеют OrderType()>1(2,3,4 и 5).

 
 

Теперь мы можем для ордеров с OrderType()>1 применять удаление OrderDelete(), а два остальных типа ордера закрывать с помощью OrderClose(). Но писать множество операций сравнения if(OrderType равно n) после OrderSelect() немного некрасиво, сделаем изящней. (Выражение a==b делает сравнение a и b, и если они равны — возвращает true.) Для таких случаев, когда проверяется равенство выражения ограниченному количеству значений, хорошо подходит оператор switch() (переключатель). Получился такой вариант:

 
 

Осталось прописать закрытие и удаление. С удалением просто- пишем OrderDelete(ticket), где ticket=OrderTicket(). Для закрытия открытых ордеров получим текущие цены закрытия с помощью MarketInfo(OrderSymbol(), …). Размер закрываемой позиции мы получим из OrderLots(), проскальзывание (slippage) я задал равным 3, цвет рисуемой стрелки закрытия я установил красным (Red). Если вы не помните, какие параметры и в каком порядке необходимо передавать функции, то нажав сочетание клавиш, можно получить подсказку. На рисунке я установил курсов между скобками в OrderClose():

 
 

Теперь скрипт практически готов, осталось только решить — в каком порядке закрывать и удалять ордера — с конца списка или с его начала. В этом месте обычно делают вторую распространенную ошибку.

 
 

Список ордеров в терминале является динамическим, в то время как проход в цикле for() будет статическим — если было сказано пройти от 0(нуля) до total-1 (количество ордеров в списке до начала удаления ордеров минус один) , то так и будет. Если ордеров было 10, и мы начнем с начала списка (с нулевого ордера по списку) , то после прохода от 0 до 4, в списке ордеров останется 5 ордеров, и размещаться они будут опять на позициях от 0 до 5. И проход в цикле от 5 до 9 будет выдавать холостые выстрелы, оставшиеся ордера не будут закрыты или удалены. Правильным будет удаление с конца списка, тогда не будет эффекта обвала. На рисунке показан порядок удаления ордеров с конца списка, размер списка после каждого удаления/закрытия будет уменьшаться, при этом ни один ордер не будет пропущен.

 
 

После прохода до нулевой позиции ордеров в терминале не останется. Окончательный вариант скрипта будет такой:

 
 

Напоследок, зададим горячую клавишу для нашего скрипта. Например, нажатие Alt+A , будет вызывать на исполнение наш скрипт на активном графике. Нажмем правой кнопкой мышки на любом скрипте(индикаторе, советнике) и выберем «Установить горячую клавишу».

 
 

Два раза кликнем напротив нашего скрипта в столбце «Управление» и выберем из списка Alt. Затем зададим клавишу (например А).

 
 

Скрипт готов к боевому применению на демо-счете. Запускаем его горячими клавишами на графике USDCHF (это я сделал специально, так как ордеров на этом инструменте в данный момент нет) и за 25 секунд закрывается 14 открытых ордеров и удаляется один отложенный — неплохой результат по скорости.

 
 

Перед исполнением скрипта были следующие ордера:

 
 
  
 

Сам скрипт StopTrade можно взять здесь

 
< Пред.   След. >
Торговые сигналы онлайн "DoxxoD" © 2010