← Back to Home
Precision, Limits, Filters, Core Binance Trading Rules Every Algo Needs

Precision, Limits, Filters, Core Binance Trading Rules Every Algo Needs

In this article, we’ll walk through a small Python utility that:

  1. Connects to Binance (spot testnet or live)

  2. Fetches and caches market metadata for all trading pairs

  3. Extracts and prints the full set of trading rules (“filters”) for a single symbol

This kind of script is invaluable when you’re building an automated trading bot or simply need to validate orders client-side against Binance’s on-exchange constraints. ## 1. Imports & Configuration

import os
import math
import time
import logging

from binance.client import Client
from binance.exceptions import BinanceAPIException, BinanceOrderException

Next up, your API credentials and a flag for testnet vs. live:

API_KEY    = "<YOUR_API_KEY>"
API_SECRET = "<YOUR_API_SECRET>"
USE_TESTNET = True  # switch to False for real trading

Replace those placeholder strings (or load from environment variables) before running. ## 2. Logging Setup

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s"
)

A consistent log format helps you trace exactly what’s happening and when. You’ll see timestamps, log levels, and your own messages in the console. ## 3. Initializing the Binance Client

try:
    client = Client(API_KEY, API_SECRET, testnet=USE_TESTNET)
    client.ping()
    logging.info(f"Client initialized (testnet={USE_TESTNET})")
    server_time = client.get_server_time()
    logging.info(f"Server time: {server_time['serverTime']}")
except BinanceAPIException as e:
    logging.error(f"Binance API error during init: {e}")
    client = None
except Exception as e:
    logging.error(f"Unexpected error during init: {e}")
    client = None
  1. Instantiate the client with your keys and testnet flag.

  2. Ping the server to verify connectivity.

  3. Fetch server time as a sanity check—if your local clock is wildly skewed, signed requests may be rejected.

  4. Error handling ensures you don’t proceed without a working client.

4. Caching Exchange Info

exchange_info_cache = {}

if client:
    try:
        info = client.get_exchange_info()
        for s in info.get("symbols", []):
            exchange_info_cache[s["symbol"]] = s
        logging.info("Fetched and cached exchange info for all symbols.")
    except BinanceAPIException as e:
        logging.error(f"Binance API error fetching exchange info: {e}")
    except Exception as e:
        logging.error(f"Error fetching exchange info: {e}")

5. Selecting a Symbol

# ORDER PARAMETERS (edit these)
symbol   = "BTCUSDT"
quantity = 0.001
price    = None  # None ⇒ MARKET order

symbol_info = exchange_info_cache.get(symbol)
if not symbol_info:
    logging.error(f"Symbol {symbol} not found in cache.")
    # Here you’d re-fetch or abort

6. Pretty‐Printing Symbol Metadata

import json

def print_symbol_info(info: dict):
    """
    Nicely prints all the fields of a Binance symbol-info dict.
    """
    # Basic summary
    print(f"Symbol:             {info.get('symbol')}")
    print(f"Status:             {info.get('status')}")
    print(f"Base / Quote Asset: {info.get('baseAsset')} / {info.get('quoteAsset')}")
    print(f"Precisions:         base={info.get('baseAssetPrecision')}, "
          f"quote={info.get('quoteAssetPrecision')}")
    print(f"Spot / Margin:      {info.get('isSpotTradingAllowed')} / {info.get('isMarginTradingAllowed')}")
    print(f"Order Types:        {', '.join(info.get('orderTypes', []))}")
    print(f"Iceberg / OCO / OTO allowed?  {info.get('icebergAllowed')}, "
          f"{info.get('ocoAllowed')}, {info.get('otoAllowed')}")
    print(f"Self-Trade Prevention (default): {info.get('defaultSelfTradePreventionMode')}")
    print(f"Allowed STP modes:   {', '.join(info.get('allowedSelfTradePreventionModes', []))}")
    print()

    # Detailed filters
    print("Filters:")
    for f in info.get("filters", []):
        ft = f.pop("filterType", "<unknown>")
        params = ", ".join(f"{k}={v}" for k, v in f.items())
        print(f"  • {ft}: {params}")
    print()

By printing them in a bullet list, you instantly see every constraint you must honor before sending an order.

7. Putting It All Together

Finally, we invoke:

print_symbol_info(symbol_info)

and watch as our console floods with a clear, human-readable summary of BTCUSDT’s every trading rule. Armed with this information, you can:

We will get the following output:

Symbol:             BTCUSDT
Status:             TRADING
Base / Quote Asset: BTC / USDT
Precisions:         base=8, quote=8
Spot / Margin:      True / False
Order Types:        LIMIT, LIMIT_MAKER, MARKET, STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT
Iceberg / OCO / OTO allowed?  True, True, True
Self-Trade Prevention (default): EXPIRE_MAKER
Allowed STP modes:   NONE, EXPIRE_TAKER, EXPIRE_MAKER, EXPIRE_BOTH, DECREMENT

Filters:
  • PRICE_FILTER: minPrice=0.01000000, maxPrice=1000000.00000000, tickSize=0.01000000
  • LOT_SIZE: minQty=0.00001000, maxQty=9000.00000000, stepSize=0.00001000
  • ICEBERG_PARTS: limit=10
  • MARKET_LOT_SIZE: minQty=0.00000000, maxQty=102.70390393, stepSize=0.00000000
  • TRAILING_DELTA: minTrailingAboveDelta=10, maxTrailingAboveDelta=2000, minTrailingBelowDelta=10, maxTrailingBelowDelta=2000
  • PERCENT_PRICE_BY_SIDE: bidMultiplierUp=5, bidMultiplierDown=0.2, askMultiplierUp=5, askMultiplierDown=0.2, avgPriceMins=5
  • NOTIONAL: minNotional=5.00000000, applyMinToMarket=True, maxNotional=9000000.00000000, applyMaxToMarket=False, avgPriceMins=5
  • MAX_NUM_ORDERS: maxNumOrders=200
  • MAX_NUM_ALGO_ORDERS: maxNumAlgoOrders=5

Here’s a field‐by‐field rundown of everything, why it matters, and how you’d use it in your trading logic: ## Market Basics

Assets & Precision

Trading Modes

Supported Order Types

LIMIT, LIMIT_MAKER, MARKET,
STOP_LOSS, STOP_LOSS_LIMIT,
TAKE_PROFIT, TAKE_PROFIT_LIMIT

Use this list to validate your UI or reject unsupported order types in your bot.

Advanced Order Features

If your strategy uses any of these, you’re good to go on BTCUSDT.

Self-Trade Prevention (STP)

You can override the default in each order to control how (or if) Binance prevents you from filling your own orders.

Filters (Client-Side Rules)

Before you submit an order, you must ensure it obeys all of these constraints, or Binance will reject it:

  1. PRICE_FILTER

    • minPrice=0.01, maxPrice=1,000,000

    • tickSize=0.01
      Prices must sit in [0.01, 1 000 000] USDT and be multiples of 0.01.

  2. LOT_SIZE

    • minQty=0.00001, maxQty=9 000

    • stepSize=0.00001
      Quantities (for limit orders) must be between 0.00001 BTC and 9 000 BTC, in increments of 0.00001 BTC.

  3. ICEBERG_PARTS

    • limit=10
      Maximum number of visible slices an iceberg order may split into.
  4. MARKET_LOT_SIZE

    • minQty=0, maxQty≈102.7039, stepSize=0
      For market orders, quantity can be up to ~102.7 BTC (no minimum above zero).
  5. TRAILING_DELTA

    • minTrailingAboveDelta=10, maxTrailingAboveDelta=2000

    • minTrailingBelowDelta=10, maxTrailingBelowDelta=2000
      Sets how far (in price-ticks) your trailing-stop must trail above/below the market price.

  6. PERCENT_PRICE_BY_SIDE

    • bidMultiplierUp=5, bidMultiplierDown=0.2

    • askMultiplierUp=5, askMultiplierDown=0.2

    • avgPriceMins=5
      Used for conditional orders that trigger based on a percentage offset from the 5-minute average price.

  7. NOTIONAL

    • minNotional=5 USDT, applyMinToMarket=True

    • maxNotional=9 000 000 USDT, applyMaxToMarket=False
      Total order value (qty × price) must be ≥ 5 USDT. The max constraint applies only to limit orders.

  8. MAX_NUM_ORDERS

    • maxNumOrders=200
      You can have at most 200 open orders (of any type) on BTCUSDT at once.
  9. MAX_NUM_ALGO_ORDERS

    • maxNumAlgoOrders=5
      You may only have 5 open “algo” orders (stop, take-profit, trailing, iceberg, OCO) simultaneously.

Bringing It All Together

Your bot’s order-validation routine should:

  1. Round/floor price to nearest tickSize and quantity to nearest stepSize.

  2. Check minPrice ≤ price ≤ maxPrice (limit orders) and minQty ≤ qty ≤ maxQty.

  3. Compute notional = qty × price (or fetch market price for market orders) and ensure it meets NOTIONAL bounds.

  4. Verify you haven’t exceeded MAX_NUM_ORDERS or MAX_NUM_ALGO_ORDERS.

  5. Respect trading permissions (spot vs. margin) and allowed order-type flags.

  6. Specify a valid STP mode if self-trade prevention matters for your strategy.

By enforcing these rules client-side, you’ll avoid filter-violation errors and keep your algorithmic trading smooth and reliable. ## Conclusion

This article encapsulates a best practice to fetch and cache exchange metadata, and validate every order against those rules client-side.

Such upfront validation leads to smoother algorithmic trading, fewer surprise API rejections, and a clearer understanding of your market’s boundaries. Feel free to extend this script with your own check_order_limits() function (we covered a more complete version earlier) to enforce every rule automatically before you ever hit Binance’s order endpoints.