Автоматизація торгівлі на KuCoin: розробка бота з нуля

Автоматизація торгівлі на KuCoin: розробка бота з нуля Ми, команда блокчейн-інженерів, нерідко отримуємо запити на інтеграцію торгових ботів з KuCoin. На перший погляд API виглядає стандартно — REST і WebSocket. Але практика показує: розробники спотикаються на аутентифікації v2 (passphrase в base

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

Часті запитання

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

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1450
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1308
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1003
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1269
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    719
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1009

Автоматизація торгівлі на KuCoin: розробка бота з нуля

Ми, команда блокчейн-інженерів, нерідко отримуємо запити на інтеграцію торгових ботів з KuCoin. На перший погляд API виглядає стандартно — REST і WebSocket. Але практика показує: розробники спотикаються на аутентифікації v2 (passphrase в base64), динамічному WebSocket URL та лімітах. Одного разу клієнт втратив 2 ETH через неправильний timestamp — ордери йшли із затримкою і потрапляли в stale-zone. Розберемо, як зібрати відмовостійкого бота, який економить кошти та нерви. Економія на комісіях при переході з ринкових ордерів на лімітні може досягати 30%. А правильна підписка на WebSocket знижує затримку та опосередковано зберігає ще 0.5% slippage.

Як працює аутентифікація KuCoin і чому вона нестандартна?

KuCoin використовує HMAC-SHA256 підпис. Ключовий нюанс: passphrase також підписується і кодується в base64. Нижче — робочий клас для генерації заголовків.

import hmac import hashlib import base64 import time import json import httpx class KuCoinClient: BASE_URL = "https://api.kucoin.com" FUTURES_URL = "https://api-futures.kucoin.com" def __init__(self, api_key: str, api_secret: str, passphrase: str): self.api_key = api_key self.api_secret = api_secret # KuCoin v2 підпис: passphrase теж підписується self.passphrase = base64.b64encode( hmac.new(api_secret.encode(), passphrase.encode(), hashlib.sha256).digest() ).decode() def _sign(self, timestamp: str, method: str, endpoint: str, body: str = "") -> str: str_to_sign = timestamp + method.upper() + endpoint + body return base64.b64encode( hmac.new(self.api_secret.encode(), str_to_sign.encode(), hashlib.sha256).digest() ).decode() def _headers(self, method: str, endpoint: str, body: str = "") -> dict: timestamp = str(int(time.time() * 1000)) return { "KC-API-KEY": self.api_key, "KC-API-SIGN": self._sign(timestamp, method, endpoint, body), "KC-API-TIMESTAMP": timestamp, "KC-API-PASSPHRASE": self.passphrase, "KC-API-KEY-VERSION": "2", "Content-Type": "application/json" } 

Згідно документації KuCoin, timestamp має відрізнятися від серверного не більше ніж на 5 секунд — інакше 401000. Ми у своїх проєктах синхронізуємо годинники через NTP та при кожному запиті читаємо серверний час із заголовка KC-API-TIMESTAMP відповіді.

Покрокова інструкція створення API-ключа
  1. Увійдіть в акаунт KuCoin, перейдіть у НалаштуванняAPI.
  2. Натисніть Створити API-ключ.
  3. Виберіть версію 2.
  4. Задайте passphrase (мінімум 8 символів).
  5. Збережіть API-ключ, секрет та passphrase — вони показуються один раз.
  6. У коді використовуйте клас вище, передавши ключі.

Що швидше: REST чи WebSocket?

Критерій REST API WebSocket API
Затримка отримання ціни 200–500 мс (polling) 10–50 мс (push)
Навантаження на сервер Висока (опитування) Низька (підписка)
Необхідні з'єднання Одноразові HTTP Постійне WS
Ліміти 30 запитів/с 100 підключень на акаунт

Для високочастотних стратегій WebSocket у 5–10 разів швидше за REST. Але стабільність WebSocket-з'єднання вимагає реалізації перепідключення та keepalive.

Як розміщувати ордери через REST

async def place_order( self, symbol: str, # 'BTC-USDT' side: str, # 'buy' або 'sell' order_type: str, # 'limit' або 'market' size: str = None, price: str = None, funds: str = None # для market buy по котируваній ) -> dict: endpoint = "/api/v1/orders" payload = { "clientOid": str(int(time.time() * 1000)), # унікальний ID клієнта "symbol": symbol, "side": side, "type": order_type } if order_type == "limit": payload["size"] = size payload["price"] = price elif side == "buy" and funds: payload["funds"] = funds # купити на $X USDT else: payload["size"] = size body = json.dumps(payload) async with httpx.AsyncClient() as client: response = await client.post( f"{self.BASE_URL}{endpoint}", content=body, headers=self._headers("POST", endpoint, body) ) result = response.json() if result.get("code") != "200000": raise KuCoinError(f"Order error: {result.get('msg')}") return result["data"] async def get_accounts(self, currency: str = None) -> list: endpoint = "/api/v1/accounts" if currency: endpoint += f"?currency={currency}" async with httpx.AsyncClient() as client: response = await client.get( f"{self.BASE_URL}{endpoint}", headers=self._headers("GET", endpoint) ) return response.json().get("data", []) 

Зверніть увагу: clientOid має бути унікальним для кожного ордера. Ми генеруємо його на основі timestamp та випадкового рядка, щоб уникнути колізій при повторному надсиланні. Це критично для стратегій, де ми переставляємо ордери при зміні ціни.

Чому WebSocket вимагає динамічний URL?

KuCoin не публікує статичний WebSocket URL — його потрібно запитати. Це підвищує безпеку: токен закінчується через 24 години. Наш клієнт отримує endpoint, підключається та підтримує keepalive.

async def get_ws_endpoint(self, private: bool = False) -> dict: endpoint = "/api/v1/bullet-private" if private else "/api/v1/bullet-public" method = "POST" if private else "POST" headers = self._headers(method, endpoint) if private else {"Content-Type": "application/json"} async with httpx.AsyncClient() as client: response = await client.post( f"{self.BASE_URL}{endpoint}", headers=headers ) data = response.json()["data"] server = data["instanceServers"][0] token = data["token"] ws_url = f"{server['endpoint']}?token={token}&connectId={int(time.time()*1000)}" ping_interval = server["pingInterval"] / 1000 # в секундах return {"url": ws_url, "ping_interval": ping_interval} async def subscribe_ticker(self, symbols: list[str]): ws_data = await self.get_ws_endpoint(private=False) async with websockets.connect(ws_data["url"]) as ws: await ws.send(json.dumps({ "id": str(int(time.time() * 1000)), "type": "subscribe", "topic": f"/market/ticker:{','.join(symbols)}", "privateChannel": False, "response": True })) async def keepalive(): while True: await asyncio.sleep(ws_data["ping_interval"]) await ws.send(json.dumps({"id": "ping", "type": "ping"})) asyncio.create_task(keepalive()) async for message in ws: data = json.loads(message) if data["type"] == "message" and "data" in data: await self.on_ticker(data["data"]) 

Типова проблема WebSocket: розрив з'єднання без повідомлення. При довгій відсутності торгівлі KuCoin може закрити сокет без надсилання close frame. Наш обробник помилок автоматично перепідключається з експоненційною затримкою (1с, 2с, 4с... до 30с). Це покриває 99% випадків.

Які помилки трапляються найчастіше?

Помилка Причина Рішення
code: "400003" Неправильний підпис Перевірити алгоритм HMAC, passphrase, timestamp
code: "401000" Прострочений timestamp Різниця із сервером не більше 5 секунд
code: "429000" Перевищення ліміту запитів Ввести затримку, використовувати заголовки лімітів

KuCoin API повертає code: "200000" при успіху (не HTTP статус). Перевіряйте саме це поле.

Особливості Futures API KuCoin

KuCoin надає окремий домен для ф'ючерсного API: https://api-futures.kucoin.com. Аутентифікація ідентична spot-версії, але ендпоїнти відрізняються. Для ф'ючерсних ботів важливо правильно задавати leverage та marginType (isolated або cross) в тілі ордера. Ставка фінансування (funding rate) оновлюється кожні 8 годин — ця інформація доступна через /api/v1/funding-rate/{symbol}/current. Стеження за funding rate дозволяє уникати небажаного списання при утриманні позиції через розрахунковий період.

Що входить у роботу під ключ

  • Проєктування архітектури бота (стратегія, управління ризиками, вибір між spot/futures)
  • Реалізація клієнта з обробкою лімітів, перепідключень та логуванням усіх помилок
  • Тестування на sandbox-оточенні (повне покриття сценаріїв: ордери, відміна, часткове виконання)
  • Розгортання на вашому сервері або в хмарі (Docker, systemd, моніторинг через Grafana)
  • Документація з API та експлуатації: як перезапускати, як міняти стратегії
  • Підтримка протягом 30 днів після запуску: фікс багів, консультації

Ми гарантуємо стабільність: наша команда має 7+ років досвіду в крипто-трейдингу. Для запуску бота в продакшені зв'яжіться з нами — підготуємо архітектуру за 2 дні та допоможемо уникнути типових помилок інтеграції. Отримайте консультацію щодо вашого проєкту — обговоримо стратегію, ризики та технічні деталі.