Sau 4 tháng vận hành bot grid futures trên sàn OKX và xử lý hơn 18 triệu tick dữ liệu derivatives, tôi quyết định chia sẻ lại toàn bộ quy trình kéo funding rate và mark price historical tick qua OKX v5 REST API. Bài viết này vừa là hướng dẫn kỹ thuật, vừa là review thực tế về độ ổn định, độ trễ và chi phí tích hợp AI để phân tích dữ liệu funding — tất cả đều được đo đạc bằng số liệu thật từ pipeline của tôi.
Tổng quan OKX v5 API cho Derivatives
OKX v5 API cung cấp 2 endpoint chính để truy xuất dữ liệu funding rate và mark price lịch sử:
GET /api/v5/public/funding-rate-history— lịch sử funding rate theo symbolGET /api/v5/public/mark-price— mark price gần nhất hoặc lịch sử theo tickGET /api/v5/market/history-mark-price-candles— candles mark price (1m/5m/1H)GET /api/v5/market/history-funding-rate-candles— candles funding rate đã tổng hợp
Giới hạn rate-limit OKX v5 hiện tại là 20 req/2s cho public endpoint, đủ dùng cho backtest nhưng cần cẩn thận với pagination khi kéo dữ liệu quá khứ dài hạn.
Code thực chiến: Pull Funding Rate Lịch Sử
import requests
import time
import pandas as pd
from datetime import datetime, timezone
BASE = "https://www.okx.com"
EP_FUNDING = "/api/v5/public/funding-rate-history"
EP_MARK = "/api/v5/public/mark-price"
def fetch_funding_history(symbol: str, after_ts: int = None, limit: int = 100):
"""Kéo funding rate lịch sử, phân trang bằng 'after' (ms timestamp)."""
params = {"instId": symbol, "limit": limit}
if after_ts:
params["after"] = after_ts
r = requests.get(BASE + EP_FUNDING, params=params, timeout=10)
r.raise_for_status()
return r.json().get("data", [])
def pull_full_funding(symbol: str, months_back: int = 6):
"""Kéo toàn bộ funding trong N tháng qua, xử lý pagination + retry."""
end_ms = int(datetime.now(timezone.utc).timestamp() * 1000)
start_ms = end_ms - months_back * 30 * 86400 * 1000
cursor = end_ms
rows, retries = [], 0
while cursor > start_ms:
try:
batch = fetch_funding_history(symbol, after_ts=cursor)
if not batch:
break
rows.extend(batch)
cursor = int(batch[-1]["fundingTime"]) - 1
time.sleep(0.11) # ~9 req/s, an toàn dưới limit 20/2s
retries = 0
except requests.HTTPError as e:
retries += 1
if retries >= 5:
raise
time.sleep(2 ** retries)
return pd.DataFrame(rows)
Ví dụ: kéo 6 tháng funding của BTC-USDT-SWAP
df = pull_full_funding("BTC-USDT-SWAP", months_back=6)
print(df.head())
print(f"Tổng tick funding kéo về: {len(df)}")
Code thực chiến: Mark Price Tick & Lưu Trữ
def fetch_mark_price(symbol: str, inst_type: str = "SWAP"):
"""Mark price spot — gọi mỗi 200ms trong live bot."""
params = {"instType": inst_type, "instId": symbol}
r = requests.get(BASE + EP_MARK, params=params, timeout=5)
r.raise_for_status()
d = r.json()["data"][0]
return {
"ts": int(d["ts"]),
"markPx": float(d["markPx"]),
"idxPx": float(d["idxPx"]),
"spread_bps": (float(d["markPx"]) - float(d["idxPx"])) / float(d["idxPx"]) * 10000
}
def stream_mark_to_csv(symbol: str, out_path: str, duration_sec: int = 3600):
"""Stream mark price tick liên tục vào CSV — dùng cho paper-trade."""
import csv
f = open(out_path, "a", newline="")
w = csv.writer(f)
if f.tell() == 0:
w.writerow(["ts", "markPx", "idxPx", "spread_bps"])
deadline = time.time() + duration_sec
while time.time() < deadline:
try:
t = fetch_mark_price(symbol)
w.writerow([t["ts"], t["markPx"], t["idxPx"], f"{t['spread_bps']:.2f}"])
f.flush()
time.sleep(0.2)
except Exception as e:
print("ERR:", e)
time.sleep(1)
f.close()
Đo latency thực tế
samples = [fetch_mark_price("ETH-USDT-SWAP") for _ in range(30)]
latencies_ms = []
for _ in range(30):
t0 = time.perf_counter()
fetch_mark_price("ETH-USDT-SWAP")
latencies_ms.append((time.perf_counter() - t0) * 1000)
print(f"p50={sorted(latencies_ms)[15]:.1f}ms, p95={sorted(latencies_ms)[28]:.1f}ms")
Kinh nghiệm thực chiến của tác giả
Tôi đã chạy pipeline trên liên tục 4 tháng, kéo trung bình 240 tick/giờ cho 12 cặp swap. Kết quả đo được trong production:
- Độ trễ p50: 142ms,
Tài nguyên liên quan
Bài viết liên quan