Статьи по MQL4
Принцип работы советника

Принцип работы советника


например, forex

У нас уже есть почти все необходимые знания для создания советника. Из торговых функций мы не затрагивали только OrderModify() и OrderCloseBy(). Но прежде чем приступать к написанию сложных советников, необходимо четко представлять себе как работает советник в режиме реального времени, будучи прикреплен к графику инструмента, и как моделируется его работа в тестере при бектесте на исторических данных.

Многие трейдеры пишут индикаторы и советники, не представляя разницы между теорией и практикой. Прогнав советник в тестере и получив заманчивые результаты, они вешают эти советники на онлайновый график, часто позже удивляются несовпадению результатов (иногда разительному) и значениям индикаторов, снятых в онлайне и при бектесте. Поэтому, мы для начала создадим советник, за который нам не придется краснеть, и который одинаково хорошо работает на любом инструменте и на любом тайм-фрейме. Этот советник не сливает, потому что он не будет торговать. Единственное его назначение — вести запись о состоянии счета, поэтому я его назвал BlackBox («Черный ящик»), по аналогии с аппаратурой для записи полета авиалайнера.

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

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

Необходимо определить момент, когда старый бар закрылся, и пришел первый тик нового (нулевого) бара. В этот момент мы производим оценку текущей ситуации согласно алгоритму советника и принимаем решение о проведении или непроведении торговых операций. Это событие (рождение нового бара) мы будем проверять пользовательской функцией isNewBar() булевого типа, она будет возвращать true, если зародился новый бар, и false в противном случае. Если новый бар не появился — проводятся рядовые действия, которые можно делать на каждом новом тике.

Создаем новый советник с помощью «Мастера создания Советника». Никаких параметров для своей работы он не требует, поэтому заполняем только имя советника.

 
 

В блоке start() пишем несколько строчек простого алгоритма:

 
 


Видно, что на каждом тике проверяется факт появления нового бара и в случае положительного значения вызывается функция EveryBar(). Эта функция вызывается только один раз в начале каждого бара (если правильно написана isNewBar()) и в течение всего развития бара больше не вызывается. Кроме того, на каждом тике вызывается функция EveryTick() — в ней могут выполняться любые действия.
Как нам определить появление нового бара? Существуют два стандартных способа.
  1. Каждый бар имеет такую характеристику как Time[] — время отсчета(открытия) нового бара , и если мы будем каждый раз спрашивать значение Time[0] и сравнивать его с тем, что было на предыдущем тике, то в момент появления нового бара эти значения не совпадут.
  2. Второй вариант — запоминать каждый раз значение предопределенной переменной Bars. При появлении нового бара это значение также изменится.

Оба этих варианта равноправны, но я рассмотрю второй. Пишем функцию:

 
 


Обратите внимание, что переменная expertBars (в которой мы запоминаем значение Bars) является глобальной. Только переменные на глобальном уровне помнят свои значения между приходами каждого тика и запуска блока start() (из которого функция isNewBar() вызывается). Если выражение expertBars!=Bars истинно, значит родился новый бар, установим значение res равным true и не забудем запомнить значение Bars на данный момент — в следующий раз в будущем мы будем сравнивать Bars с текущим значением. Таким образом, возвращаемое функцией значение res будет либо true либо false.

Идем далее, сочиняем функцию EveryBar(), чтобы долго не думать, я решил каждый новый бар распечатывать в логе список ордеров, как в скрипте OrderList. mq4 (статья «Ордера в MetaTrader4» . ).

 
 


Для этого из функции EveryBar() вызывается новая функция — PrintAllOrders() (распечатать все ордера).

 
 


Осталось написать только функцию EveryTick(). Я решил в этой функции вычислять средний профит за все тики, пришедшие в течение бара. Для этого на каждом тике суммируется текущая прибыль по счету (AccountProfit()), подсчитывается количество тиков, и при появлении нового бара сумма профитов делится на количество поступивших тиков, получаем в результате усредненную прибыль за бар.

 
 


Немного изменим функцию EveryBar() для вычисления средней прибыли.

 
 


Теперь мы с появлением нового бара вычисляем среднюю прибыль и обнуляем переменные SumProfit и ticksBars для дальнейшего из использования с чистого листа на новом баре. Запускаем на графике EURUSD M15 и видим вывод в лог:

 
 


Теперь наш советник будет каждые 15 минут выводить данные об ордерах и среднюю прибыль за этот период.

 
 


Думаю, логика работы этого советника не вызывает вопросов. Взять код советника можно здесь .
Перейти к статье «Тиковый индикатор в отдельном окне».
 
+7 (495) 710-76-76
8 (800) 200-01-31
по России бесплатно

закрыть

Вход в личный кабинет

Для счета alpari.classic введите номер счета (буква и 4 цифры) и пароль в ЛК.

Для счетов alpari.micro и alpari.partner введите логин и пароль в МТ.

Зарегистрироваться!Забыли пароль?

 
Rambler's Top100