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

Мы, команда блокчейн-инженеров, нередко получаем запросы на интеграцию торговых ботов с KuCoin. На первый взгляд API выглядит стандартно — REST и WebSocket. Но практика показывает: разработчики спотыкаются на аутентификации v2 (passphrase в base64), динамическом WebSocket URL и лимитах. Однажды клие

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

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1450
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1309
  • 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. На первый взгляд 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 дня и поможем избежать типичных ошибок интеграции. Получите консультацию по вашему проекту — обсудим стратегию, риски и технические детали.