API限流控制功能用于限制策略对交易所API的调用频率,防止触发交易所的频率限制导致账号被封禁或临时限制。FMZ平台提供了灵活的限流配置方式,支持两种限流模式和多种配置策略。
rate模式(平滑限流) - 适用于一般限流需求 - 不严格对齐时间窗口 - 调用分布相对平滑 - 推荐用于日常API调用限制
quota模式(配额限流)
- 严格对齐时间窗口
- 例如设置"1s"时,窗口对齐到整秒;设置"1m"时,窗口对齐到整分钟
- 适用于需要严格控制时间窗口的场景
- 推荐用于日内配额管理
”`javascript function main() { // 限制GetTicker每秒最多调用10次 exchange.IO(“rate”, “GetTicker”, 10, “1s”)
// 正常调用API
for (var i = 0; i < 20; i++) {
var ticker = exchange.GetTicker("BTC_USDT")
if (ticker) {
Log("Success:", ticker.Last)
} else {
Log("Rate limit exceeded") // 超过10次/秒时将返回null
}
Sleep(50)
}
}
python
def main():
# 限制GetTicker每秒最多调用10次
exchange.IO(“rate”, “GetTicker”, 10, “1s”)
# 正常调用API
for i in range(20):
ticker = exchange.GetTicker("BTC_USDT")
if ticker:
Log("Success:", ticker["Last"])
else:
Log("Rate limit exceeded") # 超过10次/秒时将返回None
Sleep(50)```
// C++暂不支持此功能
“`javascript
function main() {
// 严格限制,时间窗口对齐至整秒
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) // 每秒约6-7次调用,将触发限制
}
}
python
def main():
# 严格限制,时间窗口对齐至整秒
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) # 每秒约6-7次调用,将触发限制```
// C++暂不支持此功能
”`javascript function main() { // 仅限制GetTicker函数 exchange.IO(“rate”, “GetTicker”, 10, “1s”)
// GetTicker受限,GetDepth不受限
exchange.GetTicker("BTC_USDT")
exchange.GetDepth("BTC_USDT")
}
python
def main():
# 仅限制GetTicker函数
exchange.IO(“rate”, “GetTicker”, 10, “1s”)
# GetTicker受限,GetDepth不受限
exchange.GetTicker("BTC_USDT")
exchange.GetDepth("BTC_USDT")```
// C++暂不支持
”`javascript function main() { // GetTicker和GetDepth共享配额,合计每秒10次 exchange.IO(“rate”, “GetTicker,GetDepth”, 10, “1s”)
for (var i = 0; i < 15; i++) {
if (i % 2 == 0) {
exchange.GetTicker("BTC_USDT") // 计入共享配额
} else {
exchange.GetDepth("BTC_USDT") // 计入共享配额
}
}
}
python
def main():
# GetTicker和GetDepth共享配额,合计每秒10次
exchange.IO(“rate”, “GetTicker,GetDepth”, 10, “1s”)
for i in range(15):
if i % 2 == 0:
exchange.GetTicker("BTC_USDT") # 计入共享配额
else:
exchange.GetDepth("BTC_USDT") # 计入共享配额```
// C++暂不支持
”`javascript function main() { // 限制所有API调用,合计每分钟100次 exchange.IO(“rate”, “*”, 100, “1m”)
// 所有调用均计入总配额
exchange.GetTicker("BTC_USDT")
exchange.GetDepth("BTC_USDT")
exchange.GetAccount()
exchange.CreateOrder("BTC_USDT", "buy", 50000, 0.001)
}
python
def main():
# 限制所有API调用,合计每分钟100次
exchange.IO(“rate”, “*”, 100, “1m”)
# 所有调用均计入总配额
exchange.GetTicker("BTC_USDT")
exchange.GetDepth("BTC_USDT")
exchange.GetAccount()
exchange.CreateOrder("BTC_USDT", "buy", 50000, 0.001)```
// C++暂不支持
function 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次
}
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++暂不支持
ns:纳秒us 或 µs:微秒ms:毫秒s:秒m:分钟h:小时d:天示例:"100ms", "1s", "5m", "1h", "1d"
“`javascript
function main() {
// 每天08:15重置配额
exchange.IO(“quota”, “GetTicker”, 1000, “@0815”)
// 每天00:00重置配额
exchange.IO("quota", "CreateOrder", 500, "@0000")
// 每天23:59:59重置配额
exchange.IO("quota", "*", 5000, "@235959")
}
python
def main():
# 每天08:15重置配额
exchange.IO(“quota”, “GetTicker”, 1000, “@0815”)
# 每天00:00重置配额
exchange.IO("quota", "CreateOrder", 500, "@0000")
# 每天23:59:59重置配额
exchange.IO("quota", "*", 5000, "@235959")```
// C++暂不支持
使用@HHMM或@HHMMSS格式指定每天的重置时间点,仅在quota模式下有效。
“`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++暂不支持
”`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++暂不支持
CreateOrder:创建订单CancelOrder:取消订单Buy:买入(受CreateOrder限制)Sell:卖出(受CreateOrder限制)CreateConditionOrder:创建条件单CancelConditionOrder:取消条件单GetAccount:获取账户信息GetAssets:获取资产信息GetPositions:获取持仓信息GetOrder:获取单个订单GetOrders:获取所有订单GetHistoryOrders:获取历史订单GetConditionOrder:获取单个条件单GetConditionOrders:获取所有条件单GetHistoryConditionOrders:获取历史条件单GetTicker:获取行情数据GetTickers:获取多个交易对的行情数据GetDepth:获取市场深度GetRecords:获取K线数据GetTrades:获取最新成交记录GetMarkets:获取市场列表GetFundings:获取资金费率SetMarginLevel:设置杠杆倍数Go:并发调用(受实际调用函数限制)IO/api:自定义API调用(仅限exchange.IO(“api”, …))”`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++暂不支持
”`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++暂不支持此功能
”`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++暂不支持此功能
”`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++暂不支持
”`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++暂不支持
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() { 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++暂不支持
使用"delay"参数时,实际API调用时间与日志记录时间可能存在差异。这是因为当触发限流时,程序会进入等待状态,而日志记录的是等待结束后的时间。
“`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++暂不支持
Buy和Sell函数底层调用CreateOrder,因此它们的限流规则遵循CreateOrder的配置。
“`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++暂不支持
Go函数的限流取决于实际并发调用的函数。
“`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++暂不支持
IO/api限流仅对exchange.IO("api", ...)调用生效,不影响其他exchange.IO功能。
"delay"模式确保执行成功。{@fun/Trade/exchange.IO exchange.IO}, {@fun/Trade/exchange.Go exchange.Go}, {@fun/Trade/exchange.Buy exchange.Buy}, {@fun/Trade/exchange.Sell exchange.Sell}