Блог им. SergeyEgorov

Бесплатная библиотека для программирования роботов

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

Разработку я начал год назад и нашей главной целью было как можно быстрее, и как можно с меньшими затратами начать торговать алгоритмически. Цели как мне кажется мы вполне достигли, потому что используя наш подход мы сегодня можем реализовывать и ставить на торговлю новые алгоритмы очень быстро (в течение одного рабочего дня даже).

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


  Видео можно скачать файлом отсюда. (Формат avi, размер 27.4 Мб)


  Видео можно скачать файлом отсюда. (Формат avi, размер 135 Мб)

  Видео можно скачать файлом отсюда. (Формат avi, размер 44.8 Мб)

  Видео можно скачать файлом отсюда. (Формат avi, размер 146 Мб)

 
В ближайших планах записать несколько видео (возможно это будет еженедельно), последовательно демонстрирующих процесс доработки робота.

Исходный код библиотеки можно загрузить отсюда.

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

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

Весь исходный код в оптимальном объеме покрыт модульными тестами (сама библиотека около 700 тестов, код адаптера чуть больше 100 тестов). Часть тестов скорее являются интеграционными, потому что проверяют работу нескольких компонентов.

Тесты не избыточны и не покрывают весь код стопроцентно. То есть в процессе эксплуатации сейчас выявляются и наверняка еще будут выявляться ошибки или сбои для пограничных случаев, для которых нет тестов. В случае выявления таких ошибок, будут реализованы дополнительные тестовые наборы и с их использованием исходный код будет исправляться или трасформироваться.
★34
29 комментариев
Круто. Огромная работа проделана. А чем ваша библиотека отличается от S#?
Пишите софт для smart-lab.ru/profile/DJSich/?
Александр,

Если в двух словах, то моя библиотека, как мне кажется проще и легковеснее. Я в самом начале разработки понял что не хочу концентрировать все поведение в каком-то суперклассе Strategy, а хочу получить много небольших, но легко повторно используемых компонентов, из которых можно будет компилировать новые алгоритмы торговли, просто добавляя их в робота.

В моих видео я постарался продемонстрировать подход и весь процесс сборки робота, от начала и до конца со всем необходимым исходным кодом, включая теоретические пояснения, настройки, инсталляцию компонентов брокера, регистрацию тестовых счетов у брокера и все это заняло час времени. Разницу в подходах к разработке можно попытаться увидеть сравнив мои видео с к примеру демонстрационным видео StockSharp vimeo.com/59339982.

А объективно, из явно-видимых невооруженным глазом отличий, код моей библиотеки покрыт модульными и интеграционными тестами (представители StockSharp на мой запрос на их форуме сообщили что они модульные тесты практически не пишут). Ну а поскольку есть тесты, то мою библиотеку можно смело исправлять, дополнять и трансформировать не боясь поломать что-то внутри. Упавшие тесты сразу показывают что и где сломалось.

Ну и как показывает практика, если сначала писать тесты, внутренняя архитектура системы получается более логичной, взвешенной, интуитивно-понятной, относительно легко масштабируемой и изменяемой. Компоненты библиотеки базируются на интерфейсах, между собой слабосвязаны и как правило отвечают только за выполнение какой-то одной конкретной операции, поэтому можно легко заменить одну реализацию на другую.
avatar
мне вот очень интересно смотреть трейдерский софт изнутри.
Спасибо.
avatar
Kostya33, You're welcome!
avatar
из того что заметил, интерфейсы было бы хорошо называть с заглавной I, это обычная практика, читать на мой взгляд удобнее. ISomeInterface
avatar
Программисты — коммунисты. ) Сергей вот интересно, а какая мотивация бесплатно то все раздавать? Вот правда не понятно.
А потом «ааа почему никто не покупает» ..))
avatar
Kostya33, Ну практика префиксования интерфейсов буколкой I это же по-большому счету лишь вопрос привычки.

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

Кстати, забыл упомянуть, репозитории на битбакет поддерживают интерфейс для сообщения об ошибках, в случае обнаружения оных можно о них там писать bitbucket.org/SazanRuProject/ru.sazan.trader/issues.
avatar
Изико, На мой взгляд программная библиотека одним боком очень похожа на набор типа «Сделай сам». Ну знаете продают такие коробочки с танчиками, самолетиками, автомобильчиками. Любой может купить и сидеть дома, подрезать, подтачивать, склеивать, раскрашивать. С библиотекой теоретически так же, но есть нюанс.

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

С библиотекой такой номер не прокатывает. Для сборки даже простого робота нужны специальные знания и навыки. С практической точки зрения, способности написать программку «Hello World!» здесь будет ой как недостаточно. Ну и в разрезе биржевой торговли тоже желательно что-то уметь и понимать. Этой предпосылкой мы даже в первом приближении свой потенциальный рынок сильно урезаем.

Ну для очистки совести можем посмотреть количество зарегистрированных на популярных трейдерских сайтах (смартлаб, айтиинвест) пользователей (примерно 18 — 19 тысяч человек) мы имеем потенциально очень маленький рынок сбыта. С учетом стоимости R&D при разработке библиотеки ее надо продавать мягко говоря недешево. Цикл продажи технологически-сложного и дорогого продукта в свою очередь тоже имеет высокую стоимость. Есть риск, что смещение фокуса в моей деятельности с программирования в продажи, приведут к моей деградации как программиста. В общем на мой взгляд, как ни крути, а бизнес модель с взиманием денег за исходный код библиотеки получается хроменькой на все четыре (или сколько там их у нее) ножки.

Есть еще несколько факторов из-за которых не хочется торговать исходным кодом, самый популярный из них — это легкость его копирования и передачи. То есть рано или поздно, копии библиотеки все равно разойдутся по сети и те, кто не хочет платить за нее, все равно ее получат. Смогут пользоваться или нет, это дело десятое, но получить получат.

Резюмируя… Мне выгоднее раздавать библиотеку бесплатно, а профит в виде денег, в натуральном выражении или в виде интересных связей, получить от каких-то других видов деятельности в сотрудничестве с заинтересованными людьми из сообщества трейдеров, которым в той или иной мере интересна алгоритмическая торговля.
avatar
SergeyEgorov, те ваше потенциальное преимущество на рынке в виде знаний, готовой работающей (наверное ;) библиотеки, потраченного времени и денег вы добровольно и безвозмездно отдаете в расчете заработать как то потом, в другой, непрофильной (по всей видимости) для вас сфере… а ну ок )))
avatar
Изико, знания мои никуда не делись. А готовая и даже идеально работающая библиотека (моя не идеальна) в современном мире не является сколько-нибудь значимым конкурентным преимуществом. Вот список www.traderslaboratory.com/forums/tools-trade/11086-open-source-trading-platforms-master-list.html продуктов с открытым исходным кодом для алгоритмической торговли. Если не брать в расчет мою библиотеку, то любой желающий из здесь присутствующих вполне может найти себе в этом списке подходящий ему продукт.
avatar
SergeyEgorov, спасибо посмотрел. но полумертвые какие то проекты. потом ни одна не пригодна для торговли у нас например => бесполезные ).
avatar
Изико, вполне возможно что и неживые. В софтверной индустрии дохляка наверное больше, чем в любой другой отрасли. Порог входа не очень высокий. Любой программист может вдруг начать баловаться «open source»-ом. :-) А потом бросить.
avatar
абстрактный класс именуется так же, как и остальные классы. А вот определение интерфейса в абстрактном классе — это моветон, т.к. в C# нет множественного наследования. Поэтому интерфейсы отдельно, классы отдельно. И чтобы с первого взгляды было ясно что где, приписывают I
avatar
Kostya33, это не меняет ситуации, мы по-прежнему обсуждаем вопрос личных пристрастий в части оформления исходного кода отдельных индивидуумов. Несколько лет назад я выбросил префикс I из имен интерфейсов, потому что согласился с аргументами Дядюшки Боба Мартина, которые он приводил в своей замечательной книге www.ozon.ru/context/detail/id/5800704/.

P.S. Мне встречались случаи, когда в абстрактный класс совершенно органично встраивались абстрактные же методы, превращая по меньшей мере часть класса в интерфейс, вынуждая его пользователей этот интерфейс оборудовать.
avatar
совершенно случайно такая книжка у меня есть, правда я ее не читал. а где в ней он про это пишет?
avatar
Kostya33, Извиняюсь, указал не на тот источник. Автор все тот же Роберт Мартин, но вот книга называется Чистый код www.ozon.ru/context/detail/id/21916535/ страница 47 Интерфейсы и реализации.

Ну а «Принципы, паттерны и методики гибкой разработки на языке C#», которую я упомянул ранее, просто потрясающая вещь. Читается как художественная литература. Масса ответов на вопросы, на которые больше ни одна книга не отвечает. Очень рекомендую, как впрочем и «Чистый код». Еще я у Мартина очень люблю «Идеальный программист» www.ozon.ru/context/detail/id/7360633/ хотя в ней и нет примеров кода.
avatar
Такая книжка у меня тоже есть, и даже бумажная. многие советы из нее хорошие и правильные. Но то, что он написал на стр. 47, это бред. «Я не собираюсь сообщать пользователям, что они имеет дело с интерфейсом». Если он пользователю не сообщает об этом, интерфейс никуда не денется. И с первого взгляда в коде не понятно, от чего унаследован класс — от абстрактного класса или реализует интерфейс. И если реализацию интерфейса я могу прикрутить к своим классам, то унаследоваться от абстрактного класса я могу далеко не всегда. Вот, допустим у меня приложение на WPF и я использую много классов, унаследованных от DispatcherObject. Куда тут абстрактные классы прикручивать?

Взамен отказа от префикса I, кстати Мартин предлагает гораздо более некрасивую альтернативу — именовать реализацию интерфейса с префиксом C или постфиксом Imp: CFactory или FactoryImp. Зачем это нужно — непонятно, ведь реализаций интерфейсов больше, чем самих интерфейсов, а в результате весь код будет состоять из CClass1, CClass2 и т.д.
avatar
Kostya33, ну так я же и говорю, это вопрос личных пристрастий и вкусов. :-) Ну а на некрасивые альтернативы я никогда принципиально не соглашаюсь. Я люблю чтобы код был красивый. Я же его целыми днями читаю :-) Хочется чтобы читать было приятно.
avatar
а еще вопрос — как делаете визуализацию? рисуете ли графики, а если рисуете то в чем?
avatar
Kostya33, мои роботы графиков не рисуют, они только торгуют. Они все консольные и запущены на арендованных виртуальных (и физических) серверах, на которые в течение недели может вообще никто не заходить. Графики мы обычно заблаговременно рисуем в Wealth Lab, когда стратегии думаем и тестируем.
avatar
а почему тогда не реализовали исполнение стратегий из WealthLab? Ну или сделать хотя бы набор логики примерно такой же — DataSeries и т.д.
avatar
Kostya33, исполнение стратегий из Wealth Lab потянуло бы за собой как минимум реализацию механизма обмена данными с Wealth Lab, а мне хотелось торговать скорее. И исполнение стратегий Wealth Lab это последовательность линейно исполняемых синхронных операций. Мы бы сразу и в корне похерили событийно-управляемую модель и возможность нормально реагировать на любые изменения рынка.

А что там такого в DataSeries к чему можно было бы прикипеть душой? Структура данных из двух сопоставляемых списков, один содержит элементы типа double, другой элементы типа DateTime, плюс пачка перегруженных операторов сложения, умножения, деления, вычитания. Если я правильно помню все это было придумано, когда C# был еще версии 2.0. Сейчас все это и даже больше можно делать с помощью LINQ почти над любой коллекцией элементов.
avatar
Ну никакого обмена данными с WL это не потребовало бы. А вот работа с DataSeries гораздо приятнее чем SiRtsSpreadFactory:SpreadFactory. Вы на каждую операцию 2+2 фабрику классов создаете? И интерфейс? Пачка перегруженных операторов DataSeries очень удобная и быстра в использовании. Да, LINQ запросы можно делать над любыми коллекциями, просто какой ценой? Производительность там удручающая. У меня свой многопоточный тестер (который прогоняет стратегии на тиках и сохраненных стаканах) и я знаю о чем говорю.

И WL это совершенно не обязательно последовательность синхронных действий. Не нужно все делать в лоб. У меня есть примерно такой шаблон стратегии
interface IStrategy
{

void Initialize();
void CreateTimeScales();
void Finish();
void OnNewTicks(Listticks);
void OnOrderComplited(MasterOrder order);
void OnOrderCanceled(MasterOrder order);
void OnOrderError(MasterOrder order);
void OnNewTrade(MasterOrder order, TradeOperationRecord tradeOperationRecord);
void OnNewDoM(DoM dom);
void OnTimer();

}

это завернуто в набор кубиков конечного автомата стратегии. Все работает асинхронно.

В инициализаторе создаю из DataSeries те фильтры, которые хочу

BarDataScale scale = new BarDataScale(RobotData.Scale, RobotData.BarInterval);
Bars ticker1Bars = DataSource[_ticker][scale];

int period = RobotData[«Period»].ValueInt;

DataSeries series1 = SMA.Series( (_ticker1Bars.Open + _ticker1Bars.High) / 2.0 );

Можно сделать вот такой обработчик на новый бар
BarsCollection barsCollection = DataSource.GetBarsCollection(scale);
barsCollection.Cursor.OnPositionChanged += OnCursorPositionChanged;

После этого DataSeries апдейтяться по вызову метода Update(), в том диапазоне, в котором нужно, без моего участия. Без всяких фабрик классов и LINQ запросов

Т.е., где-то в OnNewTicks или OnTimer или OnCursorPositionChanged
я делаю series1.Update() и уверен, что все последниее тики там есть, при чем там DataSeries сами разбираются, в каком диапазоне апдейтить

Стратегии WL заворачиваются в такую логику достаточно хорошо + еще дополнительные плюшки в виде котирования, стаканов и т.д. :)
avatar
Kostya33, Шаблон Фабрика я использую достаточно часто, BuySpreadFactory, SellSpreadFactory, SpreadLegDictionaryFactory… наверняка есть и какие-то кривые фабрики или интерфейсы в моей библиотеке, ну так это не беда, это не смертельно и поправимо, библиотека изменяется и дополняется почти каждый день. Что-то новое появляется, что-то старое, неправильное удаляется. Диалектика бытия.

Если это не секрет, вызов какого поведения (метода, оператора) так катастрофически убивает производительность LINQ?

Еще раз насчет «а почему тогда не реализовали исполнение стратегий из WealthLab». Речь похоже шла не о том, чтобы торговать прямо из WealthLab, прикрутив некий адаптер для какого-нибудь брокера, а о том, чтобы взять сборки MS123 LLC и писать стратегии используя код из них? Если да, то тут мы опять возвращаемся к теме «кому что нравится или хочется». Я хочу сам писать код, хочу сам во всем разобраться, и сам всему научиться. Я понимаю что можно взять чужие разработки, и иногда так и приходится делать, потому что другого пути нет. Но любую вещь, которую можно написать самостоятельно, я буду писать самостоятельно.

Ну и если я правильно трактую обычную пользовательскую лицензию Wealth Lab, то она не дает мне права включать сборку WealthLab.dll или какую-либо другую их сборку в мои собственные продукты, или я ошибаюсь?
avatar
по LINQ, первое — это использование вместо коллекций с доступом по ключу, коллекций общего назначения с дальнейшими запросами наподобие Where, First и т.д. Приводит к полному обходу коллекции. Второе, LINQ ни как не может определить «тяжелые» свойства объекта — поля, доступ к которым занимает много времени. И когда в запросе одно и тоже поле используется N раз, время запроса увеличивается пропорционально в N раз. Особенно плохо, когда поле возвращает также результат LINQ запроса.
Разумеется, те микросекунды, которые выкраиваются на этом, при работе робота в течении дня никак не заметны, это проявляется только при многократном прогоне стратегий на оптимизаторе.

Про WL — у меня используется самописный контейнер и DataSeries, позволющие с минимум затрат импортировать стратегии. Код WL не используется
avatar
отлично, спасибо за дискуссию!
avatar

теги блога SergeyEgorov

....все тэги



UPDONW
Новый дизайн