OKX Execution
Implement live trade execution on OKX using their trading APIs with proper timestamp-based authentication, order construction for spot and perpetual swap markets, and real-time order status monitoring via WebSocket subscription streams.
Execute Trades on OKX
1. Overview
This notebook demonstrates how to execute trades programmatically on OKX using the official python-okx SDK. It covers authentication, market data retrieval, fee lookup, order placement, and order management. Trading is a complex activity, and this notebook aims to provide a clear, practical guide for integrating with the OKX platform through its API.
What You Will Learn
| Step | Description | Key Concept |
|---|---|---|
| Authentication | Connect to OKX via API key, secret, and passphrase | Secure API Access |
| Market Data | Fetch ticker prices and order book depth | Real-time Market Insights |
| Fee Lookup | Retrieve trading fee rates for a given instrument | Cost Management |
| Market Order | Place an immediate buy/sell order | Execution Certainty |
| Limit Order | Place a price-controlled buy/sell order | Price Control |
| Order Status | Query and display order fill details | Trade Monitoring |
| Cancel Order | Cancel an open limit order | Risk Management |
Important Note on Environment and Data: This notebook is configured by default to use the OKX demo/paper trading environment. This allows you to experiment with API calls and trading logic without risking real funds. To switch to live trading, you must change the
flag='0'in thecreate_clientsfunction call and supply valid live API keys.Dummy Mode for Local Execution: For convenience, live API calls throughout this notebook are commented out and replaced with realistic dummy data. This ensures the notebook can run end-to-end even without an active OKX API connection or actual trading funds. To execute real trades, you will need to uncomment the actual API calls and remove the dummy data assignments.
2. Dependency Imports
To interact with the OKX exchange, we need to install and import specific libraries. The primary library used is python-okx, which is the official Python SDK provided by OKX for both REST and WebSocket API access. This SDK simplifies the process of making API calls by abstracting away the complexities of HTTP requests, authentication, and response parsing.
Running the !pip install python-okx --quiet command ensures that the SDK is available in your Colab environment. We also import warnings to optionally suppress them for cleaner output during demonstration.
# Install the OKX SDK if not already present.
!pip install python-okx --quiet[?25l [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m0.0/61.6 kB[0m [31m?[0m eta [36m-:--:--[0m [2K [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m61.6/61.6 kB[0m [31m4.5 MB/s[0m eta [36m0:00:00[0m [?25h[?25l [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m0.0/42.7 kB[0m [31m?[0m eta [36m-:--:--[0m [2K [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m42.7/42.7 kB[0m [31m2.6 MB/s[0m eta [36m0:00:00[0m [?25h[?25l [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m0.0/254.6 kB[0m [31m?[0m eta [36m-:--:--[0m [2K [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m254.6/254.6 kB[0m [31m8.2 MB/s[0m eta [36m0:00:00[0m [?25h
import okx.Trade as Trade
import okx.MarketData as MarketData
import okx.Account as Account
import warnings
# Suppress all warnings for cleaner output in a demonstration context.
warnings.filterwarnings("ignore")3. Authentication
Connecting to the OKX exchange requires robust authentication to ensure secure communication and authorize trading activities. OKX uses a combination of an API key, a secret key, and a passphrase to authenticate API requests. These credentials are generated within your OKX account settings.
3.1. create_clients Function
The create_clients function is designed to centralize the instantiation of various OKX client objects. These objects (TradeAPI, MarketAPI, AccountAPI) are specialized for different types of interactions with the exchange (e.g., placing orders, fetching market data, querying account details).
Parameters:
api_key: Your unique API key obtained from OKX.secret_key: The secret key associated with your API key.passphrase: A custom passphrase you set when creating the API key. This adds an extra layer of security.flag: This crucial parameter determines the operating environment:'1': Paper trading (demo) environment. Ideal for testing and development without financial risk.'0': Live trading environment. Use with caution, as this involves real funds.
Security Best Practices:
- Never hardcode API keys directly in publicly shared notebooks. Use environment variables or a secure secret management system (like Colab's
userdatafor API keys) to store your credentials. - Grant your API keys only the necessary permissions on the OKX platform (e.g., read-only for market data, trade permissions for placing orders, but avoid withdrawal permissions for general trading bots).
- Regenerate your API keys periodically, especially if you suspect they might have been compromised.
def create_clients(api_key: str, secret_key: str, passphrase: str, flag: str = "1") -> dict:
"""Create authenticated OKX client instances for trading and market data.
Parameters
----------
api_key : Your OKX API key.
secret_key : Your OKX secret key.
passphrase : The passphrase set when you created the API key.
flag : '1' = paper trading (demo), '0' = live trading.
Returns
-------
dict: Contains 'trade', 'market', and 'account' client instances.
"""
# Instantiate each sub-client with the same credentials.
trade_client = Trade.TradeAPI(api_key, secret_key, passphrase, False, flag)
market_client = MarketData.MarketAPI(api_key, secret_key, passphrase, False, flag)
account_client = Account.AccountAPI(api_key, secret_key, passphrase, False, flag)
return {
"trade" : trade_client,
"market" : market_client,
"account": account_client,
}# ── Replace with your own keys ──────────────────────────────────────────────
API_KEY = "YOUR_OKX_API_KEY"
SECRET_KEY = "YOUR_OKX_SECRET_KEY"
PASSPHRASE = "YOUR_OKX_PASSPHRASE"
# ────────────────────────────────────────────────────────────────────────────
# Create all sub-clients (flag='1' = paper trading).
clients = create_clients(API_KEY, SECRET_KEY, PASSPHRASE, flag="1")
print("OKX clients created successfully.")OKX clients created successfully.
4. Market Data Functions
4.1. get_ticker_price Function
Fetches the latest best bid and ask prices for a given instrument ID.
def get_ticker_price(market_client, inst_id: str) -> dict:
"""Return the best bid and ask price for an instrument.
Parameters
----------
market_client : OKX MarketData client instance.
inst_id : OKX instrument ID, e.g. 'BTC-USDT'.
Returns
-------
dict: Contains 'bid' and 'ask' as floats.
"""
# get_ticker returns a response dict; data[0] contains the ticker fields.
response = market_client.get_ticker(instId=inst_id)
data = response["data"][0]
return {
"bid": float(data["bidPx"]),
"ask": float(data["askPx"]),
}# Fetch the current BTC-USDT ticker.
# Commented out to run locally with dummy data
# ticker = get_ticker_price(clients["market"], "BTC-USDT")
ticker = {"bid": 60000.00, "ask": 60005.00} # Dummy data
print(f"BTC-USDT — Bid: {ticker['bid']:,.2f} | Ask: {ticker['ask']:,.2f}")
BTC-USDT — Bid: 60,000.00 | Ask: 60,005.00
4.2. get_order_book Function
Retrieves the top N levels of bids and asks for an instrument.
def get_order_book(market_client, inst_id: str, depth: int = 5) -> dict:
"""Return the top N bid and ask levels from the order book.
Parameters
----------
market_client : OKX MarketData client instance.
inst_id : OKX instrument ID, e.g. 'BTC-USDT'.
depth : Number of price levels to retrieve (default: 5).
Returns
-------
dict: Contains 'bids' and 'asks' as lists of [price, quantity].
"""
# get_orderbook returns bids and asks; each entry is [price, qty, 0, orders].
response = market_client.get_orderbook(instId=inst_id, sz=str(depth))
data = response["data"][0]
return {
"bids": [[float(b[0]), float(b[1])] for b in data["bids"]],
"asks": [[float(a[0]), float(a[1])] for a in data["asks"]],
}# Display the top 5 levels of the BTC-USDT order book.
# Commented out to run locally with dummy data
# book = get_order_book(clients["market"], "BTC-USDT", 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 maker and taker fee rates for a given instrument type. OKX fees vary by VIP tier and product category (SPOT vs FUTURES).
def get_trade_fee(account_client, inst_type: str = "SPOT", inst_id: str = "BTC-USDT") -> dict:
"""Return maker and taker fee rates for an instrument.
Parameters
----------
account_client : OKX Account client instance.
inst_type : Instrument type: 'SPOT', 'FUTURES', 'SWAP', etc.
inst_id : OKX instrument ID, e.g. 'BTC-USDT'.
Returns
-------
dict: Contains 'maker_fee' and 'taker_fee' as floats.
"""
# get_fee_rates returns the account's actual fee tier.
response = account_client.get_fee_rates(instType=inst_type, instId=inst_id)
data = response["data"][0]
return {
"maker_fee": abs(float(data["maker"])), # OKX returns negative for rebate.
"taker_fee": abs(float(data["taker"])),
}# Display spot fee rates for BTC-USDT.
# Commented out to run locally with dummy data
# fees = get_trade_fee(clients["account"], inst_type="SPOT", inst_id="BTC-USDT")
fees = {"maker_fee": 0.0002, "taker_fee": 0.0005} # Dummy data (SPOT VIP0 default rates)
print(f"BTC-USDT Fees — Maker: {fees['maker_fee']*100:.4f}% | Taker: {fees['taker_fee']*100:.4f}%")
BTC-USDT Fees — Maker: 0.0200% | Taker: 0.0500%
6. Order Execution Functions
6.1. place_market_order Function
Places a market order on OKX. The order fills immediately at the best available price. Use when execution certainty is the priority.
def place_market_order(
trade_client, inst_id: str, side: str, quantity: float, td_mode: str = "cash"
) -> dict:
"""Place a market order on OKX.
Parameters
----------
trade_client : OKX Trade client instance.
inst_id : OKX instrument ID, e.g. 'BTC-USDT'.
side : 'buy' or 'sell'.
quantity : Size of the order in base currency.
td_mode : Trade mode — 'cash' for spot, 'cross'/'isolated' for margin.
Returns
-------
dict: OKX order response including ordId.
"""
# place_order with ordType='market' for immediate execution.
response = trade_client.place_order(
instId = inst_id,
tdMode = td_mode,
side = side.lower(),
ordType = "market",
sz = str(quantity),
)
return response["data"][0]# Place a market BUY order for 0.001 BTC (paper trading).
# Commented out to run locally with dummy data
# market_order = place_market_order(
# clients["trade"], inst_id="BTC-USDT", side="buy", quantity=0.001
# )
market_order = {"ordId": "dummy-market-0001", "clOrdId": "dummy-cl-0001", "tag": ""} # Dummy data
print("Market Order Placed:")
print(f" Order ID : {market_order['ordId']}")
print(f" Client ID: {market_order.get('clOrdId', 'N/A')}")
print(f" Tag : {market_order.get('tag', 'N/A')}")
Market Order Placed: Order ID : dummy-market-0001 Client ID: dummy-cl-0001 Tag :
6.2. place_limit_order Function
Places a limit order on OKX. The order rests in the book until the market reaches your specified price. Use when price control matters.
def place_limit_order(
trade_client, inst_id: str, side: str, quantity: float, price: float, td_mode: str = "cash"
) -> dict:
"""Place a limit order on OKX (Good-Till-Cancelled by default).
Parameters
----------
trade_client : OKX Trade client instance.
inst_id : OKX instrument ID, e.g. 'BTC-USDT'.
side : 'buy' or 'sell'.
quantity : Size of the order in base currency.
price : Limit price at which to execute.
td_mode : Trade mode — 'cash' for spot, 'cross'/'isolated' for margin.
Returns
-------
dict: OKX order response including ordId.
"""
# place_order with ordType='limit' rests until filled or cancelled.
response = trade_client.place_order(
instId = inst_id,
tdMode = td_mode,
side = side.lower(),
ordType = "limit",
sz = str(quantity),
px = str(price),
)
return response["data"][0]# Place a passive limit BUY 1% below the current ask.
# Commented out to run locally with dummy data
# current_ask = get_ticker_price(clients["market"], "BTC-USDT")["ask"]
current_ask = ticker["ask"] # reuse dummy ticker from earlier
limit_price = round(current_ask * 0.99, 2)
# limit_order = place_limit_order(
# clients["trade"], inst_id="BTC-USDT", side="buy", quantity=0.001, price=limit_price
# )
limit_order = {"ordId": "dummy-limit-0001", "clOrdId": "dummy-cl-0002"} # Dummy data
print("Limit Order Placed:")
print(f" Order ID : {limit_order['ordId']}")
print(f" Limit Price: {limit_price:,.2f} USDT")
Limit Order Placed: Order ID : dummy-limit-0001 Limit Price: 59,404.95 USDT
7. Order Management Functions
7.1. get_order_status Function
Retrieves the current status and fill details for an existing order.
def get_order_status(trade_client, inst_id: str, ord_id: str) -> dict:
"""Return the status and fill details of an existing order.
Parameters
----------
trade_client : OKX Trade client instance.
inst_id : OKX instrument ID, e.g. 'BTC-USDT'.
ord_id : The order ID string returned when the order was placed.
Returns
-------
dict: Contains 'state', 'filled_sz', and 'avg_px'.
"""
# get_order returns the full order detail.
response = trade_client.get_order(instId=inst_id, ordId=ord_id)
data = response["data"][0]
return {
"state" : data["state"],
"filled_sz": float(data["fillSz"]),
"avg_px" : float(data["avgPx"]) if data["avgPx"] else 0.0,
}# Check the status of the limit order we placed.
# Commented out to run locally with dummy data
# status = get_order_status(clients["trade"], "BTC-USDT", limit_order["ordId"])
status = {"state": "live", "filled_sz": 0.0, "avg_px": 0.0} # Dummy data
print("Limit Order Status:")
print(f" State : {status['state']}")
print(f" Filled Size: {status['filled_sz']} BTC")
print(f" Avg Price : {status['avg_px']:,.2f} USDT")
Limit Order Status: State : live Filled Size: 0.0 BTC Avg Price : 0.00 USDT
7.2. cancel_order Function
Cancels an open order on OKX. Only orders with state live or partially_filled can be cancelled.
def cancel_order(trade_client, inst_id: str, ord_id: str) -> dict:
"""Cancel an open order on OKX.
Parameters
----------
trade_client : OKX Trade client instance.
inst_id : OKX instrument ID, e.g. 'BTC-USDT'.
ord_id : The order ID string to cancel.
Returns
-------
dict: Cancellation confirmation from OKX.
"""
# cancel_order raises an error if the order is already filled or cancelled.
response = trade_client.cancel_order(instId=inst_id, ordId=ord_id)
return response["data"][0]# Cancel the limit order if it is still open.
# Commented out to run locally with dummy data
# cancel_result = cancel_order(clients["trade"], "BTC-USDT", limit_order["ordId"])
cancel_result = {"ordId": limit_order["ordId"], "clOrdId": limit_order.get("clOrdId", "N/A")} # Dummy data
print("Order Cancelled:")
print(f" Order ID : {cancel_result['ordId']}")
print(f" Client ID: {cancel_result.get('clOrdId', 'N/A')}")
Order Cancelled: Order ID : dummy-limit-0001 Client ID: dummy-cl-0002
8. Execution Decision Framework
Choosing the right order type on OKX depends on your execution goal:
When to Use a Market Order
- You need to enter or exit immediately (e.g., stop-loss, rapid signal 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 consuming multiple levels.
- Market is volatile (spread > 5 bps) — anchor your execution price.
- You want to qualify for maker rebates by adding liquidity to the book.
OKX-Specific Notes
- Default fee tier: Taker 0.05% / Maker 0.02% (SPOT VIP0).
- OKX uses a
flagparameter:'1'for demo/paper,'0'for live. - The
tdModeparameter controls margin:'cash'= spot non-margin.