Разработка торговых роботов при помощи визуального программирования
Введение
Как правило, торговые стратегии можно свести к конкретному алгоритму, который можно автоматизировать. Торговые роботы могут выполнять торговые операции в тысячи раз быстрее человека, но не каждый трейдер владеет навыками программирования.
botbrains.app – это no-code платформа для разработки торговых роботов. Чтобы создать торгового робота в редакторе BotBrains программировать не нужно – просто перетащите нужные блоки на схему, задайте их параметры и установите связи между ними.
У botbrains.app есть документация (docs.botbrains.app) – в ней подробно описываются все концепции редактора. В этой статье описывается интерфейс редактора, его ключевые возможности, а также в этой статье рассматривается реализация торговой стратегии "Пересечение скользящих средних".
Возможности редактора
В BotBrains можно не только разрабатывать простых торговых роботов (например, торговые роботы, основанные на пересечении скользящих средних), но и реализовывать сложные торговые алгоритмы (например, торговые роботы, основанные на торговле спреда между символами). В BotBrains можно привязать торгового робота к личному телеграм-боту - при помощи специальных блоков можно отправлять сообщения о результатах торговли и отправлять скриншоты графиков произвольного размера. В редакторе BotBrains также можно построить полноценный интерфейс робота - можно легко создавать кнопки и назначать на них действия, можно добавлять поля ввода, чтобы контролировать значения переменных прямо во время работы робота, также есть множество других блоков для создания интерфейса робота.
Ниже представлена таблица категорий блоков, доступных в редакторе botbrains. Полный список доступных блоков представлен в конце статьи.
Категория | Описание |
---|---|
События | Блоки активируются, когда наступает определенное торговое событие, например, изменение цены графика или изменение стакана цен. |
Условие | Блок условия выполняет проверку. |
Цикл | Циклы имеют множество применений. Например, при помощи цикла можно перебрать все доступные символы и определить символ, который совершил наибольшее движение за последнюю торговую сессию. |
Индикаторы | Индикатор - один из основных инструментов технического анализа. В BotBrains представлен широкий спектр индикаторов: от простых объемов до облаков Ишимоку. |
Анализ графика | Например, можно получать информацию о конкретной свече, получать максимальную/минимальную цену за определенный промежуток времени. Также можно рисовать вертикальные и горизонтальные линии на графике. |
Анализ стакана | Получение информации о спреде и полях стакана. |
Транзакции | Выставление рыночных, лимитных и стоп ордеров. Снятие лимитных и стоп ордеров. Закрытие позиций. |
Переменные | Изменение значений переменных. Например, в переменной можно хранить количество лотов, которым будет торговать робот. |
Звуки | Когда что-то происходит, можно проиграть определенный звук. Например, можно проиграть звук "Сигнал на покупку", когда соблюдены все условия для совершения покупки. |
Получение информации | Получение информации о: счете, торговой сессии, активных лимитных/стоп ордерах, символе, времени, исторических лимитных/стоп ордерах, исторических сделках. |
Перечисления | Перебор списка символов, перебор списка активных лимитных и стоп ордеров. Перебор исторических лимитных/стоп ордеров и сделок. |
Телеграм | Отправка сообщений и скриншотов графиков себе в телеграм. |
Интерфейс | Построение полноценного интерфейса торгового робота. Отдельные элементы интерфейса можно изменять при помощи блоков модификаций. На кнопки интерфейса можно назначать действия. При помощи блоков интерфейса "поле ввода" можно изменять значения переменных прямо во время торговли. Все это позволяет создавать динамические интерфейсы. |
Предопределенные константы | В основном, предопределённые константы используются для проверок. Например, есть 3 предопределенных константы для направления позиции: покупка, продажа и отсутствие направления. Можно получить направление текущей открытой позиции и сравнить его с одной из предопределенных констант. |
Отладка | При помощи блока отладки можно выводить отладочную информацию в журнал терминала. Например, при помощи блока отладки можно проверять, что переменные содержат корректные значения. |
Прочие блоки | Закрытие терминала, полное прекращение работы робота, временное приостановление работы робота. Лог в файл, уведомление в терминале, комментарий на графике. |
Математические операции | Сложение, вычитание, умножение, деление, получение остатка от деления, квадратный корень, возведение в степень. Сравнения: меньше, больше, меньше или равно, больше или равно. |
Логические операторы | Есть логические операторы для построения условий: И, ИЛИ, НЕ. |
Телепорт | Есть блоки входа и выхода из телепорта. Иногда нужно быстро и удобно переключиться на выполнение другого участка схемы - при помощи телепортов это делается за считанные секунды. |
Блоки приведения к типу | По умолчанию все пользовательские данные хранятся в виде числа. При помощи блоков приведения к типу можно явно указать, в каком формате мы хотим представить данные. Есть 4 типа: целое число, дробное число, строка, дата и время. |
Выбор переменной или константы | Выбор переменной или константы. |
Ввод значения | Ввод значения. |
Интерфейс редактора BotBrains
В редакторе BotBrains есть 3 режима: Логика, Интерфейс, Код.
Режим "Логика":
В режиме "логика" можно строить схему логики робота. В этом режиме можно использовать абсолютное большинство блоков: от блока "если" и блоков совершения транзакций до блоков отправки сообщений в телеграм и блоков ведения логов робота. В этом режиме вы прорабатываете логику вашего торгового робота. При помощи простых блоков вы указываете, что ваш робот должен делать - когда совершать покупки, когда совершать продажи, когда отправлять сообщения в телеграм, когда прекращать торговлю и так далее. Всего в редакторе botbrains доступно более 140 блоков, при помощи которых можно реализовать практически любую торговую стратегию.
Режим "Интерфейс":
В режиме "Интерфейс", как можно понять из названия, можно построить интерфейс торгового робота. Буквально за пару минут можно построить полноценный интерфейс торгового робота. У каждого элемента интерфейса есть полноценные настройки внешнего вида. При помощи блока "Модифицировать элемент интерфейса" можно изменять параметры элементов интерфейса прямо во время работы робота.
Режим "Код":
В этом режиме можно посмотреть сгенерированный код торгового робота. Чтобы сгенерировать код торгового робота, нужно просто нажать на клавишу ~ (там, где обычно находится русская буква ё), либо нажать на соответствующую кнопку в правой панели инструментов.
Запуск торгового робота
Весь код вашего торгового робота генерируется за считанные секунды после нажатия одной клавиши на клавиатуре. Чтобы запустить робота, сделанного на BotBrains, нужно убедиться, что установлены все необходимые зависимости:
- Библиотека botbrains_lib.ex5
- Включаемый файл botbrains_lib.mqh
- Включаемый файл botbrains_constants.mqh
- Файлы звуков
Если вышеуказанные зависимости не установлены, роботы, сделанные на BotBrains, не смогут быть запущены либо не будут корректно функционировать.
Скачать все необходимые зависимости вы можете по ссылке. Установка зависимостей подробно рассматривается в соответствующей статье документации.
Пример: пересечение скользящих средних
Рассмотрим реализацию торговой стратегии "Пересечение скользящих средних". Готовую схему вы можете открыть сразу в редакторе, перейдя по ссылке.
Откроем редактор, создадим в нашем роботе 5 констант:
- slow_ma_period - период медленной скользящей средней (постоянное значение: 60)
- fast_ma_period - период быстрой скользящей средней (постоянное значение: 30)
- symbol - код торгуемого символа (постоянное значение: MGCV21 или любой другой символ, доступный вам для торговли)
- admin_id - id пользователя телеграм, которому наш робот будет отправлять сообщения с информацией о торгах и скриншоты графиков (постоянное значение: ваш ID в телеграм)
- lot - количество торгуемых лотов
Чтобы определить факт пересечения двух скользящих средних, нужно создать 4 переменных:
- ma_slow - текущее значение медленной скользящей средней
- ma_fast - текущее значение быстрой скользящей средней
- ma_slow_prev - значение медленной скользящей средней на предыдущей свече
- ma_fast_prev - значение быстрой скользящей средней на предыдущей свече
Таким образом, мы можем определить пересечение медленной и быстрой скользящих средних, просто сравнив значения этих переменных. Обратите внимание, мы не задаем переменным исходное значение - значение этих переменных будет обновляться при поступлении нового тика по торгуемому инструменту.
Сделаем так, чтобы при запуске робота в журнал терминала выводилось сообщение "Робот запущен". Для этого нужно просто перетащить два блока на схему логики робота: блок события "Запуск робота" и блок "Сообщение в журнал". И связать коннекторы этих блоков:
Таким образом, мы указываем, что когда робот запускается (блок события "Запуск робота"), должен выполняться блок "Сообщение в журнал".
В настройках блока "Сообщение в журнал" укажем сообщение, которое должно выводиться при запуске робота:
При поступлении нового тика по торгуемому инструменту наш робот должен изменять значения переменных. Для этого перетащим на схему логики робота блок события "Новый тик" и 4 блока "Установить вычисляемое значение переменной". Установим связи между этими блоками:
При помощи блока "Moving Average" мы можем получить значение скользящей средней. У этого блока есть следующие параметры:
- Символ
- Таймфрейм
- Количество периодов
- Метод сглаживания
- Используемая цена
- Сдвиг
При помощи параметра "сдвиг" мы можем получить значение индикатора на определенной свече. Например, сдвиг 0 означает значение индикатора на текущей свече, а сдвиг 1 означает значение индикатора на предыдущей свече. Таким образом, мы можем получить значения быстрой и медленной скользящих средних на текущей и предыдущих свечах - для этого нужно указать разные значения для параметра "Количество периодов" и "Сдвиг".
В тело первого блока перетащим блок индикатора "Moving Average":
Зададим параметры блока "Moving Average":
Обратите внимание, в качестве значений параметров "Символ" и "Количество периодов" используются соответствующие константы. В качестве значений параметров блоков также можно использовать переменные.
Работа с переменными и константами описывается в соответствующей статье документации.
Таким образом, в переменную "ma_slow" будет записываться актуальное значение медленной скользящей средней каждый раз, когда поступает новый тик по торгуемому инструменту.
Сделаем то же самое для переменной "ma_fast":
На данном этапе мы обновляем текущие значения скользящих средних, но для определения факта пересечения нужно знать значение скользящих средних на предыдущей свече. Поэтому в последних 2-х блоках "Установить вычисляемое значение переменной" сделаем все по аналогии, но в качестве параметра "Сдвиг" блоков "Moving Average" установим 1, чтобы в переменные "ma_slow_prev" и "ma_fast_prev" записывались значения скользящих средних с предыдущей свечи.
Делаем то же самое для переменной "ma_fast_prev".
Убедимся в том, что в наши переменные записываются корректные значения. Добавим на схему блок события "Таймер". У этого блока есть всего один параметр - "Интервал (сек)". Этот параметр по умолчанию равен 1, то есть по умолчанию блок вызывается каждую секунду. Затем добавим на схему 4 блока "Отладочная информация" - этот блок просто выводит указанное значение в журнал терминала. При помощи этого блока мы сможем посмотреть, какие значения записываются в наши переменные. В каждый блок "Отладочная информация" поместим по 3 блока в указанном порядке:
- Ввод значения - это простое поле ввода, в которое мы можем ввести произвольный текст. В нашем случае мы просто введем названия переменных, чтобы понимать, к каким переменным относятся те или иные значения.
- Знак "+" - при помощи этого блока мы можем объединять две строки.
- Выбор переменной - при помощи этого блока можно выбирать переменную, значение которой нам нужно получить.
Таким образом, наша схема должна выглядеть следующим образом:
В BotBrains все пользовательские значения хранятся в виде числа. В данном случае нам нужно явно указать, что блоки ввода значения содержат в себе текст, чтобы вывелся именно сам текст, а не его числовое представление.
Для этого нужно использовать блок приведения к типу "Обычная строка". Нужно просто перенести этот блок на каждый блок ввода значения:
На данном этапе мы сможем скомпилировать код робота и даже сможем его запустить - по таймеру значения указанных переменных будут выводится в журнал терминала. Однако во время компиляции возникнет предупреждение "implicit conversion from 'number' to 'string'":
Действительно, в нашей схеме мы пытаемся сложить строковое значение (блок ввода значения, приведенный к строке) с числовым значением (значения переменных). Чтобы исправить это, нужно просто привести значения наших переменных к строкам. Мы можем сделать это двумя способами:
- Использовать тот же блок приведения к типу "Обычная строка"
- Использовать блок приведения к типу "Дробное число" - этот блок отличается от блока "Обычная строка" только тем, что мы можем ограничить количество знаков после запятой
Воспользуемся вторым способом. Для этого перенесем блок приведения к типу "Дробное число" на каждый блок выбора переменной:
В настройках каждого блока "Дробное число" укажем 2 в качестве единственного параметра - "Знаков после запятой":
Работа с типами подробно описывается в соответствующей статье документации.
Откроем терминал и на график торгуемого инструмента добавим 2 индикатора "Moving Average" с такими же параметрами, что используются в нашем роботе, чтобы мы могли сверить значения переменных со значениями индикаторов на графике:
Сгенерируем код робота, нажав на ~ (русская буква ё) или на соответствующую кнопку в правой панели инструментов:
Запустим нашего робота в терминале и сверим значения, которые выводятся в журнал терминала, с реальными значениями индикаторов на графике:
Все значения сходятся, поэтому можем продолжать работу.
Осталось всего лишь сравнивать значения переменных при поступлении нового тика по торгуемому инструменту, чтобы определить пересечение скользящих средних и совершить сделку, если все условия для ее совершения соблюдены.
Для начала определимся с условиями для вхождения в сделки. Для вхождения в лонг должны быть соблюдены 3 условия:
- Текущее значение быстрой скользящей средней больше текущего значения медленной скользящей средней
- Значение быстрой скользящей средней на предыдущей свече меньше значения медленной скользящей средней на предыдущей свече
- Направление текущей позиции не равно "покупка"
Про последнее условие можно легко забыть, из-за чего наш робот может начать совершать множество сделок за маленький промежуток времени, так как условие 1 и условие 2 могут быть соблюдены несколько раз за секунду. За счет условия номер 3 робот не будет совершать никаких покупок поверх уже существующей лонговой позиции.
Обратите внимание, в редакторе BotBrains для всех роботов можно указать максимальную и подозрительную частоту совершения сделок. При достижении максимальной частоты совершения сделок робот экстренно закроет все открытые им позиции и снимет все выставленные ордера, также робот уведомит вас через телеграм и/или сделает уведомление прямо в терминале, в зависимости от того, какие параметры вы задали в настройках безопасности робота. При достижении подозрительной частоты совершения сделок робот не будет закрывать позиции и снимать ордера, вместо этого он просто уведомит вас в телеграме и/или сделает уведомление в терминале.
Для вхождения в шорт должны быть соблюдены следующие условия:
- Текущее значение быстрой скользящей средней меньше текущего значения медленной скользящей средней
- Значение быстрой скользящей средней на предыдущей свече больше значения медленной скользящей средней на предыдущей свече
- Направление текущей позиции не равно "продажа"
Сформируем условие для вхождения в лонг:
У блока "Информация о позиции" есть 2 параметра:
- Символ - символ, о позиции по которому нужно получить информацию
- Значение блока - интересующий нас параметр позиции. Доступные опции: объем позиции, время открытия позиции, цена открытия позиции, текущая прибыль по позиции и направление позиции
В качестве параметра "Символ" используем константу "symbol" - в этой константе мы храним код торгуемого инструмента. В качестве параметра "Значение блока" используем "Направление позиции".
Таким образом, значение блока "Информация о позиции" будет равняться направлению позиции по торгуемому символу.
После этого блока следуют два блока: "НЕ" и "РАВНО". После них идет блок предопределённой константы "Направление" - в этом блоке хранятся все возможные направления: "Направление покупки", "Направление продажи" и "Нет направления". Мы проверяем, что направление текущей позиции не равно направлению покупки.
Добавим на схему блок "Рыночный ордер" и свяжем его с коннектором "Да" блока условия:
У блока рыночный ордер есть 3 параметра:
- Символ - символ, по которому должен быть выставлен рыночный ордер
- Направление - направление ордера (покупка/продажа)
- Объем - объем ордера
Обратите внимание, мы используем константы в качестве значений многих параметров. Это позволяет нам легко конфигурировать робота - мы можем просто изменить значение константы в одном месте и новое значение будет автоматически использоваться во всех местах, где используется эта константа.
Если в торговом роботе, сделанном в редакторе BotBrains, есть константы, то они будут перечислены в самом верху сгенерированного кода:
/********** <КОНСТАНТЫ РОБОТА> **********/ const double __slow_ma_period = user_value("60"); const double __fast_ma_period = user_value("30"); const double __symbol = user_value("MGCV21"); const double __admin_id = user_value("744875082"); const double __lot = user_value("1"); /********** </КОНСТАНТЫ РОБОТА> **********/
Можно думать о константах как о настройках робота. Например, если вы решили торговать другим инструментом, просто измените значение константы symbol. Либо можете изменить значение константы прямо в редакторе BotBrains и сгенерировать код заново, если не хотите работать с файлом напрямую.
Итак, на данном этапе торговый робот будет открывать лонг при пересечении быстрой скользящей средней медленной скользящей средней снизу вверх. Добавим оповещения:
- Выведем сообщение в журнал терминала
- Создадим уведомление в терминале
- В файл логов робота добавим запись о факте совершения сделки
- Проиграем звук "Сигнал на покупку"
- Отправим сообщение в телеграм
- Отправим скриншот графика в телеграм
Может показаться, что реализация всех 6 пунктов займет немало времени, на самом деле, для всего этого также есть специальные блоки. Чтобы реализовать все 6 пунктов понадобится буквально 20-30 секунд. Все, что мы делали до этого также можно сделать за считанные минуты - в разы быстрее, чем писать код вручную.
Для правильной работы блоков телеграм, необходимо зарегистрировать своего бота в телеграм боте @BotFather, получить токен вашего бота и указать его в настройках вашего робота в редакторе BotBrains. Также необходимо знать свой ID в телеграм - его вы можете узнать в боте @getmyid_bot. Все это подробно описывается в соответствующей статье документации. Также блоки телеграм доступны только pro-пользователям.
По аналогии, реализуем проверку для позиции шорт. Для этого просто выделим все блоки, относящиеся к открытию позиции лонг, скопируем (CTRL + C), вставим их (CTRL + V) и внесем необходимые изменения.
Сгенерируем код робота, скомпилируем его и запустим его в терминале чтобы проверить работоспособность нашего торгового робота.
Тестируйте торговых роботов только на демонстрационном счете! По умолчанию в настройках безопасности всех роботов, сделанных в редакторе BotBrains, торговля на реальном счете запрещена! Переходите на торговлю на реальном счете только после тщательного тестирования вашего торгового робота на демо-счете!
Выставим случайные периоды скользящих средних и запустим торгового робота на минутном таймфрейме. На данном этапе нам важно протестировать работоспособность нашего торгового робота, обнаружить потенциальные ошибки и устранить их. После 80 минут торговли торговый робот открыл 4 позиции. После открытия каждой позиции робот успешно делал оповещение в терминале, проигрывал соответствующие звуки, делал соответствующие записи в файл логов робота и в журнал терминала. Также торговый робот без всяких проблем отправлял сообщения и скриншоты графиков прямо мне в телеграм. И для всего этого мы не написали ни строчки кода. Схему такого простого робота можно построить буквально за пару минут.
Может показаться, что все в порядке. Однако при детальном рассмотрении сделок, совершенных нашим торговым роботом, можно обнаружить, что в каждую позицию, кроме первой, наш торговый робот входил в две сделки: первая сделка для выхода из текущей открытой позиции и вторая сделка для открытия следующей позиции. Это легко обнаружить - достаточно просто посмотреть на график, проверить файл логов, посмотреть сообщения, отправленные торговым роботом нам в телеграм, или банально послушать, сколько раз торговый робот создает звуковое оповещение после совершения сделки. Также мы можем проанализировать историю совершения сделок в терминале.
В редакторе BotBrains в настройках безопасности роботов можно указывать подозрительную и максимальную частоту совершения сделок. По умолчанию максимальная частота совершения сделок равна 2-м сделкам за 10 секунд. При достижении максимальной частоты совершения сделок торговый робот экстренно закроет все открытые им позиции, снимет все выставленные ордера и оповестит вас в телеграм и/или создаст уведомление в терминале.
Проблема заключается не только в том, что в результате открытия позиций в два этапа мы будем совершать в два раза больше сделок чем необходимо и входить в большинство позиций по худшей цене, но и в том, что в какой-то момент наш робот достигнет максимальной частоты совершения сделок и прекратит торговлю. Именно это и случилось в моем случае. Обратите внимание на последние записи в файле логов:
Давайте исправим эту проблему. Создадим еще одну переменную: full_lot:
При запуске робота (блок события "Запуск робота") установим значение переменной full_lot в значение константы lot:
Затем, в блоках транзакций, вместо константы lot, будем использовать переменную full_lot:
Затем, после вхождения в позицию установим значение переменной full_lot в удвоенное значение константы lot. После совершения первой сделки робот начнет торговать двойным объемом. Таким образом, он будет закрывать существующую позицию и открывать новую одной сделкой:
Теперь торговый робот будет входить во все позиции одной-единственной сделкой. Убедимся в этом, запустив робота в терминале. Если мы посмотрим на историю сделок, то увидим, что первую сделку робот открыл на 1 лот, а последующие сделки робот уже открывал на объем в 2 лота:
Давайте создадим интерфейс для торгового робота. Для этого перейдем в режим "Интерфейс" редактора и при помощи специальных блоков построим интерфейс:
Чтобы построить такой интерфейс, достаточно использовать следующие блоки интерфейса:
- Прямоугольник
- Текст
- Кнопка
Сделаем так, чтобы вместо черточек подставлялись актуальные значения быстрой и медленной скользящих средних. Для этого нужно использовать блок "Модифицировать элемент интерфейса" - при помощи этого блока можно изменять свойства блока с указанным ID.
Перенесем 4 блока "Модифицировать элемент интерфейса" на схему логики робота:
Чтобы скопировать ID блока нужно сделать следующее:
- Нажать CTRL
- Не отпуская CTRL, дважды кликнуть на интересующий наш блок
Скопируем ID первой черточки:
Откроем настройки первого блока "Модифицировать элемент интерфейса" и укажем значения параметров. Первым делом указываем ID блока, свойства которого мы хотим изменить. В нашем случае это скопированный ID первой черточки. В качества типа модификации выбираем "Текст". В качестве нового текста указываем переменную ma_fast_prev:
По аналогии зададим параметры оставшихся 3-х блоков модификации элементов интерфейса. Таким образом, при поступлении нового тика по торгуемому инструменту в переменные ma_fast, ma_slow, ma_fast_prev и ma_slow_prev записываются соответствующие значения скользящих средних, после чего значения этих переменных записываются в соответствующие текстовые элементы интерфейса.
Теперь назначим соответствующие действия на кнопки интерфейса. Для этого перенесем на схему логики робота три блока: 2 блока "Рыночный ордер" и 1 блок "Закрыть позицию":
Зададим настройки этих блоков:
Скопируем ID 1-го блока "Рыночный ордер" и укажем скопированный ID в качестве значения параметра "ID связанного блока" первой кнопки:
Таким образом, при нажатии кнопки "Купить" будет вызываться соответствующий блок. По аналогии назначим действия на остальные кнопки. Сгенерируем код робота и запустим его в терминале чтобы проверить его работоспособность:
Обратите внимание, построенный нами интерфейс в редакторе полностью был перенесен в торговый терминал. Кнопки интерфейса работают и вместо черточек мы можем видеть актуальные значения скользящих средних.
В конечном счете, сгенерированный код торгового робота выглядит следующим образом:
//+------------------------------------------------------------------+ //| moving_average_cross.mq5 | //| botbrains.app | //+------------------------------------------------------------------+ #include <botbrains_constants.mqh> #include <botbrains_lib.mqh> /********** <КОНСТАНТЫ РОБОТА> **********/ const double __slow_ma_period = user_value("60"); const double __fast_ma_period = user_value("30"); const double __symbol = user_value("MGCZ21"); const double __admin_id = user_value("744875082"); const double __lot = user_value("1"); /********** </КОНСТАНТЫ РОБОТА> **********/ /********** <ПЕРЕМЕННЫЕ РОБОТА> **********/ double __ma_slow = user_value(""); double __ma_fast = user_value(""); double __ma_slow_prev = user_value(""); double __ma_fast_prev = user_value(""); double __full_lot = user_value(""); /********** </ПЕРЕМЕННЫЕ РОБОТА> **********/ int OnInit(){ //Разрешен ли автотрейдинг в терминале: if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)){ MessageBox("Автотрейдинг в терминале запрещен, эксперт будет выгружен"); ExpertRemove(); return(-1); } //Можно ли роботу торговать на реальном счете: if(AccountInfoInteger(ACCOUNT_TRADE_MODE) == ACCOUNT_TRADE_MODE_REAL){ MessageBox("Эксперту запрещено торговать на реальном счете!"); ExpertRemove(); return(-1); } //Устанавливаем имя робота: set_robot_name("moving_average_cross"); //Устанавливаем лицензионный ключ: set_license_key("2L5J7K-K986ND-KMPT94-1Q"); //Устанавливаем язык: set_lang("ru"); //Генерируем штамп робота (magic number): generate_magic(); //Устанавливаем размер депозита на момент запуска робота: set_init_account_balance(); //Устанавливаем параметры подозрительной частоты совершения сделок: set_suspicous_deals_frequency(60, 3, false, true); //Устанавливаем параметры максимальной частоты совершения сделок: set_max_deals_frequency(10, 2, false, true); //Устанавливаем таймер с интервалом в 1 секунду: EventSetTimer(1); //Блоки, вызываемые при запуске робота: block_bYi6ikfde(); block_bYUS6GLT0(); //Создаем элементы интерфейса: create_rectangle("b1ELCu5iq", 0, 0, CORNER_LEFT_UPPER, 15, 15, 390, 195, C'20,20,20', BORDER_FLAT, STYLE_SOLID, C'10,191,254', 2, 0, false, false, false); create_button("b4rh5uKlb", 0, 0, CORNER_LEFT_UPPER, 195, 165, 150, 30, "Sell", "Ubuntu Mono", 8, C'255,255,255', C'20,20,20', C'255,51,0', false, 0, false, false, false); create_text("b5BGSldua", 0, 0, CORNER_LEFT_UPPER, 120, 135, "-", "Ubuntu Mono", 9, C'255,255,255', 0, ANCHOR_LEFT_UPPER, 0, false, false, false); create_text("b9EjNpibO", 0, 0, CORNER_LEFT_UPPER, 30, 30, "Торговый робот \"MA Cross\"", "Ubuntu Mono", 14, C'255,255,255', 0, ANCHOR_LEFT_UPPER, 0, false, false, false); create_button("bBTrBQlkS", 0, 0, CORNER_LEFT_UPPER, 30, 165, 150, 30, "Buy", "Ubuntu Mono", 8, C'255,255,255', C'20,20,20', C'51,255,0', false, 0, false, false, false); create_text("bEncRhDIR", 0, 0, CORNER_LEFT_UPPER, 285, 75, "Текущая свеча:", "Ubuntu Mono", 9, C'255,255,255', 0, ANCHOR_LEFT_UPPER, 0, false, false, false); create_text("bI0vadsS2", 0, 0, CORNER_LEFT_UPPER, -195, 270, "Text", "Ubuntu Mono", 9, C'255,255,255', 0, ANCHOR_LEFT_UPPER, 0, false, false, false); create_text("bK1cW1i6s", 0, 0, CORNER_LEFT_UPPER, 30, 135, "MA slow:", "Ubuntu Mono", 9, C'255,255,255', 0, ANCHOR_LEFT_UPPER, 0, false, false, false); create_text("bLcIIkYqO", 0, 0, CORNER_LEFT_UPPER, 285, 135, "-", "Ubuntu Mono", 9, C'255,255,255', 0, ANCHOR_LEFT_UPPER, 0, false, false, false); create_text("bSDWBsxbk", 0, 0, CORNER_LEFT_UPPER, 285, 105, "-", "Ubuntu Mono", 9, C'255,255,255', 0, ANCHOR_LEFT_UPPER, 0, false, false, false); create_text("bTK8r1zb1", 0, 0, CORNER_LEFT_UPPER, 30, 105, "MA fast:", "Ubuntu Mono", 9, C'255,255,255', 0, ANCHOR_LEFT_UPPER, 0, false, false, false); create_text("bhKcJ2pwx", 0, 0, CORNER_LEFT_UPPER, 120, 75, "Предыдущая свеча:", "Ubuntu Mono", 9, C'255,255,255', 0, ANCHOR_LEFT_UPPER, 0, false, false, false); create_text("bj6MtjhZF", 0, 0, CORNER_LEFT_UPPER, 120, 105, "-", "Ubuntu Mono", 9, C'255,255,255', 0, ANCHOR_LEFT_UPPER, 0, false, false, false); create_button("bympSPhAp", 0, 0, CORNER_LEFT_UPPER, 360, 165, 30, 30, "X", "Ubuntu Mono", 8, C'255,255,255', C'20,20,20', C'255,51,0', false, 0, false, false, false); ChartRedraw(); //Инициализация робота прошла успешно: return(INIT_SUCCEEDED); } void OnDeinit(const int reason){ Comment(""); PlaySound(NULL); //Удалить все графические объекты графика, на котором был запущен робот: remove_all_objects(0); } void OnTimer(){ //Таймер с интервалом 1 сек. (bgP4YbxaQ): block_bTonyumSN(); block_bO7LNEs4m(); block_bS1JODjZj(); block_bM4s77Wvc(); //Раз в 10 сек. сбрасываем счетчик кол-ва совершенных сделок (максимальная частота совершения сделок): if(get_timer_tick_index() % 10 == 0){ deals_max_frequency_counter_reset(); } //Раз в 60 сек. сбрасываем счетчик кол-ва совершенных сделок (подозрительная частота совершения сделок): if(get_timer_tick_index() % 60 == 0){ deals_suspicious_frequency_counter_reset(); } timer_tick_index_increment(); } void OnTick(void){ //Блоки, вызываемые при поступлении нового тика по символу, к графику которого прикреплен робот: block_bHxbWWtwW(); block_bvIvs7SMe(); block_boHVNlqnO(); } void OnTrade(){ //Проверяем частоту совершения сделок: check_deals_frequency(); } void OnChartEvent( const int id, // идентификатор события const long& lparam, // параметр события типа long const double& dparam, // параметр события типа double const string& sparam // параметр события типа string ){ if(id == CHARTEVENT_OBJECT_CLICK){ string object_name = sparam; if(ObjectGetInteger(0, object_name, OBJPROP_TYPE) == OBJ_BUTTON){ if(object_name == "b4rh5uKlb"){ block_bYGEhpZDM(); } if(object_name == "bBTrBQlkS"){ block_bCa4uSC92(); } if(object_name == "bympSPhAp"){ block_bXRrICVna(); } Sleep(100); ObjectSetInteger(0, object_name, OBJPROP_STATE, false); ChartRedraw(); } } } //Функция блока b0Wkfq6OD (set_complex_variable_value): void block_b0Wkfq6OD(){ vset(__ma_fast, ( moving_average(to_string(__symbol), PERIOD_CURRENT, (int)__fast_ma_period, MODE_SMA, PRICE_CLOSE, 0) )); block_b6LYVQGej(); } //Функция блока b1VYatoxs (interface_element_modify): void block_b1VYatoxs(){ modify_text("b5BGSldua", DoubleToString(__ma_slow_prev, 2) ); } //Функция блока b3UJfY74N (interface_element_modify): void block_b3UJfY74N(){ modify_text("bSDWBsxbk", DoubleToString(__ma_fast, 2) ); } //Функция блока b3crj4ayK (log): void block_b3crj4ayK(){ log_to_file("Открываем шорт!"); block_bzVyOb4tW(); } //Функция блока b6LYVQGej (set_complex_variable_value): void block_b6LYVQGej(){ vset(__ma_slow_prev, ( moving_average(to_string(__symbol), PERIOD_CURRENT, (int)__slow_ma_period, MODE_SMA, PRICE_CLOSE, 1) )); block_bQMre45Bd(); } //Функция блока bCa4uSC92 (place_market_order): void block_bCa4uSC92(){ place_market_order(to_string(__symbol), "BUY", __lot); } //Функция блока bHxbWWtwW (condition): void block_bHxbWWtwW(){ if (( __ma_fast > __ma_slow ) && ( __ma_fast_prev < __ma_slow_prev ) && ( get_position_info(to_string(__symbol), "POSITION_DIRECTION") != BUY_DIRECTION )){ block_bUySCvh6M(); } } //Функция блока bM4s77Wvc (print_debug_info): void block_bM4s77Wvc(){ print_debug_info(( to_string(to_double("ma_fast_prev = ")) + DoubleToString(__ma_fast_prev, 2) )); } //Функция блока bMgaVnT74 (pause): void block_bMgaVnT74(){ pause(1000); block_bT8xv0qGj(); } //Функция блока bO7LNEs4m (print_debug_info): void block_bO7LNEs4m(){ print_debug_info(( to_string(to_double("ma_fast = ")) + DoubleToString(__ma_fast, 2) )); } //Функция блока bPlXoF1uA (set_complex_variable_value): void block_bPlXoF1uA(){ vset(__full_lot, ( __lot * to_double("2") )); } //Функция блока bQ4zsFoIh (log): void block_bQ4zsFoIh(){ log_to_file("Открываем лонг!"); block_bMgaVnT74(); } //Функция блока bQMre45Bd (set_complex_variable_value): void block_bQMre45Bd(){ vset(__ma_fast_prev, ( moving_average(to_string(__symbol), PERIOD_CURRENT, (int)__fast_ma_period, MODE_SMA, PRICE_CLOSE, 1) )); block_bRUr8MnXh(); block_b1VYatoxs(); block_b3UJfY74N(); block_bofgi9HOT(); } //Функция блока bRUr8MnXh (interface_element_modify): void block_bRUr8MnXh(){ modify_text("bj6MtjhZF", DoubleToString(__ma_fast_prev, 2) ); } //Функция блока bS1JODjZj (print_debug_info): void block_bS1JODjZj(){ print_debug_info(( to_string(to_double("ma_slow_prev = ")) + DoubleToString(__ma_slow_prev, 2) )); } //Функция блока bT8xv0qGj (buy_signal_sound): void block_bT8xv0qGj(){ play_sound("buy_signal"); block_bPlXoF1uA(); } //Функция блока bTonyumSN (print_debug_info): void block_bTonyumSN(){ print_debug_info(( to_string(to_double("ma_slow = ")) + DoubleToString(__ma_slow, 2) )); } //Функция блока bTs8fZtAO (telegram_send_chart_screenshot): void block_bTs8fZtAO(){ telegram_send_chart_screenshot(to_string(__symbol), 2160, 720, (int)__admin_id); } //Функция блока bUySCvh6M (place_market_order): void block_bUySCvh6M(){ place_market_order(to_string(__symbol), "BUY", __full_lot); block_bfrp6ajWk(); block_bjBTLJMym(); block_boX0sSwri(); block_bQ4zsFoIh(); } //Функция блока bWkG0nSQa (telegram_send_message): void block_bWkG0nSQa(){ telegram_send_message("Открываем шорт!", (int)__admin_id); } //Функция блока bX2tY0y68 (terminal_print): void block_bX2tY0y68(){ terminal_print("Открываем шорт!"); } //Функция блока bXRrICVna (close_position): void block_bXRrICVna(){ close_position(to_string(__symbol)); } //Функция блока bYGEhpZDM (place_market_order): void block_bYGEhpZDM(){ place_market_order(to_string(__symbol), "SELL", __lot); } //Функция блока bYUS6GLT0 (set_complex_variable_value): void block_bYUS6GLT0(){ vset(__full_lot, ( __lot )); } //Функция блока bYi6ikfde (terminal_print): void block_bYi6ikfde(){ terminal_print("Робот запущен!"); } //Функция блока bfrp6ajWk (terminal_print): void block_bfrp6ajWk(){ terminal_print("Открываем лонг!"); } //Функция блока biLE3RJAD (sell_signal_sound): void block_biLE3RJAD(){ play_sound("sell_signal"); block_bPlXoF1uA(); } //Функция блока bjBTLJMym (telegram_send_message): void block_bjBTLJMym(){ telegram_send_message("Открываем лонг!", (int)__admin_id); } //Функция блока boHVNlqnO (set_complex_variable_value): void block_boHVNlqnO(){ vset(__ma_slow, ( moving_average(to_string(__symbol), PERIOD_CURRENT, (int)__slow_ma_period, MODE_SMA, PRICE_CLOSE, 0) )); block_b0Wkfq6OD(); } //Функция блока boX0sSwri (telegram_send_chart_screenshot): void block_boX0sSwri(){ telegram_send_chart_screenshot(to_string(__symbol), 2160, 720, (int)__admin_id); } //Функция блока bofgi9HOT (interface_element_modify): void block_bofgi9HOT(){ modify_text("bLcIIkYqO", DoubleToString(__ma_slow, 2) ); } //Функция блока bugmLdNsU (place_market_order): void block_bugmLdNsU(){ place_market_order(to_string(__symbol), "SELL", __full_lot); block_bX2tY0y68(); block_bWkG0nSQa(); block_bTs8fZtAO(); block_b3crj4ayK(); } //Функция блока bvIvs7SMe (condition): void block_bvIvs7SMe(){ if (( __ma_fast < __ma_slow ) && ( __ma_fast_prev > __ma_slow_prev ) && ( get_position_info(to_string(__symbol), "POSITION_DIRECTION") != SELL_DIRECTION )){ block_bugmLdNsU(); } } //Функция блока bzVyOb4tW (pause): void block_bzVyOb4tW(){ pause(1000); block_biLE3RJAD(); }
Доступные блоки
В редакторе BotBrains доступно более 140 блоков. Ниже представлена полная таблица доступных блоков. Обратите внимание, чтобы в полной мере понять принцип работы с редактором, настоятельно рекомендую читать документацию.
Блоки событий:
Блок | Описание |
---|---|
Начало работы робота | Блок активируется 1 раз при запуске робота. |
Прекращение работы робота | Блок активируется 1 раз при выключении робота. |
Изменение стакана цен | Блок активируется каждый раз при изменении стакана цен по указанному символу. |
Новый тик | Блок активируется каждый раз при поступлении нового тика по символу, на графике которого был запущен робот. |
Изменение открытого объема | Блок активируется каждый раз при изменении открытого объема по указанному символу. |
Изменение кол-ва лимитных ордеров | Блок активируется каждый раз при изменении количества активных лимитных ордеров по указанному символу. |
Изменение кол-ва стоп ордеров | Блок активируется каждый раз при изменении количества активных стоп ордеров по указанному символу. |
Таймер | Блок активируется 1 раз в указанное количество секунд. |
Нажатие клавиши | Блок вызывается при нажатии клавиши с указанным кодом. |
Условие:
Блок | Описание |
---|---|
Блок "Если" | Создание логической развилки в схеме робота. У блока есть 1 вход и 2 выхода. |
Блок цикла в основном используется для перебора каких-либо значений. Например, блок цикла можно использовать для перебора списка активных лимитных ордеров.
Блок | Описание |
---|---|
Цикл "До тех пор пока" | Блок будет активироваться до тех пор, пока указанное условие истинно. |
Блок |
---|
Adaptive Moving Average |
Average Directional Movement Index |
Average Directional Movement Index by Welles Wilder |
Bollinger Bands |
Double Exponential Moving Average |
Envelopes |
Fractal Adaptive Moving Average |
Ichimoku |
Moving Average |
Parabolic SAR |
Standard Deviation |
Triple Exponential Moving Average |
Variable Index Dynamic Average |
Осцилляторы:
Блок |
---|
Average True Range |
Bears Power |
Bulls Power |
Chaikin Oscillator |
Commodity Channel Index |
DeMarker |
Force Index |
MACD |
Momentum |
Moving Average of Oscillator |
RSI (Relative Strength Index) |
Relative Vigor Index |
Stochastic Oscillator |
TRIX (Triple Exponential Moving Averages Oscillator) |
Larry Williams' Percent Range |
Accumulation / Distribution |
Money Flow Index |
On Balance Volume |
Volumes |
Индикаторы Билла Вильямса:
Блок |
---|
Accelerator Oscillator |
Alligator |
Awesome Oscillator |
Fractals |
Gator |
Market Facilitation Index |
Блоки анализа графика:
Блок | Описание |
---|---|
Данные свечи | Получить информацию о конкретной свече графика. |
Информация о графике | Получить информацию о графике. Например, количество свечей графика, время открытия первой или последней доступной свечи. |
Макс. цена | Получить максимальную цену за указанный промежуток времени. |
Мин. цена | Получить минимальную цену за указанный промежуток времени. |
Средняя цена | Получить среднюю цену за указанный промежуток времени. |
Нарисовать горизонтальную линию | Нарисовать горизонтальную линию на графике. |
Нарисовать вертикальную линию | Нарисовать вертикальную линию на графике. |
Удалить все линии | Удалить все горизонтальные и вертикальные линии с графика. |
Блоки анализа стакана:
Блок | Описание |
---|---|
Информация о котировке | Получение информации об отдельных котировках стакана. |
Спред | Получение спреда по указанному символу в тиках. |
Транзакции:
Блок | Описание |
---|---|
Рыночный ордер | Выставить рыночный ордер. |
Лимитный ордер | Выставить лимитный ордер. |
Снять лимитный ордер | Снять лимитный ордер. |
Снять все лимитные ордера | Снять все лимитные ордера по указанному символу. |
Стоп ордер | Выставить стоп ордер. |
Снять стоп ордер | Снять стоп ордер. |
Снять все стоп ордера | Снять все стоп ордера по указанному символу. |
Закрыть позицию | Закрыть позицию по указанному символу. |
Закрыть все открытые позиции | Закрыть все позиции, которые были открыты текущим роботом. |
Переменные:
Блок | Описание |
---|---|
Установить простое значение переменной | Новое значение переменной задается одним полем ввода. То есть этим блоком в переменную можно записать что-то конкретное - просто число или какой-то текст. |
Установить вычисляемое значение переменной | Новое значение переменной определяется вычисленным значением. Например, при помощи этого блока в переменную можно записать текущий размер депозита или текущую цену по торгуемому символу. |
Выбор переменной | Выбор переменной. Например, блок "выбор переменной" можно использовать внутри блока условия для проверки значения переменной. |
Звуки:
Блок | Описание |
---|---|
Плавный звук | Проиграть звук "Плавный звук" |
Сирена | Проиграть звук "Сирена" |
Сигнал на покупку | Проиграть звук "Сигнал на покупку" |
Сигнал на продажу | Проиграть звук "Сигнал на продажу" |
Информация:
Блок |
---|
Информация о счете |
Информация о позиции |
Информация о лимитном ордере |
Информация о всех лимитных ордерах |
Информация о стоп ордере |
Информация о всех стоп ордерах |
Информация об историческом лимитном ордере |
Информация об историческом стоп ордере |
Информация об исторической сделке |
Информация о торговой сессии |
Информация о символе |
Информация о времени |
Перечисления:
Блоки перечислений нужны для перебора чего-либо. Например, при помощи блоков перечисления можно перебрать список символов или список активных лимитных/стоп ордеров.
Блок | Описание |
---|---|
Имя символа | Получить код символа. |
Запрос списка активных ордеров | Запросить список активных ордеров. |
Тикет активного лимитного ордера | Получить тикет активного лимитного ордера. |
Тикет активного стоп ордера | Блок возвращает тикет активного стоп ордера. |
Блок | Описание |
---|---|
Запрос исторических данных | Запросить исторические данные за определенный промежуток времени. |
Тикет сделки из истории | Получить тикет сделки из истории. |
Тикет лимитного ордера из истории | Получить тикет лимитного ордера из истории. |
Тикет стоп ордера из истории | Получить тикет стоп ордера из истории. |
Блок | Описание |
---|---|
Отправить сообщение | Отправить указанное сообщение в телеграм пользователю с указанным ID. |
Отправить скриншот графика | Отправить скриншот графика указанного символа пользователю телеграм с указанным ID. |
Перенос строки | Используется для создания переноса строки в сообщении телеграм. |
Прочее:
Блок | Описание |
---|---|
Сообщение в журнал | Вывести сообщение в журнал терминала. |
Уведомление в терминале | Сделать уведомление в терминале. |
Комментарий на графике | Показать указанный комментарий на графике указанного символа. |
Лог в файл | Сделать лог в файл логов робота. |
Пауза | Приостановить работу робота на указанное количество миллисекунд. |
Выключить робота | Выключить робота. |
Закрыть терминал | Закрыть терминал. |
Элементы интерфейса:
Блок | Описание |
---|---|
Прямоугольник | Элемент интерфейса "прямоугольник". |
Кнопка | Элемент интерфейса "кнопка". |
Текст | Элемент интерфейса "текст". |
Поле ввода | Элемент интерфейса "поле ввода". |
Модификации элементов интерфейса:
Блок | Описание |
---|---|
Модифицировать элемент интерфейса | Изменить свойство элемента интерфейса. |
Информация об элементах интерфейса:
Блок | Описание |
---|---|
Информация об элементе интерфейса | Блок возвращает значение указанного свойства блока с указанным ID. |
Предопределенные константы:
Предопределенные константы - это возможные значения тех или иных параметров. Например, блок "направление" содержит предопределенные константы возможных направлений: покупка, продажа, отсутствие направления.
Блок | Описание |
---|---|
Направление | Возможные направления (покупка, продажа, отсутствие направления). |
Способ изменения позиции | Возможные способы изменения позиции (вход в рынок, выход из рынка, разворот, закрытие встречной позиции). |
Тип сделки | Возможные типы сделок (покупка, продажа, начисление баланса, корректирующая запись и т.п.) |
Отладка:
Блок | Описание |
---|---|
Отладочная информация | Выводит указанное сообщение в журнал терминала. |
Математические операторы:
Блок | Описание |
---|---|
+ | Сложение |
- | Вычитание |
/ | Деление |
* | Умножение |
√ | Квадратный корень |
^ | Возведение в степень |
% | Остаток от деления |
( | Открывающая скобка |
) | Закрывающая скобка |
> | Больше |
< | Меньше |
>= | Больше или равно |
<= | Меньше или равно |
Логические операторы:
Блок | Описание |
---|---|
И | Логическое "И" |
ИЛИ | Логическое "ИЛИ" |
НЕ | Логическое "НЕ" |
Телепорты:
Телепорты используются тогда, когда нужно перейти на выполнение другого участка схемы. Телепорты на вход и на выход связываются между собой по номеру.Блок |
---|
Вход в телепорт |
Выход из телепорта |
Выбор переменной или константы:
Блок |
---|
Выбор переменной |
Выбор константы |
Ввод значения:
Блок | Описание |
---|---|
Ввод значения | Этот блок можно использовать для установки определенных значений прямо в схеме. |
Приведение к типу:
По умолчанию все данные представляются в виде числа. При помощи блоков приведения к типу можно явно задать формат, в котором будет представлено определенное значение.
Блок | Описание |
---|---|
Обычная строка | Привести значение к обычной строке. |
Строка в формате даты и времени | Привести значение к формату даты и времени. |
Целое число | Привести значение к целому числу. |
Дробное число | Привести значение к дробному числу. |
Заключение
На разработку этого проекта был затрачен не один месяц работы. Если у вас есть какие-либо идеи по работе редактора либо замечания касательно его работы, можете написать письмо на support@botbrains.app. Ваше мнение обязательно будет учтено.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Добрый день. Заинтересовала ваша платформа. При попытке тестирования робота (тестер стратегий МТ5,пробую работать в ограниченном режиме) всегда, независимо от типа счета (реальный или демо) при выставлении рыночного ордера выдается ошибка 10018 - рынок закрыт. Я что-то делаю не так? Либо необходима платная подписка?
К сожаления программа BotBrains не доработана. Для обычного человека она не подходит, что бы пользоваться данной прогой нужны навыки программирования mql5, а значит это не визуальный редактор советников.
Согласен. В идеале желательно вообще обойтись без необходимости генерации и компиляции кода. Да и интерфейс слишком перегружен - изучить его не сильно проще, чем написать советник.
А как быть с "пользовательскими индикаторами". Возможно-ли самостоятельное создание блока индикатора? Может это быть отдельной опцией-заказом?
Лучше бы посмотрели, как сделано в ТсЛаб. Он не зря так популярен. У него есть определённые нюансы - они создали совершенно другой подход в визуальном программировании. Там нет как таковых переменных, и другое. Это быстрее всего плохо, как и трудоемко при программировании. Но принципы забрать нужно было.
Вашем случае вы создаете визуальный код в чистом виде. Учиться так же сложно, как программированию, используя язык. Потому что от языковых конструкций не ушли никуда в принципе.