Торговый советник на MQL4: учимся программировать с нуля
В этом руководстве по MQL4 вы научитесь программировать свой собственный торговый советник в MetaEditor.
Прежде чем мы начнем, убедитесь, что вы понимаете следующие типы данных. Каждая переменная, которую мы будем использовать, для начала должна быть определена одним из следующих типов данных:
- int — это обычное число. Например: 1, 15, 521.
- double — число с десятичным знаком. Например: 1,154, 0,0144, 255,145.
- string — строка, слово, фраза. Например: «Ордер на покупку», «Ордер на продажу успешно размещен».
- bool — принимает значения либо false, либо true.
Скоро вы увидите, как их можно использовать.
Торговый советник три белых солдата
Для того, чтобы создать свой собственный торговый советник, для начала вы должны переключиться на MetaEditor. Вы смоете сделать это, нажав на иконку MetaEditor. В MetaEditor нажмите «Создать» и выберите «Советник (шаблон)». В следующем окне напишем имя нашего эксперта, нажмем на кнопку «Далее» и добавим первые стандартные переменные, нажав на кнопку «Добавить».
Мы добавим TakeProfit, StopLoss, LotSize, Slippage и MagicNumber. Все они являются типом int, кроме LotSize. LotSize должен иметь тип double.
Затем нажимаем «Далее» и «Готово». Мы видим, что MetaEditor сгенерировал файл с вашими предопределенными переменными.
Вы можете увидеть 3 области. Области OnInit(), OnDeinit() и OnTick(). Весь код, который вы пишете, попадает в одну из этих областей.
Код, который мы хотим вызвать, если прикрепим советник к графику, выполняется в области OnInit(). Код в OnDeinit() выполняется, когда мы отсоединяем советник. И, наконец, область, в которой мы будем работать больше всего — область OnTick(). Функция OnTick() вызывается каждый раз, когда мы получаем от брокера новую цену (тик) торгового инструмента, к которому прикреплен советник.
Если вы скомпилируете советника с помощью F7 и вернетесь в Metatrader, вы сможете найти советника в «Навигаторе» MetaTrader (Crtl + N). Если вы попытаетесь присоединить его к графику и перейдете на вкладку «Входные параметры», вы сможете увидеть наши предопределенные переменные.
Мы научимся программировать советника, который торгует по паттерну 3 белых солдата. Это простая стратегия, когда советник открывает сделку на покупку, когда последние 3 свечи были бычьими. Давайте начнем!
Добавим следующие строчки кода:
Для этой стратегии мы используем предопределенную переменную Close[], который является типом double. Close[] дает нам цену закрытия (например, 1.24577) для каждого свечи текущего графика. Close[0] означает текущую цену закрытия. Close[1] — предыдущую цену, и так далее. То же самое справедливо для предопределенных переменных Open[], Low[] и High[].
//Ордер на покупку — это подсказка для нас, что мы создали здесь функцию открытия ордера на покупку. Две обратных черты (//) означают, что эта строка закомментирована. Советник будет игнорировать ее при компиляции.
Если вы поместите курсор на предопределенную функцию или переменную и нажмете F1, откроется справка по MQL4, где вы сможете прочитать, что делает эта данная функция или переменная.
Далее мы используем функцию OrderSend, чтобы отправить ордер на покупку нашему брокеру. Добавим следующий код:
Что из себя представляет функция OrderSend?
- _Symbol — возвращает текущий торговый инструмент, к которому прикреплен советник.
- OP_BUY — мы хотим открыть ордер на покупку.
- LotSize — размер лота, который мы определили в самом начале.
- Ask — текущая цена Ask, по которой открываются ордера на покупку.
- Slippage — размер проскальзывания.
- StopLoss — это наш StopLoss. Или цена Ask за вычетом цены StopLoss. Запомните, что StopLoss — это целое число (500 пунктов), а Ask — это цена (например, 1.20521). Теперь, чтобы вычесть стоп-лосс из цены Ask, мы должны умножить его на 0,00001 или 0,001. Мы делаем это с помощью предопределенной переменной _Point, которая отражает текущие значением пунктов торгового инструмента.
- TakeProfit — то же самое, как и StopLoss.
- Комментарий — комментарий, который должен появиться в журнале, когда торговый советник разместит наш ордер.
- MagicNumer — магическое число, которое было определено нами вначале.
Нажмите F7, чтобы скомпилировать советник и проверить результат его работы в тестере стратегий. Вы получите что-то вроде этого:
Наш торговый советник выставляет ордера на покупку на каждом тике, если 3 последних бара были бычьими. Это не то что мы хотим, но, по крайней мере, что-то происходит.
Мы должны запрограммировать новую функцию, которая позволит нашему советнику одновременно открывать только одну сделку. MQL4 уже имеет свои предопределенные функции, например, OrderSend(). Но мы также можем написать свою собственную функцию, в которой мы можем вызвать другие пользовательские или предопределенные функции.
Давайте перейдем к концу нашего файла и запрограммируем новую функцию под названием TotalOpenOrders. Эта функция будет иметь тип int. Она будет возвращать количество открытых ордеров.
Затем добавим данную функцию в область OnTick и добавим проверку на количество открытых ордеров. Если общее количество сделок равно 0, наш торговый советник продолжает свою работу с кодом внутри скобок.
Что из себя представляет функция TotalOpenOrders?
В этой функции у нас есть счетчик (total_orders), который в конце возвращает общее количество открытых ордеров. Также у нас есть цикл for, который перебирает все открытые ордера. Если советник найдет ордер, соответствующий вашему символу и MagicNumer, счетчик увеличится на 1 (это записывается с помощью ++).
Теперь у нас все еще есть проблема. Если свеча слишком длинная, советник открывает вторую сделку на покупку непосредственно после того, как первая сделка на покупку закрывается с помощью StopLoss или TakeProfit. Мы должны добавить вторую функцию «IsNewBar».
Эта функция будет представлять тип bool. Она вернет true, если в Metatrader сгенерирована новая свеча, иначе она вернет false.
Давайте поместим эту функцию прямо над функцией TotalOpenOrder и вызовем ее в области OnTick вместе с TotalOpenOrders().
4-5 или 2-3 значные котировки
Давайте разберемся с проблемой котировок, которые могут предоставлять нам разные брокеры.
Сейчас мы используем предопределенную переменную _Point для преобразования TakeProfit и StopLoss. Но мы хотим создать функцию, которая предоставит нам одинаковое значение для 4 и 5 и соответственно 2-х и 3-х торговых инструментов. Для начала мы создаем глобальные переменные MyPoint и MySlippage. Поместим их прямо под нашими входными параметрами:
Теперь мы создаем функцию, которая сохраняет правильное значение в этих 2 переменных (MyPoint и MySlippage) и помещаем их в наши пользовательские функции:
Мы должны рассчитать эти значения только один раз. Только когда мы прикрепляем наш торговый советник к графику. Поэтому мы вызываем эти функции в разделе OnInit():
Теперь мы можем возвратить наши TakeProfit, StopLoss и Slippage к номальным значениям:
Далее мы заменяем все Slippage и _Point в функциях OnTick нашими 2 новыми глобальными переменными MyPoint и MySlippage. Таким образом, функция OrderSend будут выглядеть следующим образом:
Торговый советник и ECN брокеры
На ECN брокерах мы не можем отправить ордер с TakeProfit или StopLoss. Сначала нам придется отправить наш ордер без них, а затем изменить его.
Сначала мы сохраняем номер тикета из только что открытого ордера в переменной int ticket. Затем мы проверяем, получен ли мы данный ticket от нашего брокера. Далее мы вызываем функцию OrderModify. Функция OrderModify возвращает true или false, которые мы сохраняем в переменной bool res. Мы проверяем результат с помощью if (! Res) (так же, как if (res == false)) и выводим соответствующее сообщение.
Теперь наш код будет работать на всех ECN и не ECN брокерах.
Очистим наш код
Наш исходный код выглядит сейчас слишком сложным. Но мы можем его упростить. Для этого мы помещаем торговую логику и OpenOrder / ModifyOrder в пользовательскую функцию и вызываем ее в области OnTick().
Добавляем индикаторы
Теперь я покажу вам, как можно добавить индикаторы в наш торговый советник. Мы добавим индикатор RSI с фильтром скользящей средней.
Во-первых, нам нужны глобальные переменные для хранения значений наших индикаторов, чтобы мы могли работать с ними позже. Добавим их после MyPoint и MySlippage:
Теперь нам нужно создать функцию, которая будет возвращать текущую цену наших индикаторов и далее сохранить ее в наших предопределенных переменных. Добавим их в области пользовательских функций нашего кода:
Мы вызываем функции iRSI и iMA и сохраняем эти цены в переменных. В обоих функциях мы сначала используем текущий символ и таймфрейм, для которых мы хотим получить показания индикаторов. В нашем случае это символ и таймфрейм (период), к которому мы прикрепляем советник.
Для RSI мы хотим, чтобы период 14 рассчитывался по цене закрытия. Скользящая средняя должна быть периодом 200, Сдвиг 0. Что такое 1 в конце? Здесь мы определяем, от какой свечи мы хотим получать эти значения. 0 означает текущую свечу, 1 — предыдущую и т. д.
Чтобы эта функция работала, мы должны вызывать ее в разделе OnTick:
Теперь у нас есть все необходимые значения для создания нашей логики входа. Мы хотим открыть ордер на покупку, если RSI находится ниже уровня 30, а минимум предыдущей свечи находится выше скользящей средней:
Изменяем параметры индикаторов
На данный момент, если мы хотим изменить, скажем, период RSI от 14 до 20, мы должны сделать это в исходном коде. Теперь я покажу вам, как вы можете изменить все параметры индикаторов как обычный входной параметр в Свойствах эксперта. Для этого мы пишем:
Теперь мы должны связать эти параметры с нашими индикаторами и торговой логикой. Для этого мы изменим наш код на следующий:
Источник https://traderblog.net/torgovyj-sovetnik-na-mql4/
Источник
Источник
Источник