优宽量化平台支持对商品期货交易所API调用进行频率限制,防止触发交易所的频率限制。通过合理配置API限流,可以有效避免因频繁调用导致的接口限制问题,保障策略稳定运行。
API限流功能支持两种限流模式:
exchange.IO("rate", functionNames, maxCalls, period, [behavior])
exchange.IO("quota", functionNames, maxCalls, period, [behavior])
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| mode | string | 是 | 限流模式:”rate”(平滑限流)或 “quota”(额度限流) |
| functionNames | string | 是 | 要限制的函数名,支持单个函数、多个函数(逗号分隔)、通配符(*表示所有函数) |
| maxCalls | number | 是 | 时间周期内允许的最大调用次数 |
| period | string | 是 | 时间周期或重置时间点。支持时间单位:ns、us、µs、ms、s、m、h、d(例如:”1s”、”1m”、”1h”)。支持重置时间点:@HHMM 或 @HHMMSS(例如:”@0815”表示每天08:15重置) |
| behavior | string | 否 | 超限行为。默认为空(超限返回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", ...)调用生效
限制单个函数的调用频率:
”`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++暂不支持
“`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++暂不支持
多个函数共享同一个限流配额: “`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++暂不支持
使用通配符*限制所有API调用:
“`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++暂不支持
支持多种时间单位:ns(纳秒)、us/µs(微秒)、ms(毫秒)、s(秒)、m(分钟)、h(小时)、d(天)。
“`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++暂不支持
使用@HHMM或@HHMMSS格式指定每日的重置时间:
“`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++暂不支持
超限时 API 调用返回 null,不等待: “`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++暂不支持
超限时自动等待,直到可以调用: “`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++暂不支持
”`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++暂不支持
监控单个合约的行情,避免频繁调用: “`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++暂不支持
轮询多个合约行情,控制总体调用频率: “`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++暂不支持
对交易相关接口进行严格限流: “`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++暂不支持
使用 quota 模式控制每日总交易次数:
必须检查连接状态
exchange.IO("status")检查与交易服务器的连接状态配合立即返回模式
exchange.IO("mode", 0)立即返回模式使用商品期货市场
限流配置时机
quota模式时间对齐
delay模式的时间差异
合理设置限流参数
分级限流策略
结合实际业务
异常处理
测试验证
持续监控