Привет, Хабр!
Предлагаю вашему вниманию небольшую историю о том, как я решил посмотреть, как действия воротил рынка акций могут быть обнаружены по общедоступным тиковым данным, если изменить способ анализа рыночных данных, и что из этого вышло. Продукт получил рабочее название AdvancedCharts или кратко ACharts.
Сразу оговорюсь, что работа изначально носила характер "чем тут можно поживиться", каюсь, кто не грешен? Но это было давно, и вылилась в рассмотрение технических проблем гораздо больше чем сугубо зарабатывальческих. И сейчас рассматривается больше как исследование технических аспектов анализа рынка. Кто в наше время верит в грааль? Никто. И не приписывайте этого, пожалуйста, автору. Соответственно сдерживайте, пожалуйста, свое желание сразу кинуть помидор из разряда "нормальный грааль никто не покажет" - это стиль начала эры форекса, который в 2021 году больше унижает комментатора чем автора статьи. Обратите внимание, что легенду про 20% в месяц придумал 1й комментатор, тогда как результаты тестирования на реальном счете, приведенные в статье, гораздо скромнее.
![2021-03-17 DIS – заранее указанный уровень отскока сверху, затем явный стоп коррекции снизу/ 2021-03-17 DIS – заранее указанный уровень отскока сверху, затем явный стоп коррекции снизу/](https://habrastorage.org/getpro/habr/upload_files/f27/882/8d9/f278828d95cc966eaf67f67d9ca5531d.png)
Приходится вносить эту правку, дабы особо ретивые блюстители за эффективностью чужого времяпрепровождения (как из первых двух комментариев) понимали, что если работа, на первый взгляд, направлена на прямое извлечение прибыли, это совершенно не означает что она не может иметь других далеко идущих целей или не может приносить сопутствующих бонусов или даже простого удовольствия.
1. Предыстория, которую можно и пропустить
Текст
Начну с того, что в далеком 2008 году на волне всеобщего интереса подсел на форекс через дилинговые центры и известную платформу МТ4. Будучи человеком очень осторожным, я написал триллион всяких индикаторов и торговых стратегий, проверяющих ту или иную идею, прежде чем слепо накидывать ее на свой скромный реальный счет. Одного слива за полчаса всего торгового счета размером в 150 баксов хватило чтобы усвоить урок и таких случаев больше не повторять.
Дилинговых центров я поменял штук пять, последним из которых стал Б***КО. Ушел я оттуда за неделю-другую до нашумевшего закрытия, ибо дело уже тогда пахло керосином. Чутье не подвело. После этого форекс был заброшен, так как стало понятно, что развод лохов в СНГ интересует ДЦ гораздо больше, чем репутация.
После этого, в не менее далеком теперь 2013 году я записался на курсы биржевой торговли, организованные в онлайн режиме по скайпу одним из идеологов программы графического анализа рынков, название которой я здесь приводить не буду. Суть заключалась в том, что, якобы, торговые решения внутри дня нужно принимать только имея представление о том, какой сегодня интерес имеют крупные игроки рынка. Программа показывала этот интерес выпукло – крупные сделки и лимитные ордера отражались графическими объектами в истории с возможность фильтрации. Сам ведущий курсов занимался скальпированием с использованием этой платформы, и часто сливал деньги, когда играл «на публику», при этом утверждал, что в среднем его счет растет неплохо и составляет пару сотен тысяч долларов. Уловить каждый раз причину, по которой он вошел в рынок при онлайн-скальпинге было сложно еще и потому, что он накапливал позицию, совершая несколько сделок в одну сторону, лонг или шорт, исходя из некой суммы знаний о вчерашнем дне, неделе, прошедших крупных сделках, крупных заявках и т.п. Накапливать убыток по открытым позициям - как бы сомнительная стратегия для людей обладающих гораздо более скромными возможностями, в смысле малыми размерами счета, для тех кто понимает. Затем в дело пошли опционы, анализ где-то там чего-то сказанного руководителем МВФ или Европейского Центробанка, какие нынче процентные ставки, и так далее, и его торговая система разрослась до размеров, неподвластных неискушенному внутридневному трейдеру, к тому же еще имеющему нормальную работу на полный день, семью, и разные другие интересы. Объяснения становились все пространнее, лекции все длиннее, следовать его системе стало просто невозможно, и я соскочил. На удивление - с прибылью, так как сам на реале пока не торговал, но, будучи программистом, написал по его заказу пару-другую индикаторов-плагинов к той платформе на C# (и с трудом выбил из него оплату, потому что он-де решил, что я делаю это бесплатно из какой-то солидарности с его идеями, но это уже другая история).
В какой-то момент я обнаружил себя за границей, - программистом в одной немецкой фирме, еще и с договором на заочное обучение по программе магистратуры. Приоритеты были расставлены соответственно, и трейдинг отошел на десятый план.
Тем не менее, пройденный курс биржевой торговли, как оказалось, лег на благодатную почву, и я вынес оттуда некое понимание основного принципа – мелочевка вроде частных трейдеров, да и некрупных инвестиционных фондов нужна ровно для того, чтобы обеспечить ликвидность. Это означает, что гвалт и какофония миллионов сделок на рынке все-таки находится под управлением крупных игроков, умело направляющих все стадо в нужную сторону с целью извлечения прибыли.
Нужно отдать должное тем, кто видит глобальные движения рынка и разрабатывает стратегии на базе годовых графиков. А также тем, кто заходит прямо с противоположно конца и создает компании, занимающиеся высокочастотным микросекундным трейдингом, со скоростной оптикой до самой биржи, специальными драйверами для сетевых карт, и какими-то мега-мозгами, которые стоят, судя по объявлениям на рекрутинговых сайтах, «450килорублей в месяц плюс комиссии с прибыли от стратегий» …
Ни первое, ни второе - не наш метод, так как закинуть на торговый счет без ущерба семейному бюджету можно не больше тысячи баксов, а торговать как упомянутые маргиналы чревато потерей счета на диких стопах по дневкам, либо разорением на комиссиях за перенос позиций. Про высокочастотный вообще молчу, частнику это недоступно. Ну, по крайней мере так было тогда, когда я принимал решение о разработке.
Как сейчас? Сейчас вы, наверное, доверяете свои бюджеты «инвестиционным программам» разных российских банков, а то и открываете «торговые счета» и покупаете акции Газпрома и Аэрофлота. Есть инсайдеры, не спорю, с финансовым образованием, понимающими что где и когда покупать. Я себя к ним не причисляю.
Я смотрю на вещи с позиции программиста, которому очень хочется торговать внутри дня, иметь процентов 20% от депозита в месяц, при этом есть идея как это можно реализовать, а значит все просто – идею надо проверить. Важно не забывать – нужно найти в потоке мусора рыночных данных нечто, что укажет на «интерес крупных игроков». Грааль? Да! То есть, нужно повторить подвиг разработчиков уже упомянутой здесь платформы графического анализа. При этом ПО будет у меня свое, а значит бесплатное, и доступное для модернизации, проверки идей, и всех тех бонусов, которые так радуют сердце программиста - иметь власть над приносящей деньги программой, к тому же разработанной от и до собственными руками.
Прототип программы, реализующей мое видение анализа рынка был написан на Дельфи в 2016 году, затем отложен на два – три года из-за учебы и новой работы. Проблема с учебой была решена в 2019 году защитой магистратуры.
С этого момента работа над аналитической платформой продолжилась без помех. Точнее началась заново, теперь на С++ в QT с использованием OpenGL для отображения графиков и отфильтрованных событий. В месяц по чайной ложке.
2. Платформа для анализа рыночных данных AdvancedCharts
Теперь можно перейти к тому, что, собственно, получилось на момент публикации этого блога.
Для начала - сравнение потребления ресурсов моего домашнего ПК: при использовании терминала моего брокера (доходит до 70% CPU) и моей скромной аналитической платформы (редко выше 10% CPU, при том, что я отображаю не просто свечи, а создаю графический объект для каждой сделки, коих сотни тысяч в день на инструмент, плюс десятки изменений в секунду от лимитных ордеров по лучшей цене и в стакане). Ругаться с брокером бесполезно, они молятся на свою платформу и модернизируют в год по чайной ложке.
Сейчас идет разработка коммуникатора для источника данных https://tradernet.ru/tradernet-api/
Для подключения к API используется socket.io для программ на С++, взятый здесь, в комбинации с QNetworkAccessManager.
Например, запрос SID выглядит так (вы должны быть зарегистрированы на ffin.ru):
void connectorFFIN::connectAPI()
{
QUrl url("https://tradernet.ru/api/check-login-password");
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QUrlQuery params;
params.addQueryItem("login", "your_email@mailserver.com");
params.addQueryItem("password", "your_password");
params.addQueryItem("rememberMe", "1");
params.addQueryItem("mode", "regular");
params.addQueryItem("userId", "your_userID");
m_status=requestType::Open;
m_manager->post(request, params.query().toUtf8());
}
Результат запроса приходит в виде JsonDocument c именованными полями.Полученный таким образом SID используется в некоторых запросах, требующих авторизацию.
Запрос MarketsInfo:
void connectorFFIN::requestMarketsInfo()
{
QUrl url("https://tradernet.ru/api/");
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QUrlQuery params;
params.addQueryItem("q", "{\"cmd\":\"getMarketStatus\",\"params\":{\"market\":\"*\"}}");
m_status=requestType::MarketsInfo;
m_manager->post(request, params.query().toUtf8());
}
Запрос списка топ-инструментов:
void connectorFFIN::request_topInstruments()
{
QUrl url("https://tradernet.ru/api/");
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QUrlQuery params;
FFINPARA map;
params.addQueryItem("q", m_ffinQueryTops.GetQueryText(map));
m_status=requestType::getTopSecurities;
m_manager->post(request, params.query().toUtf8());
}
Запрос списка инструментов с поисковым запросом и фильтром:
void connectorFFIN::request_searchInstruments(const QString& keyWord)
{
QUrl url("https://tradernet.ru/api/search");
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QUrlQuery params;
FFINPARA map({{QString("text"),keyWord}});
params.addQueryItem("q", m_ffinQuerySearch.GetQueryText(map));
m_status=requestType::searchInstruments;
m_manager->post(request, params.query().toUtf8());
}
Где GetQueryText для поискового запроса «AAP» возвращает что-то вроде:
"{\"cmd\":\"tickerFinder\",\"params\":{"\"text\":\"AAP"\""+"}}"
// -------------------------^
А результат этого запроса – JsonDocument, получить список тикеров из которого можно преобразовав бинарые данные QByteArray ответа:
void cFFINQuerySearch::SetAnswer(const QByteArray& data)
{
QVector<QString> result;
QJsonDocument d = QJsonDocument::fromJson(data);
qInfo() << d;
auto arr=d["found"].toArray();
for (auto it = arr.begin(); it !=arr.end(); it++)
{
if ((*it).isObject())
{
auto item=(*it).toObject();
if (item.find("t")!=item.end())
result.push_back(item.value("t").toString());
}
}
emit signalSearchResults(result);
}
И заполнить список в окне WatchList:
![](https://habrastorage.org/getpro/habr/upload_files/bfc/0b5/42d/bfc0b542de89c700662910c1960d3e30.png)
Уже написан парсер результатов подписки на тиковые данные.
void connectorFFIN::bindEvents()
{
m_socket->on("q", sio::socket::event_listener_aux([&](std::string const& name, message::ptr const& data, bool isAck, message::list &ack_resp)
{
m_lock.lock();
QByteArray a = QByteArray(socketIOToJson(data,"").toStdString().c_str());
QJsonParseError p;
QJsonDocument doc=QJsonDocument::fromJson(a,&p);
if(p.error != QJsonParseError::NoError)
{
qInfo() << "ERROR: socket.io response parsing failed" << p.errorString();
}
emit signalTAS(doc);
m_lock.unlock();
}));
m_socket->on("b", sio::socket::event_listener_aux([&](std::string const& name, message::ptr const& data, bool isAck, message::list &ack_resp)
{
m_lock.lock();
QByteArray a = QByteArray(socketIOToJson(data,"").toStdString().c_str());
QJsonParseError p;
QJsonDocument doc=QJsonDocument::fromJson(a,&p);
if(p.error != QJsonParseError::NoError)
{
qInfo() << "ERROR: socket.io response parsing failed" << p.errorString();
}
emit signalLVL(doc);
m_lock.unlock();
}));
}
В целом результат работы выглядит так. Некоторые скриншоты я публикую на канале https://t.me/acharts
(Графики пока еще строятся на другом источнике, не ffin.ru – здесь работа еще не закончена).
Вот некоторые из них, наиболее характерные:
![2021-04-21 MSFT – накопления перед коррекциями в шорт 2021-04-21 MSFT – накопления перед коррекциями в шорт](https://habrastorage.org/getpro/habr/upload_files/08a/ea0/905/08aea09058decf5cbb92df9763b08ccf.png)
![MSFT – накопление в шорт MSFT – накопление в шорт](https://habrastorage.org/getpro/habr/upload_files/0e6/438/a92/0e6438a92ca04b6d2ced3d241d82e5a0.png)
![2021-04-19 AAPL – узкий коридор из крупных заявок обозначен еще утром, за день уровни не пробиты 2021-04-19 AAPL – узкий коридор из крупных заявок обозначен еще утром, за день уровни не пробиты](https://habrastorage.org/getpro/habr/upload_files/5c3/99e/97f/5c399e97f1202e5bd937b09b3ed51428.png)
![2021-04-06 AAPL – накопление на сильном уровне перед разворотом в шорт 2021-04-06 AAPL – накопление на сильном уровне перед разворотом в шорт](https://habrastorage.org/getpro/habr/upload_files/93f/cd6/c33/93fcd6c332f3783d71f3df2097924e37.png)
![2021-03-25 AAPL – Диапазон торговли указан купными заявками. Здесь график без контуров свечей 2021-03-25 AAPL – Диапазон торговли указан купными заявками. Здесь график без контуров свечей](https://habrastorage.org/getpro/habr/upload_files/0d5/8e8/c7e/0d58e8c7e82c360195312e00f3ab2dac.png)
![2021-08-12 MRNA – щелчок по графику обновляет индикатор TreeMap с отсортированными по объему единичными сделками в этой точке 2021-08-12 MRNA – щелчок по графику обновляет индикатор TreeMap с отсортированными по объему единичными сделками в этой точке](https://habrastorage.org/getpro/habr/upload_files/ed9/007/f82/ed9007f822fa74fd91248b4d2b3c3eba.png)
Способ компоновки данных для последующего отображения на графиках считаю своим ноу-хау, поэтому в рамках этой статьи не рассматриваю. Хотя допускаю, что есть одна-две другие платформы, которые давно уже пришли к этому и, возможно, имеют лучший результат за счет наличия ресурсов на разработку.
3.Результаты предварительной проверки на реальном счете
Называть своего брокера не буду. Важно, что на депозите от 300 долларов можно работать с дробными лотами внутри дня.
При открытии счета на 500 долларов я потерял 25 баксов на комиссии от перевода (т.е. начал работу с 475 долларов), но по результатам торговли за неполный месяц вырастил его обратно до 500.
Торговал очень осторожно, беря по 10–20 пунктов со сделки, хотя точно знал, что можно быть более агрессивным. Но это был первый месяц проверки. Дальше будет проще, хотя в целом торговать сам вручную я не планирую.
4. Выводы
Как в известной фразе, чем больше я знаю, тем с большим количеством вопросов сталкиваюсь. Аналогично, чем дальше продвигается разработка платформы, тем больше появляется возможностей, идей, которые нужно проверить. Пока все упирается в нехватку времени.
Вот примерный список.
Подключить к стабильному недорогому источнику тиковых данных с собственным API, часть уже реализована, надо расширять список. На примете http://polygon.io со сходным API. Может, следующий будет TINKOFF API https://habr.com/ru/post/592093/
Посмотреть, что можно обнаружить на разных биржах, не только Нью-Йоркской.
Посмотреть, что можно обнаружить на криптовалютах.
Посмотреть, что можно обнаружить на форексе.
Оптимизация программы, использования памяти (сами данные в бинарном виде по шести моим излюбленным инструментам на день составляют больше гигабайта, плюс их надо пропарсить, «развернуть» в структуры данных, что автоматически увеличивает объем используемой памяти в разы. Плюс память на графические объекты.
Доработка моих индикаторов, а именно - TreeMap в любой точке графика или за период; показывать Quotes на графике; есть еще не скопированная на С++ наработка из первого прототипа - анализ сделок в комбинации с Level2 – обнаружение накопления крупных позиций.
Профиль рынка в классическом виде NinjaTrader, тоже был в прототипе.
Добавление индикаторов по классическим алгоритмам (скользящие средние и т.п.)
Мелочевка по интерфейсу - скроллинг графиков, масштабирование, добавление типов графических объектов.
Адаптация ко все новым источникам данных (новые коннекторы и парсеры).
Методы машинного обучения для принятия торговых решений или хотя бы помощи в выявлении паттернов по моей системе.
За сим откланиваюсь. За конструктивную критику заранее спасибо.