输入/搜索内容
欢迎使用发明者量化交易平台
编程语言
JavaScript
TypeScript
Python
C++
My语言(麦语言)
PINE语言
Blockly可视化
Workflow工作流
密钥安全性
实盘
策略库
托管者
部署托管者
一键租用托管者
手动部署托管者
托管者操作注意事项
全局指定IP地址
命令行版本托管者程序的参数
实盘数据迁移
托管者监控
交易所
策略编辑器
回测系统
策略入口函数
策略框架与API函数
模板类库
策略参数
交互控件
期权交易
C++策略编写说明
JavaScript策略编写说明
Web3
内置库
扩展API接口
MCP 服务
交易终端
数据探索
Alpha因子分析工具
通用协议
调试工具
远程编辑
完整策略的导入与导出
多语言支持
实盘、策略分组
实盘展示
策略分享与出租
实盘消息推送
实盘报错、异常退出的常见原因
交易所特殊说明

功能概述

API限流控制功能用于限制策略对交易所API的调用频率,防止触发交易所的频率限制导致账户被封禁或临时限制。FMZ平台提供了灵活的限流配置方式,支持两种限流模式和多种配置策略。

为什么需要API限流

  • 避免触发交易所限制:大多数交易所对API调用频率有严格限制,超限会导致账户被暂时或永久封禁。
  • 合理分配API配额:在多策略、多交易对场景下,需要合理分配API调用资源。
  • 提高策略稳定性:通过主动限流,避免因频繁调用导致的连接失败和数据获取异常。
  • 符合交易所规范:遵守交易所的API使用规范,维护良好的API使用关系。

两种限流模式

rate模式(平滑限流)

  • 适用于一般限流需求
  • 不严格对齐时间窗口
  • 调用分布相对平滑
  • 推荐用于日常API调用限制

quota模式(额度限流)

  • 严格对齐时间窗口
  • 例如设置"1s"时,窗口对齐到整秒;设置"1m"时,窗口对齐到整分钟
  • 适用于需要严格控制时间窗口的场景
  • 推荐用于日内配额管理

基本用法

rate模式基本示例

示例

  • undefined
    javascript
    function main() { // Limit GetTicker to maximum 10 times per second exchange.IO("rate", "GetTicker", 10, "1s") // Normal API calls for (var i = 0; i < 20; i++) { var ticker = exchange.GetTicker("BTC_USDT") if (ticker) { Log("Success:", ticker.Last) } else { Log("Rate limit exceeded") // Returns null when exceeding 10 times/second } Sleep(50) } }
    python
    def main(): # Limit GetTicker to maximum 10 times per second exchange.IO("rate", "GetTicker", 10, "1s") # Normal API calls for i in range(20): ticker = exchange.GetTicker("BTC_USDT") if ticker: Log("Success:", ticker["Last"]) else: Log("Rate limit exceeded") # Returns None when exceeding 10 times/second Sleep(50)
    c++
    // C++暂不支持
  • quota模式基本示例

    javascript
    function main() { // Strict limit, time window aligned to whole seconds exchange.IO("quota", "GetTicker", 5, "1s") for (var i = 0; i < 10; i++) { var ticker = exchange.GetTicker("BTC_USDT") Log(_D(), "Call", i+1, ticker ? "Success" : "Quota exceeded") Sleep(150) // About 6-7 calls per second, will trigger limit } }
    python
    def main(): # Strict limit, time window aligned to whole seconds exchange.IO("quota", "GetTicker", 5, "1s") for i in range(10): ticker = exchange.GetTicker("BTC_USDT") Log(_D(), "Call", i+1, "Success" if ticker else "Quota exceeded") Sleep(150) # About 6-7 calls per second, will trigger limit
    c++
    // C++暂不支持
  • 函数名配置

    单个函数限流

    javascript
    function main() { // Only limit GetTicker function exchange.IO("rate", "GetTicker", 10, "1s") // GetTicker is limited, GetDepth is not limited exchange.GetTicker("BTC_USDT") exchange.GetDepth("BTC_USDT") }
    python
    def main(): # Only limit GetTicker function exchange.IO("rate", "GetTicker", 10, "1s") # GetTicker is limited, GetDepth is not limited exchange.GetTicker("BTC_USDT") exchange.GetDepth("BTC_USDT")
    c++
    // C++暂不支持
  • 多个函数联合限流

    javascript
    function main() { // GetTicker and GetDepth share quota, total 10 times per second exchange.IO("rate", "GetTicker,GetDepth", 10, "1s") for (var i = 0; i < 15; i++) { if (i % 2 == 0) { exchange.GetTicker("BTC_USDT") // Counted in shared quota } else { exchange.GetDepth("BTC_USDT") // Counted in shared quota } } }
    python
    def main(): # GetTicker and GetDepth share quota, total 10 times per second exchange.IO("rate", "GetTicker,GetDepth", 10, "1s") for i in range(15): if i % 2 == 0: exchange.GetTicker("BTC_USDT") # Counted in shared quota else: exchange.GetDepth("BTC_USDT") # Counted in shared quota
    c++
    // C++暂不支持
  • 使用通配符限制所有函数

    javascript
    function main() { // Limit all API calls to total 100 times per minute exchange.IO("rate", "*", 100, "1m") // All calls are counted in total quota exchange.GetTicker("BTC_USDT") exchange.GetDepth("BTC_USDT") exchange.GetAccount() exchange.CreateOrder("BTC_USDT", "buy", 50000, 0.001) }
    python
    def main(): # Limit all API calls to total 100 times per minute exchange.IO("rate", "*", 100, "1m") # All calls are counted in total quota exchange.GetTicker("BTC_USDT") exchange.GetDepth("BTC_USDT") exchange.GetAccount() exchange.CreateOrder("BTC_USDT", "buy", 50000, 0.001)
    c++
    // C++暂不支持
  • 时间周期配置

    支持的时间单位

    • ns:纳秒
    • usµs:微秒
    • ms:毫秒
    • s:秒
    • m:分钟
    • h:小时
    • d:天

    示例:"100ms", "1s", "5m", "1h", "1d"

    javascript
    function main() { // Different time period configurations exchange.IO("rate", "GetTicker", 10, "1s") // 10 times per second exchange.IO("rate", "GetDepth", 30, "1m") // 30 times per minute exchange.IO("rate", "GetAccount", 100, "1h") // 100 times per hour exchange.IO("rate", "CreateOrder", 500, "1d") // 500 times per day }
    python
    def main(): # 不同时间周期的配置 exchange.IO("rate", "GetTicker", 10, "1s") # 每秒10次 exchange.IO("rate", "GetDepth", 30, "1m") # 每分钟30次 exchange.IO("rate", "GetAccount", 100, "1h") # 每小时100次 exchange.IO("rate", "CreateOrder", 500, "1d") # 每天500次
    c++
    // C++暂不支持
  • 重置时间点配置

    使用@HHMM@HHMMSS格式指定每日重置时间点,仅在quota模式下生效。

    javascript
    function main() { // Reset quota daily at 08:15 exchange.IO("quota", "GetTicker", 1000, "@0815") // Reset quota daily at 00:00 exchange.IO("quota", "CreateOrder", 500, "@0000") // Reset quota daily at 23:59:59 exchange.IO("quota", "*", 5000, "@235959") }
    python
    def main(): # Reset quota daily at 08:15 exchange.IO("quota", "GetTicker", 1000, "@0815") # Reset quota daily at 00:00 exchange.IO("quota", "CreateOrder", 500, "@0000") # Reset quota daily at 23:59:59 exchange.IO("quota", "*", 5000, "@235959")
    c++
    // C++暂不支持
  • 行为模式

    默认模式(超限返回null)

    javascript
    function main() { exchange.IO("rate", "GetTicker", 5, "1s") // 不指定behavior参数 for (var i = 0; i < 10; i++) { var ticker = exchange.GetTicker("BTC_USDT") if (ticker) { Log("Call", i+1, "Success:", ticker.Last) } else { Log("Call", i+1, "Failed: rate limit exceeded") // 可以选择Sleep等待,或者跳过本次调用 Sleep(200) } } }
    python
    def main(): exchange.IO("rate", "GetTicker", 5, "1s") # 不指定behavior参数 for i in range(10): ticker = exchange.GetTicker("BTC_USDT") if ticker: Log("Call", i+1, "Success:", ticker["Last"]) else: Log("Call", i+1, "Failed: rate limit exceeded") # 可以选择Sleep等待,或者跳过本次调用 Sleep(200)
    c++
    // C++暂不支持
  • delay模式(超限自动等待)

    javascript
    function main() { exchange.IO("rate", "GetTicker", 5, "1s", "delay") // 指定delay参数 // 调用超限时会自动等待,确保每次调用都成功 for (var i = 0; i < 10; i++) { var ticker = exchange.GetTicker("BTC_USDT") Log("Call", i+1, "Success:", ticker.Last) // ticker不会为null } }
    python
    def main(): exchange.IO("rate", "GetTicker", 5, "1s", "delay") # 指定delay参数 # 调用超限时会自动等待,确保每次调用都成功 for i in range(10): ticker = exchange.GetTicker("BTC_USDT") Log("Call", i+1, "Success:", ticker["Last"]) # ticker不会为None
    c++
    // C++暂不支持
  • 支持的函数列表

    交易类函数

    • CreateOrder:创建订单

    • CancelOrder:取消订单

    • Buy:买入(受CreateOrder限制)

    • Sell:卖出(受CreateOrder限制)

    • CreateConditionOrder:创建条件单

    • CancelConditionOrder:取消条件单

    账户类函数

    • GetAccount:获取账户信息

    • GetAssets:获取资产信息

    • GetPositions:获取持仓信息

    订单类函数

    • GetOrder:获取单个订单

    • GetOrders:获取所有订单

    • GetHistoryOrders:获取历史订单

    • GetConditionOrder:获取单个条件单

    • GetConditionOrders:获取所有条件单

    • GetHistoryConditionOrders:获取历史条件单

    行情类函数

    • GetTicker:获取ticker数据

    • GetTickers:获取多个ticker数据

    • GetDepth:获取市场深度

    • GetRecords:获取K线数据

    • GetTrades:获取最新成交记录

    其他函数

    • GetMarkets:获取市场列表

    • GetFundings:获取资金费率

    • SetMarginLevel:设置杠杆倍数

    • Go:并发调用(受实际调用函数限制)

    • IO/api:自定义API调用(仅限exchange.IO("api", ...))

  • 实际应用场景

    场景1:防止触发交易所频率限制

    javascript
    function main() { // 假设交易所限制:GetTicker每秒20次,CreateOrder每秒5次 // 设置略低于交易所限制的值,留出安全余量 exchange.IO("rate", "GetTicker", 15, "1s") exchange.IO("rate", "CreateOrder", 4, "1s") while (true) { var ticker = exchange.GetTicker("BTC_USDT") if (ticker && ticker.Last < 50000) { exchange.CreateOrder("BTC_USDT", "buy", ticker.Last, 0.001) } Sleep(100) } }
    python
    def main(): # 假设交易所限制:GetTicker每秒20次,CreateOrder每秒5次 # 设置略低于交易所限制的值,留出安全余量 exchange.IO("rate", "GetTicker", 15, "1s") exchange.IO("rate", "CreateOrder", 4, "1s") while True: ticker = exchange.GetTicker("BTC_USDT") if ticker and ticker["Last"] < 50000: exchange.CreateOrder("BTC_USDT", "buy", ticker["Last"], 0.001) Sleep(100)
    c++
    // C++暂不支持
  • 场景2:多交易所对象统一限流

    javascript
    function main() { // 为每个交易所对象设置限流 for (var i = 0; i < exchanges.length; i++) { exchanges[i].IO("rate", "GetTicker", 10, "1s") exchanges[i].IO("rate", "CreateOrder", 2, "1s") } // 并发获取多个交易所行情 while (true) { for (var i = 0; i < exchanges.length; i++) { var ticker = exchanges[i].GetTicker("BTC_USDT") if (ticker) { Log(exchanges[i].GetName(), "Price:", ticker.Last) } } Sleep(1000) } }
    python
    def main(): # 为每个交易所对象设置限流 for i in range(len(exchanges)): exchanges[i].IO("rate", "GetTicker", 10, "1s") exchanges[i].IO("rate", "CreateOrder", 2, "1s") # 并发获取多个交易所行情 while True: for i in range(len(exchanges)): ticker = exchanges[i].GetTicker("BTC_USDT") if ticker: Log(exchanges[i].GetName(), "Price:", ticker["Last"]) Sleep(1000)
    c++
    // C++暂不支持
  • 场景3:日内配额管理

    javascript
    function main() { // 每天最多1000次API调用,每天早上8点重置 exchange.IO("quota", "*", 1000, "@0800") var callCount = 0 while (true) { var ticker = exchange.GetTicker("BTC_USDT") if (ticker) { callCount++ Log("Call count:", callCount, "Price:", ticker.Last) } else { Log("Daily quota exceeded, waiting for tomorrow 08:00") Sleep(60000) // 等待1分钟后重试 } Sleep(10000) } }
    python
    def main(): # 每天最多1000次API调用,每天早上8点重置 exchange.IO("quota", "*", 1000, "@0800") callCount = 0 while True: ticker = exchange.GetTicker("BTC_USDT") if ticker: callCount += 1 Log("Call count:", callCount, "Price:", ticker["Last"]) else: Log("Daily quota exceeded, waiting for tomorrow 08:00") Sleep(60000) # 等待1分钟后重试 Sleep(10000)
    c++
    // C++暂不支持
  • 场景4:组合限流策略

    javascript
    function main() { // 组合多种限流策略 // 1. 行情类API每秒限制 exchange.IO("rate", "GetTicker,GetDepth", 20, "1s") // 2. 交易类API每秒限制 exchange.IO("rate", "CreateOrder,CancelOrder", 5, "1s") // 3. 账户查询每分钟限制 exchange.IO("rate", "GetAccount,GetPositions", 30, "1m") // 4. 所有API每天总配额 exchange.IO("quota", "*", 10000, "@0000") Log("Multi-level rate limiting configured") // 策略主循环 while (true) { // 获取行情 var ticker = exchange.GetTicker("BTC_USDT") var depth = exchange.GetDepth("BTC_USDT") // 查询账户 if (Date.now() % 60000 < 1000) { // 每分钟查询一次 var account = exchange.GetAccount() Log("Account:", account) } // 交易逻辑 if (ticker && ticker.Last < 50000) { exchange.CreateOrder("BTC_USDT", "buy", ticker.Last, 0.001) } Sleep(500) } }
    python
    import time def main(): # 组合多种限流策略 # 1. 行情类API每秒限制 exchange.IO("rate", "GetTicker,GetDepth", 20, "1s") # 2. 交易类API每秒限制 exchange.IO("rate", "CreateOrder,CancelOrder", 5, "1s") # 3. 账户查询每分钟限制 exchange.IO("rate", "GetAccount,GetPositions", 30, "1m") # 4. 所有API每天总配额 exchange.IO("quota", "*", 10000, "@0000") Log("Multi-level rate limiting configured") # 策略主循环 while True: # 获取行情 ticker = exchange.GetTicker("BTC_USDT") depth = exchange.GetDepth("BTC_USDT") # 查询账户 if int(time.time() * 1000) % 60000 < 1000: # 每分钟查询一次 account = exchange.GetAccount() Log("Account:", account) # 交易逻辑 if ticker and ticker["Last"] < 50000: exchange.CreateOrder("BTC_USDT", "buy", ticker["Last"], 0.001) Sleep(500)
    c++
    // C++暂不支持
  • 注意事项

    1. quota模式时间窗口对齐

    quota模式严格对齐时间窗口:

    • "1s":对齐到整秒(例如:12:00:00, 12:00:01, 12:00:02...)
    • "1m":对齐到整分钟(例如:12:00:00, 12:01:00, 12:02:00...)
    • "1h":对齐到整小时(例如:12:00:00, 13:00:00, 14:00:00...)

    这意味着即使在12:00:00.500开始计数,到12:00:01.000时窗口就会重置。

    javascript
    function main() { // quota模式:严格对齐到整秒 exchange.IO("quota", "GetTicker", 3, "1s") // 假设当前时间为 12:00:00.500 exchange.GetTicker("BTC_USDT") // 第1次,成功 exchange.GetTicker("BTC_USDT") // 第2次,成功 exchange.GetTicker("BTC_USDT") // 第3次,成功 exchange.GetTicker("BTC_USDT") // 第4次,失败(超限) Sleep(500) // 等待500ms,此时时间为 12:00:01.000 // 窗口已重置 exchange.GetTicker("BTC_USDT") // 新窗口第1次,成功 }
    python
    def main(): # quota模式:严格对齐到整秒 exchange.IO("quota", "GetTicker", 3, "1s") # 假设当前时间为 12:00:00.500 exchange.GetTicker("BTC_USDT") # 第1次,成功 exchange.GetTicker("BTC_USDT") # 第2次,成功 exchange.GetTicker("BTC_USDT") # 第3次,成功 exchange.GetTicker("BTC_USDT") # 第4次,失败(超限) Sleep(500) # 等待500ms,此时时间为 12:00:01.000 # 窗口已重置 exchange.GetTicker("BTC_USDT") # 新窗口第1次,成功
    c++
    // C++暂不支持
  • 2. delay模式下的时间差异

    使用"delay"参数时,实际API调用时间与日志记录时间可能不一致。这是因为当触发限流时,程序会等待,但日志记录的是等待结束后的时间。

    javascript
    function main() { exchange.IO("rate", "GetTicker", 2, "1s", "delay") Log(_D(), "Call 1") // 12:00:00.000 exchange.GetTicker("BTC_USDT") Log(_D(), "Call 2") // 12:00:00.100 exchange.GetTicker("BTC_USDT") Log(_D(), "Call 3") // 12:00:00.200,但实际会等待到12:00:01.000 exchange.GetTicker("BTC_USDT") // 触发限流,自动等待 Log(_D(), "Call 3 completed") // 日志显示12:00:01.000+ // 看起来一秒内调用了3次,但实际第3次是在新窗口执行的 }
    python
    def main(): exchange.IO("rate", "GetTicker", 2, "1s", "delay") Log(_D(), "Call 1") # 12:00:00.000 exchange.GetTicker("BTC_USDT") Log(_D(), "Call 2") # 12:00:00.100 exchange.GetTicker("BTC_USDT") Log(_D(), "Call 3") # 12:00:00.200,但实际会等待到12:00:01.000 exchange.GetTicker("BTC_USDT") # 触发限流,自动等待 Log(_D(), "Call 3 completed") # 日志显示12:00:01.000+ # 看起来一秒内调用了3次,但实际第3次是在新窗口执行的
    c++
    // C++暂不支持
  • 3. Buy/Sell函数的限流

    BuySell函数底层调用CreateOrder,因此它们的限流遵循CreateOrder的设置。

    javascript
    function main() { // 设置CreateOrder限流 exchange.IO("rate", "CreateOrder", 5, "1s") // Buy和Sell也会受到此限制 for (var i = 0; i < 10; i++) { if (i % 2 == 0) { exchange.Buy(50000, 0.001) // 受CreateOrder限制 } else { exchange.Sell(51000, 0.001) // 受CreateOrder限制 } } }
    python
    def main(): # 设置CreateOrder限流 exchange.IO("rate", "CreateOrder", 5, "1s") # Buy和Sell也会受到此限制 for i in range(10): if i % 2 == 0: exchange.Buy(50000, 0.001) # 受CreateOrder限制 else: exchange.Sell(51000, 0.001) # 受CreateOrder限制
    c++
    // C++暂不支持
  • 4. Go函数的限流

    Go函数的限流取决于实际并发调用的函数。

    javascript
    function main() { // 限制GetTicker exchange.IO("rate", "GetTicker", 5, "1s") // 并发调用GetTicker时受限 var tasks = [] for (var i = 0; i < 10; i++) { tasks.push(exchange.Go("GetTicker", "BTC_USDT")) } for (var i = 0; i < tasks.length; i++) { var ticker = tasks[i].wait() Log("Task", i, ticker ? "Success" : "Rate limited") } }
    python
    def main(): # 限制GetTicker exchange.IO("rate", "GetTicker", 5, "1s") # 并发调用GetTicker时受限 tasks = [] for i in range(10): tasks.append(exchange.Go("GetTicker", "BTC_USDT")) for i in range(len(tasks)): ticker = tasks[i].wait() Log("Task", i, "Success" if ticker else "Rate limited")
    c++
    // C++暂不支持
  • 5. IO/api的限流

    IO/api限流仅对exchange.IO("api", ...)调用生效,不影响其他exchange.IO功能。

    javascript
    function main() { // 限制exchange.IO("api", ...)调用 exchange.IO("rate", "IO/api", 10, "1s") // 受限制 for (var i = 0; i < 15; i++) { var ret = exchange.IO("api", "GET", "/api/v5/account/balance", "") Log("API call", i, ret ? "Success" : "Rate limited") } // 不受限制 exchange.IO("currency", "LTC_USDT") // 切换交易对,不受限 exchange.IO("rate", "GetDepth", 5, "1s") // 设置其他限流,不受限 }
    python
    def main(): # 限制exchange.IO("api", ...)调用 exchange.IO("rate", "IO/api", 10, "1s") # 受限制 for i in range(15): ret = exchange.IO("api", "GET", "/api/v5/account/balance", "") Log("API call", i, "Success" if ret else "Rate limited") # 不受限制 exchange.IO("currency", "LTC_USDT") # 切换交易对,不受限 exchange.IO("rate", "GetDepth", 5, "1s") # 设置其他限流,不受限
    c++
    // C++暂不支持
  • 最佳实践

    1. 根据交易所限制进行设置:参考交易所API文档,将限制值设置为略低于交易所规定的最大值。

    2. 预留安全余量:不要将限制设置为交易所的最大值,建议设置为最大值的70%-80%。

    3. 实施分层限流:针对不同类型的API设置不同的限制,为重要API预留更多余量。

    4. 对关键调用使用delay模式:对于必须成功的API调用,使用"delay"模式确保调用成功。

    5. 监控API使用情况:定期检查策略的API调用频率,持续优化调用逻辑。

    6. 避免过度调用:合理设计策略逻辑,减少不必要的API调用。

    7. 测试限流配置:在实盘交易前,先在模拟环境中测试限流配置的合理性。

参考