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

功能概述

优宽量化平台支持对商品期货交易所API调用进行频率限制,防止触发交易所的频率限制。通过合理配置API限流,可以有效避免因频繁调用导致的接口限制问题,保障策略稳定运行。

API限流功能支持两种限流模式:

  • rate模式(平滑限流):不严格对齐时间窗口,适用于一般限流需求。例如设置每秒10次,系统会平滑地控制调用频率。
  • quota模式(额度限流):严格对齐时间窗口,例如1m对齐到整分钟,1s对齐到整秒。适用于需要严格控制时间窗口的场景。

基础用法

函数签名

javascript
exchange.IO("rate", functionNames, maxCalls, period, [behavior]) exchange.IO("quota", functionNames, maxCalls, period, [behavior])

参数说明

参数类型必填说明
modestring限流模式:"rate"(平滑限流)或 "quota"(额度限流)
functionNamesstring要限制的函数名,支持单个函数、多个函数(逗号分隔)、通配符(*表示所有函数)
maxCallsnumber时间周期内允许的最大调用次数
periodstring时间周期或重置时间点。支持时间单位:ns、us、µs、ms、s、m、h、d(例如:"1s"、"1m"、"1h")。支持重置时间点:@HHMM 或 @HHMMSS(例如:"@0815"表示每天08:15重置)
behaviorstring超限行为。默认为空(超限返回null并报错);设置为"delay"时超限会等待

支持的函数列表

优宽量化平台的API限流功能支持以下函数:

交易类(2个):

  • CreateOrder - 创建订单
  • CancelOrder - 撤销订单

账户类(2个):

  • GetAccount - 获取账户信息
  • GetPositions - 获取持仓信息

订单类(3个):

  • GetOrder - 获取订单信息
  • GetOrders - 获取订单列表
  • GetHistoryOrders - 获取历史订单

行情类(3个):

  • GetTicker - 获取行情Tick数据
  • GetDepth - 获取深度数据
  • GetRecords - 获取K线数据

其它(1个):

  • IO/api - 仅对exchange.IO("api", ...)调用生效

函数名称配置

单个函数限流

限制单个函数的调用频率:

示例

  • undefined
    javascript
    function main() { while (!exchange.IO("status")) { Sleep(1000) } // 限制GetTicker每秒最多调用3次 exchange.IO("rate", "GetTicker", 3, "1s") for (var i = 0; i < 10; i++) { if (!exchange.IO("status")) { Sleep(5000) continue } var ticker = exchange.GetTicker("rb888") if (ticker) { Log("Success:", ticker.Last) } else { Log("Rate limit exceeded", "#FF0000") } Sleep(100) } }
    python
    def main(): while not exchange.IO("status"): Sleep(1000) # 限制GetTicker每秒最多调用3次 exchange.IO("rate", "GetTicker", 3, "1s") for i in range(10): if not exchange.IO("status"): Sleep(5000) continue ticker = exchange.GetTicker("rb888") if ticker: Log("Success:", ticker["Last"]) else: Log("Rate limit exceeded", "#FF0000") Sleep(100)
    c++
    // C++暂不支持
  • 多个函数联合限流

    多个函数共享同一个限流配额:

    javascript
    function main() { while (!exchange.IO("status")) { Sleep(1000) } // GetTicker和GetDepth共享限制,合计每秒最多5次 exchange.IO("rate", "GetTicker,GetDepth", 5, "1s") for (var i = 0; i < 10; i++) { if (!exchange.IO("status")) { Sleep(5000) continue } if (i % 2 == 0) { var ticker = exchange.GetTicker("m888") Log("GetTicker:", ticker ? "Success" : "Failed") } else { var depth = exchange.GetDepth("m888") Log("GetDepth:", depth ? "Success" : "Failed") } Sleep(100) } }
    python
    def main(): while not exchange.IO("status"): Sleep(1000) # GetTicker和GetDepth共享限制,合计每秒最多5次 exchange.IO("rate", "GetTicker,GetDepth", 5, "1s") for i in range(10): if not exchange.IO("status"): Sleep(5000) continue if i % 2 == 0: ticker = exchange.GetTicker("m888") Log("GetTicker:", "Success" if ticker else "Failed") else: depth = exchange.GetDepth("m888") Log("GetDepth:", "Success" if depth else "Failed") Sleep(100)
    c++
    // C++暂不支持
  • 通配符限流

    使用通配符*限制所有API调用:

    javascript
    function main() { while (!exchange.IO("status")) { Sleep(1000) } // 限制所有API调用每秒最多10次 exchange.IO("mode", 0) // 建议配合立即返回模式 exchange.IO("rate", "*", 10, "1s") var symbols = ["rb888", "m888", "i888"] for (var i = 0; i < 5; i++) { if (!exchange.IO("status")) { Sleep(5000) continue } var symbol = symbols[i % symbols.length] var ticker = exchange.GetTicker(symbol) var account = exchange.GetAccount() Log("Round", i+1, "Ticker:", ticker ? "✓" : "✗", "Account:", account ? "✓" : "✗") Sleep(500) } }
    python
    def main(): while not exchange.IO("status"): Sleep(1000) # 限制所有API调用每秒最多10次 exchange.IO("mode", 0) # 建议配合立即返回模式 exchange.IO("rate", "*", 10, "1s") symbols = ["rb888", "m888", "i888"] for i in range(5): if not exchange.IO("status"): Sleep(5000) continue symbol = symbols[i % len(symbols)] ticker = exchange.GetTicker(symbol) account = exchange.GetAccount() Log("Round", i+1, "Ticker:", "✓" if ticker else "✗", "Account:", "✓" if account else "✗") Sleep(500)
    c++
    // C++暂不支持
  • 时间周期配置

    固定时间周期

    支持多种时间单位:ns(纳秒)、us/µs(微秒)、ms(毫秒)、s(秒)、m(分钟)、h(小时)、d(天)。

    javascript
    function main() { while (!exchange.IO("status")) { Sleep(1000) } // 不同时间周期的限流配置 exchange.IO("rate", "GetTicker", 10, "1s") // 每秒10次 exchange.IO("rate", "GetDepth", 60, "1m") // 每分钟60次 exchange.IO("rate", "GetAccount", 100, "1h") // 每小时100次 Log("Rate limits configured") }
    python
    def main(): while not exchange.IO("status"): Sleep(1000) # 不同时间周期的限流配置 exchange.IO("rate", "GetTicker", 10, "1s") # 每秒10次 exchange.IO("rate", "GetDepth", 60, "1m") # 每分钟60次 exchange.IO("rate", "GetAccount", 100, "1h") # 每小时100次 Log("Rate limits configured")
    c++
    // C++暂不支持
  • 日内重置时间点

    使用@HHMM@HHMMSS格式指定每日的重置时间:

    javascript
    function main() { while (!exchange.IO("status")) { Sleep(1000) } // 每天08:15重置配额,限制1000次 exchange.IO("quota", "GetTicker", 1000, "@0815") Log("Daily quota configured: 1000 calls, reset at 08:15") }
    python
    def main(): while not exchange.IO("status"): Sleep(1000) # 每天08:15重置配额,限制1000次 exchange.IO("quota", "GetTicker", 1000, "@0815") Log("Daily quota configured: 1000 calls, reset at 08:15")
    c++
    // C++暂不支持
  • 行为模式配置

    默认模式(返回 null)

    超限时 API 调用返回 null,不等待:

    javascript
    function main() { while (!exchange.IO("status")) { Sleep(1000) } // 默认模式:超限返回null exchange.IO("rate", "GetTicker", 3, "1s") for (var i = 0; i < 10; i++) { if (!exchange.IO("status")) { Sleep(5000) continue } var ticker = exchange.GetTicker("rb888") if (ticker) { Log("Call", i+1, "Success") } else { Log("Call", i+1, "Rate limit exceeded, returned null", "#FF0000") } Sleep(100) } }
    python
    def main(): while not exchange.IO("status"): Sleep(1000) # 默认模式:超限返回null exchange.IO("rate", "GetTicker", 3, "1s") for i in range(10): if not exchange.IO("status"): Sleep(5000) continue ticker = exchange.GetTicker("rb888") if ticker: Log("Call", i+1, "Success") else: Log("Call", i+1, "Rate limit exceeded, returned null", "#FF0000") Sleep(100)
    c++
    // C++暂不支持
  • delay模式(自动等待)

    超限时自动等待,直到可以调用:

    javascript
    function main() { while (!exchange.IO("status")) { Sleep(1000) } // delay模式:超限自动等待 exchange.IO("rate", "GetTicker", 3, "1s", "delay") Log("Testing delay mode", "#00FF00") for (var i = 0; i < 10; i++) { if (!exchange.IO("status")) { Sleep(5000) continue } var startTime = new Date().getTime() var ticker = exchange.GetTicker("m888") var endTime = new Date().getTime() Log("Call", i+1, "Time cost:", endTime - startTime, "ms") } }
    python
    import time def main(): while not exchange.IO("status"): Sleep(1000) # delay模式:超限自动等待 exchange.IO("rate", "GetTicker", 3, "1s", "delay") Log("Testing delay mode", "#00FF00") for i in range(10): if not exchange.IO("status"): Sleep(5000) continue startTime = time.time() * 1000 ticker = exchange.GetTicker("m888") endTime = time.time() * 1000 Log("Call", i+1, "Time cost:", endTime - startTime, "ms")
    c++
    // C++暂不支持
  • 限流模式对比

    rate模式 vs quota模式

    javascript
    function main() { while (!exchange.IO("status")) { Sleep(1000) } exchange.IO("mode", 0) // rate模式:平滑限流,不严格对齐时间窗口 // exchange.IO("rate", "GetTicker", 3, "1s") // quota模式:严格对齐时间窗口,例如1s对齐到整秒 exchange.IO("quota", "GetTicker", 3, "1s") for (var i = 0; i < 8; i++) { if (!exchange.IO("status")) { Sleep(5000) continue } var ticker = exchange.GetTicker("c888") Log(_D(), "Call", i+1, ticker ? "Success" : "Quota exceeded") Sleep(150) // 每150ms调用一次 } }
    python
    def main(): while not exchange.IO("status"): Sleep(1000) exchange.IO("mode", 0) # rate模式:平滑限流,不严格对齐时间窗口 # exchange.IO("rate", "GetTicker", 3, "1s") # quota模式:严格对齐时间窗口,例如1s对齐到整秒 exchange.IO("quota", "GetTicker", 3, "1s") for i in range(8): if not exchange.IO("status"): Sleep(5000) continue ticker = exchange.GetTicker("c888") Log(_D(), "Call", i+1, "Success" if ticker else "Quota exceeded") Sleep(150) # 每150ms调用一次
    c++
    // C++暂不支持
  • 实际应用场景

    场景1:单品种行情监控

    监控单个合约的行情,避免频繁调用:

    javascript
    function main() { while (!exchange.IO("status")) { LogStatus("Waiting for connection...") Sleep(1000) } // 设置行情获取频率限制 exchange.IO("rate", "GetTicker", 5, "1s", "delay") Log("Monitoring rb888 (rebar) price") while (true) { if (!exchange.IO("status")) { Sleep(5000) continue } var ticker = exchange.GetTicker("rb888") LogStatus(_D(), "rb888 Price:", ticker.Last, "Buy:", ticker.Buy, "Sell:", ticker.Sell) Sleep(200) } }
    python
    def main(): while not exchange.IO("status"): LogStatus("Waiting for connection...") Sleep(1000) # 设置行情获取频率限制 exchange.IO("rate", "GetTicker", 5, "1s", "delay") Log("Monitoring rb888 (rebar) price") while True: if not exchange.IO("status"): Sleep(5000) continue ticker = exchange.GetTicker("rb888") LogStatus(_D(), "rb888 Price:", ticker["Last"], "Buy:", ticker["Buy"], "Sell:", ticker["Sell"]) Sleep(200)
    c++
    // C++暂不支持
  • 场景2:多品种轮询策略

    轮询多个合约行情,控制总体调用频率:

    javascript
    function main() { while (!exchange.IO("status")) { Sleep(1000) } exchange.IO("mode", 0) // 所有行情函数共享配额 exchange.IO("rate", "GetTicker,GetDepth", 10, "1s") var symbols = ["rb888", "m888", "i888", "c888"] Log("Monitoring multiple symbols:", symbols.join(", ")) while (true) { if (!exchange.IO("status")) { Sleep(5000) continue } for (var i = 0; i < symbols.length; i++) { var ticker = exchange.GetTicker(symbols[i]) if (ticker) { Log(symbols[i], "Price:", ticker.Last) } } Sleep(1000) } }
    python
    def main(): while not exchange.IO("status"): Sleep(1000) exchange.IO("mode", 0) # 所有行情函数共享配额 exchange.IO("rate", "GetTicker,GetDepth", 10, "1s") symbols = ["rb888", "m888", "i888", "c888"] Log("Monitoring multiple symbols:", ", ".join(symbols)) while True: if not exchange.IO("status"): Sleep(5000) continue for symbol in symbols: ticker = exchange.GetTicker(symbol) if ticker: Log(symbol, "Price:", ticker["Last"]) Sleep(1000)
    c++
    // C++暂不支持
  • 场景3:高频交易策略

    对交易相关接口进行严格限流:

    javascript
    function main() { while (!exchange.IO("status")) { Sleep(1000) } // 分别设置不同函数的限流 exchange.IO("rate", "GetTicker", 10, "1s", "delay") exchange.IO("rate", "CreateOrder", 2, "1s", "delay") exchange.IO("rate", "CancelOrder", 5, "1s", "delay") exchange.IO("rate", "GetAccount", 1, "1s", "delay") Log("Rate limits configured for high-frequency trading") // 策略逻辑 while (true) { if (!exchange.IO("status")) { Sleep(5000) continue } var ticker = exchange.GetTicker("rb888") var account = exchange.GetAccount() // 交易逻辑(示例) LogStatus(_D(), "Price:", ticker.Last, "Balance:", account.Balance) Sleep(500) } }
    python
    def main(): while not exchange.IO("status"): Sleep(1000) # 分别设置不同函数的限流 exchange.IO("rate", "GetTicker", 10, "1s", "delay") exchange.IO("rate", "CreateOrder", 2, "1s", "delay") exchange.IO("rate", "CancelOrder", 5, "1s", "delay") exchange.IO("rate", "GetAccount", 1, "1s", "delay") Log("Rate limits configured for high-frequency trading") # 策略逻辑 while True: if not exchange.IO("status"): Sleep(5000) continue ticker = exchange.GetTicker("rb888") account = exchange.GetAccount() # 交易逻辑(示例) LogStatus(_D(), "Price:", ticker["Last"], "Balance:", account["Balance"]) Sleep(500)
    c++
    // C++暂不支持
  • 场景4:日内交易次数控制

    使用 quota 模式控制每日总交易次数:

    javascript
    function main() { while (!exchange.IO("status")) { Sleep(1000) } // 每天09:00重置,限制每日开仓100次 exchange.IO("quota", "CreateOrder", 100, "@0900") Log("Daily order limit: 100 orders, reset at 09:00") var orderCount = 0 while (true) { if (!exchange.IO("status")) { Sleep(5000) continue } var ticker = exchange.GetTicker("m888") // 交易逻辑(示例) // var orderId = exchange.CreateOrder(...) // if (orderId) { // orderCount++ // Log("Order created, daily count:", orderCount) // } else { // Log("Daily order quota exceeded", "#FF0000") // } Sleep(1000) } }
    python
    def main(): while not exchange.IO("status"): Sleep(1000) # 每天09:00重置,限制每日开仓100次 exchange.IO("quota", "CreateOrder", 100, "@0900") Log("Daily order limit: 100 orders, reset at 09:00") orderCount = 0 while True: if not exchange.IO("status"): Sleep(5000) continue ticker = exchange.GetTicker("m888") # 交易逻辑(示例) # orderId = exchange.CreateOrder(...) # if orderId: # orderCount += 1 # Log("Order created, daily count:", orderCount) # else: # Log("Daily order quota exceeded", "#FF0000") Sleep(1000)
    c++
    // C++暂不支持
  • 注意事项

    • 必须检查连接状态

      • 使用API限流功能前,必须先通过exchange.IO("status")检查与交易服务器的连接状态
      • 在循环中持续检查连接状态,确保策略稳定运行
    • 配合立即返回模式

      • 建议配合exchange.IO("mode", 0)立即返回模式使用
      • 避免行情获取函数的等待影响限流效果
    • 商品期货市场

      • 优宽量化支持的市场为商品期货
      • 合约代码格式示例:rb888(螺纹钢)、m888(豆粕)、i888(铁矿石)、c888(玉米)
    • 限流配置时机

      • 建议在策略初始化阶段配置限流规则
      • 限流配置立即生效,无需重启策略
    • quota模式时间对齐

      • quota模式严格对齐时间窗口
      • 例如设置"1s"时,时间窗口对齐到整秒;设置"1m"时,时间窗口对齐到整分钟
    • delay模式的时间差异

      • 使用"delay"参数时,API调用时间与日志记录时间可能存在差异
      • 这是因为函数在等待限流窗口,属于正常现象
    • 合理设置限流参数

      • 根据交易所的实际限制设置参数
      • 预留一定余量,避免触及交易所硬限制

    最佳实践

    • 分级限流策略

      • 对不同类型的API设置不同的限流参数
      • 重要的交易接口(CreateOrder、CancelOrder)设置更严格的限制
      • 行情接口可以相对宽松
    • 结合实际业务

      • 根据策略的实际调用频率设置限流
      • 监控实际调用情况,动态调整限流参数
    • 异常处理

      • 对返回null的情况进行妥善处理
      • 记录超限日志,便于后续分析优化
    • 测试验证

      • 在模拟环境中充分测试限流配置
      • 验证各种极端情况下的表现
    • 持续监控

      • 监控API调用频率和限流触发情况
      • 定期检查和优化限流配置