ในโลกของการเทรดคริปโตผ่าน API หลายคนอาจเคยเจอสถานการณ์แบบนี้: คุณเขียนโค้ดระบบเทรดอัตโนมัติเสร็จสรรพ ทดสอบบน Spot API ได้ผลดีมาก พอนำไปใช้กับ Futures API จริงกลับเจอ 403 Forbidden หรือราคาที่ได้ไม่ตรงตามคาดเพราะ Funding Rate ที่คิดเข้ามา หรือบางที Margin Call มาโดยไม่ทันตั้งตัว
บทความนี้จะพาคุณเข้าใจความแตกต่างเชิงลึกระหว่าง Binance Spot API และ Futures API พร้อมตัวอย่างโค้ดที่ใช้งานได้จริง และข้อผิดพลาดยอดนิยมที่นักพัฒนาไทยมักเจอบ่อยที่สุด
ความแตกต่างพื้นฐานระหว่าง Spot และ Futures API
ก่อนจะลงลึกเรื่อง Technical Detail เรามาทำความเข้าใจ Concept พื้นฐานกันก่อน
Spot API ทำงานอย่างไร
Spot API ใช้สำหรับการซื้อขายเหรียญจริง (สินทรัพย์จริง) คุณต้องมีเหรียญในกระเป๋าเงินก่อนจึงจะซื้อได้ ราคาที่เห็นคือราคาจริงที่ตลาดกำหนด ไม่มี Leverage ไม่มี Funding Fee ไม่มี Liquidation
Futures API ทำงานอย่างไร
Futures API ใช้สำหรับสัญญา Bitcoin Futures ที่คุณไม่ได้ถือเหรียญจริง แต่เป็นสัญญาที่คุณจ่าย Margin เป็นหลักประกัน คุณสามารถใช้ Leverage ได้สูงถึง 125x ในบางสินทรัพย์ แต่ข้อเสียคือมีค่า Funding Rate ที่ต้องจ่ายทุก 8 ชั่วโมง และมีความเสี่ยง Liquidation หากราคาเคลื่อนไหวตรงข้ามกับทิศทางที่คุณเปิดออเดอร์
ตารางเปรียบเทียบ Spot API กับ Futures API
| คุณสมบัติ | Binance Spot API | Binance Futures API |
|---|---|---|
| ประเภทสินทรัพย์ | เหรียญจริง (BTC, ETH, BNB) | สัญญา Futures (BTCUSD, ETHUSD) |
| Margin และ Leverage | ไม่มี (ซื้อเต็มจำนวน) | มี Leverage สูงสุด 125x |
| Funding Rate | ไม่มี | จ่าย/รับทุก 8 ชั่วโมง |
| Liquidation | ไม่มี | มี เมื่อ Margin ต่ำกว่า Maintenance |
| ความเสี่ยง | จำกัดอยู่ที่จำนวนเงินที่มี | สูญเสียมากกว่าเงินที่มีได้ (ในบางกรณี) |
| API Endpoint | api.binance.com | fapi.binance.com (Testnet: fapi-testnet.binance.com) |
| Order Book Depth | สูงสุด 5,000 orders | สูงสุด 5,000 orders |
| WebSocket Streams | wss://stream.binance.com:9443 | wss://fstream.binance.com |
ตัวอย่างโค้ดการเชื่อมต่อ Spot API
สำหรับนักพัฒนาที่ต้องการเริ่มต้นเชื่อมต่อ Spot API นี่คือตัวอย่างโค้ด Python ที่ใช้งานได้จริง:
import requests
import time
import hmac
import hashlib
class BinanceSpotAPI:
def __init__(self, api_key, api_secret):
self.api_key = api_key
self.api_secret = api_secret
self.base_url = "https://api.binance.com"
def _generate_signature(self, params):
"""สร้าง HMAC SHA256 signature"""
query_string = '&'.join([f"{k}={v}" for k, v in params.items()])
signature = hmac.new(
self.api_secret.encode('utf-8'),
query_string.encode('utf-8'),
hashlib.sha256
).hexdigest()
return signature
def get_account_balance(self):
"""ดึงยอดคงเหลือ Spot Account"""
timestamp = int(time.time() * 1000)
params = {
'timestamp': timestamp,
'recvWindow': 5000
}
params['signature'] = self._generate_signature(params)
headers = {
'X-MBX-APIKEY': self.api_key,
'Content-Type': 'application/json'
}
response = requests.get(
f"{self.base_url}/api/v3/account",
params=params,
headers=headers
)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"Error {response.status_code}: {response.text}")
def place_order(self, symbol, side, order_type, quantity, price=None):
"""เปิดออเดอร์ซื้อ/ขาย"""
timestamp = int(time.time() * 1000)
params = {
'symbol': symbol,
'side': side,
'type': order_type,
'quantity': quantity,
'timestamp': timestamp,
'recvWindow': 5000
}
if price:
params['price'] = price
params['timeInForce'] = 'GTC'
params['signature'] = self._generate_signature(params)
headers = {
'X-MBX-APIKEY': self.api_key
}
response = requests.post(
f"{self.base_url}/api/v3/order",
params=params,
headers=headers
)
return response.json()
วิธีใช้งาน
api = BinanceSpotAPI(
api_key='YOUR_SPOT_API_KEY',
api_secret='YOUR_SPOT_API_SECRET'
)
ดึงยอดคงเหลือ
balance = api.get_account_balance()
print(f"ยอด USDT: {balance['balances'][0]['free']}")
ซื้อ BTC 0.001 ตัว ที่ราคา 50,000 USDT
order = api.place_order(
symbol='BTCUSDT',
side='BUY',
order_type='LIMIT',
quantity='0.001',
price='50000'
)
print(f"Order ID: {order['orderId']}")
ตัวอย่างโค้ดการเชื่อมต่อ Futures API
สำหรับ Futures API จะมีความแตกต่างที่สำคัญหลายจุด โดยเฉพาะเรื่อง Position Mode, Margin Type และ Leverage
import requests
import time
import hmac
import hashlib
class BinanceFuturesAPI:
def __init__(self, api_key, api_secret):
self.api_key = api_key
self.api_secret = api_secret
self.base_url = "https://fapi.binance.com"
def _generate_signature(self, params):
"""สร้าง HMAC SHA256 signature สำหรับ Futures"""
query_string = '&'.join([f"{k}={v}" for k, v in params.items()])
signature = hmac.new(
self.api_secret.encode('utf-8'),
query_string.encode('utf-8'),
hashlib.sha256
).hexdigest()
return signature
def set_leverage(self, symbol, leverage):
"""ตั้งค่า Leverage สำหรับ Symbol (จำเป็นต้องทำก่อนเปิดออเดอร์)"""
timestamp = int(time.time() * 1000)
params = {
'symbol': symbol,
'leverage': leverage,
'timestamp': timestamp,
'recvWindow': 5000
}
params['signature'] = self._generate_signature(params)
headers = {'X-MBX-APIKEY': self.api_key}
response = requests.post(
f"{self.base_url}/fapi/v1/leverage",
params=params,
headers=headers
)
if response.status_code == 200:
print(f"ตั้งค่า Leverage {leverage}x สำหรับ {symbol} สำเร็จ")
return response.json()
else:
raise Exception(f"Set Leverage Error: {response.text}")
def get_position_info(self, symbol=None):
"""ดึงข้อมูล Position ปัจจุบัน"""
timestamp = int(time.time() * 1000)
params = {
'timestamp': timestamp,
'recvWindow': 5000
}
if symbol:
params['symbol'] = symbol
params['signature'] = self._generate_signature(params)
headers = {'X-MBX-APIKEY': self.api_key}
response = requests.get(
f"{self.base_url}/fapi/v2/positionRisk",
params=params,
headers=headers
)
return response.json()
def place_futures_order(self, symbol, side, order_type, quantity, price=None, leverage=10):
"""เปิดออเดอร์ Futures"""
# ตั้งค่า Leverage ก่อนเสมอ
self.set_leverage(symbol, leverage)
timestamp = int(time.time() * 1000)
params = {
'symbol': symbol,
'side': side,
'type': order_type,
'quantity': quantity,
'timestamp': timestamp,
'recvWindow': 5000
}
if price:
params['price'] = price
params['timeInForce'] = 'GTC'
params['signature'] = self._generate_signature(params)
headers = {'X-MBX-APIKEY': self.api_key}
response = requests.post(
f"{self.base_url}/fapi/v1/order",
params=params,
headers=headers
)
return response.json()
def get_funding_rate(self, symbol):
"""ดึง Funding Rate ปัจจุบัน (สำคัญมาก!)"""
params = {'symbol': symbol}
response = requests.get(
f"{self.base_url}/fapi/v1/premiumIndex",
params=params
)
data = response.json()
return {
'symbol': data['symbol'],
'fundingRate': float(data['lastFundingRate']) * 100,
'nextFundingTime': data['nextFundingTime']
}
วิธีใช้งาน
futures = BinanceFuturesAPI(
api_key='YOUR_FUTURES_API_KEY',
api_secret='YOUR_FUTURES_API_SECRET'
)
ตรวจสอบ Funding Rate ก่อนเปิดออเดอร์
funding = futures.get_funding_rate('BTCUSDT')
print(f"Funding Rate ปัจจุบัน: {funding['fundingRate']}%")
print(f"Next Funding: {funding['nextFundingTime']}")
เปิด Long Position BTC 0.01 ที่ Leverage 10x
order = futures.place_futures_order(
symbol='BTCUSDT',
side='BUY',
order_type='LIMIT',
quantity='0.01',
price='50000',
leverage=10
)
print(f"Position opened: {order['orderId']}")
ตรวจสอบ Position
positions = futures.get_position_info('BTCUSDT')
for pos in positions:
if float(pos['positionAmt']) != 0:
print(f"Position: {pos['positionAmt']}, Entry: {pos['entryPrice']}")
ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข
กรณีที่ 1: Error 403 Forbidden หรือ API Key ไม่มีสิทธิ์
อาการ: ได้รับข้อผิดพลาด {"code":-2015,"msg":"Invalid API-key, IP, or permissions for action"}
สาเหตุ: API Key ที่สร้างมาไม่ได้ Enable สิทธิ์ที่จำเป็นสำหรับ Futures หรือ IP ที่เรียกใช้ไม่ได้อยู่ใน whitelist
วิธีแก้ไข:
# แก้ไขโดยสร้าง API Key ใหม่ที่ Enable สิทธิ์ครบถ้วน
ไปที่ Binance > API Management > Create New Key
ตรวจสอบสิทธิ์ของ API Key ที่ใช้
import requests
def check_api_permissions(api_key, api_secret):
"""ตรวจสอบสิทธิ์ของ API Key"""
timestamp = int(time.time() * 1000)
params = {
'timestamp': timestamp,
'recvWindow': 5000
}
# สำหรับ Spot
spot_base = "https://api.binance.com"
# สำหรับ Futures
futures_base = "https://fapi.binance.com"
# ตรวจสอบ Spot Account
try:
spot_response = requests.get(
f"{spot_base}/api/v3/account",
headers={'X-MBX-APIKEY': api_key},
params=params
)
print(f"Spot Status: {spot_response.status_code}")
except Exception as e:
print(f"Spot Error: {e}")
# ตรวจสอบ Futures Account
try:
futures_response = requests.get(
f"{futures_base}/fapi/v2/account",
headers={'X-MBX-APIKEY': api_key},
params=params
)
print(f"Futures Status: {futures_response.status_code}")
except Exception as e:
print(f"Futures Error: {e}")
หรือใช้วิธี Enable IP Whitelist ใน Binance Dashboard
ไปที่ API Management > Edit Restrictions
เลือก "Disable IP Restriction" ชั่วคราวเพื่อทดสอบ
หรือเพิ่ม IP ของ Server ที่รันโค้ดเข้าไปใน whitelist
สำหรับ Testnet ให้ใช้ API Key ที่สร้างจาก Testnet
TESTNET_API_KEY = 'YOUR_TESTNET_KEY'
TESTNET_API_SECRET = 'YOUR_TESTNET_SECRET'
TESTNET_BASE = "https://testnet.binancefuture.com"
กรณีที่ 2: ออเดอร์ถูก Reject ด้วย Error -5022 Insufficient Margin
อาการ: ได้รับข้อผิดพลาด {"code":-5022,"msg":"Margin is insufficient"} ทั้งที่มีเงินในบัญชี
สาเหตุ: กระเป๋าเงิน Spot และ Futures แยกกัน คุณต้องโอนเงินจาก Spot Wallet ไปยัง USDT-M Futures Wallet ก่อน
วิธีแก้ไข:
import requests
import time
import hmac
import hashlib
def transfer_to_futures(api_key, api_secret, asset='USDT', amount):
"""โอนเงินจาก Spot Wallet ไปยัง Futures Wallet"""
timestamp = int(time.time() * 1000)
params = {
'asset': asset,
'amount': amount,
'type': 'MAIN_UMFUTURE', # Spot to USDT-M Futures
'timestamp': timestamp,
'recvWindow': 5000
}
query_string = '&'.join([f"{k}={v}" for k, v in params.items()])
signature = hmac.new(
api_secret.encode('utf-8'),
query_string.encode('utf-8'),
hashlib.sha256
).hexdigest()
params['signature'] = signature
headers = {'X-MBX-APIKEY': api_key}
response = requests.post(
"https://api.binance.com/sapi/v1/asset/transfer",
params=params,
headers=headers
)
if response.status_code == 200:
result = response.json()
print(f"โอนสำเร็จ! TranId: {result['tranId']}")
return result
else:
print(f"Transfer Error: {response.text}")
return None
def get_futures_balance(api_key, api_secret):
"""ดึงยอดคงเหลือใน Futures Wallet"""
timestamp = int(time.time() * 1000)
params = {
'timestamp': timestamp,
'recvWindow': 5000
}
query_string = '&'.join([f"{k}={v}" for k, v in params.items()])
signature = hmac.new(
api_secret.encode('utf-8'),
query_string.encode('utf-8'),
hashlib.sha256
).hexdigest()
params['signature'] = signature
headers = {'X-MBX-APIKEY': api_key}
response = requests.get(
"https://fapi.binance.com/fapi/v2/balance",
params=params,
headers=headers
)
if response.status_code == 200:
balances = response.json()
for b in balances:
if float(b['availableBalance']) > 0:
print(f"{b['asset']}: Available = {b['availableBalance']}")
return balances
else:
print(f"Balance Error: {response.text}")
return None
วิธีใช้งาน
api_key = 'YOUR_API_KEY'
api_secret = 'YOUR_API_SECRET'
1. โอนเงิน 100 USDT ไป Futures Wallet
transfer_result = transfer_to_futures(api_key, api_secret, 'USDT', '100')
2. ตรวจสอบยอดใน Futures
futures_balances = get_futures_balance(api_key, api_secret)
กรณีที่ 3: Liquidation โดนโดยไม่ได้ตั้ง Stop Loss
อาการ: Position ถูก Liquidate โดยไม่ทันตั้งตัว สูญเสียเงินทั้งหมดที่วางเป็น Margin
สาเหตุ: ไม่ได้ตั้ง Stop Loss หรือใช้ Leverage สูงเกินไป ไม่เข้าใจเรื่อง Liquidation Price
วิธีแก้ไข:
def calculate_liquidation_price(entry_price, leverage, position_side='LONG'):
"""คำนวณราคา Liquidation"""
if position_side == 'LONG':
# สำหรับ Long Position
liq_price = entry_price * (1 - 1 / leverage)
else:
# สำหรับ Short Position
liq_price = entry_price * (1 + 1 / leverage)
return liq_price
def place_stop_loss_order(api_key, api_secret, symbol, position_side,
quantity, stop_price, take_profit_price=None):
"""ตั้ง Stop Loss และ Take Profit พร้อมกัน"""
timestamp = int(time.time() * 1000)
# Stop Loss Order (Stop Market)
sl_params = {
'symbol': symbol,
'side': 'SELL' if position_side == 'LONG' else 'BUY',
'type': 'STOP_MARKET',
'stopPrice': stop_price,
'quantity': quantity,
'reduceOnly': True,
'timestamp': timestamp,
'recvWindow': 5000
}
query_string = '&'.join([f"{k}={v}" for k, v in sl_params.items()])
signature = hmac.new(
api_secret.encode('utf-8'),
query_string.encode('utf-8'),
hashlib.sha256
).hexdigest()
sl_params['signature'] = signature
headers = {'X-MBX-APIKEY': api_key}
sl_response = requests.post(
"https://fapi.binance.com/fapi/v1/order",
params=sl_params,
headers=headers
)
print(f"Stop Loss ตั้งสำเร็จ: {sl_response.json()}")
# Take Profit Order (Take Profit Market)
if take_profit_price:
tp_params = {
'symbol': symbol,
'side': 'SELL' if position_side == 'LONG' else 'BUY',
'type': 'TAKE_PROFIT_MARKET',
'stopPrice': take_profit_price,
'quantity': quantity,
'reduceOnly': True,
'timestamp': timestamp,
'recvWindow': 5000
}
tp_query = '&'.join([f"{k}={v}" for k, v in tp_params.items()])
tp_signature = hmac.new(
api_secret.encode('utf-8'),
tp_query.encode('utf-8'),
hashlib.sha256
).hexdigest()
tp_params['signature'] = tp_signature
tp_response = requests.post(
"https://fapi.binance.com/fapi/v1/order",
params=tp_params,
headers=headers
)
print(f"Take Profit ตั้งสำเร็จ: {tp_response.json()}")
ตัวอย่างการใช้งาน
entry_price = 50000
leverage = 10
position_size = '0.01' # 0.01 BTC
position_side = 'LONG'
คำนวณ Liquidation Price
liq_price = calculate_liquidation_price(entry_price, leverage, position_side)
print(f"ราคาเปิด: {entry_price}")
print(f"Liquidation Price: {liq_price:.2f} (ต่ำกว่า {entry_price - liq_price:.2f} USDT)")
ตั้ง Stop Loss ที่ -2% จากราคาเปิด
stop_loss_price = entry_price * 0.98
ตั้ง Take Profit ที่ +5% จากราคาเปิด
take_profit_price = entry_price * 1.05
place_stop_loss_order(
api_key='YOUR_KEY',
api_secret='YOUR_SECRET',
symbol='BTCUSDT',
position_side=position_side,
quantity=position_size,
stop_price=stop_loss_price,
take_profit_price=take_profit_price
)
เหมาะกับใคร / ไม่เหมาะกับใคร
เหมาะกับการใช้ Spot API
- ผู้เริ่มต้นเทรด: เข้าใจง่าย ความเสี่ยงจำกัด ไม่มีปัญหา Liquidation
- นักลงทุนระยะยาว (HODLer): ต้องการซื้อเหรียญแล้วถือยาว �