Binance Order Execution
End-to-end order placement on Binance — authentication, spot vs futures routing, order types, and WebSocket order status updates.
Execute Trades on Binance
1. Overview
This notebook demonstrates how to execute trades programmatically on Binance using the python-binance library. It covers the full execution workflow — from authentication and market data retrieval to placing market and limit orders.
What You Will Learn
| Step | Description |
|---|---|
| Authentication | Connect to Binance via API keys |
| Market Data | Fetch ticker prices and order book depth |
| Fee Lookup | Retrieve your account's trading fee tier |
| Market Order | Place an immediate buy/sell order |
| Limit Order | Place a price-controlled buy/sell order |
| Order Status | Query and display order fill details |
| Cancel Order | Cancel an open limit order |
Note: This notebook uses the Binance Testnet by default. Switch
testnet=Truetotestnet=Falseand supply live API keys to trade on the real exchange. Dummy Mode: Live API calls in this notebook are commented out and replaced with realistic dummy data so it can run end-to-end without a live connection or trading funds. Uncomment the real calls and remove the dummy assignments to run against a real account. The Google Colabuserdatadependency has also been replaced with plain placeholder variables so this runs outside Colab too.
2. Dependency Imports
Install and import the required libraries. python-binance is the official community client for the Binance REST and WebSocket APIs.
# Install the Binance client library if not already present.
!pip install python-binance --quietfrom binance.client import Client
from binance.enums import (
SIDE_BUY, SIDE_SELL,
ORDER_TYPE_MARKET, ORDER_TYPE_LIMIT,
TIME_IN_FORCE_GTC,
)
import warnings
# Suppress all warnings for cleaner output in a demonstration context.
warnings.filterwarnings("ignore")3. Authentication
3.1. create_client Function
This function initialises a Binance Client using your API key and secret. Set testnet=True to connect to the Binance Spot Testnet — no real funds are involved.
def create_client(api_key: str, api_secret: str, testnet: bool = True) -> Client:
"""Create and return an authenticated Binance client.
Parameters
----------
api_key : Your Binance API key.
api_secret : Your Binance API secret.
testnet : If True, connects to Binance Testnet (safe for learning).
Returns
-------
Client: Authenticated Binance client instance.
"""
# Initialise client; testnet flag routes requests to the test environment.
client = Client(api_key, api_secret, testnet=testnet)
return clientExplanation of create_client function
This function is crucial for establishing a connection to the Binance API. It takes your api_key and api_secret to authenticate your requests. The testnet parameter is very important: if set to True, it directs your requests to the Binance Spot Testnet, which is a simulated environment. This allows you to test your trading strategies and code without risking real funds. If testnet is set to False, your requests will go to the live Binance exchange, where actual trades will be executed with real money. The function returns an authenticated Client object, which you will use for all subsequent API calls.
# ── Replace with your own keys ──────────────────────────────────────────────
API_KEY = "YOUR_BINANCE_API_KEY"
API_SECRET = "YOUR_BINANCE_API_SECRET"
# ────────────────────────────────────────────────────────────────────────────
# Create the client (testnet = True by default).
# Commented out to run locally without network access / real keys
# client = create_client(API_KEY, API_SECRET, testnet=True)
client = None # Dummy placeholder client (no live connection in this offline run)
print("Binance client created successfully.")
Binance client created successfully.
4. Market Data Functions
4.1. get_ticker_price Function
Fetches the latest best bid/ask prices for a trading symbol from the Binance order book ticker endpoint.
def get_ticker_price(client: Client, symbol: str) -> dict:
"""Return the best bid and ask price for a symbol.
Parameters
----------
client : Authenticated Binance client.
symbol : Trading pair symbol, e.g. 'BTCUSDT'.
Returns
-------
dict: Contains 'bid' and 'ask' as floats.
"""
# get_orderbook_ticker returns the best bid and ask for the symbol.
ticker = client.get_orderbook_ticker(symbol=symbol)
return {
"bid": float(ticker["bidPrice"]),
"ask": float(ticker["askPrice"]),
}Explanation of get_ticker_price function
This function retrieves real-time market data, specifically the best bid and ask prices for a given trading symbol (e.g., 'BTCUSDT').
client.get_orderbook_ticker(symbol=symbol): This is the core API call. It fetches the current best bid (highest price a buyer is willing to pay) and best ask (lowest price a seller is willing to accept) from the order book.ticker['bidPrice']andticker['askPrice']: These keys in the API response contain the bid and ask prices, respectively. They are typically strings, so they are converted tofloatfor numerical operations.- Return Value: The function returns a dictionary with 'bid' and 'ask' prices, making it easy to access the current market spread.
# Fetch the current BTCUSDT ticker.
# Commented out to run locally with dummy data
# ticker = get_ticker_price(client, "BTCUSDT")
ticker = {"bid": 60000.00, "ask": 60005.00} # Dummy data
print(f"BTCUSDT — Bid: {ticker['bid']:,.2f} | Ask: {ticker['ask']:,.2f}")
BTCUSDT — Bid: 60,000.00 | Ask: 60,005.00
4.2. get_order_book Function
Retrieves the top N levels of the order book for a symbol. Useful for understanding available liquidity before placing large orders.
def get_order_book(client: Client, symbol: str, depth: int = 5) -> dict:
"""Return the top N bid and ask levels from the order book.
Parameters
----------
client : Authenticated Binance client.
symbol : Trading pair symbol, e.g. 'BTCUSDT'.
depth : Number of price levels to retrieve (default: 5).
Returns
-------
dict: Contains 'bids' and 'asks' as lists of [price, quantity].
"""
# get_order_book returns a dict with 'bids' and 'asks' lists.
book = client.get_order_book(symbol=symbol, limit=depth)
return {
"bids": [[float(p), float(q)] for p, q in book["bids"]],
"asks": [[float(p), float(q)] for p, q in book["asks"]],
}Explanation of get_order_book function
This function provides a deeper look into the market's liquidity by fetching the top depth levels of the order book for a specified symbol.
client.get_order_book(symbol=symbol, limit=depth): This API call retrieves a snapshot of the order book. Thelimitparameter controls how many bid and ask levels are returned (e.g.,depth=5gets the top 5 bids and asks).book['bids']andbook['asks']: The API response contains two lists: 'bids' (representing buy orders) and 'asks' (representing sell orders). Each element in these lists is a[price, quantity]pair.- List Comprehension
[[float(p), float(q)] for p, q in book['bids']]: This concise syntax iterates through the raw bid/ask data, converting both pricepand quantityqfrom strings to floats, ensuring they can be used for calculations. - Return Value: The function returns a dictionary containing processed lists of 'bids' and 'asks', where each is a list of
[price, quantity]pairs, ordered from best to worst price.
# Display the top 5 levels of the BTCUSDT order book.
# Commented out to run locally with dummy data
# book = get_order_book(client, "BTCUSDT", depth=5)
book = { # Dummy data
"bids": [[59999.5, 0.512], [59999.0, 1.204], [59998.5, 0.880], [59998.0, 2.001], [59997.5, 0.330]],
"asks": [[60000.5, 0.470], [60001.0, 1.150], [60001.5, 0.905], [60002.0, 1.760], [60002.5, 0.290]],
}
print("Top 5 Asks (sell side):")
for price, qty in reversed(book["asks"]):
print(f" {price:>12,.2f} | {qty:.6f} BTC")
print("-" * 35)
print("Top 5 Bids (buy side):")
for price, qty in book["bids"]:
print(f" {price:>12,.2f} | {qty:.6f} BTC")
Top 5 Asks (sell side):
60,002.50 | 0.290000 BTC
60,002.00 | 1.760000 BTC
60,001.50 | 0.905000 BTC
60,001.00 | 1.150000 BTC
60,000.50 | 0.470000 BTC
-----------------------------------
Top 5 Bids (buy side):
59,999.50 | 0.512000 BTC
59,999.00 | 1.204000 BTC
59,998.50 | 0.880000 BTC
59,998.00 | 2.001000 BTC
59,997.50 | 0.330000 BTC
5. Fee Information
5.1. get_trade_fee Function
Queries your account's current maker and taker fee rates for a given symbol. Binance fees depend on your 30-day trading volume and BNB holdings.
def get_trade_fee(client: Client, symbol: str) -> dict:
"""Return maker and taker fee rates for a symbol.
Parameters
----------
client : Authenticated Binance client.
symbol : Trading pair symbol, e.g. 'BTCUSDT'.
Returns
-------
dict: Contains 'maker_fee' and 'taker_fee' as floats (e.g., 0.001 = 0.1%).
"""
# get_trade_fee returns a list of fee objects; we extract the first match.
fees = client.get_trade_fee(symbol=symbol)
fee_info = fees[0] if fees else {"makerCommission": 0.001, "takerCommission": 0.001}
return {
"maker_fee": float(fee_info.get("makerCommission", 0.001)),
"taker_fee": float(fee_info.get("takerCommission", 0.001)),
}Explanation of get_trade_fee function
This function is used to retrieve the current trading fee rates for your account on a specific symbol. Trading fees on Binance can vary based on your VIP level, which is determined by your 30-day trading volume and BNB holdings.
client.get_trade_fee(symbol=symbol): This API call fetches an array of fee information for the specified trading pair. Even if you only query for one symbol, the API returns a list.fees[0] if fees else {'makerCommission': 0.001, 'takerCommission': 0.001}: This line safely extracts the first (and likely only) fee object from thefeeslist. It also provides default values (0.1% for both maker and taker) in case the API call returns an empty list or fails to provide specific commission rates, preventing errors.- **`fee_info.get(
# Display the fee rates for BTCUSDT.
# Commented out to run locally with dummy data
# fees = get_trade_fee(client, "BTCUSDT")
fees = {"maker_fee": 0.0002, "taker_fee": 0.0004} # Dummy data (default Binance VIP0 rates)
print(f"BTCUSDT Fees — Maker: {fees['maker_fee']*100:.4f}% | Taker: {fees['taker_fee']*100:.4f}%")
BTCUSDT Fees — Maker: 0.0200% | Taker: 0.0400%
6. Order Execution Functions
6.1. place_market_order Function
Places a market order on Binance. A market order executes immediately at the best available price. Use this when execution certainty is more important than price precision.
def place_market_order(client: Client, symbol: str, side: str, quantity: float) -> dict:
"""Place a market order on Binance.
Parameters
----------
client : Authenticated Binance client.
symbol : Trading pair symbol, e.g. 'BTCUSDT'.
side : 'BUY' or 'SELL'.
quantity : Amount of base asset to buy or sell.
Returns
-------
dict: Full order response from Binance including orderId and fills.
"""
# Map string side to the Binance enum constant.
binance_side = SIDE_BUY if side.upper() == "BUY" else SIDE_SELL
# Submit the market order via the REST API.
order = client.order_market(
symbol=symbol,
side=binance_side,
quantity=quantity,
)
return order# Place a market BUY order for 0.001 BTC on the testnet.
# Commented out to run locally with dummy data
# market_order = place_market_order(client, "BTCUSDT", side="BUY", quantity=0.001)
market_order = { # Dummy data
"orderId": 100001,
"symbol": "BTCUSDT",
"side": "BUY",
"status": "FILLED",
"executedQty": "0.00100000",
}
print("Market Order Placed:")
print(f" Order ID : {market_order['orderId']}")
print(f" Symbol : {market_order['symbol']}")
print(f" Side : {market_order['side']}")
print(f" Status : {market_order['status']}")
print(f" Qty Filled: {market_order['executedQty']} BTC")
Market Order Placed: Order ID : 100001 Symbol : BTCUSDT Side : BUY Status : FILLED Qty Filled: 0.00100000 BTC
6.2. place_limit_order Function
Places a limit order on Binance. A limit order rests in the order book until the market reaches your specified price. Use this when price control matters more than immediate execution.
def place_limit_order(
client: Client, symbol: str, side: str, quantity: float, price: float
) -> dict:
"""Place a limit order on Binance (Good-Till-Cancelled).
Parameters
----------
client : Authenticated Binance client.
symbol : Trading pair symbol, e.g. 'BTCUSDT'.
side : 'BUY' or 'SELL'.
quantity : Amount of base asset to buy or sell.
price : Limit price at which to execute.
Returns
-------
dict: Full order response from Binance including orderId.
"""
# Map string side to the Binance enum constant.
binance_side = SIDE_BUY if side.upper() == "BUY" else SIDE_SELL
# Submit the limit GTC order; it will rest in the book until filled or cancelled.
order = client.order_limit(
symbol=symbol,
side=binance_side,
quantity=quantity,
price=str(price),
timeInForce=TIME_IN_FORCE_GTC,
)
return order# Fetch current ask price and place a passive limit BUY 1% below ask.
# Commented out to run locally with dummy data
# current_ask = get_ticker_price(client, "BTCUSDT")["ask"]
current_ask = ticker["ask"] # reuse dummy ticker from earlier
limit_price = round(current_ask * 0.99, 2) # 1% below current ask.
# limit_order = place_limit_order(
# client, "BTCUSDT", side="BUY", quantity=0.001, price=limit_price
# )
limit_order = { # Dummy data
"orderId": 100002,
"symbol": "BTCUSDT",
"side": "BUY",
"status": "NEW",
}
print("Limit Order Placed:")
print(f" Order ID : {limit_order['orderId']}")
print(f" Symbol : {limit_order['symbol']}")
print(f" Side : {limit_order['side']}")
print(f" Limit Price: {limit_price:,.2f} USDT")
print(f" Status : {limit_order['status']}")
Limit Order Placed: Order ID : 100002 Symbol : BTCUSDT Side : BUY Limit Price: 59,404.95 USDT Status : NEW
7. Order Management Functions
7.1. get_order_status Function
Retrieves the current status of an order by its ID. Returns key fields such as fill quantity and average price.
def get_order_status(client: Client, symbol: str, order_id: int) -> dict:
"""Return the status of an existing order.
Parameters
----------
client : Authenticated Binance client.
symbol : Trading pair symbol, e.g. 'BTCUSDT'.
order_id : The integer order ID returned when the order was placed.
Returns
-------
dict: Contains 'status', 'executed_qty', and 'avg_price'.
"""
# Query the order by symbol and ID.
order = client.get_order(symbol=symbol, orderId=order_id)
executed_qty = float(order["executedQty"])
avg_price = (
float(order["cummulativeQuoteQty"]) / executed_qty
if executed_qty > 0 else 0.0
)
return {
"status" : order["status"],
"executed_qty": executed_qty,
"avg_price" : round(avg_price, 2),
}# Check the status of the limit order we just placed.
# Commented out to run locally with dummy data
# status = get_order_status(client, "BTCUSDT", limit_order["orderId"])
status = {"status": "NEW", "executed_qty": 0.0, "avg_price": 0.0} # Dummy data
print("Limit Order Status:")
print(f" Status : {status['status']}")
print(f" Executed Qty : {status['executed_qty']} BTC")
print(f" Avg Fill Price: {status['avg_price']:,.2f} USDT")
Limit Order Status: Status : NEW Executed Qty : 0.0 BTC Avg Fill Price: 0.00 USDT
7.2. cancel_order Function
Cancels an open order on Binance. Only orders with status NEW or PARTIALLY_FILLED can be cancelled.
def cancel_order(client: Client, symbol: str, order_id: int) -> dict:
"""Cancel an open order on Binance.
Parameters
----------
client : Authenticated Binance client.
symbol : Trading pair symbol, e.g. 'BTCUSDT'.
order_id : The integer order ID to cancel.
Returns
-------
dict: Cancellation confirmation from Binance.
"""
# Send the cancel request; raises an exception if the order is already filled.
result = client.cancel_order(symbol=symbol, orderId=order_id)
return result# Cancel the limit order if it is still open.
# Commented out to run locally with dummy data
# cancel_result = cancel_order(client, "BTCUSDT", limit_order["orderId"])
cancel_result = {"orderId": limit_order["orderId"], "status": "CANCELED"} # Dummy data
print("Order Cancelled:")
print(f" Order ID : {cancel_result['orderId']}")
print(f" Status : {cancel_result['status']}")
Order Cancelled: Order ID : 100002 Status : CANCELED
8. Execution Decision Framework
Choosing the right order type on Binance depends on your execution goal:
When to Use a Market Order
- You need to enter or exit immediately (e.g., stop-loss, signal with rapid decay).
- Order size is small relative to book depth (< 0.5% of visible liquidity).
- Speed matters more than the exact fill price.
When to Use a Limit Order
- You want price certainty and can wait for the market to come to you.
- Order size is large (> 1% of book depth) — avoids eating through multiple levels.
- Market is volatile (spread > 5 bps) — anchor your execution price.
- You want to qualify for maker rebates (limit orders that rest in the book).
Binance-Specific Notes
- Default fee tier: Taker 0.04% / Maker 0.02% (USDT-margined perpetuals).
- Holding BNB in your account reduces fees by 25%.
- The
TIME_IN_FORCE_GTCflag keeps the order alive until it fills or you cancel it.
Resources
Here are some additional resources to deepen your understanding and further explore the capabilities of the python-binance library and Binance API:
-
python-binanceGitHub Repository: The official source code, detailed documentation, and examples for thepython-binancelibrary. https://github.com/sammchardy/python-binance -
Binance API Documentation: Comprehensive documentation for all Binance API endpoints, including REST API, WebSocket, and more. https://binance-docs.github.io/apidocs/spot/en/
-
Binance Testnet: Information and access to the Binance Spot Testnet for risk-free development and testing. https://testnet.binance.vision/
-
Binance Academy: Educational articles and tutorials on various aspects of cryptocurrency trading, blockchain, and the Binance ecosystem. https://academy.binance.com/