บทความนี้จะพาคุณเรียนรู้วิธีใช้งาน OKX WebSocket streams สำหรับรับข้อมูลตลาดแบบ real-time พร้อมตัวอย่างโค้ดที่ใช้งานได้จริง ไม่ว่าจะเป็นการเชื่อมต่อ public streams หรือ private streams ที่ต้องการ authentication
WebSocket คืออะไร และทำไมต้องใช้กับ OKX
WebSocket เป็น protocol สำหรับเชื่อมต่อแบบ two-way communication ระหว่าง client และ server ผ่าน TCP connection เดียว ซึ่งแตกต่างจาก HTTP REST API ที่ต้องส่ง request ใหม่ทุกครั้ง WebSocket ช่วยให้ server สามารถ push ข้อมูลไปยัง client ได้ทันทีเมื่อมีข้อมูลใหม่ เหมาะอย่างยิ่งสำหรับแอปพลิเคชันที่ต้องการข้อมูล real-time เช่น ราคาเทรด กราฟ หรือการแจ้งเตือน
OKX เป็นหนึ่งใน exchange ที่รองรับ WebSocket อย่างครบถ้วน โดยให้บริการทั้ง public streams (ไม่ต้องล็อกอิน) และ private streams (ต้องมี API key) ข้อดีหลักของ OKX WebSocket คือ ความเร็วในการรับข้อมูล ความเสถียรของ connection และค่าใช้จ่ายที่ต่ำกว่าการใช้ REST API polling
OKX WebSocket URL และ Endpoint
OKX มี WebSocket endpoint หลักดังนี้
# Public WebSocket (รับข้อมูลตลาดทั่วไป)
wss://ws.okx.com:8443/ws/v5/public
Private WebSocket (รับข้อมูลที่เกี่ยวกับบัญชี ต้อง authentication)
wss://ws.okx.com:8443/ws/v5/private
สำหรับผู้ใช้ในภูมิภาคเอเชีย OKX มี server ที่ Singapore และ Hong Kong ช่วยลด latency ได้อย่างมีนัยสำคัญ หากคุณต้องการ latency ต่ำกว่า 50ms อาจพิจารณาใช้บริการ relay อย่าง HolySheep AI ที่มี infrastructure รองรับหลายภูมิภาค
การเชื่อมต่อ OKX WebSocket ด้วย Python
ตัวอย่างโค้ดนี้แสดงการเชื่อมต่อ OKX WebSocket public stream สำหรับรับข้อมูล trades และ tickers แบบ real-time
import json
import threading
import time
from websocket import WebSocketApp
class OKXWebSocketClient:
def __init__(self):
self.ws = None
self.url = "wss://ws.okx.com:8443/ws/v5/public"
self.subscribed = []
def on_message(self, ws, message):
"""จัดการเมื่อได้รับข้อความจาก server"""
data = json.loads(message)
# ตรวจสอบประเภทของ message
if "event" in data:
if data["event"] == "subscribe":
print(f"✅ สมัครรับข้อมูลสำเร็จ: {data}")
elif data["event"] == "error":
print(f"❌ เกิดข้อผิดพลาด: {data}")
else:
# ข้อมูลจริงจาก stream
if "data" in data:
for item in data["data"]:
print(f"📊 {item.get('instId')} | Price: {item.get('last')} | Volume: {item.get('vol')}")
def on_error(self, ws, error):
"""จัดการเมื่อเกิดข้อผิดพลาด"""
print(f"WebSocket Error: {error}")
def on_close(self, ws, close_status_code, close_msg):
"""จัดการเมื่อ connection ถูกปิด"""
print(f"Connection ถูกปิด: {close_status_code} - {close_msg}")
def on_open(self, ws):
"""จัดการเมื่อ connection เปิดสำเร็จ"""
# สมัครรับข้อมูล trades สำหรับ BTC-USDT
subscribe_trades = {
"op": "subscribe",
"args": [{
"channel": "trades",
"instId": "BTC-USDT"
}]
}
ws.send(json.dumps(subscribe_trades))
# สมัครรับข้อมูล tickers สำหรับ ETH-USDT
subscribe_tickers = {
"op": "subscribe",
"args": [{
"channel": "tickers",
"instId": "ETH-USDT"
}]
}
ws.send(json.dumps(subscribe_tickers))
print("📡 กำลังเชื่อมต่อ OKX WebSocket...")
def connect(self):
"""เริ่มเชื่อมต่อ WebSocket"""
self.ws = WebSocketApp(
self.url,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close,
on_open=self.on_open
)
# เริ่ม thread สำหรับรัน websocket
ws_thread = threading.Thread(target=self.ws.run_forever)
ws_thread.daemon = True
ws_thread.start()
return self
def disconnect(self):
"""ปิดการเชื่อมต่อ"""
if self.ws:
self.ws.close()
วิธีใช้งาน
if __name__ == "__main__":
client = OKXWebSocketClient()
client.connect()
# รัน 60 วินาที
time.sleep(60)
client.disconnect()
โค้ดนี้ใช้ไลบรารี websocket-client ซึ่งติดตั้งได้ด้วยคำสั่ง pip install websocket-client เมื่อรันโค้ดนี้ คุณจะได้รับข้อมูล trade และ ticker สำหรับ BTC-USDT และ ETH-USDT แบบ real-time
ประเภทของ OKX WebSocket Channels
OKX มี channels หลายประเภทที่ครอบคลุมการใช้งานต่างๆ
- trades - ข้อมูลการซื้อขายล่าสุด เหมาะสำหรับติดตาม price action
- tickers - ข้อมูลสรุปราคา 24h รวม high, low, open, close
- klines - ข้อมูล OHLCV candlestick รองรับ timeframe หลายระดับ
- books - ข้อมูล order book ลึกสุด 400 ระดับ
- positions - ข้อมูลตำแหน่งที่เปิด (ต้อง private stream)
- orders - ข้อมูลคำสั่งซื้อขาย (ต้อง private stream)
ตารางเปรียบเทียบ: OKX WebSocket vs บริการอื่น
| คุณลักษณะ | OKX WebSocket อย่างเป็นทางการ | HolySheep AI WebSocket | บริการ Relay อื่นๆ |
|---|---|---|---|
| Latency เฉลี่ย | 20-100ms (ขึ้นอยู่กับภูมิภาค) | <50ms | 50-200ms |
| ค่าใช้จ่าย | ฟรีสำหรับ Public streams | เริ่มต้น $0.42/MTok | ฟรี - $100/เดือน |
| Authentication | ต้องมี API Key | API Key อย่างเดียว | แตกต่างกัน |
| จำนวน Connections | จำกัดต่อ IP | ไม่จำกัด | จำกัด |
| ความเสถียร | สูง | สูงมาก | ปานกลาง |
| การรองรับ Reconnection | ต้องจัดการเอง | Auto-reconnect ในตัว | แตกต่างกัน |
เหมาะกับใคร / ไม่เหมาะกับใคร
✅ เหมาะกับ OKX WebSocket อย่างเป็นทางการ
- นักพัฒนาที่ต้องการข้อมูล real-time จาก OKX โดยตรง
- ผู้ที่มี API key ของ OKX อยู่แล้ว
- โปรเจกต์ที่ใช้งานบน server ในภูมิภาคเอเชียตะวันออกเฉียงใต้
- ผู้ที่ต้องการ integration กับ OKX trading bot
❌ ไม่เหมาะกับ OKX WebSocket อย่างเป็นทางการ
- ผู้ที่ต้องการ unified API สำหรับหลาย exchange
- ผู้ที่ต้องการ latency ต่ำกว่า 50ms อย่างต่อเนื่อง
- นักพัฒนาที่ต้องการ SDK ที่ใช้งานง่ายและมี documentation ดี
- โปรเจกต์ที่ต้องการ multi-stream พร้อมกันหลาย streams
ราคาและ ROI
OKX WebSocket อย่างเป็นทางการไม่มีค่าใช้จ่ายสำหรับ public streams แต่มีข้อจำกัดเรื่อง rate limiting หากคุณต้องการใช้งานเชิงพาณิชย์อย่างเข้มข้น ควรพิจารณาบริการ relay ที่มี SLA ชัดเจน
ตัวอย่างการคำนวณ ROI
สมมติคุณใช้ WebSocket 30 streams ต่อเดือน ค่าใช้จ่ายในการดูแล server และ infrastructure อยู่ที่ประมาณ $50/เดือน หากใช้ HolySheep AI ที่มีราคาเริ่มต้น $0.42/MTok คุณจะได้รับประโยชน์จาก latency ที่ต่ำกว่า 50% และไม่ต้องกังวลเรื่อง server maintenance
ทำไมต้องเลือก HolySheep
- ประหยัด 85%+ - อัตราแลกเปลี่ยน ¥1=$1 ทำให้ค่าบริการถูกลงอย่างมีนัยสำคัญ
- Latency ต่ำกว่า 50ms - เหมาะสำหรับแอปพลิเคชันที่ต้องการความเร็วสูง
- รองรับหลายภูมิภาค - มี server ในหลายพื้นที่ ช่วยลด latency
- เครดิตฟรีเมื่อลงทะเบียน - ทดลองใช้งานได้ก่อนตัดสินใจ
- ชำระเงินง่าย - รองรับ WeChat Pay และ Alipay
ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข
ปัญหาที่ 1: Connection Closed Unexpectedly (1006)
สาเหตุ: Server ปิด connection โดยไม่มี close frame ซึ่งมักเกิดจากการที่ client ไม่ได้ส่ง ping/pong ภายในเวลาที่กำหนด OKX กำหนดให้ต้องส่ง ping ทุก 30 วินาที
วิธีแก้ไข:
import time
from websocket import WebSocketApp
class AutoPingWebSocket:
def __init__(self, url):
self.url = url
self.ws = None
self.last_ping_time = time.time()
def keep_alive(self):
"""ส่ง ping ทุก 20 วินาทีเพื่อรักษา connection"""
def ping_loop():
while self.ws and self.ws.keep_running:
current_time = time.time()
if current_time - self.last_ping_time >= 20:
try:
self.ws.ping(b"keepalive")
self.last_ping_time = current_time
print("🏓 Ping ถูกส่งแล้ว")
except Exception as e:
print(f"❌ ส่ง ping ไม่สำเร็จ: {e}")
break
time.sleep(1)
import threading
ping_thread = threading.Thread(target=ping_loop, daemon=True)
ping_thread.start()
def connect(self):
self.ws = WebSocketApp(
self.url,
on_open=lambda ws: self.keep_alive(),
on_message=self.on_message,
on_error=self.on_error
)
import threading
threading.Thread(target=self.ws.run_forever, daemon=True).start()
def on_message(self, ws, message):
print(f"ได้รับข้อความ: {message}")
def on_error(self, ws, error):
print(f"เกิดข้อผิดพลาด: {error}")
ปัญหาที่ 2: Subscription Failed - Channel Not Found
สาเหตุ: ชื่อ channel หรือ instrument ID ไม่ถูกต้อง OKX ใช้ format ที่เฉพาะเจาะจง เช่น "BTC-USDT-SWAP" ไม่ใช่ "BTCUSDT"
วิธีแก้ไข:
# ❌ วิธีที่ผิด - ใช้ชื่อย่อ
wrong_subscription = {
"op": "subscribe",
"args": [{"channel": "tickers", "instId": "BTCUSDT"}]
}
✅ วิธีที่ถูก - ใช้ชื่อเต็มตาม OKX format
correct_subscription = {
"op": "subscribe",
"args": [{"channel": "tickers", "instId": "BTC-USDT"}]
}
สำหรับ Futures ต้องใช้ format ที่ถูกต้อง
futures_subscription = {
"op": "subscribe",
"args": [{"channel": "tickers", "instId": "BTC-USD-SWAP"}]
}
สำหรับ Options
options_subscription = {
"op": "subscribe",
"args": [{"channel": "tickers", "instId": "BTC-USD-240329-65000-C"}]
}
ตรวจสอบ instrument IDs ที่รองรับทั้งหมด
GET https://www.okx.com/api/v5/market/instruments?instType=SPOT
ปัญหาที่ 3: Rate Limit Exceeded
สาเหตุ: ส่งคำขอ subscribe/unsubscribe บ่อยเกินไป OKX จำกัดที่ 300 connections ต่อ 10 วินาที ต่อ IP
วิธีแก้ไข:
import time
from collections import defaultdict
class RateLimiter:
def __init__(self, max_requests=50, window_seconds=10):
self.max_requests = max_requests
self.window_seconds = window_seconds
self.requests = defaultdict(list)
def is_allowed(self, key="default"):
"""ตรวจสอบว่าสามารถส่ง request ได้หรือไม่"""
current_time = time.time()
# ลบ request ที่เก่ากว่า window
self.requests[key] = [
t for t in self.requests[key]
if current_time - t < self.window_seconds
]
# ตรวจสอบจำนวน request
if len(self.requests[key]) >= self.max_requests:
sleep_time = self.window_seconds - (current_time - self.requests[key][0])
if sleep_time > 0:
print(f"⏳ Rate limit รอ {sleep_time:.2f} วินาที")
time.sleep(sleep_time)
return True
return False
# เพิ่ม request ปัจจุบัน
self.requests[key].append(current_time)
return True
def safe_subscribe(self, ws, channel, instId):
"""subscribe โดยมี rate limit protection"""
if self.is_allowed("subscribe"):
subscribe_msg = {
"op": "subscribe",
"args": [{"channel": channel, "instId": instId}]
}
ws.send(json.dumps(subscribe_msg))
return True
return False
วิธีใช้งาน
rate_limiter = RateLimiter(max_requests=45, window_seconds=10)
client = OKXWebSocketClient()
client.connect()
สมัครรับข้อมูลหลาย symbols โดยมี rate limit protection
symbols = ["BTC-USDT", "ETH-USDT", "SOL-USDT", "XRP-USDT", "DOGE-USDT"]
for symbol in symbols:
rate_limiter.safe_subscribe(client.ws, "tickers", symbol)
time.sleep(0.5) # รอเล็กน้อยระหว่างแต่ละ subscription
ปัญหาที่ 4: Private Stream Authentication Failed
สาเหตุ: Signature สำหรับ authentication ไม่ถูกต้อง หรือ API key ไม่มีสิทธิ์เข้าถึง private streams
วิธีแก้ไข:
import hmac
import base64
import datetime
from urllib.parse import quote
def generate_signature(secret_key, timestamp, method, path, body=""):
"""สร้าง signature สำหรับ OKX WebSocket authentication"""
message = timestamp + method + path + body
mac = hmac.new(
bytes(secret_key, encoding="utf8"),
bytes(message, encoding="utf8"),
digestmod="sha256"
)
signature = base64.b64encode(mac.digest()).decode()
return signature
def get_auth_params(api_key, secret_key, passphrase):
"""สร้าง parameters สำหรับ authentication"""
timestamp = datetime.datetime.utcnow().isoformat() + "Z"
method = "GET"
path = "/users/self/verify"
signature = generate_signature(secret_key, timestamp, method, path)
return {
"apiKey": api_key,
"passphrase": passphrase,
"timestamp": timestamp,
"sign": signature
}
วิธีใช้งานสำหรับ private stream
def connect_private_stream(api_key, secret_key, passphrase):
"""เชื่อมต่อ private stream ด้วย authentication"""
auth_params = get_auth_params(api_key, secret_key, passphrase)
ws = WebSocketApp("wss://ws.okx.com:8443/ws/v5/private")
def on_open(ws):
# ส่ง login request
login_msg = {
"op": "login",
"args": [auth_params]
}
ws.send(json.dumps(login_msg))
ws.on_open = on_open
ws.run_forever()
Best Practices สำหรับ Production
เมื่อนำ OKX WebSocket ไปใช้งานจริงใน production environment ควรคำนึงถึงสิ่งต่อไปนี้
- Implement reconnection logic - ควรมี exponential backoff เมื่อ connection หลุด
- Message queue - ใช้ queue สำหรับเก็บ messages ที่รับมาก่อนประมวลผล
- Heartbeat monitoring - ตรวจสอบว่าได้รับข้อมูลอย่างสม่ำเสมอ หากไม่ได้รับนานเกินไปให้ reconnect
- Graceful shutdown - ปิด connection อย่างถูกต้องเมื่อหยุดใช้งาน
- SSL certificate verification - ตรวจสอบ SSL certificate ทุกครั้ง
สรุป
OKX WebSocket streams เป็นเครื่องมือทรงพลังสำหรับการรับข้อมูลตลาดแบบ real-time ด้วย latency ที่ต่ำและความเสถียรสูง การเข้าใจวิธีการเชื่อมต่อ การ subscribe และการจัดการข้อผิดพลาดอย่างถูกต้องจะช่วยให้คุณสร้างแอปพลิเคชันที่เชื่อถือได้ หากคุณต้องการ unified solution ที่รวม OKX และ exchange อื่นๆ เข้าด้วยกัน พร้อม latency ที่ต่ำกว่