Комментарии 14
Исполнение сделки в реалиях откладывается на потом, и зависит от способа реализации их исполнения, в момент подачи ордера или же параллельно по стакану гуляет специальный сервис (в этом случае встречные сделки в стакане временно могут иметь пересечения).
Ожидал от статьи внутренности этого процесса, разделение сделок на микротранзакции, способ хранения собственно списка лимитных сделок, использование нестандартного железа и прочее прочее.
p.s. просто от балды, без какого либо опыта и использования готовых библиотек, писал на php сервер торговой биржи (однопоточный) с подключением клиентов по websocket (react php) и получал десятки тысяч сделок в секунду от сотни 'тестовых клиентов' на слабом десктопном железе (там все сильно зависело, сколько встречных заявок затрагивает ордер, но реалии таковы что обычно таких единицы максимум десятки, никто не 'торгует широко', так как это увеличивает неопределенность, гораздо выгоднее и проще строить свои стратегии, дробя свои объемы как раз по структуре стакана).
По поводу ощущений от статьи — действительно пара унылых аналогий без каких либо подробностей.
По поводу выполнения заявок — ваша информация сильно устарела, либо вы путаете биржу с брокером, либо классическую биржу с биржей криптовалюты.
При определённых усилиях можно поставить заявку за <= 100us. Про то как приходит информация, у вас и вовсе крайне примитивное понимание. На самом деле в 99% случаев имеет место rpc протокол, который поддерживает слепок рыночного состояния на машинах клиентов командами вида add/delete/change. Время отклика разное у разных торговых систем, но у самих биржевых движков, исключая всяких паразитических сущностей типа брокера, это обычно не больше десятков микросекунд.
remote procedure call и локальный слепок рыночного состояния на машинах, вы о чем вообще? биржа никаким боком не занимается клиентскими машинами, она дает только поток сырых данных по своему протоколу или по фикс.
Я имел в виду именно биржу а не посредника. Конечно, я не знаком на практике с современными движками, но я уже несколько лет 'пристально' изучаю криптовалютные биржи, так как они банально доступнее тех двух-трех единственных, существующих сейчас в большом мире денег.
Вот вам ваши add remove change:
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}]}
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»}
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»,[]]]}}
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]]
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 и вещаются через мультикаст.
Про крипто биржи даже врать не буду, не знаю, последние мои взгляды в ту сторону показывали какие-то унылые джейсоны и задержи по пол-секунды ибо интернет и прочие мегаоптимизации, есть тут как минимум один такой оптимизатор на хабре.
Некоторые биржи в криптовалютах 'третьего эшелона' написаны на столько криворукими разработчиками что лагают и тормозят на секунды и даже минуты (тот же yobit, 'не к столу будет сказано'), так будто внутри у них ядро на sql с блокировками на обычных десктопных машинах ;)
p.s. особенности ДОСТАВКИ данных до клиента никаким образом не связаны с тем как именно данные обрабатываются внутри биржи.
Меня немного интересует, популярно, как именно внутри высокоскоростной бирже реализовано торговое ядро, способное обрабатывать очень большое количество транзакций с минимальной задержкой как на прием заявок так на их исполнение.
Так то — 10 лет назад на плюсах писали что бы уместится в железках, и в идеале, ещё и отмасштабироваться через n лет. А сейчас, что бы с умным видом смузи хлебнуть.
Правда, это сильно упрощало работу для HFT, но усложняло для насдака и очень сильно. Видимо, поэтому, они отказались.
Я нашел такие ссылки:
- kernel bypass, DPDK (Data Plane Development Kit) — Введение в DPDK: архитектура и принцип работы / Блог компании Selectel / Хабр
- RDMA — Удалённый прямой доступ к памяти / wikipedia
- FPGA — Программируемая пользователем вентильная матрица / wikipedia
Первая статья хороша, интересные рекомендации — Optimizing Computer Applications for Latency: Part 1: Configuring the Hardware.
Возможно, ссылки были в оригинале. Но удалились по каким-то причинам.
И какая технология по опыту даёт наибольшее ускорение для торговых платформ? Если верить аналогиям, то профилирование кода с помощью Intel VTune TM Amplifier и Intel Processor Trace technology с последующим его ускорением (замена обычных работников на Усейнов Болтов) даёт наибольший выигрыш с 5-ти до 2-х минут. Как оно на практике?
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
Есть еще например такая оптимизация. Письма на столе могут лежать неаккуратно и занимать много места. Более того, часть писем лежат в каких-то больших запечатанных конвертах. В этом случае чтобы положить на стол новое письмо надо сначала убрать самое старое с поверхности стола в ящик. Если письмо запечатано в большой красивый дизайнерский конверт, то его приходится оттуда для начала достать. Тут поможет несколько вещей. Во-первых, письма надо складывать поаккуратнее, чтобы большее их количество влезло на поверхность стола. Во-вторых, их стоит доставать из лишних упаковок, чтобы они занимали меньше места и чтоб сотрудникам, которые будут их читать, не требовалось делать это самостоятельно. В-третьих, стоит увеличить поверхность стола по возможности. При этом увеличение количества ящиков в столе не особо поможет. Главное чтобы ящики легко выдвигались. А лучше вообще избежать их использования.
Производительность торговой платформы на простом примере