Мой новый проект на Rust

Приветствую читателей блога! Немного забросил написание статей, но у меня есть уважительная причина, я снова вернулся к разработке). Поэтому забот хватает и без блога.

На работе сейчас это подготовка одного ответственного архитектурного решения, написание и оптимизация запросов для MongoDB и немного C#, но про это рассказывать не очень интересно. Обычная и даже немного скучная работа.

Гораздо интереснее то, что я делаю в рамках домашнего проекта. А здесь я вернулся к разработке на Rust. Это уже 3-й раз, когда я серьезно погружаюсь в этот язык. По результату последних изысканий возникли некоторые мысли, которыми я хочу поделиться.

Первый раз я подступился к нему где-то в 2016 году, но это было скорее общее знакомство без конкретной цели. И это было ошибкой. Нет конкретной цели, нет реальных задач и все это в итоге превращается в какой-то вялотекущий абстрактный интерес. Даже несмотря на более чем десятилетний опыт в программной разработке мне было сложно понять и освоить язык. С одной стороны, он очень сильно отличался от того, к чему я привык, а писал я тогда на PHP и C#. С другой стороны, на тот момент было не очень много учебных материалов. Особенно печально дело обстояло с популярными библиотеками, т.е. они вроде и есть, но воспользоваться ими сложно, т.к. нормальной документации нет. Сейчас ситуация изменилась в лучшую сторону.

Rust чем-то похож на C++, часто эти языки относят к одному классу, и хотя я когда-то писал на C++, но в понимании Rust-а мне это не сильно помогло. Или помогло, но я этого просто не заметил). «Он, конечно, крутой и классный, но уж больно замороченный» – примерно так я тогда думал.

Потом я поменял работу и стал писать на Go. Для меня продолжилась бэкенд разработка, но уже совсем другая. Специфика Go разработки все-таки сильно отличается от PHP.

Go – хороший язык, он очень простой, производительный и развитый в плане поддержки, т.е. библиотек для него хватает, есть куча статей, обучающих материалов, в общем изучать его одно удовольствие. И если бы меня спросили, а подходит ли Go для того, чтобы начать изучать программирование, то я бы ответил утвердительно. На первый взгляд – это идеальный язык для того, чтобы начать. Со мной, возможно, не согласятся Python разработчики или поклонники какого-нибудь другого языка, но я опираюсь на свой опыт, а он очевидно ограничен. Я думаю так, кто-то иначе.

В защиту своей позиции еще раз отмечу, что это очень простой язык. Он настолько простой, что мне в свое время понадобилась всего неделя, чтобы его изучить и на каком-то начальном уровне начать писать реальное, коммерческое приложение.

Однако примерно через год – полтора активной работы с Go я стал замечать скуку. Наверное, это не относится к одному лишь языку, так или иначе это связано и со спецификой работы. Любая более-менее однообразная работа надоедает. И хотя в программировании много интересных и сложных задач, но бывает и рутина. Особенно часто она встречается в продуктовой разработке, в тех компаниях, которые развивают свой, как правило, один единственный, но большой и сложный продукт, т.е. вся разработка вокруг него.

И огромное достоинство Go в плане его простоты и лаконичности со временем превращается в не меньший недостаток – невыразительность. Он слишком простой, чтобы лаконично выразить какие-то сложные мысли. На нем приходится писать много boilerplate кода (шаблонного кода).

Я не беру во внимание производительность, хотя, конечно, Rust быстрее, но сейчас это не важно. Главные претензии к Go – отсутствие выразительных языковых средств, особенно при работе с коллекциями и потенциально небезопасная concurrency. Там хорошая поддержка многозадачности (горутины), но с ней же и легко допустить ошибки, самая популярная проблема – гонки данных. Впрочем, это не является какой-то уникальной проблемой Go. Редкий язык может похвастаться безопасной многозадачностью, Rust в этом плане является приятным исключением.

Я не буду сейчас подробно разбирать Go, но постараюсь уделить этому замечательному языку отдельную статью и рассказать про его плюсы и минусы. В любом случае я с удовольствием рекомендую этот язык тем, кто только начинает свой путь в программировании. И не только начинающим. Это отличный язык для любого программиста, который занимается backend разработкой.

В общем на тот момент, а это был 2018 год, после полутора лет активного программирования на Go мне захотелось разнообразия и в своем домашнем проекте я снова вернулся на Rust.

Этот заход был гораздо удачнее, во-первых, уже была какая-то база знаний по языку, а во-вторых, была конкретная цель – разработка системы анализа естественных текстов (Natural Language Processing, NLP), конкретно интересовал русский язык, а именно задача обнаружения грамматических и пунктуационных ошибок: неправильные словосочетания, запятые и все такое…

Задача с одной стороны амбициозная, а с другой она в меньшей степени затрагивает имеющуюся библиотечную инфраструктуру, т.е. мне по большей части хватало самого языка. Были задействованы некоторые популярные библиотеки типа regex, lazy_static, rayon, parking_lot и др. Но в общем и целом – это просто дополнение стандартных языковых возможностей. На позднем этапе добавил web-фрейморк Rocket, но добавил только из-за потребности в web API, по которому можно было нормально взаимодействовать с системой.

Основной акцент в разработке был на логику, на реализацию алгоритмической части. Особенность проекта в том, что в нем нужна хорошая производительность. С учетом того, что все это основано на самообучении (вывод правил на основе статистического обучения) и нужно обрабатывать большие текстовые массивы (я использовал художественные книги), на основе которых выводились правила, то делать это хотелось быстро. В теории, конечно, можно было потратить неважно сколько времени и сохранить найденные правила, чтобы потом их переиспользовать, но на практике все упирается в отладку и эксперименты. В многочисленные эксперименты. И ждать больше нескольких минут, чтобы провести еще один эксперимент – не вариант. А таких экспериментов проводилось сотни, тысячи.

Язык помог реализовать нужную логику относительно просто и производительно. Определенных успехов в проекте я добился, т.е. некоторые ошибки система действительно находит, но далеко не все. В итоге это стало выруливать на серьезные исследования в области ML (Machine learning), а у меня на тот момент просто не хватило фундаментальных знаний по этой теме. Какие-то свои велосипедные решения отчасти сработали, отчасти – нет. Перспективы развить это и довести до ума остались, и возможно я еще вернусь к этому проекту, но пока отложил. Всего этот этап занял примерно год практической разработки на Rust-е.

Что я могу сказать по итогу этого второго погружения? Rust – очень крутой и производительный язык, он сделан по уму, он приятный в использовании. Можно ли его назвать сложным? Скорее да, чем нет. У меня не было какого-то специального времени на изучение языка, я сразу сел и стал писать свой проект. Но если примерно оценить мою производительность в написании кода, то по времени у меня заняло примерно 3 месяца, чтобы более-менее уверенно начать на нем писать. «Более-менее» – это значит я перестал бороться с компилятором, я стал понимать, что и как нужно писать, чтобы компилятор это принял сразу.

Еще 2018 год знаменателен тем, что разработчики Rust-а утвердили стандарт 2018, который вводил много новых языковых возможностей, стабилизировал ранее принятые решения и определил планы по поддержке асинхронного программирования (зарезервировали async/await). Сама поддержка async/await появилась позднее, но уже тогда в 2018 было понятно, что язык становится лучше, он эволюционирует.

Сложно выделить что-то одно и сказать – это главное, но очевидно, что движение в сторону дружелюбности языка – это супер важно. И Rust делал и делает шаги в этом направлении. Это выражается в хорошо подготовленной документации, в развитии компилятора, который здорово помогает в исправлении ошибок, он буквально подсказывает, что вы делаете неправильно и как это исправить.

Также с тех пор ослаблены некоторые синтаксические правила языка (например, Non-lexical lifetimes) без ущерба для его возможностей, т.е. компилятор все такой же строгий, но уже не такой догматичный.

Эти изменения появлялись постепенно, а сам стандарт 2018 официально был утвержден только в конце 2018 года. Есть и дальнейшие планы по развитию, но к чему я это все рассказываю? Это я к тому, что язык активно развивается. И куда ему развиваться решают не какие-то специальные люди или компании (привет, Go с его многострадальными дженериками), а сообщество. Также сообщество активно разрабатывает крутые библиотеки и фреймворки.

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

Самое ценное для меня то, что там было много разных проектов. Я успел поучаствовать в 3-х крупных, еще было примерно столько же небольших или точнее досрочно свернутых. Это, кстати, особенность аутсорсинга, клиент может отвалиться в любой момент, например, у него закончился бюджет, а привлечь инвесторов он не смог. Проект в этом случае просто замораживают. Есть шансы на то, что спустя какое-то время он найдет деньги и вернётся, но это происходит редко.

Из тех трех больших два были на тему торговых систем или торговых ботов. Там эти боты были ориентированы на криптобиржи типа Binance, BitMEX и др., но по большому счету торговать можно на любой бирже (безотносительно приставки «крипто»), было бы нормальное API. Сейчас я не буду углубляться в детали, отмечу лишь, что в этих проектах речь шла про арбитраж.

Но есть и другое направление для разработки торговых ботов – это алготрейдинг, формально арбитраж тоже можно сюда отнести, но я для себя их разделяю. Говоря про алготрейдинг, я имею в виду сделки в рамках одной биржи. Идея в том, чтобы, воспользовавшись какими-то хитрыми математическими моделями, статистическими показателями, предсказать повышение/понижение цены и заработать на прогнозе. Причем все это делает сам бот и предсказывает, и выставляет заявку, и отменяет ее, если его прогноз не оправдался. В теории это работает, а на практике – не очень. Но люди пытаются и такие разработки весьма популярны. Можно сказать, что это Святой Грааль трейдера – сделать автоматическую систему, которая будет торговать за него и зарабатывать, а он будет лежать на пляже и пить коктейли).

Многие ищут этот Грааль, но те, кто нашли – вряд ли будут делиться деталями реализации, какой в этом смысл? Чтобы потом его повторили сотни и тысячи других людей, и он перестал работать?

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

*Меня часто привлекали к оценке входящих проектов, т.е. я участвовал в presale оценке по части трудоемкости, реализуемости клиентского запроса.

С арбитражем в этом смысле проще, он более формализован, но нюансов там тоже хватает. Не так-то просто сделать арбитражного бота, который будет торговать в плюс. Вообще есть разные виды и стратегии арбитража, какие-то из них более, какие-то менее реалистичны. Может быть, потом опишу этот увлекательный опыт, полный драматизма и бесконечных алгоритмических изысканий: время сдавать проект, а бот так и не зарабатывает…

Спойлер: у нас все получилось).

Возвращаясь к теме повествования. Все это я рассказал, чтобы было понятно, чем я занимаюсь сейчас. Да, это очередная торговая система, работающая в парадигме алготрейдинга.

Для меня это не первая и даже не вторая попытка, до этого я уже делал что-то подобное на Go в своих домашних проектах. А теперь я делаю это на Rust-е. Будут микросервисы, новые алгоритмические идеи и Тинькофф Инвестиции. API у них есть, не идеальный, конечно, но жить можно.

С одной стороны, я понимаю сложность задачи, с другой – это интересно. Нет проблемы спроектировать и написать систему, проблема в алгоритмической части. Все, что касается прогнозных моделей – это бесконечные исследования и эксперименты. Что-то я уже попробовал в предыдущих проектах, что из этого не работает – я знаю, осталось попробовать другие варианты).

Почему Rust? Во-первых, он мне нравится, а во-вторых – быстродействие. Вся эти история с алготрейдингом – это история про расчеты и обработку ценовых колебаний в режиме реального времени. И это должно происходить быстро, очень быстро. Обработка текущих данных более чем за 1-2 секунды – это уже неприемлемо. Хотелось бы уложиться в одну секунду.

При этом данных может быть много (если мониторить сразу несколько бумаг).

В это время нужно еще включить реагирование, т.е. система должна успеть сформировать заявку на покупку/продажу, т.е. сделать она это должна на основе обработанных, проанализированных данных.

У меня нет цели торговать каждую секунду, да это и невозможно из-за ограничений на API по частоте запросов, есть цель среагировать максимально быстро, среагировать пока есть «окно возможностей».

Со мной могут не согласиться трейдеры, торгующие на больших таймфремах (часовые, дневные свечи), но я опираюсь на свой опыт и его результаты. Я уже пробовал по-другому, по-другому не работает. Вообще считаю, что попытки построить прогнозы на больших временных интервалах – бессмысленны. Там слишком много внешних по отношению к системе событий, которые будут ломать любую математику. Очередной Трамп или Маск напишет очередной волшебный твит и цена на какие-то акции улетит в небеса или наоборот – рухнет. Вы никак не можете это спрогнозировать.

Если вам не понятно, что такое таймфрейм и при чем здесь свечи, то вот поясняющий рисунок.

Свеча – это просто графическое отображение цены открытия и цены закрытия за какой-то интервал, в данном случае за один день, он здесь и является таймфремом. Если цена закрытия больше цены открытия, т.е. цена выросла, то свеча зеленая, а если наоборот, т.е. цена упала, то свеча красная. Выбросы сверху и снизу – это максимум и минимум за этот день.

В теории даже по такому дневному графику можно сделать какие-то выводы и спрогнозировать, например, что 1 апреля был восходящий тренд, и 5-го он, наверное, тоже сохранится (2, 3, 4 – длинные выходные, биржа зарыта). Но, что будет на самом деле не скажет никто. За это время может произойти десяток разных событий, которые могут испугать акционеров и они побегут избавляться от акций.   

1-го апреля цена закрытия на конец дня была 81.09 $. Я пишу эту статью 2-го апреля, просто из любопытства посмотрим, что там будет 5-го числа с акциями AMD.

UPD. 5-го апреля цена закрытия на конец дня составила 81.43, т.е. формально цена выросла, но совсем немного – на 0.42%. С учетом того, что цена в этот день падала до 80.40, то рост скорее случайный, чем закономерный. Вложения, сделанные 1 апреля на основе тренда были бы рискованными.

Есть попытки отслеживать новостной фон в автоматическом режиме и формировать реакцию на основе таких событий, но это тоже непросто. Машине сложно интерпретировать текст и в любом случае – это реакция на что-то, что уже случилось. В ту секунду, когда появится тот самый твит, потрясающий мироздание, тысячи трейдеров кинутся на биржу, чтобы купить или продать. Вы уверены, что сможете их опередить? Если у вас есть система, которая может обнаружить новость, правильно ее интерпретировать и среагировать за секунду, то, возможно, что да).

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

Почему микросервисы? Я буду делать проект сам, т.е. всего один разработчик. По своей сути это стартап и у него довольно туманные перспективы. Проще и быстрее было бы делать его в виде монолита, но… Я просто хочу попробовать сделать правильную микросервисную архитектуру. Для меня это учеба, учеба по архитектуре на практике. Я сам здесь и разработчик, и архитектор, я могу пробовать и так и эдак.

До этого я уже участвовал в двух больших коммерческих проектах, основанных на микросервисах. В обоих случаях была командная работа, я принимал участие в роли разработчика. И хотя я имел определённое влияние на архитектуру, но все же не отвечал за нее. Какие-то решения прошли мимо меня, какие-то достались в наследство.   

В обоих случаях мне не понравились микросервисы. Было много лишних усилий, куча проблем и сложностей, которые приходилось решать из-за того, что мы в принципе пошли по этому пути. И еще из-за того, как мы проектировали и писали микросервисы. У меня есть подозрение, что делали мы их не совсем правильно и часть проблем можно было избежать. Я попробую сделать правильно, контролируя весь процесс от и до.

Вообще проблема с микросервисами не нова, многие команды с ними так или иначе сталкиваются. Но в больших, долгоиграющих проектах особых альтернатив им нет. Монолит на определённом этапе развития проекта тоже становится проблемой. Я не буду сейчас углубляться в эту тему, позже посвящу ей отдельную статью и рассмотрю все это подробно.

Почему Тинькофф Инвестиции? Потому, что я клиент этого банка. Потому, что у меня там есть брокерский счет. Потому, что я пользуюсь их приложением для инвестиций. Это не реклама, есть и другие варианты, просто первым я попробовал именно его. Не скажу, что там все идеально, но в общем и целом меня устраивает.

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

В первую очередь этот проект у меня для души. У меня есть желание и возможность писать на том языке, который выбираю я, а не мой работодатель. Если честно, Go за последние 4 года мне уже поднадоел, хочется переключиться на другой язык. Еще это учебный проект, мне интересно получить новый практический опыт в роли архитектора.

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

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

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

Валерий Чугреев, 02.04.2020

Подписаться
Уведомить о
guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии