OKX V5 Demo Trading API: Test Strategies Risk-Free
Learn how to use OKX V5 Demo Trading API to test algorithms, validate strategies, and build bots without risking real capital.
Learn how to use OKX V5 Demo Trading API to test algorithms, validate strategies, and build bots without risking real capital.
Paper trading is where serious algorithmic traders separate themselves from gamblers. The OKX V5 Demo Trading API gives you a full sandbox environment — real market data, real order book mechanics, real WebSocket feeds — but with simulated funds. You can blow up your account a dozen times, learn exactly why, and never lose a dollar. Platforms like Bybit and Binance offer similar sandboxes, but OKX's V5 API stands out for its unified endpoint structure and the depth of its demo environment coverage.
The OKX demo trading environment isn't a watered-down simulator. It mirrors the production API almost exactly. You get access to spot, futures, perpetual swaps, and options markets. Order types — limit, market, post-only, reduce-only, conditional — all work identically to live trading. The key difference: your balance is simulated, and you operate against a demo order book that tracks real prices but fills against OKX's own matching engine in paper mode.
This matters enormously when you're building a trading bot. A fake environment that doesn't respect real slippage or real order book depth will give you misleading results. OKX's demo environment uses live price feeds, so your strategy sees the same candles, the same volatility, the same spread dynamics as real trading. The only thing missing is actual counterparty risk.
Demo API keys on OKX are separate from your live API keys. You need to generate them specifically for the demo environment. Log into OKX, navigate to Account > API Management, and look for the 'Demo Trading' toggle. Create a new API key there — you'll get an API key, secret, and passphrase just like production. The passphrase is required for every authenticated request, which is a security layer Binance doesn't enforce the same way.
Demo API keys only work against the demo base URL: https://www.okx.com with the header x-simulated-trading: 1. If you forget this header, your requests will hit the live environment — or fail if your live keys don't have matching permissions.
Authentication in OKX V5 uses HMAC-SHA256 signatures. The signature covers the timestamp, HTTP method, request path, and body concatenated together. This is slightly different from Bybit's approach and significantly different from how older OKX V3 endpoints worked — don't mix them up.
import hmac
import hashlib
import base64
import time
import requests
import json
API_KEY = 'your_demo_api_key'
SECRET_KEY = 'your_demo_secret_key'
PASSPHRASE = 'your_passphrase'
BASE_URL = 'https://www.okx.com'
def get_timestamp():
return str(int(time.time()))
def sign(timestamp, method, path, body=''):
message = timestamp + method.upper() + path + body
mac = hmac.new(
SECRET_KEY.encode('utf-8'),
message.encode('utf-8'),
digestmod=hashlib.sha256
)
return base64.b64encode(mac.digest()).decode()
def get_headers(method, path, body=''):
ts = get_timestamp()
return {
'OK-ACCESS-KEY': API_KEY,
'OK-ACCESS-SIGN': sign(ts, method, path, body),
'OK-ACCESS-TIMESTAMP': ts,
'OK-ACCESS-PASSPHRASE': PASSPHRASE,
'Content-Type': 'application/json',
'x-simulated-trading': '1' # Required for demo environment
}
# Test: fetch demo account balance
path = '/api/v5/account/balance'
headers = get_headers('GET', path)
response = requests.get(BASE_URL + path, headers=headers)
print(json.dumps(response.json(), indent=2))
Once authentication is working, placing orders is straightforward. The OKX V5 order placement endpoint is POST /api/v5/trade/order. The same endpoint works for spot and derivatives — you control which with the instType parameter. This unified structure is one of the reasons developers often prefer OKX's V5 API over Binance's split between spot and futures APIs.
def place_limit_order(inst_id, side, price, size, td_mode='cash'):
"""
Place a limit order in OKX demo environment.
inst_id: e.g. 'BTC-USDT' for spot, 'BTC-USDT-SWAP' for perpetual
side: 'buy' or 'sell'
td_mode: 'cash' for spot, 'cross' or 'isolated' for derivatives
"""
path = '/api/v5/trade/order'
body = json.dumps({
'instId': inst_id,
'tdMode': td_mode,
'side': side,
'ordType': 'limit',
'px': str(price),
'sz': str(size)
})
headers = get_headers('POST', path, body)
response = requests.post(BASE_URL + path, headers=headers, data=body)
result = response.json()
if result.get('code') == '0':
order_id = result['data'][0]['ordId']
print(f'Order placed successfully. Order ID: {order_id}')
return order_id
else:
error_msg = result.get('msg', 'Unknown error')
error_code = result.get('code')
print(f'Order failed. Code: {error_code}, Message: {error_msg}')
return None
# Example: buy 0.01 BTC at $60,000 on demo spot market
order_id = place_limit_order(
inst_id='BTC-USDT',
side='buy',
price=60000,
size=0.01
)
# Check order status
if order_id:
check_path = f'/api/v5/trade/order?instId=BTC-USDT&ordId={order_id}'
check_headers = get_headers('GET', check_path)
status_response = requests.get(BASE_URL + check_path, headers=check_headers)
order_data = status_response.json()['data'][0]
print(f"Order state: {order_data['state']}")
print(f"Filled size: {order_data['fillSz']}")
Error handling deserves more attention than most tutorials give it. OKX returns errors in two places: HTTP-level errors (4xx/5xx) and application-level errors inside the JSON body where code is not '0'. Your bot needs to handle both. Common demo-specific errors include rate limit violations (OKX enforces the same rate limits in demo as in production) and invalid instrument IDs. If you're testing a perpetual swap strategy, make sure to use the correct suffix — BTC-USDT-SWAP, not BTC-USDT.
REST is fine for placing orders, but if you're building any kind of reactive strategy — scalping, grid trading, signal execution — you need WebSocket. OKX's V5 WebSocket API covers public channels (no auth needed) for order books, trades, and tickers, and private channels for order updates and position changes. The demo WebSocket endpoint uses the same URL as production but responds to your demo keys.
import asyncio
import websockets
import json
import time
import hmac
import hashlib
import base64
WS_PUBLIC_URL = 'wss://ws.okx.com:8443/ws/v5/public'
WS_PRIVATE_URL = 'wss://ws.okx.com:8443/ws/v5/private'
def generate_ws_login_args():
ts = str(int(time.time()))
sign_str = ts + 'GET' + '/users/self/verify'
mac = hmac.new(
SECRET_KEY.encode('utf-8'),
sign_str.encode('utf-8'),
digestmod=hashlib.sha256
)
signature = base64.b64encode(mac.digest()).decode()
return [{
'apiKey': API_KEY,
'passphrase': PASSPHRASE,
'timestamp': ts,
'sign': signature
}]
async def subscribe_to_orders():
async with websockets.connect(WS_PRIVATE_URL) as ws:
# Login to private channel
login_msg = json.dumps({
'op': 'login',
'args': generate_ws_login_args()
})
await ws.send(login_msg)
login_response = await ws.recv()
print(f'Login: {login_response}')
# Subscribe to order updates on demo
sub_msg = json.dumps({
'op': 'subscribe',
'args': [{
'channel': 'orders',
'instType': 'SPOT',
'instId': 'BTC-USDT'
}]
})
await ws.send(sub_msg)
# Listen for updates
async for message in ws:
data = json.loads(message)
if 'data' in data:
for order in data['data']:
print(f"Order {order['ordId']}: {order['state']} | Filled: {order['fillSz']}")
# Run: asyncio.run(subscribe_to_orders())
# Note: Add 'x-simulated-trading: 1' via custom headers if your WS library supports it
# For most demo testing, the private channel uses your demo keys directly
One practical tip: pair your OKX demo bot with a signal source like VoiceOfChain, which provides real-time trading signals derived from on-chain data and market momentum. You can subscribe to VoiceOfChain's signal feed, pipe those signals into your demo bot, and measure actual execution quality — slippage, fill rates, timing — before ever committing capital. This is the right way to validate whether a signal-following strategy actually works in practice.
Having a demo environment is only useful if you treat it seriously. The biggest mistake traders make is running a strategy for two days in demo, seeing green PnL, and going live. That's not validation — that's confirmation bias. A proper demo validation cycle looks different.
Exchanges like Gate.io and KuCoin also offer testnet environments, but OKX's demo is particularly valuable for derivatives strategies because the funding rate mechanics are simulated accurately. If you're building a funding rate arbitrage bot, you need that accuracy — a demo environment that ignores funding will give you completely wrong PnL projections.
One important limitation: demo trading doesn't simulate liquidity crises. During a real market crash, actual order books thin out dramatically and slippage explodes. Your demo results will always be cleaner than live — factor in at least 20-30% performance degradation when estimating live trading results from demo metrics.
The OKX V5 Demo Trading API is one of the most capable paper trading environments available to algo traders today. It gives you production-identical endpoints, live price feeds, realistic derivatives mechanics, and full WebSocket support — everything you need to build and validate a real trading system before putting capital at risk. Combined with a real-time signal source like VoiceOfChain, you can close the gap between strategy idea and live deployment with actual data rather than hopes. Build in demo. Validate seriously. Go live with confidence.