exchange.IO("rate", ...)
Limits how often each API function is called: rate for smoothed limiting, quota for quota limiting.
exchange.IO(k, functionNames, maxCalls, period)
exchange.IO(k, functionNames, maxCalls, period, behavior)Examples
-
rate mode rate limiting - Limit GetTicker to a maximum of 10 calls per second; returns null when the limit is exceeded.
javascriptfunction main() { exchange.IO("rate", "GetTicker", 10, "1s") for (var i = 0; i < 20; i++) { var ticker = exchange.GetTicker("BTC_USDT") if (ticker) { Log("Ticker:", ticker.Last) } else { Log("Rate limit exceeded") } } }pythondef main(): exchange.IO("rate", "GetTicker", 10, "1s") for i in range(20): ticker = exchange.GetTicker("BTC_USDT") if ticker: Log("Ticker:", ticker["Last"]) else: Log("Rate limit exceeded")rustfn main() { let _ = exchange.IO(("rate", "GetTicker", 10, "1s")); for _i in 0..20 { // GetTicker returns Err when the limit is exceeded match exchange.GetTicker("BTC_USDT") { Ok(ticker) => Log!("Ticker:", ticker.Last), Err(_) => Log!("Rate limit exceeded"), } } } -
rate mode rate limiting - Use the
delayparameter to automatically wait instead of returning null when the limit is exceeded.javascriptfunction main() { exchange.IO("rate", "GetTicker", 10, "1s", "delay") for (var i = 0; i < 20; i++) { var ticker = exchange.GetTicker("BTC_USDT") Log("Call", i+1, "Ticker:", ticker.Last) } }pythondef main(): exchange.IO("rate", "GetTicker", 10, "1s", "delay") for i in range(20): ticker = exchange.GetTicker("BTC_USDT") Log("Call", i+1, "Ticker:", ticker["Last"])rustfn main() { let _ = exchange.IO(("rate", "GetTicker", 10, "1s", "delay")); for i in 0..20 { let ticker = exchange.GetTicker("BTC_USDT").unwrap(); Log!("Call", i + 1, "Ticker:", ticker.Last); } } -
Multiple functions sharing a rate limit quota.
javascriptfunction main() { // GetTicker and GetDepth share the rate limit quota, with a combined maximum of 10 calls per second exchange.IO("rate", "GetTicker,GetDepth", 10, "1s") for (var i = 0; i < 20; i++) { if (i % 2 == 0) { Log("Ticker:", exchange.GetTicker("BTC_USDT")) } else { Log("Depth:", exchange.GetDepth("BTC_USDT")) } } }pythondef main(): exchange.IO("rate", "GetTicker,GetDepth", 10, "1s") for i in range(20): if i % 2 == 0: Log("Ticker:", exchange.GetTicker("BTC_USDT")) else: Log("Depth:", exchange.GetDepth("BTC_USDT"))rustfn main() { // GetTicker and GetDepth share the rate limit quota, with a combined maximum of 10 calls per second let _ = exchange.IO(("rate", "GetTicker,GetDepth", 10, "1s")); for i in 0..20 { if i % 2 == 0 { Log!("Ticker:", exchange.GetTicker("BTC_USDT")); } else { Log!("Depth:", exchange.GetDepth("BTC_USDT")); } } } -
Use a wildcard to uniformly limit the call frequency of all APIs.
javascriptfunction main() { exchange.IO("rate", "*", 100, "1m") for (var i = 0; i < 10; i++) { exchange.GetTicker("BTC_USDT") exchange.GetDepth("BTC_USDT") exchange.GetAccount() Log("Round", i+1, "completed") Sleep(1000) } }pythondef main(): exchange.IO("rate", "*", 100, "1m") for i in range(10): exchange.GetTicker("BTC_USDT") exchange.GetDepth("BTC_USDT") exchange.GetAccount() Log("Round", i+1, "completed") Sleep(1000)rustfn main() { let _ = exchange.IO(("rate", "*", 100, "1m")); for i in 0..10 { let _ = exchange.GetTicker("BTC_USDT"); let _ = exchange.GetDepth("BTC_USDT"); let _ = exchange.GetAccount(); Log!("Round", i + 1, "completed"); Sleep(1000); } } -
quota mode - strict rate limiting aligned to time windows.
javascriptfunction main() { exchange.IO("quota", "GetTicker", 3, "1s") for (var i = 0; i < 10; i++) { var ticker = exchange.GetTicker("BTC_USDT") if (ticker) { Log(_D(), "Ticker:", ticker.Last) } else { Log(_D(), "Quota exceeded, waiting for next window") } Sleep(100) } }pythondef main(): exchange.IO("quota", "GetTicker", 3, "1s") for i in range(10): ticker = exchange.GetTicker("BTC_USDT") if ticker: Log(_D(), "Ticker:", ticker["Last"]) else: Log(_D(), "Quota exceeded, waiting for next window") Sleep(100)rustfn main() { let _ = exchange.IO(("quota", "GetTicker", 3, "1s")); for _i in 0..10 { match exchange.GetTicker("BTC_USDT") { Ok(ticker) => Log!(_D(None), "Ticker:", ticker.Last), Err(_) => Log!(_D(None), "Quota exceeded, waiting for next window"), } Sleep(100); } } -
quota mode - intraday quota, resets daily at the specified time.
javascriptfunction main() { exchange.IO("quota", "GetTicker", 1000, "@0815") var count = 0 while (true) { var ticker = exchange.GetTicker("BTC_USDT") if (ticker) { count++ Log("Call count:", count, "Ticker:", ticker.Last) } else { Log("Daily quota exceeded, waiting for reset at 08:15") Sleep(60000) // Wait 1 minute } Sleep(1000) } }pythondef main(): exchange.IO("quota", "GetTicker", 1000, "@0815") count = 0 while True: ticker = exchange.GetTicker("BTC_USDT") if ticker: count += 1 Log("Call count:", count, "Ticker:", ticker["Last"]) else: Log("Daily quota exceeded, waiting for reset at 08:15") Sleep(60000) # Wait 1 minute Sleep(1000)rustfn main() { let _ = exchange.IO(("quota", "GetTicker", 1000, "@0815")); let mut count = 0; loop { match exchange.GetTicker("BTC_USDT") { Ok(ticker) => { count += 1; Log!("Call count:", count, "Ticker:", ticker.Last); } Err(_) => { Log!("Daily quota exceeded, waiting for reset at 08:15"); Sleep(60000); // Wait 1 minute } } Sleep(1000); } } -
Combining multiple rate-limiting rules.
javascriptfunction main() { exchange.IO("rate", "GetTicker", 10, "1s") // GetTicker 10 times per second exchange.IO("rate", "GetDepth", 5, "1s") // GetDepth 5 times per second exchange.IO("rate", "CreateOrder", 2, "1s") // CreateOrder 2 times per second exchange.IO("quota", "*", 1000, "@0000") // All APIs reset daily at 00:00, cap of 1000 calls Log("Rate limits configured successfully") for (var i = 0; i < 5; i++) { exchange.GetTicker("BTC_USDT") exchange.GetDepth("BTC_USDT") Sleep(200) } }pythondef main(): exchange.IO("rate", "GetTicker", 10, "1s") # GetTicker 10 times per second exchange.IO("rate", "GetDepth", 5, "1s") # GetDepth 5 times per second exchange.IO("rate", "CreateOrder", 2, "1s") # CreateOrder 2 times per second exchange.IO("quota", "*", 1000, "@0000") # All APIs reset daily at 00:00, cap of 1000 calls Log("Rate limits configured successfully") for i in range(5): exchange.GetTicker("BTC_USDT") exchange.GetDepth("BTC_USDT") Sleep(200)rustfn main() { let _ = exchange.IO(("rate", "GetTicker", 10, "1s")); // GetTicker 10 times per second let _ = exchange.IO(("rate", "GetDepth", 5, "1s")); // GetDepth 5 times per second let _ = exchange.IO(("rate", "CreateOrder", 2, "1s")); // CreateOrder 2 times per second let _ = exchange.IO(("quota", "*", 1000, "@0000")); // All APIs reset daily at 00:00, cap of 1000 calls Log!("Rate limits configured successfully"); for _i in 0..5 { let _ = exchange.GetTicker("BTC_USDT"); let _ = exchange.GetDepth("BTC_USDT"); Sleep(200); } }
Returns
| Type | Description |
string / number / bool / object / array / any | Returns the result of the command on success, or a null value on failure. |
Arguments
| Name | Type | Required | Description |
k | string | Yes | Selects the function of |
functionNames | string | Yes | API function name (such as |
maxCalls | number | Yes | Maximum number of calls per period; a value of 0 or less deletes the rule for |
period | string | Yes | Period, written like a Go duration: |
behavior | string | No | Decides what happens over the limit: |
See Also
Remarks
API Rate Limiting Control (rate / quota modes)
javascript
exchange.IO("rate", functionNames, maxCalls, period, [behavior])
exchange.IO("quota", functionNames, maxCalls, period, [behavior])
- rate: smooth rate limiting (token bucket). The bucket holds the burst size, refills at count/period and starts full.
- quota: quota limiting. At most the given number of calls per period; periods are aligned to the clock (
1mresets at second 0 of every minute,1dat 00:00 UTC, i.e. 08:00 Beijing time).
| Parameter | Type | Description |
|---|---|---|
| functionNames | string | Function names, comma-separated; * is the fallback rule for functions without a rule of their own |
| maxCalls | number / string | Maximum calls per period; rate accepts "count/burst"; 0 or less deletes the rule |
| period | string | Time period (500ms/1s/1h30m/1d) or daily reset time (@0815, Beijing time) |
| behavior | string | Optional; delay means wait when the limit is exceeded, defaults to returning null |
The rate limiting of
Buy/Sellfollows the settings ofCreateOrder;Gofollows the settings of the actual concurrent function;IO/apionly takes effect forexchange.IO("api", ...).
Rules are set per exchange object and last for the current run only. By default an exceeded limit raises an error and the call returns null, with a message such as rate limit exceeded: GetTicker 10/1s (quota limit exceeded: ... for quota rules, and quota limit exceeded: GetTicker 1000/day (resets at 0815) for rules reset daily at a fixed time); with delay the call waits until it is allowed, and the wait is interrupted when the live trading stops. GetAccount and GetAssets are the same request, so a rule set for either name applies to both.
Function names that can be limited
| Category | Function names |
|---|---|
| Market data | GetTicker, GetTickers, GetDepth, GetTrades, GetRecords, GetMarkets, GetFundings |
| Account | GetAccount, GetAssets, GetPositions, SetMarginLevel |
| Trading | CreateOrder (Buy and Sell also count), CancelOrder, ModifyOrder |
| Order queries | GetOrder, GetOrders, GetHistoryOrders |
| Condition orders | CreateConditionOrder, ModifyConditionOrder, CancelConditionOrder, GetConditionOrder, GetConditionOrders, GetHistoryConditionOrders |
| Custom requests | IO/api: limits only exchange.IO("api", ...), not the other exchange.IO() commands |
| Fallback | *: applies to exchange requests without a rule of their own |
- Limits apply only to the requests above made by exchange objects;
HttpQuery(),Dial()and the otherexchange.IO()commands are not affected. - A call is counted against one rule only: a function with its own rule is not counted against
*. - Concurrent calls through
exchange.Go()are counted by the function actually called.