Как стать автором
Обновить

Производительность торговой платформы на простом примере

Время на прочтение7 мин
Количество просмотров4.6K
Всего голосов 31: ↑26 и ↓5+21
Комментарии14

Комментарии 14

На сколько я знаю, биржи не обеспечивают ИСПОЛНЕНИЕ торговой заявки за эти миллисекунды. Речь идет исключительно о приеме заявки пользователя и постановки ее в очередь, не более. А запросы на получение информации — и вовсе обычные и линейно масштабируются от количества серверов и ширины каналов (за исключением пользовательских данных депозитов но и там есть где разгуляться).

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

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

p.s. просто от балды, без какого либо опыта и использования готовых библиотек, писал на php сервер торговой биржи (однопоточный) с подключением клиентов по websocket (react php) и получал десятки тысяч сделок в секунду от сотни 'тестовых клиентов' на слабом десктопном железе (там все сильно зависело, сколько встречных заявок затрагивает ордер, но реалии таковы что обычно таких единицы максимум десятки, никто не 'торгует широко', так как это увеличивает неопределенность, гораздо выгоднее и проще строить свои стратегии, дробя свои объемы как раз по структуре стакана).

По поводу ощущений от статьи — действительно пара унылых аналогий без каких либо подробностей.


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


При определённых усилиях можно поставить заявку за <= 100us. Про то как приходит информация, у вас и вовсе крайне примитивное понимание. На самом деле в 99% случаев имеет место rpc протокол, который поддерживает слепок рыночного состояния на машинах клиентов командами вида add/delete/change. Время отклика разное у разных торговых систем, но у самих биржевых движков, исключая всяких паразитических сущностей типа брокера, это обычно не больше десятков микросекунд.

Вы умудрились написать слова но ничего не объяснили, зато интонация такая будто вы много знаете, может ответите полнее?

remote procedure call и локальный слепок рыночного состояния на машинах, вы о чем вообще? биржа никаким боком не занимается клиентскими машинами, она дает только поток сырых данных по своему протоколу или по фикс.

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

Вот вам ваши add remove change:
bitmex
1539172819528 {«table»:«trade»,«action»:«insert»,«data»:[{«timestamp»:«2018-10-10T12:00:11.320Z»,«symbol»:«XBTUSD»,«side»:«Sell»,«size»:1,«price»:6503.5,«tickDirection»:«ZeroMinusTick»,«trdMa»
1539172819543 {»table":«instrument»,«action»:«update»,«data»:[{«symbol»:«XBTUSD»,«lastTickDirection»:«ZeroMinusTick»,«timestamp»:«2018-10-10T12:00:11.320Z»}]}
1539172819568 {«table»:«orderBookL2»,«action»:«update»,«data»:[{«symbol»:«XBTUSD»,«id»:8799349650,«side»:«Buy»,«size»:1423529}]}

1539172819579 {«table»:«orderBookL2»,«action»:«update»,«data»:[{«symbol»:«XBTUSD»,«id»:8799349650,«side»:«Buy»,«size»:1423495}]}
1539172819580 {«table»:«orderBookL2»,«action»:«delete»,«data»:[{«symbol»:«XBTUSD»,«id»:8799997900,«side»:«Buy»}]}
1539172819580 {«table»:«orderBookL2»,«action»:«insert»,«data»:[{«symbol»:«XBTUSD»,«id»:8799997800,«side»:«Buy»,«size»:31,«price»:22}]}
coinbase/gdex
1515283201682 {«type»:«received»,«order_id»:«4be5cc83-d6b4-4259-815b-c8a61ab5ce6c»,«order_type»:«limit»,«size»:«0.00020000»,«price»:«17013.52000000»,«side»:«buy»,«client_oid»:«1ce59180-fce7-4777-8432-0abbe0c0ddd5»,«product_id»:«BTC-USD»,«sequence»:4791229850,«time»:«2018-01-07T00:00:01.638000Z»}
1515283201684 {«type»:«open»,«side»:«buy»,«price»:«17013.52000000»,«order_id»:«4be5cc83-d6b4-4259-815b-c8a61ab5ce6c»,«remaining_size»:«0.00020000»,«product_id»:«BTC-USD»,«sequence»:4791229851,«time»:«2018-01-07T00:00:01.638000Z»}
1515283201739 {«type»:«received»,«order_id»:«29ab41be-b472-4e1f-82b0-ed8be48c98b7»,«order_type»:«limit»,«size»:«0.03000000»,«price»:«17089.22000000»,«side»:«buy»,«product_id»:«BTC-USD»,«sequence»:4791229852,«time»:«2018-01-07T00:00:01.695000Z»}
1515283201742 {«type»:«open»,«side»:«buy»,«price»:«17089.22000000»,«order_id»:«29ab41be-b472-4e1f-82b0-ed8be48c98b7»,«remaining_size»:«0.03000000»,«product_id»:«BTC-USD»,«sequence»:4791229853,«time»:«2018-01-07T00:00:01.695000Z»}
binance
1545912000472 {«stream»:«btcusdt@trade»,«data»:{«e»:«trade»,«E»:1545912000365,«s»:«BTCUSDT»,«t»:90554819,«p»:«3724.13000000»,«q»:«0.00282000»,«b»:219008869,«a»:219008870,«T»:1545912000357,«m»:true,«M»:true}}
1545912001277 {«stream»:«btcusdt@depth»,«data»:{«e»:«depthUpdate»,«E»:1545912001134,«s»:«BTCUSDT»,«U»:330216562,«u»:330216569,«b»:[[«3724.13000000»,«0.00000000»,[]],[«3721.51000000»,«0.07836600»,[]],[«3718.57000000»,«0.00000000»,[]],[«3717.92000000»,«0.04300000»,[]],[«3697.52000000»,«0.05673000»,[]]],«a»:[[«3723.51000000»,«0.04400000»,[]],[«3732.85000000»,«0.00000000»,[]]]}}
1545912001508 {«stream»:«btcusdt@trade»,«data»:{«e»:«trade»,«E»:1545912001402,«s»:«BTCUSDT»,«t»:90554820,«p»:«3723.49000000»,«q»:«0.00278900»,«b»:219008875,«a»:219008876,«T»:1545912001397,«m»:true,«M»:true}}
1545912001828 {«stream»:«btcusdt@trade»,«data»:{«e»:«trade»,«E»:1545912001722,«s»:«BTCUSDT»,«t»:90554821,«p»:«3723.49000000»,«q»:«0.00003100»,«b»:219008875,«a»:219008880,«T»:1545912001714,«m»:true,«M»:true}}
1545912002240 {«stream»:«btcusdt@depth»,«data»:{«e»:«depthUpdate»,«E»:1545912002133,«s»:«BTCUSDT»,«U»:330216570,«u»:330216580,«b»:[[«3723.49000000»,«0.00000000»,[]],[«3721.53000000»,«0.00000000»,[]],[«3721.51000000»,«0.07555300»,[]]],«a»:[[«3723.51000000»,«6.04400000»,[]],[«3724.13000000»,«0.17640300»,[]],[«3724.15000000»,«0.19325500»,[]],[«3724.48000000»,«0.00000000»,[]]]}}
у bitfinex поверьте тоже есть add remove change плюс сами сделки раздроблены и в поток событий приходят два — на начало и конец, только там сырой поток заметно закодирован
bitfinex
1548547200035 [156646,[21847827324,1.8627234135,-50]]
1548547200035 [156646,[21847734859,1.8628749345,-2593.7]]
1548547200035 [156536,[21845702039,0,-1]]
1548547200035 [156536,[21847827319,117.29,-2]]
1548547200037 [156556,[21847804762,0.00067281,74.25375503]]
p.s. некоторые биржи офицально используют движки бирж из большого мира, например об этом написали bitstamp
bitstamp
1548547201887 {«event»:«order_created»,«data»:{«microtimestamp»:«1548547201447753»,«amount»:0.003091,«order_type»:1,«amount_str»:«0.00309100»,«price_str»:«3122.63»,«price»:3122.63,«id»:2789681125,«datetime»:«1548547201»},«channel»:«live_orders_btceur»}
1548547201888 {«event»:«order_changed»,«data»:{«microtimestamp»:«1548547201550466»,«amount»:0.224909,«order_type»:0,«amount_str»:«0.22490900»,«price_str»:«3122.63»,«price»:3122.63,«id»:2789681107,«datetime»:«1548547200»},«channel»:«live_orders_btceur»}
1548547201888 {«event»:«order_deleted»,«data»:{«microtimestamp»:«1548547201573565»,«amount»:0,«order_type»:1,«amount_str»:«0»,«price_str»:«3122.63»,«price»:3122.63,«id»:2789681125,«datetime»:«1548547201»},«channel»:«live_orders_btceur»}
1548547201888 {«event»:«order_deleted»,«data»:{«microtimestamp»:«1548547201599738»,«amount»:0.51014411,«order_type»:1,«amount_str»:«0.51014411»,«price_str»:«3132.49»,«price»:3132.49,«id»:2789681065,«datetime»:«1548547199»},«channel»:«live_orders_btceur»}
1548547202307 {«event»:«trade»,«data»:{«microtimestamp»:«1548547201694638»,«amount»:0.003091,«buy_order_id»:2789681107,«sell_order_id»:2789681125,«amount_str»:«0.00309100»,«price_str»:«3122.63»,«timestamp»:«1548547201»,«price»:3122.63,«type»:1,«id»:81934153},«channel»:«live_trades_btceur»}
1548547202307 {«event»:«order_deleted»,«data»:{«microtimestamp»:«1548547201702558»,«amount»:4.002506,«order_type»:1,«amount_str»:«4.00250600»,«price_str»:«3132.50»,«price»:3132.5,«id»:2789681109,«datetime»:«1548547200»},«channel»:«live_orders_btceur»}
remote procedure call и локальный слепок рыночного состояния на машинах, вы о чем вообще

Про incremental refresh. В нативных протоколах по сути тоже самое, но они рассчитаны на rdma/sharedmemory в кейсе высокой отзывчивости и не масштабируются по количеству клиентов, поэтому используют шлюзы ретрансляторы. От FAST и SBE, до просто предачи всё тех же сообщений но закодированных в виде POD объектов. Сходу могу предложить почитать спеку moex на этот счёт(у остальных всё более менее похоже) — http://ftp.moex.com/pub/FAST/.


FIX — это либо послеторговый контроль, либо торговля. Маркет дату так передавать супер неээфективно, и, на сколько я знаю, особо никто так и не делает. Ну точнее как, это конечно сообщения из спеки FIX (X и W), вот только закодированы они в FIX/SBE/wte и вещаются через мультикаст.


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

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

Некоторые биржи в криптовалютах 'третьего эшелона' написаны на столько криворукими разработчиками что лагают и тормозят на секунды и даже минуты (тот же yobit, 'не к столу будет сказано'), так будто внутри у них ядро на sql с блокировками на обычных десктопных машинах ;)

p.s. особенности ДОСТАВКИ данных до клиента никаким образом не связаны с тем как именно данные обрабатываются внутри биржи.

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

Так то — 10 лет назад на плюсах писали что бы уместится в железках, и в идеале, ещё и отмасштабироваться через n лет. А сейчас, что бы с умным видом смузи хлебнуть.

Особенно интересно, где fstrlab нашел шлюзы для выставления заявок по UDP (не путать с получением рыночных данных вроде FAST). maydjin странно почему они не могут обновлять софт — на питерской бирже НКД по бондам до сих пор нет в FIX-протоколе. А от большинства отечественных поделок вроде QUIK вообще тошнит, если взглянуть внутрь хотя бы тех же SQL таблиц с данными.
Вплоть до конца 2016 года отлично работал NASDAQ UFO… www.nasdaqtrader.com/content/technicalsupport/specifications/TradingProducts/UFO.pdf
Правда, это сильно упрощало работу для HFT, но усложняло для насдака и очень сильно. Видимо, поэтому, они отказались.
Это хорошо — не изучал все биржи, надо было уточнить, что речь про отечественные поделки. Спасибо за ссылку — посмотрю.
Интересная статья, спасибо. Аналогии может и хороши, но их недостаточно, мне — человеку не погруженному в тему RDMA, DPDK,… чтобы понять их суть и пользу. Можно ли попросить дополнить статью ссылками на полезные материалы по указанным технологиям. Вероятно, ссылки от погруженного в тему человека будет полезнее, чем ссылки от поисковой системы.

Я нашел такие ссылки:

Первая статья хороша, интересные рекомендации — Optimizing Computer Applications for Latency: Part 1: Configuring the Hardware.

Возможно, ссылки были в оригинале. Но удалились по каким-то причинам.

И какая технология по опыту даёт наибольшее ускорение для торговых платформ? Если верить аналогиям, то профилирование кода с помощью Intel VTune TM Amplifier и Intel Processor Trace technology с последующим его ускорением (замена обычных работников на Усейнов Болтов) даёт наибольший выигрыш с 5-ти до 2-х минут. Как оно на практике?
Очень интересно по теме пишет cloudflare (сетевая часть):
blog.cloudflare.com/single-rx-queue-kernel-bypass-with-netmap
blog.cloudflare.com/io_submit-the-epoll-alternative-youve-never-heard-about

По программной части интересно рассказывают вот эти докладчики:
www.youtube.com/watch?v=BxfT9fiUsZ4
www.youtube.com/watch?v=MHaZwyhpl-M

Ну и статья на хабре:
habr.com/ru/post/339702 — так же советую посмотреть их код на githab-е, по части solarflare

Есть еще например такая оптимизация. Письма на столе могут лежать неаккуратно и занимать много места. Более того, часть писем лежат в каких-то больших запечатанных конвертах. В этом случае чтобы положить на стол новое письмо надо сначала убрать самое старое с поверхности стола в ящик. Если письмо запечатано в большой красивый дизайнерский конверт, то его приходится оттуда для начала достать. Тут поможет несколько вещей. Во-первых, письма надо складывать поаккуратнее, чтобы большее их количество влезло на поверхность стола. Во-вторых, их стоит доставать из лишних упаковок, чтобы они занимали меньше места и чтоб сотрудникам, которые будут их читать, не требовалось делать это самостоятельно. В-третьих, стоит увеличить поверхность стола по возможности. При этом увеличение количества ящиков в столе не особо поможет. Главное чтобы ящики легко выдвигались. А лучше вообще избежать их использования.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории