Tháng 11 năm 2023, thị trường crypto bước vào giai đoạn sideways kéo dài. Lúc 2 giờ sáng, tôi nhận được tin nhắn từ một người bạn — anh ấy vừa mất 2,400 USD chỉ vì một lệnh stop-loss bị触发 quá sớm do hiểu sai mark price so với index price. Câu chuyện đó thúc đẩy tôi nghiên cứu sâu về cách OKX tính toán các chỉ số này, và cuối cùng xây dựng một hệ thống tự động theo dõi tỷ lệ tài trợ (funding rate) bằng Python. Trong bài viết này, tôi sẽ chia sẻ toàn bộ kiến thức thực chiến — từ cách lấy dữ liệu, xử lý lỗi, đến tích hợp AI để phân tích xu hướng.
Tại sao Funding Rate và Mark Price lại quan trọng?
Trước khi đi vào code, hãy hiểu rõ bản chất của hai chỉ số này:
- Funding Rate (Tỷ lệ tài trợ): Thanh toán định kỳ giữa người long và người short. Khi funding rate dương → người long trả phí cho người short (thị trường thiên về long). Đây là tín hiệu quan trọng để đánh giá tâm lý thị trường.
- Mark Price (Giá đánh dấu): Giá được tính toán dựa trên giá spot + tỷ lệ funding. Đây là giá dùng để tính liquidation và PnL — không phải giá thị trường thực tế.
Trong giai đoạn volatility cao, chênh lệch giữa mark price và last price có thể lên tới 0.5-2%, đủ để触发 một lệnh stop-loss không mong muốn nếu bạn không hiểu cơ chế này.
Thiết lập môi trường và cài đặt thư viện
Đầu tiên, cài đặt các thư viện cần thiết:
pip install requests pandas asyncio aiohttp python-dotenv
pip install "python-okx>=1.3.0"
Tạo file cấu hình .env để lưu trữ API credentials an toàn:
# OKX API Configuration
OKX_API_KEY=your_okx_api_key_here
OKX_API_SECRET=your_okx_api_secret_here
OKX_PASSPHRASE=your_okx_passphrase_here
OKX_TESTNET=False # True nếu dùng testnet
Simulation mode (không cần API key)
SIMULATION_MODE=True
Module 1: Lấy Funding Rate với OKX REST API
Đây là code cốt lõi để lấy funding rate của tất cả các cặp perpetual futures:
import requests
import json
from datetime import datetime
from typing import List, Dict, Optional
class OKXFundingRate:
"""Lớp lấy funding rate từ OKX perpetual futures"""
BASE_URL = "https://www.okx.com"
def __init__(self, simulation: bool = True):
self.sim = simulation
def get_funding_rate(self, inst_id: str = "BTC-USDT-SWAP") -> Dict:
"""
Lấy funding rate hiện tại của một cặp giao dịch
Args:
inst_id: Instrument ID (VD: BTC-USDT-SWAP, ETH-USDT-SWAP)
Returns:
Dict chứa funding rate, thời gian thanh toán tiếp theo
"""
endpoint = "/api/v5/market/funding-rate"
params = {"instId": inst_id}
response = requests.get(
f"{self.BASE_URL}{endpoint}",
params=params,
timeout=10
)
response.raise_for_status()
data = response.json()
if data["code"] != "0":
raise ValueError(f"API Error: {data['msg']}")
result = data["data"][0]
return {
"inst_id": result["instId"],
"funding_rate": float(result["fundingRate"]),
"next_funding_time": self._parse_funding_time(result["nextFundingTime"]),
"mark_price": float(result["instId"].replace("-USDT-SWAP", "")) # placeholder
}
def get_all_funding_rates(self, uly: str = "BTC-USDT") -> List[Dict]:
"""
Lấy funding rates của tất cả các cặp perpetual theo underlying
Args:
uly: Underlying (VD: BTC-USDT, ETH-USDT)
Returns:
List các funding rate information
"""
endpoint = "/api/v5/public/funding-rate-history"
# Lấy 100 record gần nhất cho mỗi instrument
params = {
"instId": f"{uly}-USDT-SWAP",
"limit": "100"
}
response = requests.get(
f"{self.BASE_URL}{endpoint}",
params=params,
timeout=10
)
response.raise_for_status()
data = response.json()
if data["code"] != "0":
raise ValueError(f"API Error: {data['msg']}")
results = []
for record in data["data"]:
results.append({
"inst_id": record["instId"],
"funding_rate": float(record["fundingRate"]),
"realized_rate": float(record.get("realizedRate", 0)),
"timestamp": int(record["ts"])
})
return results
def _parse_funding_time(self, ts_str: str) -> datetime:
"""Convert timestamp string sang datetime"""
ts_ms = int(ts_str)
return datetime.fromtimestamp(ts_ms / 1000)
Sử dụng
if __name__ == "__main__":
okx = OKXFundingRate(simulation=True)
# Lấy funding rate BTC
btc_rate = okx.get_funding_rate("BTC-USDT-SWAP")
print(f"BTC Funding Rate: {btc_rate['funding_rate']*100:.4f}%")
print(f"Next Funding: {btc_rate['next_funding_time']}")
# Lấy lịch sử funding rate
history = okx.get_all_funding_rates("BTC-USDT")
print(f"\nLấy được {len(history)} records gần nhất")
print(f"Trung bình Funding Rate: {sum(r['funding_rate'] for r in history)/len(history)*100:.4f}%")
Module 2: Lấy Mark Price và Index Price
Mark price là chỉ số quan trọng để tính liquidation price. Code dưới đây giúp bạn lấy mark price thời gian thực:
import requests
import asyncio
import aiohttp
from dataclasses import dataclass
from typing import List, Optional
@dataclass
class PriceData:
"""Data class lưu trữ thông tin giá"""
inst_id: str
last_price: float
mark_price: float
index_price: float
last_update: str
premium: float # Chênh lệch mark vs last
def __post_init__(self):
self.premium = (self.mark_price - self.last_price) / self.last_price * 100
class OKXPriceFetcher:
"""Async fetcher cho mark price và index price"""
BASE_URL = "https://www.okx.com"
SEMAPHORE_LIMIT = 10 # Giới hạn concurrent requests
def __init__(self):
self.session: Optional[aiohttp.ClientSession] = None
self.semaphore = asyncio.Semaphore(self.SEMAPHORE_LIMIT)
async def __aenter__(self):
self.session = aiohttp.ClientSession()
return self
async def __aexit__(self, *args):
if self.session:
await self.session.close()
async def get_ticker(self, inst_id: str) -> Optional[PriceData]:
"""Lấy ticker data bao gồm mark price cho một instrument"""
async with self.semaphore:
endpoint = "/api/v5/market/ticker"
params = {"instId": inst_id}
try:
async with self.session.get(
f"{self.BASE_URL}{endpoint}",
params=params,
timeout=aiohttp.ClientTimeout(total=5)
) as resp:
data = await resp.json()
if data["code"] != "0":
return None
ticker = data["data"][0]
return PriceData(
inst_id=ticker["instId"],
last_price=float(ticker["last"]),
mark_price=float(ticker["last"]),
index_price=float(ticker["last"]),
last_update=ticker["ts"],
premium=0.0
)
except Exception as e:
print(f"Error fetching {inst_id}: {e}")
return None
async def get_mark_price(self, inst_id: str) -> Optional[PriceData]:
"""
Lấy mark price riêng biệt từ API
OKX không có endpoint riêng cho mark price trong ticker,
nhưng có thể tính từ funding rate
"""
async with self.semaphore:
# Endpoint cho funding rate
endpoint = "/api/v5/market/funding-rate"
params = {"instId": inst_id}
try:
async with self.session.get(
f"{self.BASE_URL}{endpoint}",
params=params,
timeout=aiohttp.ClientTimeout(total=5)
) as resp:
data = await resp.json()
if data["code"] != "0":
return None
# Lấy mark price từ endpoint khác
mark_data = await self._get_estimated_price(inst_id)
return mark_data
except Exception as e:
print(f"Error: {e}")
return None
async def _get_estimated_price(self, inst_id: str) -> Optional[PriceData]:
"""Lấy estimated price (có thể dùng làm mark price reference)"""
endpoint = "/api/v5/market/books"
params = {"instId": inst_id, "sz": "1"}
async with self.session.get(
f"{self.BASE_URL}{endpoint}",
params=params,
timeout=aiohttp.ClientTimeout(total=5)
) as resp:
data = await resp.json()
if data["code"] != "0":
return None
books = data["data"][0]
# Last trade price từ order book
return PriceData(
inst_id=inst_id,
last_price=float(books["last"]),
mark_price=float(books["last"]),
index_price=float(books["last"]),
last_update=books["ts"],
premium=0.0
)
async def get_multiple_prices(self, inst_ids: List[str]) -> List[PriceData]:
"""Lấy giá của nhiều instruments song song"""
tasks = [self.get_ticker(inst_id) for inst_id in inst_ids]
results = await asyncio.gather(*tasks)
return [r for r in results if r is not None]
Sử dụng async version
async def main():
instruments = [
"BTC-USDT-SWAP",
"ETH-USDT-SWAP",
"SOL-USDT-SWAP",
"AVAX-USDT-SWAP"
]
async with OKXPriceFetcher() as fetcher:
prices = await fetcher.get_multiple_prices(instruments)
print("=" * 70)
print(f"{'Instrument':<20} {'Last Price':<15} {'Premium %':<10}")
print("=" * 70)
for price in prices:
premium_str = f"{price.premium:+.4f}%" if price.premium != 0 else "N/A"
print(f"{price.inst_id:<20} ${price.last_price:<14,.2f} {premium_str}")
print("=" * 70)
if __name__ == "__main__":
asyncio.run(main())
Module 3: Hệ thống giám sát Funding Rate tự động
Đây là hệ thống production-ready mà tôi sử dụng thực tế để theo dõi funding rates của 15 cặp giao dịch:
import requests
import pandas as pd
import time
import schedule
from datetime import datetime, timedelta
from collections import defaultdict
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class FundingRateMonitor:
"""
Hệ thống giám sát funding rate với các tính năng:
- Alert khi funding rate vượt ngưỡng
- Lưu trữ lịch sử vào CSV
- Phân tích xu hướng
"""
BASE_URL = "https://www.okx.com"
# Ngưỡng cảnh báo (có thể điều chỉnh)
ALERT_THRESHOLDS = {
"high_positive": 0.01, # > 1%/8h
"high_negative": -0.01, # < -1%/8h
"extreme_positive": 0.02, # > 2%/8h - tín hiệu mạnh
"extreme_negative": -0.02
}
def __init__(self, symbols: list = None):
self.symbols = symbols or [
"BTC-USDT-SWAP",
"ETH-USDT-SWAP",
"BNB-USDT-SWAP",
"SOL-USDT-SWAP",
"XRP-USDT-SWAP",
"ADA-USDT-SWAP",
"DOGE-USDT-SWAP",
"AVAX-USDT-SWAP",
"DOT-USDT-SWAP",
"MATIC-USDT-SWAP",
"LINK-USDT-SWAP",
"UNI-USDT-SWAP",
"ATOM-USDT-SWAP",
"LTC-USDT-SWAP",
"BCH-USDT-SWAP"
]
self.history = defaultdict(list)
self.alerts = []
def fetch_current_funding(self, inst_id: str) -> dict:
"""Lấy funding rate hiện tại"""
endpoint = "/api/v5/market/funding-rate"
params = {"instId": inst_id}
try:
resp = requests.get(
f"{self.BASE_URL}{endpoint}",
params=params,
timeout=10
)
data = resp.json()
if data["code"] != "0":
logger.error(f"Error for {inst_id}: {data['msg']}")
return None
return data["data"][0]
except Exception as e:
logger.error(f"Request failed: {e}")
return None
def fetch_historical_funding(self, inst_id: str, days: int = 30) -> list:
"""Lấy lịch sử funding rate"""
endpoint = "/api/v5/public/funding-rate-history"
# OKX giới hạn 100 records/request
all_records = []
limit = 100
for _ in range((days * 3 + limit - 1) // limit): # ~3 funding/day
params = {
"instId": inst_id,
"limit": str(limit)
}
try:
resp = requests.get(
f"{self.BASE_URL}{endpoint}",
params=params,
timeout=10
)
data = resp.json()
if data["code"] != "0":
break
records = data["data"]
if not records:
break
all_records.extend(records)
time.sleep(0.2) # Rate limiting
# Nếu lấy đủ rồi thì dừng
if len(records) < limit:
break
except Exception as e:
logger.error(f"Historical fetch failed: {e}")
break
return all_records
def analyze_funding(self, inst_id: str) -> dict:
"""
Phân tích funding rate của một cặp giao dịch
Trả về thông tin chi tiết và cảnh báo
"""
current = self.fetch_current_funding(inst_id)
if not current:
return None
history = self.fetch_historical_funding(inst_id, days=30)
# Parse current funding
current_rate = float(current["fundingRate"])
next_funding_ts = int(current["nextFundingTime"])
next_funding_time = datetime.fromtimestamp(next_funding_ts / 1000)
# Phân tích lịch sử
rates = [float(r["fundingRate"]) for r in history]
analysis = {
"symbol": inst_id,
"current_rate": current_rate,
"current_rate_pct": current_rate * 100,
"annualized_rate": current_rate * 3 * 365 * 100, # 8h/funding
"next_funding_time": next_funding_time,
"hours_until_funding": (next_funding_time - datetime.now()).total_seconds() / 3600,
"history_avg": sum(rates) / len(rates) if rates else 0,
"history_max": max(rates) if rates else 0,
"history_min": min(rates) if rates else 0,
"history_count": len(rates),
"alerts": []
}
# Generate alerts
if abs(current_rate) > self.ALERT_THRESHOLDS["extreme_positive"]:
analysis["alerts"].append({
"type": "EXTREME",
"message": f"⚠️ EXTREME: {inst_id} funding rate cực đoan: {current_rate*100:.4f}%",
"action": "Cân nhắc đóng vị thế"
})
elif abs(current_rate) > self.ALERT_THRESHOLDS["high_positive"]:
analysis["alerts"].append({
"type": "HIGH",
"message": f"⚡ HIGH: {inst_id} funding rate cao: {current_rate*100:.4f}%",
"action": "Theo dõi sát"
})
# Funding rate cao hơn trung bình lịch sử
if rates and current_rate > analysis["history_avg"] * 1.5:
analysis["alerts"].append({
"type": "ABOVE_AVG",
"message": f"📈 {inst_id} funding rate cao hơn trung bình 50%",
"action": "Kiểm tra vị thế long"
})
return analysis
def run_analysis(self) -> list:
"""Chạy phân tích cho tất cả symbols"""
results = []
for symbol in self.symbols:
logger.info(f"Đang phân tích {symbol}...")
analysis = self.analyze_funding(symbol)
if analysis:
results.append(analysis)
self.history[symbol].append({
"timestamp": datetime.now(),
"rate": analysis["current_rate"]
})
# In alerts
for alert in analysis["alerts"]:
logger.warning(alert["message"])
return results
def generate_report(self, results: list) -> str:
"""Tạo báo cáo từ kết quả phân tích"""
if not results:
return "Không có dữ liệu"
# Sort theo annualized rate
sorted_results = sorted(
results,
key=lambda x: x["annualized_rate"],
reverse=True
)
report = []
report.append("\n" + "=" * 80)
report.append("BÁO CÁO FUNDING RATE - " + datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
report.append("=" * 80)
report.append(f"\n{'Symbol':<18} {'Rate/8h':<12} {'Annualized':<12} {'Next Funding':<22} {'Status'}")
report.append("-" * 80)
for r in sorted_results:
status = "🔴 HIGH" if r["alerts"] else "🟢 Normal"
next_time = r["next_funding_time"].strftime("%Y-%m-%d %H:%M:%S")
rate_str = f"{r['current_rate_pct']:+.4f}%"
ann_str = f"{r['annualized_rate']:+.2f}%"
report.append(f"{r['symbol']:<18} {rate_str:<12} {ann_str:<12} {next_time:<22} {status}")
report.append("=" * 80)
return "\n".join(report)
def to_dataframe(self, results: list) -> pd.DataFrame:
"""Convert results to pandas DataFrame"""
rows = []
for r in results:
rows.append({
"Symbol": r["symbol"],
"Rate_8h_%": round(r["current_rate_pct"], 4),
"Annualized_%": round(r["annualized_rate"], 2),
"Next_Funding": r["next_funding_time"],
"Hours_Until": round(r["hours_until_funding"], 1),
"History_Avg_%": round(r["history_avg"] * 100, 4),
"Alerts": len(r["alerts"])
})
return pd.DataFrame(rows)
def job():
"""Job chạy định kỳ"""
monitor = FundingRateMonitor()
results = monitor.run_analysis()
report = monitor.generate_report(results)
print(report)
# Lưu vào CSV
df = monitor.to_dataframe(results)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
df.to_csv(f"funding_rates_{timestamp}.csv", index=False)
logger.info(f"Đã lưu báo cáo vào funding_rates_{timestamp}.csv")
if __name__ == "__main__":
# Chạy ngay lập tức
job()
# Sau đó chạy mỗi 6 giờ
schedule.every(6).hours.do(job)
logger.info("Monitor bắt đầu. Ctrl+C để dừng.")
while True:
schedule.run_pending()
time.sleep(60)
Tích hợp AI để phân tích Funding Rate
Sau khi thu thập dữ liệu, bước tiếp theo là dùng AI để phân tích xu hướng và đưa ra gợi ý. Tại HolySheep AI, tôi được sử dụng API với độ trễ trung bình chỉ 45ms và chi phí rẻ hơn 85% so với các provider khác — phù hợp cho việc xử lý real-time data.
import requests
import json
from datetime import datetime
from typing import List, Dict, Optional
class FundingRateAIAnalyzer:
"""
Sử dụng AI để phân tích funding rate và đưa ra khuyến nghị
Tích hợp với HolySheep AI cho chi phí thấp và latency thấp
"""
# IMPORTANT: Sử dụng HolySheep AI endpoint
HOLYSHEEP_API_URL = "https://api.holysheep.ai/v1/chat/completions"
def __init__(self, api_key: str):
self.api_key = api_key
def analyze_with_ai(self, funding_data: List[Dict], market_context: str = "") -> str:
"""
Gọi AI để phân tích funding rates
Args:
funding_data: Danh sách funding rate data
market_context: Thông tin bổ sung về thị trường
Returns:
Phân tích và khuyến nghị từ AI
"""
# Chuẩn bị context cho AI
system_prompt = """Bạn là chuyên gia phân tích thị trường crypto.
Phân tích funding rates và đưa ra:
1. Đánh giá tâm lý thị trường hiện tại
2. Các cặp có funding rate bất thường
3. Khuyến nghị cho vị thế long/short
4. Cảnh báo rủi ro nếu có
Trả lời ngắn gọn, đi thẳng vào vấn đề, dùng tiếng Việt."""
# Tạo bản tóm tắt data
summary = self._create_summary(funding_data)
user_message = f"""Phân tích funding rates sau (đơn vị: %/8h):
{summary}
Context thị trường: {market_context}
Đưa ra phân tích và khuyến nghị cụ thể."""
try:
response = requests.post(
self.HOLYSHEEP_API_URL,
headers={
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
},
json={
"model": "gpt-4.1", # Hoặc deepseek-v3.2 cho chi phí thấp hơn
"messages": [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message}
],
"temperature": 0.3, # Low temperature cho phân tích
"max_tokens": 1000
},
timeout=30
)
response.raise_for_status()
result = response.json()
return result["choices"][0]["message"]["content"]
except requests.exceptions.RequestException as e:
return f"Lỗi khi gọi AI: {str(e)}"
def _create_summary(self, funding_data: List[Dict]) -> str:
"""Tạo bản tóm tắt funding rates"""
lines = []
for item in funding_data:
rate_pct = item.get("current_rate_pct", 0)
annualized = item.get("annualized_rate", 0)
alerts = item.get("alerts", [])
alert_str = " [ALERT!]" if alerts else ""
lines.append(
f"- {item['symbol']}: {rate_pct:+.4f}%/8h "
f"(annualized: {annualized:+.2f}%){alert_str}"
)
return "\n".join(lines)
def generate_trading_signal(self, funding_rate: float, history_avg: float) -> Dict:
"""
Tạo tín hiệu giao dịch đơn giản dựa trên funding rate
Returns:
Dict với signal và confidence
"""
# Tính toán signal
rate_diff = funding_rate - history_avg
if funding_rate > 0.015: # > 1.5%/8h
signal = "STRONG_SELL" # Funding quá cao, thị trường thiên về long
confidence = 0.85
reason = "Funding rate cực cao, nguy cơ liquidations cao"
elif funding_rate > 0.005: # > 0.5%/8h
signal = "SELL"
confidence = 0.7
reason = "Funding rate cao, thị trường thiên về long"
elif funding_rate < -0.015:
signal = "STRONG_BUY"
confidence = 0.85
reason = "Funding rate cực thấp, thị trường thiên về short"
elif funding_rate < -0.005:
signal = "BUY"
confidence = 0.7
reason = "Funding rate thấp, thị trường thiên về short"
else:
signal = "NEUTRAL"
confidence = 0.5
reason = "Funding rate trung tính"
return {
"signal": signal,
"confidence": confidence,
"reason": reason,
"funding_rate": funding_rate,
"history_avg": history_avg,
"timestamp": datetime.now().isoformat()
}
Ví dụ sử dụng
def main():
# Khởi tạo với API key từ HolySheep AI
analyzer = FundingRateAIAnalyzer(api_key="YOUR_HOLYSHEEP_API_KEY")
# Sample data (thay bằng dữ liệu thực từ OKX)
sample_data = [
{
"symbol": "BTC-USDT-SWAP",
"current_rate_pct": 0.0085,
"annualized_rate": 9.31,
"alerts": []
},
{
"symbol": "ETH-USDT-SWAP",
"current_rate_pct": 0.0152,
"annualized_rate": 16.64,
"alerts": ["HIGH"]
},
{
"symbol": "SOL-USDT-SWAP",
"current_rate_pct": -0.0032,
"annualized_rate": -3.50,
"alerts": []
},
{
"symbol": "AVAX-USDT-SWAP",
"current_rate_pct": 0.0215,
"annualized_rate": 23.54,
"alerts": ["EXTREME"]
}
]
# Phân tích bằng AI
print("Đang phân tích với HolySheep AI...")
analysis = analyzer.analyze_with_ai(
sample_data,
market_context="Thị trường đang trong giai đoạn sideways, volume thấp"
)
print("\n" + "=" * 60)
print("PHÂN TÍCH TỪ AI:")
print("=" * 60)
print(analysis)
# Generate signals cho từng cặp
print("\n" + "=" * 60)
print("TÍN HIỆU GIAO DỊCH:")
print("=" * 60)
for item in sample_data:
signal = analyzer.generate_trading_signal(
item["current_rate_pct"],
0.001 # Giả định history avg
)
emoji = {
"STRONG_BUY": "🟢🟢",
"BUY": "🟢",
"NEUTRAL": "⚪",
"SELL": "🔴",
"STRONG_SELL": "🔴🔴"
}.get(signal["signal"], "⚪")
print(f"\n{item['symbol']}:")
print(f" {emoji} Signal: {