Your Trading Bot's Biggest Bottleneck Is the API Layer
By @CoinMarketMan - 14-Jul-2026
Найбільший вузьке місце вашого торгового бота — це API-шар
Ви тижнями вдосконалюєте рушій сигналів. Дивергенція когорт, оцінка ризику ліквідації, екстремальні ставки фінансування. Бектест виглядає точно. Потім ви розгортаєте бота, і вже за 48 годин він пропускає три угоди, бо цикл опитування даних наштовхнувся на ліміт запитів і тихо повертав застарілі дані двадцять хвилин. Сигнал був правильним. Архітектура навколо нього — ні.
Це найпоширеніша причина збоїв у торгових ботах на Hyperliquid, і вона майже не пов'язана з генерацією альфи. Шар приймання даних — частина, яка з'єднує вашого бота з ринком через API-виклики, — саме тут ламається більшість ботів. Надлишкове опитування, марнотратний вибір ендпоінтів, відсутність кешування, відсутність відступу, відсутність розуміння того, коли дані насправді оновлюються. Розробники оптимізують сигнал і ставляться до API-шару як до сантехніки. Але сантехніка, що протікає, зруйнує будинок, незалежно від того, наскільки гарним виглядає проект.
Цей посібник присвячений правильному проектуванню цього шару з самого початку — зокрема для ботів, що використовують аналітичний API HyperTracker на Hyperliquid.
Чому шар даних важливіший за сигнал
Рушій сигналів — це чиста функція. Однакові вхідні дані, однаковий результат, щоразу. Якщо ви подаєте йому чисті дані з надійною регулярністю, він видає чисті рішення. Якщо ви подаєте йому застарілі дані, дубльовані дані або дані іншої форми, ніж очікувалося, бо ендпоінт повернув помилку, яку ваш код проковтнув мовчки, — рушій сигналів не зможе виправити ситуацію. Він видаватиме впевнені рішення на основі інформації, яка вже не відображає стан ринку.
Шар даних знаходиться між вашим ботом і кожним фрагментом ринкової аналітики, на якому той діє. На Hyperliquid наші дані оновлюються з ковзними інтервалами: знімки стану кожні 15–20 хвилин і знімки потоку ордерів у п'ятихвилинних вікнах. Це означає, що ваша частота опитування, логіка кешування та обробка помилок повинні бути спроектовані навколо цих конкретних ритмів оновлення. Опитування частіше, ніж оновлюються дані, витрачає ваш ліміт запитів. Опитування рідше означає, що ви пропускаєте вікна сигналів.
Узгодження частоти опитування з оновленням даних
Найбільш марна річ, яку може робити бот, — це опитувати ендпоінт частіше, ніж змінюються базові дані. Якщо метрики когорт оновлюються кожні 15–20 хвилин, а ваш бот опитує кожні 60 секунд, п'ятнадцять із шістнадцяти викликів повертають ідентичні дані. Ви витрачаєте ліміт, додаєте затримку до циклу подій і нічого не отримуєте.
Розклад оновлень, навколо якого слід проектувати
API HyperTracker має різні частоти оновлення залежно від категорії ендпоінта:
| Категорія ендпоінта | Частота оновлення | Рекомендований інтервал опитування |
| --- | --- | --- |
| Метрики когорт (/cohort-metrics) | ~15–20 хв | Кожні 5 хв (вчасно підхоплює оновлення) |
| Знімки потоку ордерів (/orders) | Ковзні 5-хв вікна | Кожні 5 хв (вирівняно з вікном) |
| Ризик ліквідації (/liq-risk) | ~15–20 хв | Кожні 5 хв |
| Метрики позицій (/position-metrics) | ~15–20 хв | Кожні 5 хв |
| Таблиці лідерів (/leaderboard) | ~15–20 хв | Кожні 15–30 хв (менш чутливо до часу) |
Рекомендований інтервал опитування 5 хвилин для більшості ендпоінтів — це баланс. Ви хочете підхоплювати свіжі дані швидко після оновлення, але не знаєте точної секунди, коли вони оновляться в межах вікна 15–20 хвилин. Опитування кожні 5 хвилин означає, що ви отримаєте новий знімок протягом 5 хвилин після його появи, що достатньо швидко для стратегій, що працюють на таймфреймах 1 година і більше.
Проектування бюджету запитів
Кожен тарифний план має місячний ліміт запитів і ліміт на хвилину. Архітектура вашого бота повинна враховувати обидва, а обмеження відрізняються залежно від вашого плану.
| Тариф | Запитів на місяць | Ліміт | Ефективний бюджет на день | | --- | --- | --- | --- | | Pulse ($179/mo) | 50 000 | 60/хв | ~1 667 запитів | | Surge ($399/mo) | 150 000 | 100/хв | ~5 000 запитів | | Flow ($799/mo) | 400 000 | 200/хв | ~13 333 запитів | | Stream ($1,999/mo) | 2 000 000 | 500/хв | ~66 667 запитів |
Бот на тарифі Pulse, що опитує 4 ендпоінти кожні 5 хвилин, використовує 4 x 288 = 1 152 запити на день. Це залишає 515 запитів для разових запитів, дозаповнення або другого циклу опитування для додаткових активів. Є запас, але він стає тісним, якщо додати більше ендпоінтів або активів без планування.
На тарифі Surge той самий цикл із 4 ендпоінтами і 5-хвилинним інтервалом використовує ті ж 1 152 запити, але ваш денний бюджет — ~5 000, тож можна моніторити кілька активів або додати другий, швидший цикл для потоку ордерів по основному активу. Головне: змоделюйте бюджет до того, як писати код опитування, бо вносити усвідомлення лімітів запитів у бота, побудованого без цього, боляче.
Патерн таблиці бюджету запитів
До написання будь-якого коду опитування накидайте таку таблицю:
Ендпоінт | Активи | Інтервал | Викликів/день
-------------------+--------+----------+----------
/cohort-metrics | 3 | 5 хв | 864
/orders | 1 | 5 хв | 288
/liq-risk | 3 | 5 хв | 864
/position-metrics | 1 | 15 хв | 96
-------------------+--------+----------+----------
Всього | | | 2 112
Бюджет (Pulse) | | | 1 667 <- ПЕРЕВИЩЕНО
Виправлення: перевести /liq-risk на 15-хв інтервал:
/liq-risk | 3 | 15 хв | 288
Нове всього | | | 1 536 <- ОК
Це проста арифметична вправа, але більшість розробників її пропускають і виявляють, що перевищили бюджет, коли бот починає повертати помилки 429 у продакшені. Спершу моделюйте, потім будуйте.
Кешування: шар, який більшість ботів пропускає
Ваш бот повинен підтримувати локальне сховище даних (навіть простий словник у пам'яті), що зберігає найсвіжішу відповідь від кожного ендпоінта, який він опитує. Це слугує трьом цілям.
По-перше, дедублікація. Якщо ви опитуєте /cohort-metrics кожні 5 хвилин, але дані оновлюються кожні 15–20 хвилин, три з чотирьох опитувань повернуть ідентичні дані. Ваш кеш повинен порівнювати вхідну відповідь зі збереженою версією і передавати її в рушій сигналів лише якщо щось справді змінилося. Це запобігає повторному оцінюванню сигналів на застарілих даних і генерації зайвого шуму в логах.
По-друге, виявлення застарілості. Додайте позначку часу до кожного запису кешу. Якщо кеш для певного ендпоінта не оновлювався довше, ніж вдвічі перевищує очікуваний інтервал оновлення (наприклад, 40 хвилин для 20-хвилинного оновлення), щось пішло не так. Або API недоступний, або мережа нестабільна, або цикл подій вашого бота завис. Сповіщення про застарілість ініціює розслідування до того, як бот торгуватиме на даних, яким може бути година.
По-третє, витончена деградація. Якщо опитування зазнає невдачі (мережева помилка, 500, ліміт запитів), кеш все одно зберігає попередню успішну відповідь. Ваш бот може продовжувати роботу на цих даних із явним розумінням, що діє на застарілій інформації. Це розуміння важливе: бот, що торгує на свідомо застарілих даних, може зменшити розміри позицій або розширити стопи. Бот, який не знає, що його дані застаріли, не може адаптуватися.
class DataCache:
def __init__(self, stale_threshold_seconds=2400):
self.store = {}
self.stale_threshold = stale_threshold_seconds
def update(self, endpoint, data):
prev = self.store.get(endpoint)
changed = prev is None or prev["data"] != data
self.store[endpoint] = {
"data": data,
"fetched_at": time.time(),
"changed": changed,
}
return changed
def get(self, endpoint):
entry = self.store.get(endpoint)
if entry is None:
return None, True # no data, considered stale
age = time.time() - entry["fetched_at"]
return entry["data"], age > self.stale_threshold
def is_stale(self, endpoint):
_, stale = self.get(endpoint)
return stale
Обробка помилок і відступ
API-виклики зазнають невдач. Мережа переривається. Ліміти запитів вичерпуються. Питання в тому, чи обробляє ваш бот ці збої витончено, чи падає, повторює запити агресивно (спалюючи ще більше ліміту) або, що гірше, мовчки продовжує роботу без даних.
Три режими збою
Ліміт запитів (HTTP 429). API каже вам сповільнитися. Правильна реакція — експоненціальний відступ: чекайте 1 секунду, потім 2, потім 4, потім 8, з обмеженням у 60 секунд. Не повторюйте запит негайно. Не повторюйте з фіксованим інтервалом у 1 секунду. Кожен негайний повтор, коли ви вже перевищили ліміт, поглиблює проблему.
Помилка сервера (HTTP 5xx). Щось пішло не так на стороні API. Повторіть із відступом, до 3 спроб. Якщо всі 3 зазнають невдачі, залогуйте помилку, позначте запис кешу як потенційно застарілий і рухайтеся далі. Не блокуйте весь цикл подій в очікуванні відновлення.
Помилка клієнта (HTTP 4xx, не 429). Ваш запит сформовано неправильно. Повтор не допоможе. Залогуйте помилку з повним навантаженням запиту для налагодження і пропустіть цей цикл опитування.
async def poll_with_backoff(endpoint, params, max_retries=3):
for attempt in range(max_retries):
try:
response = await fetch(endpoint, params)
if response.status == 200:
return response.json()
elif response.status == 429:
wait = min(2 ** attempt, 60)
logger.warning(f"Rate limited on {endpoint}, waiting {wait}s")
await asyncio.sleep(wait)
elif response.status >= 500:
wait = min(2 ** attempt, 30)
logger.warning(f"Server error {response.status} on {endpoint}")
await asyncio.sleep(wait)
else:
logger.error(f"Client error {response.status} on {endpoint}")
return None
except NetworkError as e:
logger.error(f"Network error on {endpoint}: {e}")
await asyncio.sleep(min(2 ** attempt, 30))
logger.error(f"All retries exhausted for {endpoint}")
return None
Вибір ендпоінтів: беріть лише те, що потрібно
HyperTracker надає 21 ендпоінт. Вашому боту, ймовірно, потрібні 3–5 із них. Один із найбільших поглиначів бюджету — опитування ендпоінтів "про всяк випадок", коли ваш рушій сигналів насправді не споживає ці дані.
Починайте від сигналу, а не від API. Запитайте себе: які дані потребує моя сигнальна функція на вході? Якщо вона використовує позиціонування когорт, опитуйте /cohort-metrics. Якщо вона використовує ризик ліквідації, опитуйте /liq-risk. Якщо вона не використовує дані таблиць лідерів, не опитуйте /leaderboard. Кожен ендпоінт, доданий до циклу опитування, коштує вам денного бюджету запитів і додає потенційну точку відмови.
Поширені відповідності сигнал-ендпоінт
| Тип сигналу | Необхідний(і) ендпоінт(и) | Додаткове збагачення |
| --- | --- | --- |
| Дивергенція когорт | /cohort-metrics | /position-metrics (контекст OI) |
| Затухання ризику ліквідації | /liq-risk | /cohort-metrics (напрямне підтвердження) |
| Дисбаланс потоку ордерів | /orders | /cohort-metrics (хто рухає потік) |
| Екстремальна ставка фінансування | Нативний API Hyperliquid | /cohort-metrics (позиція Smart Money) |
| Копіювання торгівлі / стеження за гаманцем | /positions | /leaderboard (вибір цільового гаманця) |
Зверніть увагу, що /cohort-metrics присутній майже в кожному типі сигналу як основне або збагачувальне джерело. Якщо ви будуєте систему навколо когортної аналітики, це ваш головний ендпоінт. Наші дані класифікують кожен гаманець на Hyperliquid в одну з 16 поведінкових когорт (8 за розміром рахунку, 8 за всебічним PnL), і когортний агрегат — це місце, де зосереджена щільність сигналу.
Структурування циклу опитування
Цикл опитування — це серцебиття вашого бота. Зробіть його правильно, і система безперебійно працюватиме тижнями. Зробіть його неправильно, і ви будете налагоджувати гонки станів і пропущені опитування о 3 ночі.
Патерн зміщеного інтервалу
Не запускайте всі опитування ендпоінтів в одну секунду. Якщо ви опитуєте 4 ендпоінти з 5-хвилинним інтервалом, розподіліть їх в межах цього інтервалу. Опитуйте /cohort-metrics о t+0, /orders о t+75с, /liq-risk о t+150с, /position-metrics о t+225с. Це вирівнює інтенсивність запитів і уникає сплесків, які можуть спрацювати на похвилинний ліміт.
POLL_SCHEDULE = [
{"endpoint": "/cohort-metrics", "offset_sec": 0, "interval_sec": 300},
{"endpoint": "/orders", "offset_sec": 75, "interval_sec": 300},
{"endpoint": "/liq-risk", "offset_sec": 150, "interval_sec": 300},
{"endpoint": "/position-metrics","offset_sec": 225, "interval_sec": 900},
]
async def run_polling_loop(cache, signal_engine):
while True:
now = time.time()
for task in POLL_SCHEDULE:
elapsed = (now - start_time) % task["interval_sec"]
if abs(elapsed - task["offset_sec"]) < 2:
data = await poll_with_backoff(task["endpoint"], params)
if data and cache.update(task["endpoint"], data):
signal_engine.evaluate(cache)
await asyncio.sleep(1)
Ключова деталь: рушій сигналів викликається лише тоді, коли кеш виявляє справжню зміну даних. Жодних зайвих оцінок, жодних витрат обчислень даремно, і кожне рішення вашого бота ґрунтується на свіжій інформації.
Альтернативи через Webhook і WebSocket
На тарифах Flow ($799/mo) і Stream ($1,999/mo) HyperTracker підтримує вебхуки і WebSocket-з'єднання. Вони повністю інвертують модель опитування: замість того, щоб ваш бот запитував дані за таймером, API надсилає дані вашому боту, коли вони змінюються.
Вебхуки усувають весь цикл опитування для охоплюваних ендпоінтів. Ви реєструєте URL зворотного виклику, і коли метрики когорт оновлюються, ваш бот отримує POST із новими даними. Без опитування, без витрачених запитів, без вікон застарілості.
WebSocket-з'єднання (тариф Stream) забезпечують постійний канал для безперервних оновлень. Якщо ви будуєте систему з високою частотою, яка повинна реагувати протягом секунд після оновлення даних, шлях через WebSocket повністю усуває затримку від periodичного опитування.
Але для більшості розробників-початківців описаний вище патерн опитування є правильною основою. Вебхуки і WebSocket — це оптимізації, до яких ви переходите, коли стратегія вашого бота доведена і вам потрібна менша затримка або вища пропускна спроможність.
Зведення докупи: референсна архітектура
Ось повний стек для добре спроектованого торгового бота на Hyperliquid, від API до виконання:
+----------------------------------------------------------+
| RISK MANAGEMENT |
| (vetoes signals, enforces position limits, can halt) |
+----------------------------------------------------------+
| ^
v |
+------------------+ +------------------+ |
| SIGNAL ENGINE |-->| EXECUTION |--+
| (pure function) | | (Hyperliquid |
| | | Python SDK) |
+------------------+ +------------------+
^
| (only on cache change)
+----------------------------------------------------------+
| DATA CACHE |
| - deduplication (skip unchanged responses) |
| - staleness detection (alert if data > 2x refresh age) |
| - graceful degradation (serve last-known-good on error) |
+----------------------------------------------------------+
^
| (staggered polling with backoff)
+----------------------------------------------------------+
| API POLLING LAYER |
| - staggered intervals per endpoint |
| - exponential backoff on 429/5xx |
| - request budget tracking (daily + per-minute) |
| - endpoint selection based on signal requirements |
+----------------------------------------------------------+
|
v
HyperTracker API
(REST / Webhooks / WebSocket)
Кожен шар має єдину відповідальність. Шар опитування відповідає за API-комунікацію та відновлення після помилок. Шар кешу відповідає за свіжість даних і дедублікацію. Рушій сигналів відповідає за прийняття рішень. Шар виконання відповідає за управління ордерами. А управління ризиками знаходиться над усім, із повноваженням блокувати будь-яку дію будь-якого шару.
Дані течуть угору крізь стек, і кожен шар додає конкретну гарантію. До моменту, коли сигнал досягає шару виконання, ви знаєте, що дані свіжі, сигнал оцінювався на змінених (а не повторних) вхідних даних, і шар ризиків схвалив угоду. Це бот, якого можна залишити працювати вночі.
Будуйте бота на попередньо обчисленій аналітиці
API HyperTracker надає вам когортну аналітику, оцінку ризику ліквідації, знімки потоку ордерів і метрики позицій по всьому Hyperliquid. 16 поведінкових когорт, кожен гаманець класифіковано, доставляється через REST, вебхуки або WebSocket. Починайте з безкоштовного тарифу і масштабуйтеся в міру дозрівання вашого бота.
Поширені помилки (і як їх уникнути)
Опитування всіх ендпоінтів з однаковою частотою. Дані таблиць лідерів змінюються не так швидко, як знімки потоку ордерів. Узгоджуйте інтервал опитування кожного ендпоінта з його частотою оновлення та чутливістю вашого сигналу до цих даних. Не кожному ендпоінту потрібен 5-хвилинний режим.
Ігнорування місячного ліміту до останнього моменту. Бот, який нормально працює три тижні, а потім вичерпує місячний ліміт на четвертому тижні, гірший за той, що трохи повільніший, але працює весь місяць. Відстежуйте сумарні запити щодня і сповіщайте себе за порогом (наприклад, коли ви використали більше, ніж пропорційна частка місячного бюджету для поточного дня місяця).
Мовчазне поглинання помилок. Найгірший варіант: блок try/except, що перехоплює всі виключення і повертає None, який потім передається в рушій сигналів як "немає даних". Ваш рушій сигналів інтерпретує "немає даних" інакше, ніж "дані кажуть, що нічого цікавого не відбувається". Розрізняйте "API повернув порожні результати" (дійсний стан) і "API-виклик зазнав невдачі" (помилка). Це різні стани.
Отримання історичних даних у гарячому циклі. HyperTracker має історичні дані, що сягають місяців тому для позицій і заповнень. Ці дані призначені для бектестингу та досліджень: їх слід отримати один раз, зберегти локально і ніколи не перезавантажувати у вашому циклі опитування в реальному часі. Ендпоінти для历史历史 даних мають ті ж ліміти, що й ендпоінти реального часу, тому повторне їх отримання з'їдає ваш бюджет без причини.
Спочатку сигнал, а шар даних — наостанок. Сигнал — це цікава частина. Оцінка дивергенції когорт, складові сигнали, налаштування порогів. Але якщо ви будуєте сигнал, не знаючи, скільки API-викликів можете дозволити, як часто оновлюються дані або як помилки поширюються системою, — вам доведеться вбудовувати шар даних навколо обмежень, для яких слід було проектувати від початку. Спершу будуйте сантехніку. Тестуйте її в режимі тільки логування (без торгівлі) кілька днів. Потім підключайте сигнал.
Висновок
Ваш сигнал — це альфа. Ваш API-шар — це інфраструктура, яка надійно доставляє цю альфу, день за днем, не спалюючи ліміт запитів і не деградуючи мовчки. Розробники, які роблять це правильно, будують ботів, що працюють місяцями. Ті, хто ставиться до шару даних як до другорядного, витрачають більше часу на налагодження інфраструктури, ніж на вдосконалення своєї переваги.
Змоделюйте бюджет запитів до написання коду. Кешуйте агресивно. Обробляйте помилки явно. Опитуйте з тією частотою, з якою дані насправді оновлюються, і розподіляйте запити, щоб ніколи не створювати сплесків. Зробіть ці п'ять речей — і API-шар стане невидимим, що і є ознакою хорошої інфраструктури.