Type/to search
Built-in Functions
Global
Log
Market
Trade
Account
Futures
Exchange
IO
exchange.IO
exchange.IO("api", ...)
exchange.IO("currency", ...)
exchange.IO("base", ...)
exchange.IO(mode, value)
exchange.IO("rate", ...)
Network
Storage
Threads
TA
Talib
OS
Structures
Built-in Variables and Constants
Conventions
Exchanges

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.

    javascript
    function 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") } } }
    python
    def 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")
    rust
    fn 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 delay parameter to automatically wait instead of returning null when the limit is exceeded.

    javascript
    function 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) } }
    python
    def 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"])
    rust
    fn 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.

    javascript
    function 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")) } } }
    python
    def 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"))
    rust
    fn 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.

    javascript
    function 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) } }
    python
    def 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)
    rust
    fn 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.

    javascript
    function 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) } }
    python
    def 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)
    rust
    fn 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.

    javascript
    function 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) } }
    python
    def 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)
    rust
    fn 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.

    javascript
    function 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) } }
    python
    def 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)
    rust
    fn 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

TypeDescription

string / number / bool / object / array / any

Returns the result of the command on success, or a null value on failure.

Arguments

NameTypeRequiredDescription

k

string

Yes

Selects the function of exchange.IO(): rate is smooth rate limiting (a token bucket that allows short bursts), quota is quota limiting (calls counted per time window, windows aligned to the clock).

functionNames

string

Yes

API function name (such as GetTicker, CreateOrder, GetAccount); several names separated by commas share one rule. * is the fallback rule and applies only to functions without a rule of their own; IO/api stands for exchange.IO("api", ...). An empty string clears all rules.

maxCalls

number

Yes

Maximum number of calls per period; a value of 0 or less deletes the rule for functionNames. In rate mode it can be the string "count/burst", for example "10/5": 10 calls per period with bursts of at most 5; without a burst the burst equals the count.

period

string

Yes

Period, written like a Go duration: 500ms, 1s, 1m, 1h30m (units ns, us, ms, s, m, h), or 1d; or a daily reset time @HHMM / @HHMMSS (Beijing time), for example @0815.

behavior

string

No

Decides what happens over the limit: delay waits and then runs; by default the call returns a null value.

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 (1m resets at second 0 of every minute, 1d at 00:00 UTC, i.e. 08:00 Beijing time).
ParameterTypeDescription
functionNamesstringFunction names, comma-separated; * is the fallback rule for functions without a rule of their own
maxCallsnumber / stringMaximum calls per period; rate accepts "count/burst"; 0 or less deletes the rule
periodstringTime period (500ms/1s/1h30m/1d) or daily reset time (@0815, Beijing time)
behaviorstringOptional; delay means wait when the limit is exceeded, defaults to returning null

The rate limiting of Buy/Sell follows the settings of CreateOrder; Go follows the settings of the actual concurrent function; IO/api only takes effect for exchange.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
CategoryFunction names
Market dataGetTicker, GetTickers, GetDepth, GetTrades, GetRecords, GetMarkets, GetFundings
AccountGetAccount, GetAssets, GetPositions, SetMarginLevel
TradingCreateOrder (Buy and Sell also count), CancelOrder, ModifyOrder
Order queriesGetOrder, GetOrders, GetHistoryOrders
Condition ordersCreateConditionOrder, ModifyConditionOrder, CancelConditionOrder, GetConditionOrder, GetConditionOrders, GetHistoryConditionOrders
Custom requestsIO/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 other exchange.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.