REST API для історичних ринкових даних: розробка під ключ

Історія угод потрібна аналітиці, звітності та перевіркам, але з відкритих джерел вона надходить із прогалинами й затримками. Ми розробляємо REST API для вивантаження історичних ринкових даних під ключ: від аудиту джерел до передачі готової специфікації. Віддача прискорюється в рази, а прогалини в глибині історії закриває регламент регулярних перевірок.
Часті запитання

REST API розробка історичних даних: де губиться історія

Сервіс історичних ринкових даних ламається не тоді, коли падає, а коли відповідає кодом успіху з неповним тілом. Клієнт запитує діапазон свічок, отримує коректну відповідь і будує на ній розрахунок — а всередині діапазону бракує кількох інтервалів.

Такі прогалини в котируваннях не видно в логах: ні збою, ні затримки, просто історія коротша за заявлену.

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

Якщо сторінки склеюються без перевірки безперервності, на стиках з’являються діри, а часовий пояс і округлення мітки добивають картину: свічка формально є, але стоїть не на своєму місці.

Ціна для продукту — не косметика. Бектест на рваній історії показує дохідність, якої не було, індикатори рахуються за неповним вікном, звіт розходиться з графіком. Далі руйнується довіра до аналітики, і відновити його дорожче, ніж полагодити віддачу.

Розбираємо, як це закривається в REST API розробці під історичні ринкові дані: контракт на діапазон і точність мітки, перевірка цілісності історії на вході, ідемпотентне довантаження пропущеного, кеш під повторні запити й режим віддачі, який не залежить від лімітів запитів зовнішнього джерела.

Що дає вивантаження історії: повнота, швидкість, стійкість

Повнота історії — перше, що перевіряють на прийманні. Раніше котирування бралися з одного джерела, і на тонких інструментах в архіві залишалися прогалини.

Тепер вивантаження котирувань іде з кількох джерел, ряди приводяться до єдиної схеми, а пробіли закриваються повторним запитом — звіт про якість показує, які ділянки підтверджені незалежно, а які відновлені.

Швидкість відклику тримається на попередньо порахованих вітринах: типовий запит діапазону віддається за частки секунди, важкі вибірки йдуть в асинхронну підготовку файлу з повідомленням про готовність. 95-й перцентиль часу відповіді більше не залежить від того, за скільки років запрошено історію.

Стійкість сервісу дають кеш, обмеження частоти звернень до джерел і повторні спроби з наростаючою паузою. Якщо зовнішнє джерело недоступне, віддається остання узгоджена версія ряду, а не помилка — термінал і аналітика продовжують працювати. Незалежною перевіркою слугує звірка з публічними агрегаторами, наприклад CoinMarketCap.

Ручні правки прогалин пішли з процесу аналітиків: розходження між джерелами потрапляють у звіт, а не в графік. Замовники у відгуках відзначають саме це — «архів перестав бути окремою задачею: дані за потрібний період готові до початку торгового дня, а не до його середини».

REST API розробка: варіанти віддачі історії та обмеження

Одну й ту саму історію котирувань можна віддавати чотирма способами, і вибір диктує профіль споживача: сервісу перевірки стратегій потрібен весь масив одразу, торговому роботу — безперервний потік, аналітику — довільний зріз за інструментами й періодами.

Ми розводимо ці сценарії за окремими контурами: потокова підписка не конкурує за з’єднання з пакетним вивантаженням, а важкі зрізи йдуть на репліку сховища й не гальмують запис нових даних. Різниця між режимами не в зручності, а в тому, які обмеження ви приймаєте разом із ними.

Чотири режими та їхні межі

Режим Коли підходить Обмеження
Посторінкова вибірка Інтеграції, звіти, добір пропущених інтервалів Кількість запитів зростає з глибиною історії; під час рестарту потрібен курсор, інакше отримаєте повтори або діри
Пакетне вивантаження Первинне завантаження, перевірка стратегій, відновлення архіву Дані відстають від поточного моменту; розкласти файл за своєю схемою доведеться на боці споживача
Потокова підписка Онлайн-котирування, ризик-моніторинг, розрахунок індикаторів на льоту Віддає лише «з цього моменту»; після розриву з’єднання потрібен догін через історичний запит
Пряма вибірка зі сховища Аналітика, довільні зрізи, звірка даних Лише читання й окрема копія; схема фіксована, будь-які зміни — через погодження

Обмеження — властивість режиму, а не дефект: потік не віддає глибину, файл не наздоганяє реальний час, репліка не пише. Тому в описі API ми фіксуємо межі кожного режиму й правила переходу між ними — догін після розриву, курсор під час рестарту, звірку даних між копіями.

Від аудиту джерел до передачі: етапи інженерної роботи

Проєкт починається не з коду, а з розбору того, звідки надходять дані. Біржові вивантаження, агрегатори й внутрішні архіви відрізняються гранулярністю, таймзоною та правилами ревізії — уже тут видно, які ряди доведеться зрощувати, а які можна віддавати як є.

  1. Аудит джерел даних. Дивимося формати вивантажень, глибину історії, обмеження на частоту запитів і поведінку майданчика під час збоїв. На виході — перелік джерел із позначками, де очікуються розриви й дублікати.
  2. Проєктування схеми даних. Фіксуємо сутності (угоди, свічки, стакан), таймзони, точність округлення та правила зрощування рядів. Схема стає контрактом: за нею будується і сховище, і структура відповідей API.
  3. Реалізація. Збираємо шар завантаження з повторними спробами та ідемпотентним записом, щоб повторний імпорт не плодив дублікати, і шар віддачі — з курсорною пагінацією та передбачуваними кодами помилок.
  4. Перевірка на еталонному наборі. Невеликий відрізок історії розмічаємо вручну й звіряємо з джерелом до останнього запису. Розходження ловимо до того, як вони поїдуть в аналітику.
  5. Приймальна перевірка. Проганяємо сценарії замовника: рідкісні інструменти, межі періодів, пікові навантаження. Фіксуємо, що віддача вкладається в обумовлені строки й не втрачає записи.
  6. Передача й спостереження. Віддаємо опис схеми, конфігурацію та порядок розгортання, а після запуску стежимо за свіжістю даних і затримкою відповіді.

Порядок не випадковий: кожен крок спирається на артефакт попереднього — перелік джерел, схему, еталон. Тому приймання закривається до передачі, а не після.

Що залишається у вас: специфікація, схеми, регламенти

Сервіс історичних ринкових даних живе довше, ніж команда, яка його запустила: за півроку його розвиватиме інша зміна інженерів — або ваша, без авторів під рукою.

Тому працюючий інтерфейс ми передаємо разом із пакетом артефактів, за якими сервіс можна підтримувати, не відновлюючи логіку за кодом.

  • Специфікація інтерфейсу — методи, параметри, формати відповідей, коди помилок і ліміти звернень у машинозчитуваному вигляді: з неї генеруються клієнти й тести.
  • Схема даних — таблиці, ключі, типи, індекси та правила зберігання історії; за нею видно, чому вибірка за діапазоном дат залишається швидкою на зростаючому обсязі.
  • Регламент оновлення — розклад завантаження, вікно довантаження пропущених періодів, перевірка цілісності та звірка з джерелом.
  • Політика доступу — ролі та області видимості, строки життя ключів, квоти на споживача, журнал звернень і порядок відкликання доступу.
  • Документація для команди — локальний запуск, змінні середовища, міграції, метрики, чек-лист релізу й порядок відкату.
  • Автотести та еталонні приклади запитів — фіксують очікувану поведінку, щоб правки в розборі історичних даних ловилися до викату.
  • Інструкція на випадок збою — що робити при пропусках або повільних відповідях джерела, як переключитися на резервний потік і чим підтвердити відновлення.

Практика: як закрили діри в історії та прискорили віддачу

Проєкт — агрегатор біржових даних: сервіс REST API віддавав історичні свічки й угоди для аналітики та торгових роботів.

На вході за окремі періоди бракувало до 3% хвилинних свічок, а збирання річного набору за інструментом займало близько сорока хвилин — клієнти витягували історію посторінково й часто обривалися на часі очікування.

Відновлення історії

Репліки знімалися з кількох джерел, кожна угода зводилася до первинного ключа «інструмент + мітка часу», розходження розбиралися правилом пріоритету джерела. Пропущені інтервали добиралися з архівних дампів і логів, агрегати за спірні вікна перераховувалися заново.

Після прогону повнота хвилинного ряду вийшла на 100%, а розходження між джерелами впали до часток відсотка.

Пікове навантаження та віддача

Під піком сервіс раніше ріс у затримці: черга запитів накопичувалася, частина клієнтів не дочікувалася відповіді на довгих діапазонах. Гарячі діапазони ми винесли в колонкове сховище ClickHouse, попередньо розрахували тижневі й місячні агрегати та обмежили розмір сторінки.

На піку в двадцять разів вищому за звичайний віддача тримається рівно, збирання річного набору скоротилося до хвилини.

Результат проєкту: історія без пропусків, віддача під піком без обривів, документовані правила зведення джерел і повторюваний прогін відновлення за розкладом.

Чим вивантаження історії відрізняється від потоку реального часу

Архівне вивантаження в REST-інтерфейсі відповідає на запит за діапазоном: клієнт передає інтервал часу та ідентифікатор інструмента, сервіс віддає сторінку записів із курсором на наступну.

Результат детермінований — повтор із тим самим курсором повертає ті самі рядки, тому обрив зв’язку лікується повторним запитом, а не відновленням підписки.

Потік реального часу влаштований інакше: підписка живе в постійному з’єднанні, і кожен запис доставляється один раз. Збій тут сам не повторюється — втрачене повідомлення довантажують із журналу за міткою останнього прийнятого запису, інакше в історії залишається діра.

Затримка віддачі в потоці вимірюється хвостом розподілу, а не середнім: рідкісні сплески на піку обсягу споживач помічає одразу.

Звідси різні вимоги до зберігання. Архіву потрібен повний масив, розбитий за датами, з індексом за ключем і часом — він зростає монотонно, тому його виводять у холодний контур, де читання дорожче за запис.

Потоку достатньо короткого гарячого буфера, але буфер зобов’язаний переживати перезапуск вузла: без журналу на диску підписка після падіння втрачає вікно, яке з джерела вже не підняти.

Довантаження змін — окремий контур. В архівному вивантаженні вікно навмисно перекривають на кілька інтервалів і звіряють краї діапазону, щоб не втратити записи на межі. У потоці довантаження йде за курсором з ідемпотентним ключем запису: дублі відсікаються, пропуски закриваються.

І там, і там контрольні суми — кількість записів і крайні мітки часу — звіряють регулярно, інакше розходження спливе вже у звітності замовника.

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

Проєктування починається з питання, що робити під час розриву — перегравати діапазон чи довантажувати за курсором. Від відповіді залежить і схема зберігання, і те, як виглядатиме звірка даних.

Технічні сумніви перед стартом робіт

Збої та краї даних інженерні команди перевіряють до старту — і питання у всіх приблизно одні: пропуски, поведінка при відмові джерела, межі історії, звірка та вивантаження. Нижче прямі відповіді, без обіцянок «усе буде стабільно».

Що робити з пропусками в історичних даних джерела?

Пропуск не заповнюємо мовчки: він позначається явною ознакою повноти у відповіді, а не зникає між сусідніми точками. Діапазон із пробілом можна перезапросити — повторне довантаження ідемпотентне, дублі не з’являються.

Окремий ендпоінт віддає карту покриття за інструментами й періодами, щоб споживач бачив межі достовірності заздалегідь.

Що станеться, якщо джерело перестане відповідати?

Віддаємо останній підтверджений зріз разом із часом його актуальності та ознакою застарівання. Споживач сам вирішує, працювати з цими даними чи чекати — замість порожньої відповіді й розбору помилки на своєму боці.

Чи можна розширити глибину історії пізніше?

Так, бекфіл іде діапазонами й порціями, контракт відповіді не змінюється — розширення не ламає вже написаних клієнтів. Нові та раніше завантажені ділянки звіряються на стиках, щоб на межі не з’явилося подвійних або роз’їханих значень.

Як перевіряється, що дані збігаються з джерелом?

Звірка йде за контрольними сумами зрізів за вибіркові періоди; розходження потрапляють у звіт, а не розчиняються в логах. Це дає відтворюваність: те саме вікно, запитане повторно, повертає той самий результат.

Ми можемо забрати своє вивантаження?

Вивантаження віддається потоком у файл за тією ж схемою полів, що й у REST-відповідях, — дані переносні й не замкнені всередині сервісу. Формат обираємо під ваш конвеєр обробки.

Далі — обговорення: опишіть задачу, повернемося з оцінкою та планом.

Обговоримо задачу та повернемося з оцінкою й планом

Перша розмова потрібна не для знайомства, а щоб зафіксувати межі робіт: без розуміння глибини історії, набору інструментів і допустимої затримки актуалізації оцінка перетворюється на вилку, а схема даних — на переробку в середині проєкту. Тому уточнюємо те, від чого напряму залежить обсяг робіт.

  • Глибина історії та джерела: біржові стрічки, вендорські архіви, власні вивантаження — за який період потрібні дані й де можливі пропуски.
  • Склад даних: тики чи агреговані свічки, інтервали, перелік інструментів і майданчиків, чи потрібне коригування котирувань на спліти й дивіденди.
  • Вимоги до якості: повнота рядів, точність до знака, єдина часова зона, правила розв’язання розходжень між джерелами та відсів дублів.
  • Формат відповіді та навігація за обсягом: JSON, CSV або Parquet; посторінкова видача, курсори, фільтри за діапазоном дат і інструментом.
  • Навантаження та доступи: скільки одночасних запитів витримує споживач, чи потрібні ключі, розподіл прав і обмеження частоти звернень.
  • Актуалізація та стійкість: як часто довантажуємо нові дані, за який час закриваємо пропуск в архіві, що бачить клієнт при відмові джерела.
  • Приймання: на яких наборах звіряємо видачу з еталоном і яку частку запитів вважаємо такою, що вклалася в цільовий час відповіді.

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

Напрямки блокчейн-розробки

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1369
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    816
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1142