Блог им. karat39

Изучаю FIX протокол с нуля. Подводим итоги первой части. Первая борьба за миллисекунды.

Начало положено тут
Продолжение тут

Вступление

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

Теоретически аспекты. Разложим немного по полочкам.

     Все сообщения протокола можно разложить на несколько тем. Я начну с первой группы:
  1. Сообщения для поддержания связи.
  • Logon; Тип=A; Сообщение для инициализации сессии. Грубо говоря для подключения к серверу
  • Logout; Тип=5; Сообщение для завершения сессии. Сообщаем серверу о прекращении связи
  • Hearbeat; Тип=0; Сообщение для поддержания связи. 
  • Request; Тип=1; Сообщение для поддержания связи. Запрос второй стороны, жива ли первая
  • Reject; Тип=3; Сообщение об ошибке. Получаем его, если мы не правильно оформили свое сообщение
  • Resend Request; Тип=2; Повторный запрос сообщений, в случае утери. Задается интервал номеров сообщений.
  • Sequence Reset; Тип=4; Используется для сброса номеров сообщений. 
     На этом наверное буду заканчивать первую часть описания. В нее вошли функции, отвечающие исключительно за связь между клиентом и сервером. Давайте посмотрим теперь немного практики. И еще почертим.
Когда мы устанавливаем подключение к серверу, мы должны передать ему три параметра:
  • метод шифрования (0 по умолчанию)
  • интервал в секундах. Этот параметр указывает с каким интервалом мы будем обмениваться сообщениями поддержания связи (Hearbeat и Request)
  • флаг сброса счетчика сообщений. (Y — сбросит на ноль).
При успешной операции, сервер нам отвечает тем же.
Изучаю FIX протокол с нуля. Подводим итоги первой части. Первая борьба за миллисекунды.
     Далее, сервер с указанной периодичностью, начнет слать в наш адрес сообщения запросы подтверждения связи. Я написал быстренько небольшое приложение, которое поможет показать на практике этот процесс. Я сделал таймер, который каждую секунду проверяет, не пришло ли нам что нибудь на сокет. 
Тут я моделирую, что мы глухи
Изучаю FIX протокол с нуля. Подводим итоги первой части. Первая борьба за миллисекунды.
А тут, я ему отвечаю на его запросы
Изучаю FIX протокол с нуля. Подводим итоги первой части. Первая борьба за миллисекунды.  В принципе, вот и все общение. Далее, с опытом, придется еще отработать механизмы обрыва связи и механизм потери сообщений. 

Боевой кодинг. Начало борьбы за миллисекунды

     С получением опыта пришлось существенно доработать классы. Где то появилась избыточность кода. Все идет на минимизацию расчетов.
К примеру. Приведу старые скрины кода из первой части. В каждом классе у меня были 2 метода:
  • ToString() — создавал на основе класса строку соответствующего сообщения в формате FIX для передачи на сервер
  • GetMessageSize() — подсчет длины строки для формирования заголовка сообщения

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

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

Вроде как мелочь, да и переписывать классы пришлось часа 4. Но такой ход позволил скосить в среднем до 10 миллисекунд на операцию и теперь на отправку и получения ответа уходит стабильно менее 90мл сек (раньше было около 100 постоянно и выше). Мелочь, а приятно.
На этом пока все. Теперь предстоит долгий путь создания кода под торговые операции.


★37
51 комментарий
Да кстати, был совет от собеседника, выложить код на опенсурс. Проект собирался делать открытым. То есть отдать в свободное плавание. Как только пойму, что на очередном этапе ошибки все устранены, начну выкладывать поэтапно.
avatar
Андрей К, это было бы оч круто
avatar
Очень интересный топик плюс однозначно
Глубоко  раскрыл молодец
avatar
100 мс? это с пингом до биржи туда/обратно?
10 мс сыкономить на каком-то методе при формировании сообщения??? а вы точно милли- с микро- секундами не путаете?
Бабёр-Енот, борюсь в коде за каждую десятку. Привык подходить качественно к задаче, насколько хватает опыта. Если найду, где еще 5 скосить, буду переделывать тоже.
avatar
Андрей К, время, затраченное процессором на твой код, должно измеряться даже не микро-, а наносекундами, ибо микросекундами измеряются сетевые задержки. А теперь прикинь — сможешь ты ускорить свой код на пять порядков в текущей парадигме с классами на каждую несчастную подстроку? Ты когда текстовый редактор пишешь — каждую букву тоже отдельным классом со своим интерфейсом описываешь?
avatar
Ребята, голова вареная после торгов. Гляньте в скрине, там же миллисекунды? Такова моя реальность. В первой статье я писал, что не гоняюсь за скоростным трейдингом. Мне терминала за глаза.
avatar
Андрей К, не, круто на самом деле... 
А мне чет показалось сначала что вы локально к эмулятору какому-то конектитесь...)
Бабёр-Енот, нет, не эмулятор. Я все в статье первой написал. Я запросил тестовый аккаунт у биржи (хотя у них то наверное эмулятор и стоит). Они быстро очень оформляют. Он работает круглосуточно, можно проверять свой код.
avatar

Я одно не пойму, зачем вы это делаете, когда есть открытый quickfixn.org/ Не проще ли присоединиться к проекту и его оптимизировать если это потребуется?

avatar
Игорь, ответ на этот вопрос я дал в самом начале.
avatar
Молодец. Продолжай дальше.
avatar
весьма сомневаюсь что 10 мс получились в результате такого примитивного рефакторинга. ну если вы конечно не миллиардами эти сообщения клепаете. и для «боевого кодинга» переходите на с++ или вообще на си, там будет побыстрее.
avatar
Михаил Иванов, я очень щепетильный человек. Стараюсь ерунду не писать. Перед этим сделал замеры ровно сто раз.
Насчет C++, я к сожалению его не знаю так хорошо (а решать поставленную задачу мне нужно именно сейчас), а почему был выбран c#, я ответил в самом начале. Мне доставляет удовольствие, как он работает с классами и коллекциями. Мог бы выбрать еще и Delphi, но паскаль так не справится.
avatar
Андрей К, на фиксе борьба идет за микросекунды. Миллисекунды даже скрипты на луа выдают.

Согласен с выше написанным — сильное сомнение в применимости вышенаписанного в боевых торгах.
avatar
Евгений, Москва не сразу строилась. Цель конечно изначально была не в переплюнуть готовые проекты, но честно сказать, втянулся, поживем увидим. Я же не рекламирую свой код. Я на основе программирования, показываю теоретические основы Фикса. Литературы в доступном изложении маловато. Попутно и я его изучаю во всех деталях.
avatar
Андрей К, ваше сообщение больше похоже на проплаченного автора с хабры. Пишите много, разумоного мало. Задача — набрать кючевые слова. Может я и не прав, но все именно так и выглядит.
avatar
Евгений, вы в праве так считать, честно сказать, не знаю что ответить. =) Загнан в тупик про хабру, ничего там не понимаю.
avatar
Андрей К, ваш ответ как раз выдает проф писателя за деньги.

Согласитесь, странно это все. Зарегистрированы 2 года назад. Ничего не писали. Теперь начали, и сразу в стиле платных писателей — слов много, смысла мало.

Пишите, конечно. Раз раскрутка сайта идет.
avatar
Евгений, да, действительно, я ничего не писал, но много комментировал. Это моя принципиальная позиция на СЛ. Будет расти уровень контента на СЛ, возможно, буду писать и по рынку. Пока я это делаю на другом форуме. На данный момент решил только поделиться получением знаний про протокол.
avatar
Андрей К, где вы еще пишите?
avatar
Евгений, извините, сказать не могу.
avatar
Андрей К, ))
avatar
Андрей К, а как проводили замеры? я не троллю, мне весьма интересно откуда могла получится такая штуковина. если я вас правильно понял, то раньше вы три раза составляли строку и подсчитывали ее длину (строка на предпоследнем скриншоте). строка состоит из двух Int.ToString и одного bool.ToString, к которым добавлены некоторые Tags. Эта работа займет скорее микросекунды. Откуда же взяться целым 10мс?
avatar
Михаил Иванов, как учили в свое время в университете. Лучше пока придумать, опыта не хватает. Сделал ряд замеров работы, собрал данные, свел в таблицу результатов, вычислил среднее время работы того и того кода.
avatar
Андрей К, понятно. Вот такой код делается за 19 мс. комп — скромный ноутбук с i5. И все же, откуда у вас взялось 10 мс?

 DateTime n1 = DateTime.Now;

            int one = 1;
            int two = 551;
            bool yes = true;

            for (int i = 0; i < 10000; i ++)
            {

                string res = String.Format("{0}={1}\u0001{2}={3}\u0001{4}={5}\u0001",
                    1,
                    one.ToString(),
                    2,
                    two.ToString(),
                    3,
                    yes.ToString()
                    );
                int len = res.Length;
            }

            TimeSpan n2 = DateTime.Now — n1;
            Console.WriteLine(n2.Milliseconds.ToString());
            Console.ReadKey();
avatar
Михаил Иванов, не могу однозначно ответить. Пока только на вскидку, у меня же там этот код вызывается не 1 раз при создании сообщения. а 3 раза. Торговая сессия закончится, по разбираюсь ради интереса.
avatar
Андрей К, посмотрите пожалуйста. вполне возможно вы и увеличили скорость работы, но явно не понимаете, как именно ;)
avatar
Михаил Иванов, возможно. Будем посмотреть =)). Но честно говоря, целенаправленно изменял код именно на этом.
avatar
Андрей К, несмотря на твое мнение — Delphi прекрасно справляется с этой задачей, укладываясь в те самые наносекунды…
avatar
_landy, верю, но принял решение на c# по личным причинам. + мне нравится работа с классами и строками. Дальше семерки делфи я мало, что программировал (я из старой гвардии делфийцев), семерка не справится с такой изящностью кода я думаю.
avatar
Андрей К, я тоже, поэтому и говорю, что именно семерка как раз показывает недостижимую для последующих версий компактность и эффективность кода.

PS: Самый главный тормоз в твоем коде - String.Format, тебе нужно уйти от него, формируя строку обычными конкатенациями.
avatar
_landy, я действительно по поводу этого Format переживаю =).
avatar
avatar
как ты на винде собрался лоулатенсиничать та?

прям беда :)
avatar
crazyFakir, будем как есть. Если хватит времени, я решил для себя, что попробую cи + linux. Проект пока в рамках набивания руки на fix.
avatar
Андрей К,  странные подходы, тк писать на с++
то далеко не быдлокодить на шарпе
ну а джава к шарпу ближе как никто и опля — линукс в работе прям щас :)
avatar
crazyFakir, к сожалению очень далек от этого. 10 лет отдал Delphi на крупных проектах. Намек про джаву я понял при вашей ссылке на книгу. Но на все распылиться сейчас не могу. Сконцентрировался пока на c#. В первой статье я писал. Что я изучил рынок вакансий и неспешно подбираю их. Для этого мне пришлось подналечь на c#. Кстати говоря, вакансии делятся именно на c#/c и на java. Я выбрал первое.
avatar
Андрей К, ответ вполне ламерский, ткчт — нет вопросов :)
avatar
crazyFakir, наверное так и есть =)
avatar
Андрей К, 
будем как есть.

ну дык почитай про шедулер виндов и не теряй время зря

экономить мс на винде это как на спининг вместо лески надеть льняную веревку — БЕССМЫСЛЕННО :)
делятся именно на c#/c
писали такие же кодеры как  и ты… вы будете явно  рады встрече :)

пс: говорю по-доброму, без издевок. просто треп :)
avatar
crazyFakir, спасибо за свой опыт. Дело в том, что алгоритмы делал мимнимум от минуток, ну а вообще в среднем на часах. Рад любому совету от опытных. Закончу этот проект, буду дальше думать на чем и где создать его копию для сравнения.
avatar
crazyFakir, я правильно понял, что вы советуете java под линукс для скоростного алго?
avatar
Андрей К, да упаси бес советовать, просто на досуге грю, что нет смысла ловить мс на винде. это будет не медленно, а себе на уме.

линукс более предсказуем и имеет какой-то инструментарий для более-менее понятного времени отклика системы.

для более жесткого реал-тайма нужно что-то типа qnx видимо, сам не делал.

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

иначе получиться всеравно эС-шарп — т.е. ни то ни сё, а времени сожрет кучу. имхо :)

что до работы, то пройдя от джуниора лучше ее искать на западе нынче, а там сильно больше джавы требуется.
имхо-2. :)
avatar
crazyFakir, да, я уже обратил внимание, что все западные только java требуют.
avatar
Андрей К, ну уж прям не все, но многие. :)
avatar
Андрей К, если учесть что FIX это вполне себе суръезно, то да — джава на линухе будет более правильно.

всмысле нет разниц с С# почти по сути за редким, а вот кроссплатформеность у джавы сильно лучше.

скорости примерно равны будут на такой задаче.

джава + линукс > вин+шарп // стопудова :)
avatar
еще тынц

старт очень простой
avatar
спасибо!!!
avatar

теги блога Андрей К

....все тэги



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