跳至内容

使用 API 限流器处理速率限制

注意

以下信息适用于开发直接集成到 Hummingbot 客户端的 spotperp 连接器的开发者。有关使用 Gateway 开发 gateway 连接器的信息,请参阅 构建 Gateway 连接器。

本节将详细介绍将 AsyncThrottler 集成到连接器中的必要步骤。AsyncThrottler 类使用异步上下文管理器来限制 API 和/或 WebSocket 请求,避免达到交易所服务器的速率限制。

提示

AsyncThrottler 集成到连接器中是完全可选的,但建议启用,以提供更好的用户体验,并允许用户手动配置每个 Hummingbot 实例可用的速率限制。

RateLimitLinkedLimitWeightPair 数据类

RateLimit 数据类用于表示交易所定义的速率限制,而 LinkedLimitWeightPair 数据类用于将某个端点的消耗权重与其 API 池关联(如果未指定,则默认为 1)。

提示

limit_id 可以是任意分配的值。在接下来几节的示例中,分配给各个速率限制的 limit_id 要么是通用的 API 池名称,要么是 API 端点的路径 URL。

速率限制的类型

在开始开发之前,识别交易所的速率限制实现方式非常重要。

AsyncThrottler 类可以处理多种类型的速率限制。以下各节将详细说明(并附示例)如何初始化必要的 RateLimit,以及针对不同类型的速率限制,连接器与限流器之间的交互方式。

1. 每个端点的速率限制

注意

kucoin 是一个使用此类速率限制实现的连接器示例。

这指的是按端点施加的速率限制。对于这种类型的速率限制,需要为每个端点获取的关键信息是其对应的限制数量时间间隔。请注意,时间间隔是滚动计算的。例如,如果某个端点的速率限制为 20,时间间隔为 60 秒,则意味着限流器会检查在过去 60 秒内(从当前时刻起算)是否已对该端点发起了 20 次调用。

配置速率限制

如上所述,需要从交易所获取的关键信息是每个端点的 limit(限制数)和 time_interval(时间间隔,单位为秒)。可在 kucoin 连接器中查看采用此实现方式的交易所示例。

Kucoin 的速率限制信息可在此处查看

所有速率限制都应在 kucoin_constants.py 文件中进行初始化。

RATE_LIMITS = [
    RateLimit(WS_CONNECTION_LIMIT_ID, limit=WS_CONNECTION_LIMIT, time_interval=WS_CONNECTION_TIME_INTERVAL),
    RateLimit(WS_REQUEST_LIMIT_ID, limit=100, time_interval=10),

    RateLimit(limit_id=PUBLIC_WS_DATA_PATH_URL, limit=NO_LIMIT, time_interval=1),
    RateLimit(limit_id=PRIVATE_WS_DATA_PATH_URL, limit=NO_LIMIT, time_interval=1),
    RateLimit(limit_id=TICKER_PRICE_CHANGE_PATH_URL, limit=NO_LIMIT, time_interval=1),
    RateLimit(limit_id=SYMBOLS_PATH_URL, limit=NO_LIMIT, time_interval=1),
    RateLimit(limit_id=SNAPSHOT_NO_AUTH_PATH_URL, limit=NO_LIMIT, time_interval=1),
    RateLimit(limit_id=ACCOUNTS_PATH_URL, limit=NO_LIMIT, time_interval=1),
    RateLimit(limit_id=SERVER_TIME_PATH_URL, limit=NO_LIMIT, time_interval=1),
    RateLimit(limit_id=GET_ORDER_LIMIT_ID, limit=NO_LIMIT, time_interval=1),
    RateLimit(limit_id=FEE_PATH_URL, limit=NO_LIMIT, time_interval=1),
    RateLimit(limit_id=ALL_TICKERS_PATH_URL, limit=NO_LIMIT, time_interval=1),
    RateLimit(limit_id=LIMIT_FILLS_PATH_URL, limit=NO_LIMIT, time_interval=1),
    RateLimit(limit_id=ORDER_CLIENT_ORDER_PATH_URL, limit=NO_LIMIT, time_interval=1),
    RateLimit(limit_id=POST_ORDER_LIMIT_ID, limit=45, time_interval=3),
    RateLimit(limit_id=DELETE_ORDER_LIMIT_ID, limit=60, time_interval=3),
    RateLimit(limit_id=ORDERS_PATH_URL, limit=45, time_interval=3),
    RateLimit(limit_id=FILLS_PATH_URL, limit=9, time_interval=3),
]

2. 速率限制池

注意

binancebinance_perpetualndax 是使用此类速率限制实现的连接器示例

速率限制池指的是共享同一速率限制的一组端点。对于此类速率限制类型,需要为每个端点获取的关键信息是其分配的池(或多个池)以及相应的限制和时间间隔。

配置速率限制

实现此机制的交易所示例可参见ndax连接器。

所有速率限制都在ndax_constants.py文件中初始化。

# Pool IDs
HTTP_ENDPOINTS_LIMIT_ID = "AllHTTP"
WS_ENDPOINTS_LIMIT_ID = "AllWs"

RATE_LIMITS = [
  # REST API Pool(applies to all REST API endpoints)
  RateLimit(limit_id=HTTP_ENDPOINTS_LIMIT_ID, limit=HTTP_LIMIT, time_interval=MINUTE),
  # WebSocket Pool(applies to all WS requests)
  RateLimit(limit_id=WS_ENDPOINTS_LIMIT_ID, limit=WS_LIMIT, time_interval=MINUTE),
  # Public REST API endpoint
  RateLimit(
      limit_id=MARKETS_URL,
      limit=HTTP_LIMIT,
      time_interval=MINUTE,
      linked_limits=[LinkedLimitWeightPair(HTTP_ENDPOINTS_LIMIT_ID)],
  ),
  # WebSocket Auth endpoint
  RateLimit(
      limit_id=ACCOUNT_POSITION_EVENT_ENDPOINT_NAME,
      limit=WS_LIMIT,
      time_interval=MINUTE,
      linked_limits=[LinkedLimitWeightPair(WS_ENDPOINTS_LIMIT_ID)],
  ),
]

请注意,我们为 API 池分配了一个任意的限制 ID(即HTTP_ENDPOINTS_LIMIT_ID),并使用LinkedLimitWeightPair将端点分配给 API 池。同时请注意,一个端点可能属于多个其他端点。

还值得注意的是,API 池可能存在更复杂的实现方式,例如在bybit_perpetual连接器中的实现,详见此处

3. 加权请求速率限制

注意

binancebinance_perpetual是采用此类速率限制实现的连接器示例。

对于加权速率限制,每个端点都会被分配一个请求权重。通常,这些交易所会将速率限制池与请求权重结合使用,不同端点对给定池的影响也不同。针对这些交易所需要获取的关键信息包括每个端点的权重、API 池的限制及其时间间隔。

配置速率限制

实施此类速率限制的交易所示例可参见binance连接器。

Binance 的速率限制可在GET /api/v3/exchangeInfo端点的 API 响应中找到,详见此处

RATE_LIMITS = [
    # Pools
    RateLimit(limit_id=REQUEST_WEIGHT, limit=1200, time_interval=ONE_MINUTE),
    RateLimit(limit_id=ORDERS, limit=10, time_interval=ONE_SECOND),
    RateLimit(limit_id=ORDERS_24HR, limit=100000, time_interval=ONE_DAY),
    # Weighted Limits
    RateLimit(limit_id=SNAPSHOT_PATH_URL, limit=MAX_REQUEST, time_interval=ONE_MINUTE,
              linked_limits=[LinkedLimitWeightPair(REQUEST_WEIGHT, 50)]),
    RateLimit(limit_id=BINANCE_CREATE_ORDER, limit=MAX_REQUEST, time_interval=ONE_MINUTE,
              linked_limits=[LinkedLimitWeightPair(REQUEST_WEIGHT, 1),
                             LinkedLimitWeightPair(ORDERS, 1),
                             LinkedLimitWeightPair(ORDERS_24HR, 1)]),
]

Binance 同时采用了 API 池和加权请求机制。在上述示例中,BINANCE_CREATE_ORDER端点在 3 个 API 池中的请求权重均为 1,而SNAPSHOT_PATH_URL端点在REQUEST_WEIGHT API 池中的请求权重为 50。请注意,不同的 API 池具有不同的速率限制和时间间隔。

将速率限制集成到连接器中

节流器应被所有涉及受交易所限制的服务器 API 调用的相关类所使用(无论是 HTTP 请求还是 WebSocket 请求)。主要包括Exchange/DerivativeAPIOrderBookDataSourceUserStreamDataSource类。这样做可确保节流器管理由连接器任何组件发出的所有 REST API/WebSocket 请求。

使用节流器

节流器作为异步上下文管理器使用。

async with throttler.execute_task(path_url):
    res = await aiohttp.ClientSession().get(path_url)

警告

path_url必须与在RATE_LIMITS常量中定义的端点limit_id相匹配。节流器会将path_url与其分配的速率限制或 API 池进行匹配。