Нормалізація даних криптобірж: де рветься потік
Одна й та сама угода на двох майданчиках надходить різними полями. Десь торгова пара — одне поле, десь два незалежні тикери; обсяг — то в базовій валюті, то в котирувальній, а сторона угоди іноді вже зведена до «купівля/продаж», іноді віддається прапором ініціатора.
Різні формати котирувань розходяться найсильніше на мітках часу: одні майданчики віддають мілісекунди, інші — секунди, частина — у локальному поясі замість UTC, а публікація угоди та її потрапляння в потік рознесені в часі.
Якщо агрегувати як є, свічки за один інтервал не збігатимуться між майданчиками, а подія опиниться в чужому вікні.
Далі починається ручне звіряння угод: аналітик зводить вивантаження в таблиці, зіставляє ідентифікатори, перераховує обсяги й вручну розбирає розбіжності у вивантаженнях майданчиків.
На день історії за кількома майданчиками йдуть години, і підсумок усе одно залежить від того, чи помітила людина пропуск.
Найдорожче обходиться втрата історії під час збою. Якщо збирач не фіксує запис до того, як віддати дані далі, падіння процесу залишає діру, а майданчик заднім числом угоди не віддає — прогалина в ряду залишається назавжди й псує будь-які розрахунки на її межі.
Тому нормалізація даних криптобірж будується на вході, а не на етапі звіту — розбираємо, як це закривається.
Що дає єдиний шар нормалізації
Єдиний шар нормалізації приводить усі майданчики до однієї схеми: інструмент, сторона угоди, ціна та обсяг у базовій одиниці, мітка часу в спільному часовому поясі, ознака типу виконання та розбивка часткових закриттів.
Приведення йде на вході, тому аналітика, торгові модулі та звітність читають один і той самий формат котирувань — без окремих перехідників під кожну біржу.
Транспортом слугує Kafka: партиціювання за інструментом зберігає порядок подій, а повторний розбір не руйнує вже записану історію.
Підключення нового майданчика зводиться до конектора та карти полів, а не до перезбирання сховища й правок у коді споживачів.
На практиці це дні роботи замість тижнів: нове джерело піднімається в тестовому контурі, звіряється з еталоном на історичному відрізку й включається в загальний потік.
Автоматичне зведення джерел закриває основну частину записів — від 97 до 99% залежно від майданчика. Спот і деривативи однієї пари зіставляються за інструментом і часом, розбіжності ловляться за контрольними сумами обсягів за хвилину.
Залишок іде в чергу на розбір: це вибіркова перевірка аномалій, а не потік ручних звірянь, які раніше з'їдали час чергової зміни.
Цілісність історії угод тримається на ідемпотентному записі за ключем «майданчик + ідентифікатор угоди» та незмінному лозі сирих відповідей.
Нормалізацію можна переграти заново й отримати той самий результат — це рятує при уточненні правил або додатковому розборі пропущеної ділянки.
Заодно зникає цілий клас помилок: розсинхрон часових поясів, різні позначення однієї пари, втрачені часткові виконання та задвоєні угоди при перезапуску збору.
Способи збору котирувань: порівняння підходів
Біржа не віддає котирування одним способом: свіжість і глибина історії надходять із різних каналів.
Потокова підписка на котирування тримає постійне з'єднання й віддає зміни в міру появи — затримка надходження котирувань вимірюється частками секунди, але буфер каналу обмежений, і при обриві зв'язку пропущений інтервал доводиться добирати окремо.
Пакетні вивантаження історії дають глибину історії угод і повний зріз книги за минулі періоди, зате формуються порціями й помітно відстають від поточного моменту.
Опитування за розкладом займає середину: воно передбачуване й не потребує постійного з'єднання, але на волатильному ринку між двома запитами встигає пройти рух, який у потоці ми побачили б одразу.
| Підхід | Коли підходить | Обмеження |
|---|---|---|
| Потокова підписка на котирування | Онлайн-торгівля, ризик-контроль, вітрини реального часу | Потрібен контроль розривів і довантаження пропусків, кількість одночасних підписок обмежена |
| Опитування за розкладом | Портфельна аналітика, звіти, оповіщення, рідкісні сигнали | Затримка надходження котирувань зростає разом з інтервалом, а часті запити впираються в ліміти біржі |
| Пакетні вивантаження історії | Перевірка стратегій на минулих даних, аудит, розбір інцидентів | Глибина історії угод обмежена вікном вивантаження, дані надходять із запізненням |
Що беремо у зв'язку
Сумісність досягається не вибором одного підходу, а їх зв'язкою: потік тримає гарячий шар і оперативні вітрини, вивантаження доливають історію, опитування страхує на випадок розриву.
Ключова умова — єдина модель інструмента й часу, інакше одна й та сама угода надходить із різних каналів із різними ідентифікаторами й не склеюється.
Етапи впровадження: від аудиту джерел до передачі
Порядок робіт будуємо так, щоб кожне рішення підтверджувалося поведінкою джерела, а не припущенням. Спершу фіксуємо, що майданчики реально віддають, потім збираємо цільову схему й лише після цього пишемо код — інакше переробка обійдеться дорожче, ніж сам розбір.
- Аудит біржових джерел. Розбираємо потоки угод, стакана й вивантаження історії: формати відповідей, частоту оновлення, пагінацію, ліміти запитів, поведінку при обриві з'єднання. Окремо позначаємо джерела, які віддають дані із затримкою або перераховують заднім числом.
- Карта розбіжностей. Зводимо в одну таблицю відмінності майданчиків: ідентифікатори інструментів, точність ціни й обсягу, часові пояси та мітки часу, позначення сторони угоди. Вона ж стає робочим документом при додаванні нової біржі.
- Правила зведення записів. Описуємо єдину схему події: ключ, приведення символів, округлення, розмітку дублів і перевідкриттів. Правила версіонуємо — правка не ламає вже зібрані набори даних.
- Збірка. Реалізуємо приймання, нормалізацію й запис у сховище з ідемпотентною обробкою: повторний запуск не створює дублів, пропуск закривається добором історії.
- Перевірка на історичних даних. Проганяємо правила на накопиченому архіві: звіряємо кількість подій та обсяги, стики при перезапуску, відновлення після пропусків. Кожну розбіжність розбираємо до причини, а не згладжуємо фільтром.
- Передача системи замовнику. Віддаємо конфігурації, схему зберігання, регламент контролю якості даних і порядок дій при збої джерела, навчаємо команду. Після передачі система працює й розвивається силами замовника — наша підтримка залишається опцією, а не умовою.
Що передаємо на руки: конфігурації та регламенти
Передаємо не лише робочий контур, а й комплект, за яким його можна розвивати без нас. Кожен артефакт прив'язаний до конкретної операції: підключити нову біржу, розібрати розбіжність у свічці, змінити відповідального або зрозуміти, чому джерело відвалилося вночі.
- Конфігурації підключень — за кожною біржею: перелік торгових пар і потоків, ліміти звернень, схема перепідключення, поведінка при розсинхроні та пропуску повідомлень.
- Схема нормалізації — єдина модель інструмента й події угоди, правила приведення тикерів і позначок часу до однієї шкали, обробка перейменувань і дроблень.
- Довідники відповідностей — таблиці між біржовими та внутрішніми ідентифікаторами й порядок додавання нового джерела без правки коду.
- Правила доступу — ролі на читання даних, зміну мапінгу та конфігурацій; журнал змін, щоб кожне втручання було пояснюваним.
- Регламент супроводу — реакція на новий лістинг, зміну формату й відключення джерела, періодичність звірянь, точки ескалації.
- Документація системи — архітектурна схема, опис потоків даних, чек-ліст підключення біржі та список відомих обмежень.
- Приймальний набір — тестові події з очікуваним результатом нормалізації, щоб розбіжності ловилися перевіркою, а не через тижні після запуску.
Окремо фіксуємо, що залишається на вашому боці: ключі доступу, контакти з біржами, політика зберігання історії.
Кейс: консолідація котирувань із чотирьох майданчиків
Клієнт — фонд алгоритмічної торгівлі на чотирьох майданчиках, включно з Bybit. Кожна віддавала угоди й стакан у своєму вигляді: час у секундах і мілісекундах, у частини майданчиків — локальний, без зсуву, а один і той самий інструмент писався як BTC/USDT, BTCUSDT і XBTUSD.
Звіряння йшло вручну: аналітик збирав вивантаження в таблиці й знаходив розбіжності вже в готовому звіті — за обсягами, часом і пропущеними інтервалами. Один торговий день займав близько шести годин, і на цьому обсязі губилися рідкісні, але значущі аномалії.
| Метрика | До | Після |
|---|---|---|
| Частка автоматично зведених записів | 63% | 99,4% |
| Час підготовки звіту за день | 5-6 годин ручного звіряння | 9 хвилин |
| Розбіжності на 10 000 угод | близько 430 | поодинокі, кожне пояснюване |
Основою стала єдина модель даних: час приводиться до UTC, інструменти — до спільного довідника з перерахунком позначень, угоди дедуплікуються за ідентифікатором майданчика, снепшот стакана склеюється з наступними змінами. Кожен запис зберігає джерело, тому розбіжність розбирається до вихідного повідомлення.
Перевірки на розриви й розсинхрон виконуються на вході, а не у звіті: запис із неповним ланцюжком подій позначається й іде в окрему чергу на розбір. Звіт формується за розкладом, і ручне звіряння перетворилося з обов'язкового етапу на виняток.
Що робити, якщо в біржі вже є свій канал постачання?
Ламати робочий канал не потрібно. Якщо в біржі вже є свій канал постачання котирувань, він стає ще одним приймачем у загальній схемі: нормалізувальний шар ставиться поверх нього й приводить потік до єдиного вигляду, а не підміняє джерело.
Технічно це виглядає так: приймач читає те, що вже віддає наявний контур — потокове з'єднання, файли вивантажень або FIX, — і публікує події у внутрішню модель.
У ній у кожної події зафіксовано інструмент, тип, мітку часу з точністю до джерела та ознаку походження, тому розрахунковий модуль, архів і вітрина не знають і не повинні знати, з якого каналу надійшли дані.
Далі починається співіснування двох контурів і поступова міграція джерел. Новий контур і самописне рішення йдуть паралельно: розбіжності за обсягом і за цінами рахуються автоматично, і джерело перемикається на нормалізовану гілку лише після підтвердженої збіжності. Порядок — по одному джерелу за раз, з можливістю повернути попередній маршрут без зупинки збору.
Відмова від самописного рішення відбувається не «за один день», а в міру перекриття джерел: спочатку з нього знімається запис і він залишається в режимі читання для звірянь, потім вимикається.
Так вбудовування в наявну схему не перетворюється на разовий ризикований переїзд — ціну помилки платить одне джерело, а не весь збір котирувань.
Технічні сумніви: розбір частих запитань
Майданчики змінюють схеми відповідей без анонсів: поле перейменували, вкладеність зсунули, число перетворили на рядок. Ламається не приймання, а розбір — і далі розходиться все: ордери, угоди, свічки, свічкові агрегати.
Тому контракт на вхід описуємо декларативно: схема, типи полів, обов'язковість, правила приведення. Розбіжності йдуть у карантин, а не в основну вітрину. Нижче — запитання, які найчастіше ставлять інженери замовника.
Майданчик змінив формат відповіді — вітрина поїде?
Мапінг полів живе окремим шаром конфігурації, а не в коді обробки. Нова схема підключається як нова версія, стара залишається доступною для звіряння.
Поки потік не пройде перевірку на еталонній вибірці реальних відповідей, він іде в карантин — розбіжності видно, але дані споживачів не псуються.
Як вирівнюєте мітки часу різних майданчиків?
Зберігаємо два значення: час події за годинником майданчика та час приймання в нас. Мітки приводимо до єдиного часового поясу, розбираємо цілі секунди, мілі- й мікросекунди, окремо рахуємо та компенсуємо мережеву затримку. Свічки, зібрані з різних джерел, після цього не розходяться між собою.
Що станеться при відмові джерела або розриві зв'язку?
Перепідключення з наростаючою паузою, паралельно резервний транспорт опитування та буфер на диску, щоб не втратити пропущений інтервал. Повтори гасяться за ключем запису, тому дублікати не накопичуються. Пропуск фіксується у звіті про повноту, а не залишається непоміченим.
Підключаєте нове джерело й переобробляєте історію?
Адаптер джерела збирається за загальним контрактом, окремо описується довідник інструментів і правила зіставлення тикерів.
Історія довантажується порціями з перевіркою контрольних сум, запис ідемпотентний — повторний прогін за той самий період не створює дублів і сходиться з вихідними даними.
Обговоримо ваше завдання й повернемося з планом
Щоб обговорити завдання нормалізації предметно, на вході потрібен перелік джерел котирувань і поточна схема доставки даних.
Чим конкретніший список майданчиків, інструментів і потрібних типів повідомлень, тим точніша оцінка складу робіт — без припущень, які потім перетворюються на переробки. Надішліть те, що є: чернетку, таблицю зіставлення полів, фрагмент конфігурації.
Далі розбираємо за пунктами:
- Перелік джерел котирувань — майданчики, кількість інструментів, чи потрібні угоди, стакани, індекси та мітки часу.
- Поточна схема отримання — пряме підключення, сторонній агрегатор, вивантаження, наявність історичних архівів.
- Цільовий формат і споживачі — куди віддаємо дані та які поля обов'язкові для торгової системи, аналітики або сховища.
- Вимоги до затримки й повноти — допустиме відставання котирувань, глибина історії, поведінка при розриві з'єднання.
- Особливості інструментів — нестандартні тикери, різні кроки ціни та розміри лота, правила округлення на кожному майданчику.
- Що вже працює — схеми таблиць, черги, власні скрипти нормалізації: збережемо те, що не заважає, і не будемо ламати робочий потік.
- Обмеження й строки — доступи, перевірки на вашому боці, дата введення в експлуатацію, хто приймає результат.
Після розбору повернемося з оцінкою складу робіт, планом впровадження та строками за етапами, з точками приймання на кожному.







