ในโลกของสกุลเงินดิจิทัล กลยุทธ์ Funding Rate Arbitrage เป็นหนึ่งในวิธีการที่ได้รับความนิยมในหมู่นักเทรดระดับมืออาชีพ บทความนี้จะพาคุณเรียนรู้การดึงข้อมูลประวัติ Funding Rate จาก Bybit API และการสร้างระบบ Backtesting เพื่อทดสอบประสิทธิภาพของกลยุทธ์
Funding Rate คืออะไรและทำงานอย่างไร
Funding Rate เป็นกลไกที่ใช้ในสัญญา Perpetual Futures เพื่อให้ราคาของสัญญาใกล้เคียงกับราคา Spot ของสินทรัพย์อ้างอิง โดยมีการชำระเงินทุก 8 ชั่วโมง:
- Funding Rate สูง (บวก): ผู้ที่ถือสถานะ Long ต้องจ่ายเงินให้ผู้ถือสถานะ Short
- Funding Rate ต่ำ (ลบ): ผู้ที่ถือสถานะ Short ต้องจ่ายเงินให้ผู้ถือสถานะ Long
- โอกาส Arbitrage: เมื่อ Funding Rate สูงผิดปกติ สามารถ Short สัญญา Perpetual และ Long Spot เพื่อรับ Funding ทุก 8 ชั่วโมง
การรับข้อมูล Funding Rate จาก Bybit API
Bybit มี Public API ที่สามารถใช้ดึงข้อมูล Funding Rate ได้ฟรีโดยไม่ต้องยืนยันตัวตน
import requests
import pandas as pd
from datetime import datetime, timedelta
import time
class BybitFundingRateCollector:
"""คลาสสำหรับรวบรวมข้อมูล Funding Rate จาก Bybit API"""
BASE_URL = "https://api.bybit.com"
def __init__(self, symbols=None):
"""
กำหนด symbols ที่ต้องการเก็บข้อมูล
ค่าเริ่มต้น: symbols ยอดนิยมในตลาด Perpetual Futures
"""
self.symbols = symbols or [
'BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT',
'XRPUSDT', 'ADAUSDT', 'DOGEUSDT', 'AVAXUSDT'
]
def get_funding_rate(self, symbol, start_time=None, end_time=None, limit=200):
"""
ดึงข้อมูล Funding Rate History ของ symbol ที่กำหนด
Parameters:
- symbol: ชื่อคู่เทรด เช่น 'BTCUSDT'
- start_time: timestamp เริ่มต้น (milliseconds)
- end_time: timestamp สิ้นสุด (milliseconds)
- limit: จำนวนข้อมูลสูงสุด (max 1000)
Returns:
- DataFrame ที่มี columns: symbol, fundingRate, fundingRateTimestamp, settlementTime
"""
endpoint = "/public/v3/perpetual/usdt-perpetual/public/contract/instrument-info"
params = {
'category': 'linear',
'symbol': symbol,
'limit': limit
}
try:
response = requests.get(
f"{self.BASE_URL}{endpoint}",
params=params,
timeout=10
)
response.raise_for_status()
data = response.json()
if data['retCode'] == 0:
return self._parse_funding_data(data['result']['list'])
else:
print(f"Error for {symbol}: {data['retMsg']}")
return pd.DataFrame()
except requests.exceptions.RequestException as e:
print(f"Request failed for {symbol}: {e}")
return pd.DataFrame()
def get_funding_rate_for_period(self, symbol, days=90):
"""
ดึงข้อมูล Funding Rate ย้อนหลังตามจำนวนวันที่กำหนด
Parameters:
- symbol: ชื่อคู่เทรด
- days: จำนวนวันย้อนหลัง
Returns:
- DataFrame พร้อมข้อมูล Funding Rate
"""
end_time = int(time.time() * 1000)
start_time = int((time.time() - days * 24 * 3600) * 1000)
all_data = []
current_start = start_time
while current_start < end_time:
df = self._fetch_funding_chunk(symbol, current_start, end_time)
if df.empty:
break
all_data.append(df)
# ดึงข้อมูลช่วงถัดไป
last_timestamp = df['fundingRateTimestamp'].min()
current_start = last_timestamp - 1
# หยุดชั่วคราวเพื่อหลีกเลี่ยง rate limit
time.sleep(0.2)
if all_data:
combined_df = pd.concat(all_data, ignore_index=True)
combined_df = combined_df.drop_duplicates()
combined_df = combined_df.sort_values('fundingRateTimestamp')
return combined_df
return pd.DataFrame()
def _fetch_funding_chunk(self, symbol, start_time, end_time, limit=200):
"""ดึงข้อมูล Funding Rate เป็นช่วงๆ"""
endpoint = "/public/v3/perpetual/usdt-perpetual/public/contract/instrument-info"
params = {
'category': 'linear',
'symbol': symbol,
'limit': limit
}
try:
response = requests.get(
f"{self.BASE_URL}{endpoint}",
params=params,
timeout=10
)
response.raise_for_status()
data = response.json()
if data['retCode'] == 0:
return self._parse_funding_data(data['result']['list'])
except Exception as e:
print(f"Chunk fetch error: {e}")
return pd.DataFrame()
def _parse_funding_data(self, raw_data):
"""แปลงข้อมูลดิบเป็น DataFrame"""
parsed = []
for item in raw_data:
parsed.append({
'symbol': item.get('symbol'),
'fundingRate': float(item.get('fundingRate', 0)),
'fundingRateTimestamp': int(item.get('fundingRateE4', 0)) // 10000,
'markPrice': float(item.get('markPrice', 0)),
'indexPrice': float(item.get('indexPrice', 0)),
'nextFundingTime': item.get('nextFundingTime'),
'settleTime': item.get('settleTime')
})
return pd.DataFrame(parsed)
def collect_all_symbols(self, days=90):
"""
ดึงข้อมูล Funding Rate สำหรับทุก symbol ที่กำหนด
Returns:
- Dictionary ของ DataFrames โดยใช้ symbol เป็น key
"""
results = {}
for symbol in self.symbols:
print(f"กำลังดึงข้อมูล {symbol}...")
df = self.get_funding_rate_for_period(symbol, days)
if not df.empty:
results[symbol] = df
print(f"✓ ได้ข้อมูล {symbol} {len(df)} รายการ")
else:
print(f"✗ ไม่พบข้อมูล {symbol}")
time.sleep(0.3) # หลีกเลี่ยง rate limit
return results
การใช้งาน
if __name__ == "__main__":
collector = BybitFundingRateCollector(symbols=['BTCUSDT', 'ETHUSDT', 'SOLUSDT'])
# ดึงข้อมูลย้อนหลัง 90 วัน
funding_data = collector.collect_all_symbols(days=90)
# แสดงผลสถิติ
for symbol, df in funding_data.items():
print(f"\n{symbol} Funding Rate Statistics:")
print(df['fundingRate'].describe())
การสร้างระบบ Backtesting สำหรับ Funding Rate Arbitrage
หลังจากได้ข้อมูล Funding Rate แล้ว ขั้นตอนถัดไปคือการสร้างระบบ Backtesting เพื่อทดสอบว่ากลยุทธ์มีประสิทธิภาพจริงหรือไม่
import pandas as pd
import numpy as np
from datetime import datetime
import warnings
warnings.filterwarnings('ignore')
class FundingRateArbitrageBacktester:
"""
ระบบ Backtesting สำหรับกลยุทธ์ Funding Rate Arbitrage
กลยุทธ์:
1. เข้า Short สัญญา Perpetual เมื่อ Funding Rate > threshold
2. รับ Funding Payment ทุก 8 ชั่วโมง
3. ปิดสถานะเมื่อ Funding Rate < exit_threshold หรือถึงเป้าหมายกำไร
"""
def __init__(self,
initial_capital=10000,
funding_threshold=0.001, # 0.1% ต่อ 8 ชั่วโมง
exit_threshold=0.0001, # 0.01% ต่อ 8 ชั่วโมง
leverage=3,
maker_fee=0.0002,
taker_fee=0.0006,
max_position_per_trade=0.3): # ใช้ทุนไม่เกิน 30% ต่อสถานะ
self.initial_capital = initial_capital
self.funding_threshold = funding_threshold
self.exit_threshold = exit_threshold
self.leverage = leverage
self.maker_fee = maker_fee
self.taker_fee = taker_fee
self.max_position_per_trade = max_position_per_trade
self.trades = []
self.equity_curve = []
self.current_capital = initial_capital
def run_backtest(self, funding_rate_df, price_df=None, symbol='UNKNOWN'):
"""
รัน Backtesting บนข้อมูล Funding Rate
Parameters:
- funding_rate_df: DataFrame ที่มี columns [fundingRate, fundingRateTimestamp]
- price_df: DataFrame ที่มี columns [open, high, low, close, timestamp]
- symbol: ชื่อคู่เทรดสำหรับบันทึก
Returns:
- Dictionary ที่มีผลลัพธ์การ backtest
"""
if funding_rate_df.empty:
return self._empty_result()
# คำนวณ Funding Rate รายวัน (8 ชั่วโมง = 3 ครั้งต่อวัน)
funding_rate_df = funding_rate_df.copy()
funding_rate_df['daily_funding_rate'] = funding_rate_df['fundingRate'] * 3
funding_rate_df['date'] = pd.to_datetime(
funding_rate_df['fundingRateTimestamp'], unit='s'
)
# กรองข้อมูลที่มีค่า funding rate เกิน threshold
signals = funding_rate_df[
funding_rate_df['fundingRate'].abs() >= self.funding_threshold
].copy()
if signals.empty:
return self._empty_result()
# จำลองการเทรด
for idx, row in signals.iterrows():
trade_result = self._simulate_trade(row, symbol, price_df)
if trade_result:
self.trades.append(trade_result)
# อัปเดต Capital
pnl = trade_result['pnl']
self.current_capital += pnl
# บันทึก Equity Curve
self.equity_curve.append({
'timestamp': row['fundingRateTimestamp'],
'equity': self.current_capital,
'trade_id': len(self.trades)
})
return self._calculate_performance()
def _simulate_trade(self, signal_row, symbol, price_df=None):
"""
จำลองการเทรดครั้งเดียว
กลยุทธ์: Short Perpetual + Long Spot
รับ Funding = position_size * funding_rate (ทุก 8 ชม.)
จ่ายค่า Fee เมื่อเปิดและปิดสถานะ
"""
entry_funding = signal_row['fundingRate']
entry_time = signal_row['fundingRateTimestamp']
# คำนวณขนาดสถานะ
position_value = self.current_capital * self.max_position_per_trade
position_size = position_value * self.leverage
# ค่า Funding ที่คาดว่าจะได้รับต่อ 8 ชั่วโมง
funding_per_period = position_size * entry_funding
# ตรวจสอบว่าเป็น Short (รับ funding เมื่อ funding rate > 0)
is_short_position = entry_funding > 0
# คำนวณระยะเวลาถือสถานะ (จนกว่า funding rate จะลดลงต่ำกว่า exit threshold)
holding_periods = 1 # อย่างน้อย 1 period
# จำลองว่า holding ไปจนถึง signal ถัดไปที่ตรงเงื่อนไขออก
# (ใน backtest จริง ต้องมี price data ประกอบ)
# รายได้จาก Funding
total_funding = funding_per_period * holding_periods
# ค่าใช้จ่าย: Fees
entry_fee = position_value * self.taker_fee
exit_fee = position_value * self.taker_fee
total_fees = entry_fee + exit_fee
# คำนวณ PnL
# สมมติว่าไม่มี position เปลี่ยนแปลงจากราคา (hedge กับ spot)
# กำไรมาจาก Funding ลบค่า Fee
pnl = total_funding - total_fees
# คำนวณ ROI
roi = (pnl / position_value) * 100
return {
'symbol': symbol,
'entry_time': entry_time,
'entry_funding_rate': entry_funding,
'position_size': position_size,
'holding_periods': holding_periods,
'funding_earned': total_funding,
'fees': total_fees,
'pnl': pnl,
'roi_percent': roi,
'is_short': is_short_position
}
def _calculate_performance(self):
"""คำนวณผลตอบแทนและสถิติ"""
if not self.trades:
return self._empty_result()
df_trades = pd.DataFrame(self.trades)
total_pnl = df_trades['pnl'].sum()
win_rate = (df_trades['pnl'] > 0).mean() * 100
avg_pnl = df_trades['pnl'].mean()
# คำนวณ Max Drawdown
equity_series = pd.DataFrame(self.equity_curve)
if not equity_series.empty:
equity_series['cummax'] = equity_series['equity'].cummax()
equity_series['drawdown'] = (equity_series['equity'] - equity_series['cummax']) / equity_series['cummax']
max_drawdown = equity_series['drawdown'].min() * 100
else:
max_drawdown = 0
# Sharpe Ratio (ประมาณ)
if len(df_trades) > 1:
returns = df_trades['pnl'] / self.initial_capital
sharpe_ratio = returns.mean() / returns.std() * np.sqrt(365) if returns.std() > 0 else 0
else:
sharpe_ratio = 0
return {
'total_trades': len(df_trades),
'total_pnl': total_pnl,
'final_capital': self.current_capital,
'total_return_percent': (self.current_capital / self.initial_capital - 1) * 100,
'win_rate': win_rate,
'avg_pnl_per_trade': avg_pnl,
'max_drawdown_percent': max_drawdown,
'sharpe_ratio': sharpe_ratio,
'trades': df_trades
}
def _empty_result(self):
return {
'total_trades': 0,
'total_pnl': 0,
'final_capital': self.current_capital,
'total_return_percent': 0,
'win_rate': 0,
'avg_pnl_per_trade': 0,
'max_drawdown_percent': 0,
'sharpe_ratio': 0,
'trades': pd.DataFrame()
}
การใช้งาน
if __name__ == "__main__":
# สร้างข้อมูล Funding Rate ตัวอย่าง (ในการใช้งานจริง ดึงจาก API)
sample_data = {
'fundingRate': [0.001, 0.0015, 0.0012, 0.0008, 0.0005, 0.0018, 0.0011],
'fundingRateTimestamp': [
1704067200, 1704096000, 1704124800, 1704153600,
1704182400, 1704211200, 1704240000
]
}
df_funding = pd.DataFrame(sample_data)
# รัน Backtest
backtester = FundingRateArbitrageBacktester(
initial_capital=10000,
funding_threshold=0.0005,
leverage=3
)
result = backtester.run_backtest(df_funding, symbol='BTCUSDT')
print("=" * 50)
print("BACKTEST RESULTS - Funding Rate Arbitrage")
print("=" * 50)
print(f"จำนวนการเทรด: {result['total_trades']}")
print(f"กำไร/ขาดทุนรวม: ${result['total_pnl']:.2f}")
print(f"ผลตอบแทนรวม: {result['total_return_percent']:.2f}%")
print(f"อัตราชนะ: {result['win_rate']:.1f}%")
print(f"Max Drawdown: {result['max_drawdown_percent']:.2f}%")
print(f"Sharpe Ratio: {result['sharpe_ratio']:.2f}")
การวิเคราะห์ผลลัพธ์และปรับแต่งกลยุทธ์
หลังจากรัน Backtest แล้ว สิ่งสำคัญคือการวิเคราะห์ผลลัพธ์และปรับแต่งพารามิเตอร์ให้เหมาะสมกับสภาวะตลาด
- Funding Threshold: ปรับค่า threshold ตามสภาวะตลาด - ตลาดขาขึ้น threshold สูงขึ้นเพราะ funding rate มักจะสูง
- Leverage: ใช้ leverage ต่ำ (2-3x) เพื่อลดความเสี่ยงจากความผันผวนของราคา
- Position Sizing: กระจายความเสี่ยงโดยไม่ใช้เงินเกิน 30% ต่อสถานะ
- Exit Strategy: ปิดสถานะเมื่อ funding rate ลดลงต่ำกว่า threshold หรือเมื่อมีสัญญาณกลับตัวของราคา
การใช้ AI วิเคราะห์ข้อมูล Funding Rate อัตโนมัติ
ในการวิเคราะห์ข้อมูล Funding Rate จำนวนมาก การใช้ AI ช่วยวิเคราะห์จะช่วยประหยัดเวลาและค้นพบ patterns ที่ซ่อนอยู่ได้ดียิ่งขึ้น สมัครที่นี่ เพื่อทดลองใช้ HolySheep AI ซึ่งมี API ราคาถูกและเร็ว:
import requests
import json
class FundingRateAnalyzer:
"""ใช้ AI วิเคราะห์ข้อมูล Funding Rate อัตโนมัติ"""
# ใช้ HolySheep AI API - ราคาถูกกว่า 85%+ เมื่อเทียบกับ OpenAI
HOLYSHEEP_API_URL = "https://api.holysheep.ai/v1/chat/completions"
API_KEY = "YOUR_HOLYSHEEP_API_KEY" # แทนที่ด้วย API key จริงของคุณ
def __init__(self):
self.headers = {
"Authorization": f"Bearer {self.API_KEY}",
"Content-Type": "application/json"
}
def analyze_funding_opportunity(self, symbol, current_funding_rate,
historical_avg, volatility, market_sentiment):
"""
ใช้ AI วิเคราะห์โอกาส Funding Rate Arbitrage
Returns:
- คำแนะนำการเทรดพร้อมความมั่นใจ
"""
prompt = f"""คุณเป็นผู้เชี่ยวชาญด้าน Crypto Trading
วิเคราะห์โอกาส Funding Rate Arbitrage สำหรับ {symbol}:
ข้อมูลปัจจุบัน:
- Funding Rate ปัจจุบัน: {current_funding_rate:.4f} ({current_funding_rate*100:.2f}% ต่อ 8 ชม.)
- ค่าเฉลี่ย historical: {historical_avg:.4f}
- Volatility: {volatility:.4f}
- Market Sentiment: {market_sentiment}
โปรดให้:
1. ความมั่นใจในการเข้าเทรด (0-100%)
2. Risk/Reward Ratio ที่คาดว่าจะได้รับ
3. ข้อควรระวังในการเทรด
4. ขนาดสถานะที่แนะนำ (% ของ Capital)
ตอบเป็น JSON format ดังนี้:
{{"confidence": number, "risk_reward": number, "warnings": string, "recommended_size": number}}"""
payload = {
"model": "gpt-4.1", # หรือ deepseek-v3.2 สำหรับงานวิเคราะห์
"messages": [
{"role": "system", "content": "คุณเป็นที่ปรึกษาการลงทุนคริปโตที่มีประสบการณ์"},
{"role": "user", "content": prompt}
],
"temperature": 0.3,
"max_tokens": 500
}
try:
response = requests.post(
self.HOLYSHEEP_API_URL,
headers=self.headers,
json=payload,
timeout=30
)
if response.status_code == 200:
result = response.json()
content = result['choices'][0]['message']['content']
# แปลง response เป็น dict
# ควรใช้ json.loads() ในการ parse
return json.loads(content)
else:
print(f"API Error: {response.status_code}")
return None
except Exception as e:
print(f"Request failed: {e}")
return None
def generate_backtest_report(self, backtest_results):
"""
ใช้ AI สร้างรายงานการ Backtest อย่างละเอียด
"""
prompt = f"""สร้างรายงานวิเคราะห์ Backtest สำหรับกลยุทธ์ Funding Rate Arbitrage:
ผลลัพธ์:
- จำนวนการเทรด: {backtest_results.get('total_trades', 0)}
- กำไร/ขาดทุนรวม: ${backtest_results.get('total_pnl', 0):.