API限流控制功能用于限制策略对交易所API的调用频率,防止触发交易所的频率限制导致账户被封禁或临时限制。FMZ平台提供了灵活的限流配置方式,支持两种限流模式和多种配置策略。
rate模式(平滑限流) - 适用于一般限流需求 - 不严格对齐时间窗口 - 调用分布相对平滑 - 推荐用于日常API调用限制
quota模式(额度限流)
- 严格对齐时间窗口
- 例如设置"1s"时,窗口对齐到整秒;设置"1m"时,窗口对齐到整分钟
- 适用于需要严格控制时间窗口的场景
- 推荐用于日内配额管理
”`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++暂不支持
“`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++暂不支持
”`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++暂不支持
”`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++暂不支持
”`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++暂不支持
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
}
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() {
// 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++暂不支持
使用@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:获取ticker数据
GetTickers:获取多个ticker数据
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功能。
1. **根据交易所限制进行设置**:参考交易所API文档,将限制值设置为略低于交易所规定的最大值。
2. **预留安全余量**:不要将限制设置为交易所的最大值,建议设置为最大值的70%-80%。
3. **实施分层限流**:针对不同类型的API设置不同的限制,为重要API预留更多余量。
4. **对关键调用使用delay模式**:对于必须成功的API调用,使用```"delay"```模式确保调用成功。
5. **监控API使用情况**:定期检查策略的API调用频率,持续优化调用逻辑。
6. **避免过度调用**:合理设计策略逻辑,减少不必要的API调用。
7. **测试限流配置**:在实盘交易前,先在模拟环境中测试限流配置的合理性。
{@fun/Trade/exchange.IO exchange.IO}, {@fun/Trade/exchange.Go exchange.Go}, {@fun/Trade/exchange.Buy exchange.Buy}, {@fun/Trade/exchange.Sell exchange.Sell}