В данной статье посмотрим робота, который реализован с использованием многопоточного подхода.
Смотрит стаканы поступающих с биржи бумаг, ожидая «Плиту». При этом смотрит то кол-во бумаг, которое Вы в него подключили, как скринер.
Где это точно пригодится?
Если задача стоит смотреть стаканы по 200 инструментам, и есть какая-то маломальски сложная вычислительная логика. Вероятно, это загрузит Ваш ЦП и начнутся проблемы с накоплением очереди сообщений.
Если нужно просматривать стаканы со всей площадки целиком и что-то делать, можно для этого сделать отдельный поток, и уже внутри него раз в N миллисекунд просматривать рынок. Про это наш пример.
Открываем исходный код робота MarketDepthScreener.
На ГитХаб он лежит здесь: https://github.com/AlexWan/OsEngine/blob/master/project/OsEngine/Robots/High%20Frequency/MarketDepthScreener.cs
Внутри проекта тут:
Шаг 1. Конструктор. Создание источника скринера.
- Создание поля для хранения источника скринер. Это нужно, чтобы в любом месте робота можно было потом обратиться к источнику.
- Вызываем у робота процедуру создания источника типа BotTabScreener.
- Источники такого типа хранятся в массиве TabsScreener. Сохраняем объект в ранее созданное поле.
- Создаём индикатор Momentum. Он будут размещён НА ВСЕХ бумагах, которые Вы подключите в скринер.
Шаг 2. Создание параметров.
В примере можно подсмотреть сразу три типа параметра:
- String – в данном случае перечисление.
- Decimal – число с плавающей запятой.
- Int – целое число.
- Создание полей для хранения параметров. Это нужно, чтобы в любом месте робота можно было потом обратиться к параметру.
- Создание самих параметров.
А так это выглядит в интерфейсе:
За что отвечают параметры:
1. Regime – режим работы.- Off – Выключен.
- On – Включен и будет входить и в лонг и в шорт.
- OnlyClosePosition – сможет только закрыть позицию, а входить не будет.
2. Max positions – максимальное одновременное кол-во позиций.
3. Min momentum value – минимальное значение индикатора Momentum для открытия позиции.
4. Momentum length – длина расчёта индикатора Momentum.
5. Volume type – режим выбора объёма.- Contracts – кол-во контрактов инструмента.
- Contract currency – валюта контракта.
- Deposit percent – процент от депозита.
6. Volume – значение объёма. Что именно, зависит от предыдущего пункта. В случае Contracts тут указывается объём инструмента. В случае Contract currency здесь указывается кол-во рублей или долларов, которыми нужно войти. В случае с Deposit percent здесь указывается % от общего депозита, которым нужно войти в контракт.
7. Asset in portfolio – тут нужно указывать название валюты, которое будет использовано для расчёта объёма, если Вы выбрали тип объёма “Deposit percent”. В тестере оставляем «Prime». На крипте это обычно “USDT”.
8. Best bid min ratio – во сколько раз объём в лучшей покупке должен быть больше относительно других объёмов в стакана на покупку, чтобы случился сигнал. Т.е. нам нужна очень крупная заявка в лучшем биде. Это значение указывает, во сколько раз она должна быть больше.
9. Profit percent – расстояние от входа до ордера на закрытие.
10. Stop percent – расстояние от входа до цены, после которой позиция будет закрыта по маркету.
11. Order life time milliseconds – время жизни ордера на открытие в миллисекундах. 1000 – 1 секунда.
Шаг 3. Поток, обслуживающий логику.
Создание потока находится в конструкторе:
- Создание потока и отправка его на работу в метод WorkerPlace. Посмотрим его чуть ниже.
- Подписываемся на событие удаления робота. Если пользователь удалит робота, рабочий поток остановится, т.к. в обработчике этого события мы сменили у флага значение. Так поток поймёт, что бот удалён и выйдет из логики работы.
Сам метод с работой нашего потока выглядит так:
- Бесконечный цикл, в котором «крутится» поток.
- Если флаг, означающий что пользователь удалил робота, активирован, то поток выходит из метода, прекращая своё существование.
- Если робот выключен, поток спит 1 секунду и уходит на второй круг.
- Цикл, который отправляет все бумаги из скринера в торговую логику.
- Задержка для нашего потока. В данном случае это 1 / 10 секунды.
- Обязательно ставьте в таких случаях обработчики ошибок с записью их в лог.
Шаг 3. Логика.
Распределение логики между открытием и закрытием:
- Точка входа в логику. В параметрах передаёт источник (BotTabSimple) инструмента, через который можно торговать.
- Проверяем, включен ли робот.
- Запрашиваем у текущего инструмента (по которому завершилась свеча) его текущие открытые позиции.
- Если позиций нет и режим работы робота не «Только закрытие», то заходим в метод открытия позиции.
- Если позиции есть, заходим в метод закрытия позиции.
Логика открытия позиций. Шаг первый. Просмотр фильтра по Моментуму:
- Обращаемся к источнику скринера и проверяем, сколько позиций всего набрал робот по разным инструментам. Не превышает ли это то значение, которое указал пользователь.
- Берём значение индикатора Momentum. Также в этом процессе проверяем, чтобы параметры индикатора на конкретном инструменте совпадали с тем, что пользователь установил в настройках робота.
- Если моментум опустился ниже нужного значения, установленного пользователем, то заходим в следующий шаг открытия позиции.
Логика открытия позиций. Шаг второй. Просмотр стакана:
- Если у источника по каким-то причинам нет стакана вообще, выходим из логики.
- Копируем стакан из источника. Это важно! Т.к. стакан в источнике может динамически изменяться, и, если это случиться пока мы его анализируем, у нас в логике может возникнуть ошибка. Поэтому нам нужно получить слепок, на который мы быстро посмотрим. Поэтому делаем слепок мгновенный через GetCopy();
- Если у стакана нет уровней покупок или их меньше 10, выходим из логики.
- Берём объёмы в лучшей покупке. Это должна быть наша плита.
- В цикле просматриваем все уровни покупок в стакане, чтобы наша «плита» была в «BestBidMinRatioToAll» больше чем остальные. Если вдруг какой-то уровень в стакане не соответствует, выходим из логики.
- Считаем цену ордера на покупку и объём для входа. Цену считаем, как «цена лучшей покупки в стакане» + один шаг цены.
- Отправляем лимитный ордер на покупку в стакан.
Логика закрытия позиций (Часть 1. Ордер на покупку стоит в стакане):
- Ордер на покупку активен, тогда заходим в эту ветку логики.
- Берём открывающий ордер по позиции.
- Если время жизни ордера истекло, отзываем его и помечаем позицию как «Canceled».
- Если в предыдущий заход в этот метод мы уже отзывали открывающий ордер и помечали его как «Canceled», ничего не делаем. Не спамим коннектор, ждём, когда биржа отзовёт ордер. Это может занять время.
Логика закрытия позиций (Часть 2. Позиция открыта):
- Ветка, в которой точно известно, что по позиции открывающий ордер исполнился, и по позиции есть открытый объём.
- Если MyTrades ещё не пришли, выходим из логики.
- Если это первый вход в ветку закрытия, и цена стопа ещё не определена.
- Рассчитываем цену стопа и устанавливаем её в StopOrderRedLine. Будем по этой переменной смотреть потом пробой стопа.
- Рассчитываем цену ордера на закрытие и выставляем его в рынок.
- Берём цену лучшей продажи в стакане.
- Если вдруг стоп уровень уже пробился или пробивался ранее.
- Отзываем закрывающую лимитку, если она ещё не отозвана. Делаем это один раз, когда впервые попали в эту ветку логики.
- Помечаем позицию как однажды пробившую стоп.
- Если ордер на закрытие ещё не отозвался, выходим из ветки логики. Не спамим.
- Закрываем позицию по маркету. Делаем это один раз. Не спамим.
Подключение разных источников в интерфейсе и запуск тестера.
Если Вы никогда не настраивали источник BotTabScreener, то нужно почитать вот эту статью: https://smart-lab.ru/company/os_engine/blog/1030326.php
В итоге это выглядит так:
- Робот в Bot Station Light выглядит, как и все остальные. Одна строка.
- Если нажать на кнопку Chart у этого робота, то откроется окно робота, в котором можно подключить множество инструментов. Сам источник BotTabScreener это таблица с инструментами.
- Если в таблице подключенных инструментов в скринер нажать на кнопку Chart, откроется окно конкретного инструмента, где можно посмотреть графики, сделки и индикаторы.
Удачных алгоритмов!
Комментарии открыты для друзей!
OsEngine: https://github.com/AlexWan/OsEngine
Поддержка OsEngine: https://t.me/osengine_official_support
Регистрируйся в АЛОР и получай бонусы: https://www.alorbroker.ru/open
Сайт АЛОР БРОКЕР: https://www.alorbroker.ru
Раздел «Для клиентов»: https://www.alorbroker.ru/openinfo/for-clients
Программа лояльности от АЛОР БРОКЕР и OsEngine: https://smart-lab.ru/company/os_engine/blog/972745.php