When working with cryptocurrency derivatives, accurate and reliable market data is essential—especially when dealing with futures and perpetual contracts. One of the most critical data points for traders and developers alike is the mark price, which helps prevent unfair liquidations by reflecting the true fair value of a contract.
If you're using the OKX exchange API through the popular ccxt library in Python, you might have encountered a challenge when trying to retrieve historical mark price candlesticks. While fetch_mark_ohlcv seems like the right method, it may return empty results or not behave as expected. This article explains how to properly access historical mark price data using the OKX REST API, explores available methods, and provides actionable code examples.
Understanding Mark Price vs. Last Traded Price
Before diving into implementation, it's important to understand the difference between:
- Last traded price: The price at which the most recent trade occurred.
- Mark price: A smoothed, index-based price designed to prevent manipulation and ensure fair settlements.
For risk management, backtesting, and strategy development, historical mark price OHLCV (Open, High, Low, Close, Volume) data is often more reliable than last traded prices.
Using fetch_mark_ohlcv in CCXT
The ccxt library provides a unified method called fetch_mark_ohlcv to retrieve mark price candles. However, as noted in your query, calling this method may result in an empty response:
import ccxt.async_support as ccxt
import time
import asyncio
async def fetch_data():
exchange = ccxt.okx()
since = int(time.time() - 300000) * 1000 # ~5 minutes ago
ohlcv = await exchange.fetch_mark_ohlcv('ETH/USDT', '1m', since=since, limit=100)
print(ohlcv)
await exchange.close()Despite correct parameters, the response body shows:
{"code":"0","msg":"","data":[]}This happens because OKX’s /api/v5/market/mark-price-candles endpoint only returns recent data—typically within the last few minutes—and does not support deep historical queries.
👉 Access real-time and historical market data securely via OKX API
Solution: Use the History Mark Price Candles Endpoint
To retrieve older or extended historical mark price data, you must use the dedicated endpoint:
GET /api/v5/market/history-mark-price-candlesUnfortunately, as of CCXT version 2.2.80, this endpoint is not directly exposed via a high-level method like fetch_mark_ohlcv. However, you can still access it using CCXT’s built-in implicit methods.
✅ Correct Way to Call history-mark-price-candles
Here’s how to use the private method wrapper in CCXT to call this endpoint:
import ccxt.async_support as ccxt
import asyncio
async def fetch_historical_mark_candles():
exchange = ccxt.okx({
'enableRateLimit': True,
})
try:
# Use implicit method: public_get_market_history_mark_price_candles
params = {
'instId': 'ETH-USDT',
'bar': '1H', # Timeframe: 1m, 5m, 1H, 1D, etc.
'limit': '100', # Max records to return
# Optional: 'after', 'before' for pagination (in milliseconds)
}
response = await exchange.public_get_market_history_mark_price_candles(params)
if response.get('code') == '0' and response.get('data'):
candles = response['data']
for candle in candles:
timestamp = int(candle[0]) # Milliseconds
open_price = float(candle[1])
high_price = float(candle[2])
low_price = float(candle[3])
close_price = float(candle[4])
print(f"{timestamp}: O={open_price}, H={high_price}, L={low_price}, C={close_price}")
else:
print("No data returned or error:", response.get('msg'))
except Exception as e:
print("Error:", str(e))
finally:
await exchange.close()
# Run the async function
asyncio.run(fetch_historical_mark_candles())🔍 Note: The symbol format uses hyphens (ETH-USDT), not slashes (ETH/USDT), in request parameters.
Key Parameters for Historical Requests
| Parameter | Description |
|---|---|
instId | Trading pair (e.g., ETH-USDT, BTC-USDT) |
bar | Candlestick interval (1m, 5m, 1H, 1D, etc.) |
limit | Number of records (max usually 100) |
after | Return data newer than this timestamp (ms) |
before | Return data older than this timestamp (ms) |
You can paginate through large datasets by adjusting before and after.
When to Use Each Method?
| Method | Use Case |
|---|---|
fetch_mark_ohlcv() | Real-time or near-real-time mark price candles (last few minutes) |
public_get_market_history_mark_price_candles() | Retrieving older historical mark price data beyond the live window |
👉 Retrieve extended historical derivatives data with low-latency API access
Common Issues & Fixes
❌ Empty Data Array ("data": [])
- Cause: Querying too far in the past with
/mark-price-candles, or incorrect time formatting. - Fix: Use
/history-mark-price-candlesinstead for older data.
❌ Invalid Symbol Format
- Mistake: Passing
'ETH/USDT'instead of'ETH-USDT'. - Fix: Always use hyphen-separated format in direct API calls.
❌ Rate Limiting
- OKX enforces strict rate limits on public endpoints.
- Solution: Enable
enableRateLimit: Truein exchange config.
Core Keywords for SEO & Search Intent
To ensure visibility and relevance for developers searching for solutions:
- OKX API
- fetch mark ohlcv
- historical mark price candles
- CCXT Python
- mark price OHLCV
- OKX REST API
- cryptocurrency market data
- fetch historical candles
These keywords are naturally integrated throughout this guide to align with common developer queries while maintaining readability and technical accuracy.
Frequently Asked Questions (FAQ)
Q: Does fetch_mark_ohlcv support historical data on OKX?
No. The fetch_mark_ohlcv method maps to /api/v5/market/mark-price-candles, which only returns recent data (typically within the last few minutes). For deeper history, use the /history-mark-price-candles endpoint via public_get_market_history_mark_price_candles.
Q: Why am I getting an empty array from OKX mark price API?
Empty responses usually occur when:
- You're querying outside the available time window.
- You're using the wrong endpoint for historical data.
- Timestamps are incorrectly formatted (should be in milliseconds).
Switching to the history endpoint resolves most cases.
Q: Can I use CCXT to call undocumented or implicit APIs?
Yes. CCXT supports implicit API methods like public_get_{path} and private_post_{path}. These allow access to endpoints not yet wrapped in high-level functions.
Q: What timeframes are supported for mark price candles?
Supported bars include: 1m, 5m, 15m, 30m, 1H, 4H, 1D, 1W, 1M.
Q: Is authentication required to get historical mark price data?
No. The /market/history-mark-price-candles endpoint is public. No API keys are needed unless you're making high-frequency requests.
Q: How far back can I fetch historical mark price data?
OKX typically retains several months of historical mark price data, but exact retention varies. Always paginate using before/after timestamps to stream longer histories.
👉 Build robust trading bots with precise mark price data from OKX
By leveraging the correct endpoints and understanding the limitations of unified methods like fetch_mark_ohlcv, developers can reliably integrate high-quality historical mark price data into their trading systems. Whether you're building risk engines, backtesting frameworks, or analytics dashboards, using the proper API calls ensures accuracy and consistency across your applications.