Type/to search
Welcome to FMZ Quant Trading Platform
Programming Languages
JavaScript
TypeScript
Python
C++
MyLanguage
PINE Language
Blockly Visual Programming
Workflow
Key Security
Live Trading
Strategy Library
Docker
Deploy Docker
One-Click Docker Rental
Manual Deployment of Bot
Docker Operation Precautions
Global IP Address Specification
Command Line Parameters for Bot Program
Live Trading Data Migration
Docker Monitor
Exchange
Strategy Editor
Backtesting System
Strategy Entry Functions
Strategy Framework and API Functions
Template Library
Strategy Parameters
Interactive Controls
Options Trading
C++ Strategy Writing Guide
JavaScript Strategy Writing Guide
Web3
Built-in Libraries
Extended API Interface
MCP Service
Trading Terminal
Data Explorer
Alpha Factor Analysis Tool
General Protocol
Debugging Tool
Remote Editing
Import and Export of Complete Strategies
Multi-language Support
Live Trading and Strategy Grouping
Live Trading Display
Strategy Sharing and Renting
Live Trading Message Push
Common Causes of Live Trading Errors and Abnormal Exits
Exchange-Specific Notes

Feature Overview

The API rate limiting control feature is used to restrict the frequency of strategy calls to exchange APIs, preventing account bans or temporary restrictions caused by triggering exchange rate limits. The FMZ platform provides flexible rate limiting configuration methods, supporting two rate limiting modes and multiple configuration strategies.

Why API Rate Limiting is Needed

  • Avoid triggering exchange restrictions: Most exchanges have strict limits on API call frequency, and exceeding limits can result in temporary or permanent account bans.

  • Reasonable allocation of API quotas: In multi-strategy, multi-trading pair scenarios, API call resources need to be allocated reasonably.

  • Improve strategy stability: Through proactive rate limiting, avoid connection failures and data acquisition anomalies caused by frequent calls.

  • Comply with exchange specifications: Adhere to exchange API usage specifications and maintain good API usage relationships.

Two Rate Limiting Modes

rate mode (Smooth Rate Limiting)

  • Suitable for general rate limiting needs
  • Does not strictly align with time windows
  • Relatively smooth call distribution
  • Recommended for daily API call restrictions

quota mode (Quota Rate Limiting)

  • Strictly aligns with 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 requiring strict time window control
  • Recommended for intraday quota management

Basic Usage

Basic Example of rate Mode

Examples

  • undefined
    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++
    // C++ not supported yet
  • Basic Quota Mode Example

    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++
    // C++ not supported yet
  • Function Name Configuration

    Single Function Rate Limiting

    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++
    // C++ not supported yet
  • Multiple Function Joint Rate Limiting

    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++
    // C++ not supported yet
  • Using Wildcards to Limit All Functions

    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++
    // C++ not supported yet
  • Time Period Configuration

    Supported Time Units

    • ns: nanoseconds
    • us or µs: microseconds
    • ms: milliseconds
    • s: seconds
    • m: minutes
    • h: hours
    • d: days

    Examples: "100ms", "1s", "5m", "1h", "1d"

    javascript
    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 }
    python
    def 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
    c++
    // C++ not supported yet
  • Reset Time Point Configuration

    Use @HHMM or @HHMMSS format to specify daily reset time point, only effective in quota mode.

    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++
    // C++ not supported yet
  • Behavior Modes

    Default Mode (Return null when limit exceeded)

    javascript
    function main() { exchange.IO("rate", "GetTicker", 5, "1s") // Do not specify behavior parameter 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") // Can choose to Sleep and wait, or skip this call Sleep(200) } } }
    python
    def main(): exchange.IO("rate", "GetTicker", 5, "1s") # Do not specify behavior parameter 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") # Can choose to Sleep and wait, or skip this call Sleep(200)
    c++
    // C++ not supported yet
  • Delay Mode (Auto wait when limit exceeded)

    javascript
    function main() { exchange.IO("rate", "GetTicker", 5, "1s", "delay") // Specify delay parameter // Will automatically wait when call limit exceeded, ensuring 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 } }
    python
    def main(): exchange.IO("rate", "GetTicker", 5, "1s", "delay") # Specify delay parameter # Will automatically wait when call limit exceeded, ensuring every call succeeds for i in range(10): ticker = exchange.GetTicker("BTC_USDT") Log("Call", i+1, "Success:", ticker["Last"]) # ticker will not be None
    c++
    // C++ not supported yet
  • Supported Function List

    Trading Functions

    • CreateOrder: Create order

    • CancelOrder: Cancel order

    • Buy: Buy (subject to CreateOrder restrictions)

    • Sell: Sell (subject to CreateOrder restrictions)

    • CreateConditionOrder: Create conditional order

    • CancelConditionOrder: Cancel conditional order

    Account Functions

    • GetAccount: Get account information

    • GetAssets: Get asset information

    • GetPositions: Get position information

    Order Functions

    • GetOrder: Get single order

    • GetOrders: Get all orders

    • GetHistoryOrders: Get historical orders

    • GetConditionOrder: Get single conditional order

    • GetConditionOrders: Get all conditional orders

    • GetHistoryConditionOrders: Get historical conditional orders

    Market Data Functions

    • GetTicker: Get ticker data

    • GetTickers: Get multiple ticker data

    • GetDepth: Get market depth

    • GetRecords: Get K-line data

    • GetTrades: Get latest trade records

    Other Functions

    • GetMarkets: Get market list

    • GetFundings: Get funding rates

    • SetMarginLevel: Set leverage ratio

    • Go: Concurrent call (subject to actual function call restrictions)

    • IO/api: Custom API call (limited to exchange.IO("api", ...))

  • Practical Application Scenarios

    Scenario 1: Prevent triggering exchange rate limits

    javascript
    function main() { // Assume exchange limits: GetTicker 20 times per second, CreateOrder 5 times per second // Set values slightly below exchange limits, leaving 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) } }
    python
    def main(): # Assume exchange limits: GetTicker 20 times per second, CreateOrder 5 times per second # Set values slightly below exchange limits, leaving 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)
    c++
    // C++ not supported yet
  • Scenario 2: Unified Rate Limiting for Multiple Exchange Objects

    javascript
    function 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 market data 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) } }
    python
    def 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 market data 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)
    c++
    // C++ not supported yet
  • Scenario 3: Daily Quota Management

    javascript
    function main() { // Maximum 1000 API calls per day, reset at 8:00 AM daily 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 retry } Sleep(10000) } }
    python
    def main(): # Maximum 1000 API calls per day, reset at 8:00 AM daily 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 retry Sleep(10000)
    c++
    // C++ not supported yet
  • Scenario 4: Combined Rate Limiting Strategy

    javascript
    function main() { // Combine multiple rate limiting strategies // 1. Market data API rate limit per second exchange.IO("rate", "GetTicker,GetDepth", 20, "1s") // 2. Trading API rate limit per second exchange.IO("rate", "CreateOrder,CancelOrder", 5, "1s") // 3. Account query rate limit 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") // Strategy main loop while (true) { // Get market data var ticker = exchange.GetTicker("BTC_USDT") var depth = exchange.GetDepth("BTC_USDT") // Query account 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) } }
    python
    import time def main(): # Combine multiple rate limiting strategies # 1. Market data API rate limit per second exchange.IO("rate", "GetTicker,GetDepth", 20, "1s") # 2. Trading API rate limit per second exchange.IO("rate", "CreateOrder,CancelOrder", 5, "1s") # 3. Account query rate limit 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") # Strategy main loop while True: # Get market data ticker = exchange.GetTicker("BTC_USDT") depth = exchange.GetDepth("BTC_USDT") # Query account 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)
    c++
    // C++ not supported yet
  • Important Notes

    1. Quota Mode Time Window Alignment

    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 even if counting starts at 12:00:00.500, the window will reset at 12:00:01.000.

    javascript
    function main() { // Quota mode: strictly aligns to whole seconds exchange.IO("quota", "GetTicker", 3, "1s") // Assume 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 (quota exceeded) Sleep(500) // Wait 500ms, now time is 12:00:01.000 // Window has reset exchange.GetTicker("BTC_USDT") // 1st call in new window, success }
    python
    def main(): # Quota mode: strictly aligns to whole seconds exchange.IO("quota", "GetTicker", 3, "1s") # Assume 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 (quota exceeded) Sleep(500) # Wait 500ms, now time is 12:00:01.000 # Window has reset exchange.GetTicker("BTC_USDT") # 1st call in new window, success
    c++
    // C++ not supported yet
  • 2. Time Discrepancy in Delay Mode

    When using the "delay" parameter, the actual API call time may differ from the logged time. This is because when rate limiting is triggered, the program waits, but the log records the time after the wait ends.

    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, but will actually wait until 12:00:01.000 exchange.GetTicker("BTC_USDT") // Rate limit triggered, auto wait Log(_D(), "Call 3 completed") // Log shows 12:00:01.000+ // Appears to have called 3 times in one second, but actually the 3rd call executed in the new window }
    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, but will actually wait until 12:00:01.000 exchange.GetTicker("BTC_USDT") # Rate limit triggered, auto wait Log(_D(), "Call 3 completed") # Log shows 12:00:01.000+ # Appears to have called 3 times in one second, but actually the 3rd call executed in the new window
    c++
    // C++ not supported yet
  • 3. Rate Limiting for Buy/Sell Functions

    The Buy and Sell functions internally call CreateOrder, so their rate limiting follows the CreateOrder settings.

    javascript
    function main() { // Set CreateOrder rate limit 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 CreateOrder limit } else { exchange.Sell(51000, 0.001) // Subject to CreateOrder limit } } }
    python
    def main(): # Set CreateOrder rate limit 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 CreateOrder limit else: exchange.Sell(51000, 0.001) # Subject to CreateOrder limit
    c++
    // C++ not supported yet
  • 4. Rate Limiting for Go Functions

    The rate limiting for Go functions depends on the actual concurrently called functions.

    javascript
    function main() { // Limit GetTicker exchange.IO("rate", "GetTicker", 5, "1s") // Subject to limits when calling GetTicker concurrently 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(): # Limit GetTicker exchange.IO("rate", "GetTicker", 5, "1s") # Subject to limits when calling GetTicker concurrently 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++
    // C++ not supported yet
  • 5. Rate Limiting for IO/api

    IO/api rate limiting only applies to exchange.IO("api", ...) calls and does not affect other exchange.IO functions.

    javascript
    function main() { // Limit exchange.IO("api", ...) calls exchange.IO("rate", "IO/api", 10, "1s") // Subject to limits 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 subject to limits exchange.IO("currency", "LTC_USDT") // Switch trading pair, not limited exchange.IO("rate", "GetDepth", 5, "1s") // Set other rate limits, not limited }
    python
    def main(): # Limit exchange.IO("api", ...) calls exchange.IO("rate", "IO/api", 10, "1s") # Subject to limits 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 subject to limits exchange.IO("currency", "LTC_USDT") # Switch trading pair, not limited exchange.IO("rate", "GetDepth", 5, "1s") # Set other rate limits, not limited
    c++
    // C++ not supported yet
  • Best Practices

    1. Configure based on exchange limitations: Refer to the exchange API documentation and set limit values slightly below the maximum values specified by the exchange.

    2. Reserve safety margin: Do not set limits to the exchange's maximum values. It is recommended to set them to 70%-80% of the maximum values.

    3. Implement tiered rate limiting: Set different limits for different types of APIs, reserving more capacity for important APIs.

    4. Use delay mode for critical calls: For API calls that must succeed, use "delay" mode to ensure call success.

    5. Monitor API usage: Regularly check the API call frequency of strategies and continuously optimize call logic.

    6. Avoid excessive calls: Design strategy logic reasonably to reduce unnecessary API calls.

    7. Test rate limiting configuration: Before live trading, test the reasonableness of rate limiting configuration in a simulation environment first.

See Also