Наши рекомендации:

  1. Главная
  2. Уроки MQL4
  3. 3.3 Создаем простой советник с сеткой ордеров по системе Мартингейл

3.3 Создаем простой советник с сеткой ордеров по системе Мартингейл

mql программирование

Всем доброго времени суток!

Многие люди отрицают возможность заработать на Форекс по системе усреднения и Мартингейла. Они называют данный подход рулеткой, сливатором или кочергой. Часть активных пользователей, только заметив это название в топике темы, тут же бегут писать свой гневный коммент о том, что это лохотрон и подход дилетантов.

Как бы вы не относились к идее сеточной торговли, не стоит игнорировать тот факт, что в умелых руках с правильно настроенным риском, данная система способна показывать стабильный результат на протяжении многих лет. Часть из представленных ПАММ счетов и сигналов нашей команды подтверждают этот факт.

Если же вы не знаете, что такое Мартингейл, то пришло время познать что-то новое!

На этом уроке мы научимся создавать простой советник по системе Мартингейл с фиксированным шагом ордеров и небольшим набором настроек. Текста будет много, но иначе, к сожалению, никак. С каждым новым уроком становится все сложнее описывать всю ту вакханалию, которая происходит в редакторе Meta Editor. Тем временем размер советника, создаваемого в этом уроке составляет уже 300 строк, что уже можно считать серьезной, полноценной программой.

Описание торговой логики работы советника

Для того, чтобы не открывать беспорядочно сделки в разные стороны, данный советник будет осуществлять вход первого ордера сетки по сигналу индикатора. Для разнообразия в этом уроке я решил примерить классический индикатор MACD. Суть стратегии поражает своей простотой. Мы будем входить в покупки, как только гистограмма MACD пересечет нулевую отметку снизу вверх и закрепиться за ней. Продажи, соответственно, происходят зеркально, когда индикатор опускается ниже отметки 0. Период советника будет М15.

mql система

Стоп Лосса у данной системы нет. Если цена идет в нашу сторону — сделка закрывается по Тейк Профиту и советник переходит в состояние ожидания нового сигнала. Если же цена настроена против нас, то в работу включается блог построения сетки с функцией Мартингейла. Т.е. когда цена проходит X пунктов против направления ордера — открывается дополнительная сделка в этом же направлении с увеличенным лотом. Шаг ордеров такой сетки будет фиксированным и задается в настройках.

Чтобы усложнить программирование в советнике будет также две дополнительных фишки — перевод ТП всех ордеров в безубыток при достижении N колена, чтобы снизить риск и скорее закрыть затяжную сетку. А также настройка запуска усреднения, при которой лот будущий ордеров перестанет увеличиваться, чтобы снизить нагрузку на маржу.

Обе сетки на покупку и продажу будут работать независимо друг от друга.

Начинаем писать программный код

Создаем новый советник, указываем ему имя, автора, ссылку. Задавать параметры и обработчики событий не нужно, жмем Далее — Готово.

Присоединяем к коду встроенную библиотеку для расшифровки ошибок. При тестировании она поможет находить ваши недочеты и выдаст конкретный текст ошибки на английском языке.

Теперь нам нужно задать внешние переменные, чтобы более гибко управлять советником и иметь возможность его оптимизировать. Я разбил все настройки на три блока:

  • Основные настройки перекочевали из предыдущих уроков, тут все понятно. Торговый лот, который будет использоваться для первого ордера сетки, максимальное проскальзывание, Тейк Профит сетки ордеров, комментарий к ордеру и магик номер всех ордеров советника.
  • Настройки индикатора MACD. Он имеет три параметра: быстрая, медленная скользящая и сигнальная. Их все мы переносим в советник
  • Настройки работы сетки ордеров. Вначале мы должны задать расстояние от последнего ордера, пройдя которое советник отроет следующее колено сетки. Т.е. шаг сетки Grid Distance будет задан строго в пунктах и строиться она будет только, если цена будет идти против направления торговли. Следующий параметр Lot Multiplier будет отвечать за множитель лота для каждого последующего колена, это и есть работа мартингейла. Далее задаем номер колена, на котором увеличение торгового лота будет отключено Averaging Level дабы снизить риск маржин колла. Последние два параметра будут отвечать за безубыток всей сетки. Breakeven Level — номер колена, на котором ТП сетки больше не учитывается и она переводится в безубыток с целью уменьшить риск, когда в рынке уже достаточно колен. Параметр Breakeven Step же осуществляет отступ в пунктах от уровня БУ. Нужно заметить, что он может быть отрицательного значения.
Ниже добавим переменную локального уровня Update_Time для запоминания времени открытия текущей свечи. Также для работы с сеткой я предпочитаю использовать структуру — набор элементов произвольного типа. В справке есть подробное описание, как она работает и по сути тут нет ничего сложного. Структура это набор определенного количества параметров под определенным именем структуры.
Выше мы объявили структуру под именем SetkaEnv. Внутри ее тела находится 11 элементов, которые нам будут нужны для работы сеточного советника:

  • count_buy, count_sell — подсчет количества ордеров сетки в обоих направлениях
  • lasttimeB, lasttimeS — время открытия последнего ордера сетки отдельно для Buy и Sell
  • last_distanceB, last_distanceS — расстояние от текущей цены до цены открытия последнего ордера сетки отдельно для покупок и продаж.
  • firstlotB, firstlotS — значения самого малого лота у ордера сетки, т.е. первого.
  • lastlotB, lastlotS — значения лота последнего открытого ордера сетки, т.е. самого крупного
  • avgB, avgS — переменные, которые будет содержать в себе ценовое значение безубытка обеих сеток на покупку и продажу.

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

Все, структура готова к работе. Теперь, чтобы получить количество ордеров на покупку мы просто прописываем в коде env.count_buy. Точка «.» между словами обозначает, что переменная count_buy принадлежит структуре.

Переменные в структуре ничем не отличаются от обычных. Вы можете также просто объявить double переменную count_buy и записывать в нее значение количества ордеров сетки. Но на мой взгляд, работать со структурой немного удобнее, плюс поговаривают, что она обрабатывается быстрее. В этом случае все, что относится к сетке ордеров мы сможем видеть невооруженным глазом по приставке env.

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

Пишем основной код советника внутри функции OnTick()

mql4 уроки

Наш будущий код будет разбит на три основных блока, расположенными друг за другом в функции OnTick().

  1. Первый блок будет определять сигнал индикатора MACD один раз в свечу, проверять наличие открытых ордеров и, если их нет, открывая первый ордер сетки.
  2. Второй блок будет модифицировать ТП всех ордеров советника, если он еще не выставился, либо по какой-то причине удалился.
  3. Третий, самый обширный блок создан для работы с сеткой ордеров — их анализ, проверка расстояния и открытие новых колен.

Тем не менее, располагаться в коде они будут в порядке 3-2-1. Вначале будет идти анализ сетки, потом модификация и только потом уже открытие первого ордера. Это нужно для правильной логики работы всей программы.

1 Блок: проверка условий на вход первого ордера

mql4 уроки

Как я уже писал ранее, для определения сигнала на вход мы будем использовать встроенный в Meta Trader индикатор MACD. Данные мы будем брать на первой закрытой свече [1], т.е. нам нет необходимости дергать индюк каждый тик, достаточно импортировать показания 1 раз в свечу. Для запоминания времени открытия свечи мы будем использовать переменную Update_Time. 

Импорт данных технического индикатора происходит с помощью функции iMACD. Для того, чтобы понять, что гистограмма индикатора пересекла нулевую отметку нам нужны значения на [1] и [2] свечах. Т.е. для покупок гистограмма на [1] свече должна закрыться выше нуля, а на второй ниже 0. Параметры, передаваемые в функцию:

  • Имя символа. Берем текущий, т.е. NULL
  • Таймфрейм графика. Текущий, т.е. 0
  • Период быстрой средней. Берем из внешних настроек InpFastEMA
  • Период медленной средней. Из настроек InpSlowEMA
  • Период сигнальной линии. Из настроек InpSignalSMA
  • Тип цены. Берем по классике цену закрытия PRICE_CLOSE
  • Индекс линии индикатора. Данный индикатор имеет два показателя: гистограмму и сигнальную линию. Нам нужен первый, поэтому указываем MODE_MAIN
  • Сдвиг — номер свечи, с которой нужно получить данные. В нашем случае нам нужно получить данные с [1] и [2] свечей.

После этого необходимо проверить, чтобы в рынке не было открытых ордеров данного направления и данные индикатора подходили под сигнал.

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

Открытие ордеров происходит с помощью пользовательской функции OpenTrade с двумя параметрами — направление сделки и мульт торгового лота. Эту функцию мы будем использовать для всех ордеров нашего советника.

Т.к. первый блок открывает самый первый ордер сетки, то множитель отсутствует, и мы передаем ноль. В зависимости от направления будущего ордера мы должны определить:

  • Цену, по которой будет открытие. Bid для продаж, Ask для покупок
  • Цвет стрелочки для отображения места открытия ордера на графике.
  • Комментарий после успешного открытия ордера.
  • Текущее количество ордеров в заданном направлении
  • Лот первого ордера сетки
  • Лот последнего ордера сетки

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

Ниже с помощью оператора if осуществляется проверка на наличие множителя у передаваемых параметров. Если данная функция запущена из блока работы с сеткой, то мульт будет больше 0. В этом случае нам необходимо определить лот для очередного ордера сетки. Ранее нами была добавлена внешняя переменная Averaging_Level, которая перестает увеличивать торговый лот при достижении определенного колена, поэтому нам необходимо осуществить проверку, что текущий ордер по счету превышает значение параметра Averaging_Level. Если это так, то новый лот будет равен последнему известному значению. Если не так, то определение торгового лота будущего ордера происходит с помощью математической функции MathPow — возведение основания в степень. Данный подход позволяет работать с множителем менее 1.5 для сеток, где начальный лот составляет 0.01 и является более подходящем, чем банальное умножение последнего известного лота на множитель.

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

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

2 Блок: модификация ТП открытых ордеров

mql4 уроки

Функцию открытия ордеров мы прописали, теперь нужно произвести модификацию Тейк Профита всех сделок, у которых нет целей. Тут нет ничего сложного, мы просто циклом проходимся по всем открытым ордерам нашего советника, учитываем символ, тип ордера и магик номер. Далее если ТП выделенного ордера равен нулю, то идет его расчет и дальнейшая модификация.

При расчете ТП для одного ордера в рынке мы просто берем его цену открытия и прибавляем к ней необходимое значение в пунктах. Но т.к. в данном коде у нас осуществляется работа с сеткой ордеров, у которой один общий ТП, то его расчет нужно производить от уровня безубытка всей корзины. Для этого нам нужны переменный env.avgB и env.avgS, которые мы будем рассчитывать в третьем блоке кода. Сейчас суть проста, если у них есть значения, значит мы учитываем их как уровень БУ. Если же значение отсутствует, значит текущий ордер единственный в этом направлении у советника и расчет нужно вести от его цены открытия.

Данный код вставляем в функцию OnTick выше первого блока.

3 Блок: подсчет ордеров и работа с Мартингейлом

mql4 уроки

Первые ордера наш советник уже открывает, на следующем тике производит модификацию. Осталось добавить функции построения сетки. Чтобы не захламлять OnTick дополнительным кодом, мы создадим три отдельные функции для получения информации по текущим ордерам, расчета уровня БУ и модификации ордеров сетки. В OnTick в самом начале мы запустим пользовательскую функцию

Пользовательская функция CheckMartingale будет использовать структуру для сохранения данных по ордерам в ее переменные. Вначале мы должны произвести обнуление всех переменных структуры, чтобы старые данные не учитывались в расчете. Для этого воспользуемся общей функцией ZeroMemory.

Далее нам необходимо циклом пройтись по всем открытым ордерам. В зависимости от направления активировать запись их количества в счетчики env.count_buy и env.count_sell. Для того чтобы определить минимальной из лотов открытых ордеров (лота первого ордера сетки) нам придется сравнивать значения лота каждого ордера с минимальным. Для определения времени открытия последнего ордера, его расстояния от текущей цены и лота последнего ордера нам необходимо сравнивать время каждого ордера с самым поздним из известных.

По полученным данным мы определяем если ли вообще ордера в рынке и если да, то больше ли дистанция, пройденная ценой в сторону убытка, чем заданная дистанция GridDistance из настроек. Соответственно, если цена уже ушла на достаточное расстояние от цены открытия последнего ордера мы открываем новое колено сетки с помощью функции OpenTrade, задав ей значение множителя из настроек.

После того как ордер успешно открыт, мы увеличиваем значение счетчика ордеров на единицу и запускаем функцию модификации всех ордеров сетки, чтобы пересчитать уровень БУ и выставить новый, актуальный Тейк Профит.

Функцию открытия ордера OpenTrade мы уже прописали в первом блоке, поэтому нам осталось рассчитать общий уровень БУ и определить новый ТП сетки с помощью пользовательской функции CountGridTP(). Уже по полученным данным модифицировать сетку в функции Modify_grid().

Расчет безубытка происходит с помощью цикла по всем открытым ордерам. Нам нужно узнать суммарную цену лота (Price_Lot), для этого необходимо умножить последовательно лот ордера на его цену открытия. Также нужно определить суммарный лот всех ордеров (SumLots) и их количество (count).

Далее безубыток определяется очень просто делением Price_Lot на SumLots. Данная формула позволит вам узнать ту цену на графике, при достижении которой все ордера можно будет закрыть в ноль.

Стоит уточнить, что эта формула не учитывает своп и комиссии при открытии сделки, поэтому если ордера будут долго находиться в рынке, то уровень БУ будет не совсем корректным, но для нас сейчас это не критично.

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

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

Далее активируется очередной цикл по всем открытым ордерам, выделение и модификация их ТП на новое значение. Внутри цикла по ордерам мы добавили второй цикл for для модификации (до 5 попыток) на случай, если модификация не пройдет с первого раза.

Переходим к функции отрисовки горизонтальной линии draw_level(). У функции есть три параметра: наименование объекта (разное для покупок и продаж), цена на которой линия будет располагаться и ее цвет. Объект горизонтальная линия имеет тип OBJ_HLINE. После открытия нового колена сетки эта линия должна перерисовываться на цену env.avgB или env.avgS. Если же переменной price задать цену, равную нулю, то линия просто удалится с графика. С помощью свойств OBJPROP_PRICE, OBJPROP_STYLE и OBJPROP_COLOR линии задается цена, ее стиль и цвет:

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

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

Если вы запутались с порядком расположения блоков и функций внутри кода, то я вас не виню. Пример урока как всегда во вложении в самом конце статьи.

На этом все, код готов, можно компилировать. Давайте посмотрим, как ведет полученный код себя на графике:

mql4 уроки

mql4 уроки

Сделаем пробный прогон в тестере стратегий:

mql4 уроки

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

Стоит заметить, что торговля Мартингейлом является опасным методом торговли на финансовом рынке Форекс (да и на любом другом), поэтому я вам крайне не рекомендую пробовать этот советник на реальных счетах. У нас получился, конечно, не примитивный Ilan 1.6, но все же и не Грааль. Если же этот бот засел вам в душу, то вначале необходимо провести оптимизацию с качественными котировками, плавающим спредом и определить максимальную просадку на истории и корректно рассчитать необходимый депозит. Предупрежден — значит вооружен!

Заключение

Поздравляю тех, кто дочитал текст этого урока до конца, а не просто пролистал его за минуту. Вы прокачали свою выносливость на +30 и научились создавать свой первый советник с функцией построения сетки ордеров по методу Мартингейл. Познали азы работы со структурой, определения уровня безубытка группы ордеров, а также создали горизонтальные объекты на графике.

Хотя данная  статья и получилась вполне объемной на текст, данный советник по системе Мартингейл является очень простым по своей логике. 300 строк кода для такой сложной системы это очень даже мало. Для вас же этот шаблон советника mql4 может стать будущим черновиком для действительно интересного продукта. Как вариант, вы можете заменить логику входа первого ордера, изменить статический шаг сетки на динамический, добавить в код АвтоММ и фильтр времени торговли, активировать предварительный выход по сигналам сторонних индикаторов, добавить горизонтальную линию будущего ордера сетки, сделать возможность частичного закрытия крайних ордеров сетки и т.д. Тут все ограничивается только вашим полетом мыслей.

Если вы хотите попробовать в своей торговле действительно навороченный код, то рекомендую вам ознакомиться с нашим платным советником Night Hawk. Данный мартингейл сеточник писался мною 1,5 года и его код занимает 2100 строк, что очень даже внушительно.

На этом все, подписывайтесь на нашу рассылку. Всем профитов!

0. Начало работы

2 комментария. Оставить новый

  • Скажите как поставить ограничение на колено! Мне вот надо 4 к примеру, а он открывает сколько балансу позволяет!

    Ответить
    • Добрый вечер. Можно ввести внешнюю переменную MaxLevels и давить ее в 167 и 173 строчки советника.

      Ответить

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Заполните поле
Заполните поле
Пожалуйста, введите корректный адрес email.
Вы должны согласиться с условиями для продолжения

Меню