API限流控制
功能概述
API限流控制功能用于限制策略对交易所API的调用频率,防止因触发交易所的频率限制而导致账号被封禁或临时受限。FMZ平台提供了灵活的限流配置方式,支持两种限流模式和多种配置策略。
为什么需要API限流
-
避免触发交易所限制:大多数交易所对API调用频率有严格限制,一旦超限,可能导致账号被临时或永久封禁。
-
合理分配API配额:在多策略、多交易对场景下,需要合理分配API调用资源。
-
提高策略稳定性:通过主动限流,避免因频繁调用导致的连接失败和数据获取异常。
-
符合交易所规范:遵守交易所的API使用规范,维护良好的API使用关系。
两种限流模式
rate模式(平滑限流)
-
适用于一般的限流需求
-
不严格对齐时间窗口
-
调用分布相对平滑
-
推荐用于日常的API调用限制
quota模式(额度限流)
-
严格对齐时间窗口
-
例如:设置
"1s"时,窗口对齐到整秒;设置"1m"时,窗口对齐到整分钟 -
适用于需要严格控制时间窗口的场景
-
推荐用于日内配额管理
基本用法
rate模式基本示例
示例
- undefinedjavascriptfunction 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) } }pythondef 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)rustfn main() { // Limit GetTicker to maximum 10 times per second let _ = exchange.IO(("rate", "GetTicker", 10, "1s")); // Normal API calls for _i in 0..20 { match exchange.GetTicker("BTC_USDT") { Ok(ticker) => Log!("Success:", ticker.Last), Err(_) => Log!("Rate limit exceeded"), // Returns Err when exceeding 10 times/second } Sleep(50); } }c++// C++暂不支持
-
quota模式基本示例
javascriptfunction 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 } }pythondef 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 limitrustfn main() { // Strict limit, time window aligned to whole seconds let _ = exchange.IO(("quota", "GetTicker", 5, "1s")); for i in 0..10 { match exchange.GetTicker("BTC_USDT") { Ok(_) => Log!(_D(None), "Call", i + 1, "Success"), Err(_) => Log!(_D(None), "Call", i + 1, "Quota exceeded"), } Sleep(150); // About 6-7 calls per second, will trigger limit } }c++// C++暂不支持 -
函数名配置
单个函数限流
javascriptfunction 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") }pythondef 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")rustfn main() { // Only limit GetTicker function let _ = exchange.IO(("rate", "GetTicker", 10, "1s")); // GetTicker is limited, GetDepth is not limited let _ = exchange.GetTicker("BTC_USDT"); let _ = exchange.GetDepth("BTC_USDT"); }c++// C++暂不支持 -
多个函数联合限流
javascriptfunction 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 } } }pythondef 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 quotarustfn main() { // GetTicker and GetDepth share quota, total 10 times per second let _ = exchange.IO(("rate", "GetTicker,GetDepth", 10, "1s")); for i in 0..15 { if i % 2 == 0 { let _ = exchange.GetTicker("BTC_USDT"); // Counted in shared quota } else { let _ = exchange.GetDepth("BTC_USDT"); // Counted in shared quota } } }c++// C++暂不支持 -
使用通配符限制所有函数
javascriptfunction 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) }pythondef 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)rustfn main() { // Limit all API calls to total 100 times per minute let _ = exchange.IO(("rate", "*", 100, "1m")); // All calls are counted in total quota let _ = exchange.GetTicker("BTC_USDT"); let _ = exchange.GetDepth("BTC_USDT"); let _ = exchange.GetAccount(); let _ = exchange.CreateOrder("BTC_USDT", "buy", 50000, 0.001); }c++// C++暂不支持 -
时间周期配置
支持的时间单位
-
ns:纳秒 -
us或µs:微秒 -
ms:毫秒 -
s:秒 -
m:分钟 -
h:小时 -
d:天
示例:
"100ms","1s","5m","1h","1d"javascriptfunction 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 }pythondef 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次rustfn main() { // 不同时间周期的配置 let _ = exchange.IO(("rate", "GetTicker", 10, "1s")); // 每秒10次 let _ = exchange.IO(("rate", "GetDepth", 30, "1m")); // 每分钟30次 let _ = exchange.IO(("rate", "GetAccount", 100, "1h")); // 每小时100次 let _ = exchange.IO(("rate", "CreateOrder", 500, "1d")); // 每天500次 }c++// C++暂不支持 -
-
重置时间点配置
使用
@HHMM或@HHMMSS格式指定每日的重置时间点,仅在 quota 模式下有效。javascriptfunction 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") }pythondef 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")rustfn main() { // Reset quota daily at 08:15 let _ = exchange.IO(("quota", "GetTicker", 1000, "@0815")); // Reset quota daily at 00:00 let _ = exchange.IO(("quota", "CreateOrder", 500, "@0000")); // Reset quota daily at 23:59:59 let _ = exchange.IO(("quota", "*", 5000, "@235959")); }c++// C++暂不支持 -
行为模式
默认模式(超限返回null)
javascriptfunction 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) } } }pythondef 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)rustfn main() { let _ = exchange.IO(("rate", "GetTicker", 5, "1s")); // 不指定 behavior 参数 for i in 0..10 { match exchange.GetTicker("BTC_USDT") { Ok(ticker) => Log!("Call", i + 1, "Success:", ticker.Last), Err(_) => { Log!("Call", i + 1, "Failed: rate limit exceeded"); // 可选择 Sleep 等待,或跳过本次调用 Sleep(200); } } } }c++// C++暂不支持 -
delay模式(超限自动等待)
javascriptfunction 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 } }pythondef 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不会为Nonerustfn main() { let _ = exchange.IO(("rate", "GetTicker", 5, "1s", "delay")); // 指定delay参数 // 调用超限时会自动等待,确保每次调用都成功 for i in 0..10 { let ticker = exchange.GetTicker("BTC_USDT").unwrap(); Log!("Call", i + 1, "Success:", ticker.Last); // ticker不会返回Err } }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:防止触发交易所的频率限制
javascriptfunction 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) } }pythondef 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)rustfn main() { // 假设交易所限制:GetTicker 每秒 20 次,CreateOrder 每秒 5 次 // 将频率设置为略低于交易所限制的值,以预留安全余量 let _ = exchange.IO(("rate", "GetTicker", 15, "1s")); let _ = exchange.IO(("rate", "CreateOrder", 4, "1s")); loop { if let Ok(ticker) = exchange.GetTicker("BTC_USDT") { if ticker.Last < 50000.0 { let _ = exchange.CreateOrder("BTC_USDT", "buy", ticker.Last, 0.001); } } Sleep(100); } }c++// C++ 暂不支持 -
场景2:多交易所对象统一限流
javascriptfunction 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) } }pythondef 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)rustfn main() { // 为每个交易所对象设置限流 for e in exchanges.iter() { let _ = e.IO(("rate", "GetTicker", 10, "1s")); let _ = e.IO(("rate", "CreateOrder", 2, "1s")); } // 并发获取多个交易所的行情 loop { for e in exchanges.iter() { if let Ok(ticker) = e.GetTicker("BTC_USDT") { Log!(e.GetName(), "Price:", ticker.Last); } } Sleep(1000); } }c++// C++ 暂不支持 -
场景3:日内配额管理
javascriptfunction 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) } }pythondef 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)rustfn main() { // 每天最多 1000 次 API 调用,每天早上 8 点重置 let _ = exchange.IO(("quota", "*", 1000, "@0800")); let mut callCount = 0; loop { match exchange.GetTicker("BTC_USDT") { Ok(ticker) => { callCount += 1; Log!("Call count:", callCount, "Price:", ticker.Last); } Err(_) => { Log!("Daily quota exceeded, waiting for tomorrow 08:00"); Sleep(60000); // 等待 1 分钟后重试 } } Sleep(10000); } }c++// C++ 暂不支持 -
场景4:组合限流策略
javascriptfunction main() { // 组合使用多种限流策略 // 1. 行情类API每秒限流 exchange.IO("rate", "GetTicker,GetDepth", 20, "1s") // 2. 交易类API每秒限流 exchange.IO("rate", "CreateOrder,CancelOrder", 5, "1s") // 3. 账户查询类API每分钟限流 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) } }pythonimport time def main(): # 组合使用多种限流策略 # 1. 行情类API每秒限流 exchange.IO("rate", "GetTicker,GetDepth", 20, "1s") # 2. 交易类API每秒限流 exchange.IO("rate", "CreateOrder,CancelOrder", 5, "1s") # 3. 账户查询类API每分钟限流 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)rustfn main() { // 组合使用多种限流策略 // 1. 行情类API每秒限流 let _ = exchange.IO(("rate", "GetTicker,GetDepth", 20, "1s")); // 2. 交易类API每秒限流 let _ = exchange.IO(("rate", "CreateOrder,CancelOrder", 5, "1s")); // 3. 账户查询类API每分钟限流 let _ = exchange.IO(("rate", "GetAccount,GetPositions", 30, "1m")); // 4. 所有API每日总配额 let _ = exchange.IO(("quota", "*", 10000, "@0000")); Log!("Multi-level rate limiting configured"); // 策略主循环 loop { // 获取行情数据 let ticker = exchange.GetTicker("BTC_USDT"); let depth = exchange.GetDepth("BTC_USDT"); // 查询账户信息 if UnixNano() / 1000000 % 60000 < 1000 { // 每分钟查询一次 let account = exchange.GetAccount(); Log!("Account:", account); } // 交易逻辑 if let Ok(t) = ticker { if t.Last < 50000.0 { let _ = exchange.CreateOrder("BTC_USDT", "buy", t.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时,当前时间窗口也会重置。
javascriptfunction 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次,成功 }pythondef 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次,成功rustfn main() { // quota模式:严格对齐到整秒 let _ = exchange.IO(("quota", "GetTicker", 3, "1s")); // 假设当前时间为 12:00:00.500 let _ = exchange.GetTicker("BTC_USDT"); // 第1次,成功 let _ = exchange.GetTicker("BTC_USDT"); // 第2次,成功 let _ = exchange.GetTicker("BTC_USDT"); // 第3次,成功 let _ = exchange.GetTicker("BTC_USDT"); // 第4次,失败(超限) Sleep(500); // 等待500ms,此时时间为 12:00:01.000 // 窗口已重置 let _ = exchange.GetTicker("BTC_USDT"); // 新窗口第1次,成功 }c++// C++暂不支持 -
2. delay模式下的时间差异
使用
"delay"参数时,实际的API调用时间与日志记录的时间可能并不一致。这是因为触发限流时程序会进入等待,而日志记录的是等待结束后的时间。javascriptfunction 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次是在新窗口执行的 }pythondef 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次是在新窗口执行的rustfn main() { let _ = exchange.IO(("rate", "GetTicker", 2, "1s", "delay")); Log!(_D(None), "Call 1"); // 12:00:00.000 let _ = exchange.GetTicker("BTC_USDT"); Log!(_D(None), "Call 2"); // 12:00:00.100 let _ = exchange.GetTicker("BTC_USDT"); Log!(_D(None), "Call 3"); // 12:00:00.200,但实际会等待到12:00:01.000 let _ = exchange.GetTicker("BTC_USDT"); // 触发限流,自动等待 Log!(_D(None), "Call 3 completed"); // 日志显示12:00:01.000+ // 看起来一秒内调用了3次,但实际第3次是在新窗口执行的 }c++// C++暂不支持 -
3. Buy/Sell函数的限流
Buy和Sell函数在底层均调用CreateOrder,因此其限流规则遵循CreateOrder的设置。javascriptfunction 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限制 } } }pythondef 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限制rustfn main() { // 设置CreateOrder限流 let _ = exchange.IO(("rate", "CreateOrder", 5, "1s")); // Buy和Sell也会受到此限制 for i in 0..10 { if i % 2 == 0 { let _ = exchange.Buy(50000, 0.001); // 受CreateOrder限制 } else { let _ = exchange.Sell(51000, 0.001); // 受CreateOrder限制 } } }c++// C++暂不支持 -
4. Go函数的限流
Go函数的限流取决于实际被并发调用的函数。javascriptfunction 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") } }pythondef 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")rustfn main() { // 限制GetTicker let _ = exchange.IO(("rate", "GetTicker", 5, "1s")); // 并发调用GetTicker时受限 // Rust中exchange.Go为类型化写法,使用Go::GetTicker token let mut tasks = Vec::new(); for _i in 0..10 { tasks.push(exchange.Go(Go::GetTicker, ("BTC_USDT",))); } for (i, task) in tasks.iter().enumerate() { match task.wait(0) { Ok(_) => Log!("Task", i, "Success"), Err(_) => Log!("Task", i, "Rate limited"), } } }c++// C++暂不支持 -
5. IO/api的限流
IO/api限流仅对exchange.IO("api", ...)调用生效,不会影响其他exchange.IO功能。javascriptfunction 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") // 设置其它限流,不受限 }pythondef 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") # 设置其它限流,不受限rustfn main() { // 限制exchange.IO("api", ...)调用 let _ = exchange.IO(("rate", "IO/api", 10, "1s")); // 受限制 for i in 0..15 { match exchange.IO(("api", "GET", "/api/v5/account/balance", "")) { Ok(_) => Log!("API call", i, "Success"), Err(_) => Log!("API call", i, "Rate limited"), } } // 不受限制 let _ = exchange.IO(("currency", "LTC_USDT")); // 切换交易对,不受限 let _ = exchange.IO(("rate", "GetDepth", 5, "1s")); // 设置其它限流,不受限 }c++// C++暂不支持 -
最佳实践
-
根据交易所限制设置:请参考交易所的 API 文档,将限流值设置为略低于交易所限制的水平。
-
留出安全余量:请勿将限流值设置为交易所允许的最大值,建议设置为最大值的 70%-80%。
-
分层限流:针对不同类型的 API 设置不同的限流值,并为重要 API 保留更多余量。
-
使用 delay 模式处理关键调用:对于必须成功的 API 调用,请使用
"delay"模式以确保调用成功。 -
监控 API 使用情况:定期检查策略的 API 调用频率,并持续优化调用逻辑。
-
避免过度调用:合理设计策略逻辑,避免不必要的 API 调用。
-
测试限流配置:在实盘运行前,先在模拟环境中测试限流配置是否合理。
-
参考