API Rate Limiting Control
Overview
The API rate limiting control feature is used to limit how frequently a strategy calls the exchange's API, preventing account bans or temporary restrictions caused by triggering the exchange's rate limits. The FMZ platform provides flexible rate limiting configuration options, supporting two rate limiting modes and multiple configuration strategies.
Why API Rate Limiting Is Needed
-
Avoid triggering exchange limits: Most exchanges impose strict limits on API call frequency; once exceeded, your account may be temporarily or permanently banned.
-
Allocate API quota sensibly: In multi-strategy, multi-trading-pair scenarios, API call resources need to be allocated sensibly.
-
Improve strategy stability: By proactively rate limiting, you avoid connection failures and data retrieval anomalies caused by frequent calls.
-
Comply with exchange rules: Adhere to the exchange's API usage rules and maintain a healthy API usage relationship.
Two Rate Limiting Modes
rate mode (smooth rate limiting)
-
Suitable for general rate limiting needs
-
Does not strictly align to time windows
-
Distributes calls relatively smoothly
-
Recommended for everyday API call limiting
quota mode (quota-based rate limiting)
-
Strictly aligns to time windows
-
For example: when set to
"1s", the window aligns to whole seconds; when set to"1m", the window aligns to whole minutes -
Suitable for scenarios that require strict time window control
-
Recommended for intraday quota management
Basic Usage
Basic rate Mode Example
Examples
- 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++ is not supported yet
-
Basic quota Mode Example
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++ is not supported yet -
Function Name Configuration
Rate Limiting a Single Function
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++ not supported yet -
Joint Rate Limiting Across Multiple Functions
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++ not supported yet -
Restrict All Functions Using Wildcards
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++ not supported yet -
Time Period Configuration
Supported Time Units
-
ns: nanoseconds -
usorµs: microseconds -
ms: milliseconds -
s: seconds -
m: minutes -
h: hours -
d: days
Example:
"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(): # Configurations for different time periods 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 dayrustfn main() { // Configurations for different time periods let _ = exchange.IO(("rate", "GetTicker", 10, "1s")); // 10 times per second let _ = exchange.IO(("rate", "GetDepth", 30, "1m")); // 30 times per minute let _ = exchange.IO(("rate", "GetAccount", 100, "1h")); // 100 times per hour let _ = exchange.IO(("rate", "CreateOrder", 500, "1d")); // 500 times per day }c++// C++ not supported yet -
-
Reset Time Point Configuration
Use
@HHMMor@HHMMSSformat to specify the daily reset time point, valid only in quota mode.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++ not supported yet -
Behavior Modes
Default Mode (returns null when limit exceeded)
javascriptfunction main() { exchange.IO("rate", "GetTicker", 5, "1s") // behavior parameter not specified 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") // Optionally Sleep to wait, or skip this call Sleep(200) } } }pythondef main(): exchange.IO("rate", "GetTicker", 5, "1s") # behavior parameter not specified 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") # Optionally Sleep to wait, or skip this call Sleep(200)rustfn main() { let _ = exchange.IO(("rate", "GetTicker", 5, "1s")); // behavior parameter not specified 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"); // Optionally Sleep to wait, or skip this call Sleep(200); } } } }c++// C++ not supported yet -
delay mode (automatically wait when rate limit is exceeded)
javascriptfunction main() { exchange.IO("rate", "GetTicker", 5, "1s", "delay") // Specify the delay parameter // When the call exceeds the rate limit, it automatically waits to ensure every call succeeds for (var i = 0; i < 10; i++) { var ticker = exchange.GetTicker("BTC_USDT") Log("Call", i+1, "Success:", ticker.Last) // ticker will not be null } }pythondef main(): exchange.IO("rate", "GetTicker", 5, "1s", "delay") # Specify the delay parameter # When the call exceeds the rate limit, it automatically waits to ensure every call succeeds for i in range(10): ticker = exchange.GetTicker("BTC_USDT") Log("Call", i+1, "Success:", ticker["Last"]) # ticker will not be Nonerustfn main() { let _ = exchange.IO(("rate", "GetTicker", 5, "1s", "delay")); // Specify the delay parameter // When the call exceeds the rate limit, it automatically waits to ensure every call succeeds for i in 0..10 { let ticker = exchange.GetTicker("BTC_USDT").unwrap(); Log!("Call", i + 1, "Success:", ticker.Last); // ticker will not return Err } }c++// Not yet supported in C++ -
List of Supported Functions
Trading Functions
CreateOrder: Create an orderCancelOrder: Cancel an orderBuy: Buy (subject to CreateOrder restrictions)Sell: Sell (subject to CreateOrder restrictions)CreateConditionOrder: Create a conditional orderCancelConditionOrder: Cancel a conditional order
Account Functions
GetAccount: Get account informationGetAssets: Get asset informationGetPositions: Get position information
Order Functions
GetOrder: Get a single orderGetOrders: Get all ordersGetHistoryOrders: Get historical ordersGetConditionOrder: Get a single conditional orderGetConditionOrders: Get all conditional ordersGetHistoryConditionOrders: Get historical conditional orders
Market Data Functions
GetTicker: Get a single tickerGetTickers: Get multiple tickersGetDepth: Get market depthGetRecords: Get K-line (candlestick) dataGetTrades: Get the latest trade records
Other Functions
GetMarkets: Get the list of marketsGetFundings: Get funding ratesSetMarginLevel: Set the leverage levelGo: Concurrent call (subject to the restrictions of the actual function being called)IO/api: Custom API call (limited to exchange.IO("api", ...))
-
Practical Application Scenarios
### Scenario 1: Preventing Exchange Rate Limit Triggers
javascriptfunction main() { // Assume exchange limits: GetTicker 20 times per second, CreateOrder 5 times per second // Set the rate slightly below the exchange limit to reserve a safety margin 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(): # Assume exchange limits: GetTicker 20 times per second, CreateOrder 5 times per second # Set the rate slightly below the exchange limit to reserve a safety margin 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() { // Assume exchange limits: GetTicker 20 times per second, CreateOrder 5 times per second // Set the rate slightly below the exchange limit to reserve a safety margin 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++ not supported yet -
Scenario 2: Unified Rate Limiting Across Multiple Exchange Objects
javascriptfunction main() { // Set rate limiting for each exchange object for (var i = 0; i < exchanges.length; i++) { exchanges[i].IO("rate", "GetTicker", 10, "1s") exchanges[i].IO("rate", "CreateOrder", 2, "1s") } // Concurrently fetch tickers from multiple exchanges 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(): # Set rate limiting for each exchange object for i in range(len(exchanges)): exchanges[i].IO("rate", "GetTicker", 10, "1s") exchanges[i].IO("rate", "CreateOrder", 2, "1s") # Concurrently fetch tickers from multiple exchanges 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() { // Set rate limiting for each exchange object for e in exchanges.iter() { let _ = e.IO(("rate", "GetTicker", 10, "1s")); let _ = e.IO(("rate", "CreateOrder", 2, "1s")); } // Concurrently fetch tickers from multiple exchanges loop { for e in exchanges.iter() { if let Ok(ticker) = e.GetTicker("BTC_USDT") { Log!(e.GetName(), "Price:", ticker.Last); } } Sleep(1000); } }c++// C++ is not supported yet -
Scenario 3: Intraday Quota Management
javascriptfunction main() { // Maximum 1000 API calls per day, resets at 08:00 every morning 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) // Wait 1 minute before retrying } Sleep(10000) } }pythondef main(): # Maximum 1000 API calls per day, resets at 08:00 every morning 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) # Wait 1 minute before retrying Sleep(10000)rustfn main() { // Maximum 1000 API calls per day, resets at 08:00 every morning 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); // Wait 1 minute before retrying } } Sleep(10000); } }c++// C++ is not supported yet -
Scenario 4: Combined Rate Limiting Strategy
javascriptfunction main() { // Combine multiple rate limiting strategies // 1. Rate limit market data APIs per second exchange.IO("rate", "GetTicker,GetDepth", 20, "1s") // 2. Rate limit trading APIs per second exchange.IO("rate", "CreateOrder,CancelOrder", 5, "1s") // 3. Rate limit account query APIs per minute exchange.IO("rate", "GetAccount,GetPositions", 30, "1m") // 4. Total daily quota for all APIs exchange.IO("quota", "*", 10000, "@0000") Log("Multi-level rate limiting configured") // Main strategy loop while (true) { // Fetch market data var ticker = exchange.GetTicker("BTC_USDT") var depth = exchange.GetDepth("BTC_USDT") // Query account info if (Date.now() % 60000 < 1000) { // Query once per minute var account = exchange.GetAccount() Log("Account:", account) } // Trading logic if (ticker && ticker.Last < 50000) { exchange.CreateOrder("BTC_USDT", "buy", ticker.Last, 0.001) } Sleep(500) } }pythonimport time def main(): # Combine multiple rate limiting strategies # 1. Rate limit market data APIs per second exchange.IO("rate", "GetTicker,GetDepth", 20, "1s") # 2. Rate limit trading APIs per second exchange.IO("rate", "CreateOrder,CancelOrder", 5, "1s") # 3. Rate limit account query APIs per minute exchange.IO("rate", "GetAccount,GetPositions", 30, "1m") # 4. Total daily quota for all APIs exchange.IO("quota", "*", 10000, "@0000") Log("Multi-level rate limiting configured") # Main strategy loop while True: # Fetch market data ticker = exchange.GetTicker("BTC_USDT") depth = exchange.GetDepth("BTC_USDT") # Query account info if int(time.time() * 1000) % 60000 < 1000: # Query once per minute account = exchange.GetAccount() Log("Account:", account) # Trading logic if ticker and ticker["Last"] < 50000: exchange.CreateOrder("BTC_USDT", "buy", ticker["Last"], 0.001) Sleep(500)rustfn main() { // Combine multiple rate limiting strategies // 1. Rate limit market data APIs per second let _ = exchange.IO(("rate", "GetTicker,GetDepth", 20, "1s")); // 2. Rate limit trading APIs per second let _ = exchange.IO(("rate", "CreateOrder,CancelOrder", 5, "1s")); // 3. Rate limit account query APIs per minute let _ = exchange.IO(("rate", "GetAccount,GetPositions", 30, "1m")); // 4. Total daily quota for all APIs let _ = exchange.IO(("quota", "*", 10000, "@0000")); Log!("Multi-level rate limiting configured"); // Main strategy loop loop { // Fetch market data let ticker = exchange.GetTicker("BTC_USDT"); let depth = exchange.GetDepth("BTC_USDT"); // Query account info if UnixNano() / 1000000 % 60000 < 1000 { // Query once per minute let account = exchange.GetAccount(); Log!("Account:", account); } // Trading logic if let Ok(t) = ticker { if t.Last < 50000.0 { let _ = exchange.CreateOrder("BTC_USDT", "buy", t.Last, 0.001); } } Sleep(500); } }c++// C++ not supported yet -
Notes
1. Time Window Alignment in quota Mode
The quota mode strictly aligns to time windows:
-
"1s": aligns to whole seconds (e.g., 12:00:00, 12:00:01, 12:00:02……) -
"1m": aligns to whole minutes (e.g., 12:00:00, 12:01:00, 12:02:00……) -
"1h": aligns to whole hours (e.g., 12:00:00, 13:00:00, 14:00:00……)
This means that even if counting starts at 12:00:00.500, the current time window will still reset at 12:00:01.000.
javascriptfunction main() { // quota mode: strictly aligns to whole seconds exchange.IO("quota", "GetTicker", 3, "1s") // Assume the current time is 12:00:00.500 exchange.GetTicker("BTC_USDT") // 1st call, success exchange.GetTicker("BTC_USDT") // 2nd call, success exchange.GetTicker("BTC_USDT") // 3rd call, success exchange.GetTicker("BTC_USDT") // 4th call, failed (limit exceeded) Sleep(500) // Wait 500ms; the time is now 12:00:01.000 // Window has been reset exchange.GetTicker("BTC_USDT") // 1st call in the new window, success }pythondef main(): # quota mode: strictly aligns to whole seconds exchange.IO("quota", "GetTicker", 3, "1s") # Assume the current time is 12:00:00.500 exchange.GetTicker("BTC_USDT") # 1st call, success exchange.GetTicker("BTC_USDT") # 2nd call, success exchange.GetTicker("BTC_USDT") # 3rd call, success exchange.GetTicker("BTC_USDT") # 4th call, failed (limit exceeded) Sleep(500) # Wait 500ms; the time is now 12:00:01.000 # Window has been reset exchange.GetTicker("BTC_USDT") # 1st call in the new window, successrustfn main() { // quota mode: strictly aligns to whole seconds let _ = exchange.IO(("quota", "GetTicker", 3, "1s")); // Assume the current time is 12:00:00.500 let _ = exchange.GetTicker("BTC_USDT"); // 1st call, success let _ = exchange.GetTicker("BTC_USDT"); // 2nd call, success let _ = exchange.GetTicker("BTC_USDT"); // 3rd call, success let _ = exchange.GetTicker("BTC_USDT"); // 4th call, failed (limit exceeded) Sleep(500); // Wait 500ms; the time is now 12:00:01.000 // Window has been reset let _ = exchange.GetTicker("BTC_USDT"); // 1st call in the new window, success }c++// C++ is not supported yet -
-
2. Time discrepancy in delay mode
When using the
"delay"parameter, the actual API call time may not match the time recorded in the log. This is because the program enters a waiting state when rate limiting is triggered, while the log records the time after the wait ends.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, but it will actually wait until 12:00:01.000 exchange.GetTicker("BTC_USDT") // Triggers rate limiting, waits automatically Log(_D(), "Call 3 completed") // Log shows 12:00:01.000+ // It appears that 3 calls were made within one second, but the 3rd call was actually executed in a new window }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, but it will actually wait until 12:00:01.000 exchange.GetTicker("BTC_USDT") # Triggers rate limiting, waits automatically Log(_D(), "Call 3 completed") # Log shows 12:00:01.000+ # It appears that 3 calls were made within one second, but the 3rd call was actually executed in a new windowrustfn 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, but it will actually wait until 12:00:01.000 let _ = exchange.GetTicker("BTC_USDT"); // Triggers rate limiting, waits automatically Log!(_D(None), "Call 3 completed"); // Log shows 12:00:01.000+ // It appears that 3 calls were made within one second, but the 3rd call was actually executed in a new window }c++// C++ is not supported yet -
3. Rate limiting for the Buy/Sell functions
Both the
BuyandSellfunctions callCreateOrderunder the hood, so their rate-limiting rules follow theCreateOrdersettings.javascriptfunction main() { // Set CreateOrder rate limiting exchange.IO("rate", "CreateOrder", 5, "1s") // Buy and Sell are also subject to this limit for (var i = 0; i < 10; i++) { if (i % 2 == 0) { exchange.Buy(50000, 0.001) // Subject to the CreateOrder limit } else { exchange.Sell(51000, 0.001) // Subject to the CreateOrder limit } } }pythondef main(): # Set CreateOrder rate limiting exchange.IO("rate", "CreateOrder", 5, "1s") # Buy and Sell are also subject to this limit for i in range(10): if i % 2 == 0: exchange.Buy(50000, 0.001) # Subject to the CreateOrder limit else: exchange.Sell(51000, 0.001) # Subject to the CreateOrder limitrustfn main() { // Set CreateOrder rate limiting let _ = exchange.IO(("rate", "CreateOrder", 5, "1s")); // Buy and Sell are also subject to this limit for i in 0..10 { if i % 2 == 0 { let _ = exchange.Buy(50000, 0.001); // Subject to the CreateOrder limit } else { let _ = exchange.Sell(51000, 0.001); // Subject to the CreateOrder limit } } }c++// C++ is not supported yet -
4. Rate Limiting for Go Functions
Rate limiting for the
Gofunction depends on the actual function being called concurrently.javascriptfunction main() { // Rate limit GetTicker exchange.IO("rate", "GetTicker", 5, "1s") // Concurrent calls to GetTicker are rate limited 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(): # Rate limit GetTicker exchange.IO("rate", "GetTicker", 5, "1s") # Concurrent calls to GetTicker are rate limited 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() { // Rate limit GetTicker let _ = exchange.IO(("rate", "GetTicker", 5, "1s")); // Concurrent calls to GetTicker are rate limited // In Rust, exchange.Go uses a typed syntax with the 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++ is not supported yet -
5. Rate Limiting for IO/api
IO/apirate limiting only takes effect onexchange.IO("api", ...)calls, and does not affect otherexchange.IO
functions.javascriptfunction main() { // Limit exchange.IO("api", ...) calls exchange.IO("rate", "IO/api", 10, "1s") // Rate limited 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") } // Not rate limited exchange.IO("currency", "LTC_USDT") // Switch trading pair, not rate limited exchange.IO("rate", "GetDepth", 5, "1s") // Set other rate limits, not rate limited }pythondef main(): # Limit exchange.IO("api", ...) calls exchange.IO("rate", "IO/api", 10, "1s") # Rate limited for i in range(15): ret = exchange.IO("api", "GET", "/api/v5/account/balance", "") Log("API call", i, "Success" if ret else "Rate limited") # Not rate limited exchange.IO("currency", "LTC_USDT") # Switch trading pair, not rate limited exchange.IO("rate", "GetDepth", 5, "1s") # Set other rate limits, not rate limitedrustfn main() { // Limit exchange.IO("api", ...) calls let _ = exchange.IO(("rate", "IO/api", 10, "1s")); // Rate limited 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"), } } // Not rate limited let _ = exchange.IO(("currency", "LTC_USDT")); // Switch trading pair, not rate limited let _ = exchange.IO(("rate", "GetDepth", 5, "1s")); // Set other rate limits, not rate limited }c++// C++ is not supported yet -
Best Practices
1. Set according to exchange limits: Please refer to the exchange's API documentation and set the rate limit value slightly below the exchange's limit.
2. Leave a safety margin: Do not set the rate limit value to the maximum allowed by the exchange; it is recommended to set it to 70%-80% of the maximum.
3. Tiered rate limiting: Set different rate limit values for different types of APIs, and reserve a larger margin for important APIs.
4. Use delay mode for critical calls: For API calls that must succeed, use
"delay"mode to ensure the call succeeds.5. Monitor API usage: Regularly check the strategy's API call frequency and continuously optimize the call logic.
6. Avoid excessive calls: Design the strategy logic reasonably to avoid unnecessary API calls.
7. Test rate limit configuration: Before running live, test whether the rate limit configuration is reasonable in a simulated environment.
See Also