สำหรับนักเทรดเชิงปริมาณและนักพัฒนาระบบเทรดอัตโนมัติ การได้ข้อมูล Tick Data คุณภาพสูงเป็นพื้นฐานสำคัญในการสร้างกลยุทธ์ที่ทำกำไรได้จริง บทความนี้จะพาคุณไปรู้จักกับการใช้งาน Tardis (แพลตฟอร์มรวบรวมข้อมูลตลาดคริปโตชั้นนำ) ร่วมกับ HolySheep AI ในการ Export ข้อมูล Tick เป็นรูปแบบ CSV และนำไปใช้ในการทำ Backtest อย่างมีประสิทธิภาพ
Tardis คืออะไร และทำไมต้อง Export เป็น CSV
Tardis Exchange Data API เป็นแพลตฟอร์มที่รวบรวมข้อมูลตลาดคริปโตจาก Exchange ชั้นนำทั่วโลก มีข้อมูล Tick Data, Order Book, และ Trade History ที่ครบถ้วนและมีความแม่นยำสูง การ Export เป็นรูปแบบ CSV ทำให้สามารถนำข้อมูลไปใช้กับเครื่องมือ Backtesting หลากหลายตัว เช่น Backtrader, Zipline, หรือระบบ Custom ที่พัฒนาเอง
จุดเด่นของ Tardis
- รองรับ Exchange กว่า 50 แห่ง รวมถึง Binance, Bybit, OKX, และ Coinbase
- ข้อมูล Tick Data มีความละเอียดถึงระดับ Millisecond
- มี Historical Data ย้อนหลังหลายปี
- API มีความเสถียรและ Response Time ต่ำ
การตั้งค่า API และการเชื่อมต่อ
ก่อนเริ่มต้นการ Export ข้อมูล คุณต้องมี API Key จาก Tardis และตั้งค่า HolySheep AI เป็น Gateway สำหรับการประมวลผลข้อมูลเพิ่มเติม ซึ่งช่วยลดต้นทุนได้อย่างมากเมื่อเทียบกับการใช้งาน OpenAI โดยตรง
การติดตั้ง Library ที่จำเป็น
# ติดตั้ง Library ที่จำเป็น
pip install tardis-client pandas numpy requests python-dotenv
สร้างไฟล์ .env สำหรับเก็บ API Keys
cat > .env << 'EOF'
TARDIS_API_KEY=your_tardis_api_key_here
HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY
EOF
การ Export ข้อมูล Tick จาก Tardis เป็น CSV
ในการใช้งานจริง ผมทดสอบการ Export ข้อมูล BTC/USDT Perpetual Futures จาก Binance ย้อนหลัง 30 วัน รวมประมาณ 15 ล้าน Rows โดยใช้ Script ด้านล่างนี้
import os
import pandas as pd
from tardis_client import TardisClient, Channels
from datetime import datetime, timedelta
import asyncio
from dotenv import load_dotenv
load_dotenv()
class TardisToCSVExporter:
"""คลาสสำหรับ Export ข้อมูล Tick จาก Tardis เป็น CSV"""
def __init__(self, api_key: str):
self.api_key = api_key
self.client = TardisClient(api_key)
self.buffer = []
async def fetch_realtime_trades(self, exchange: str, symbol: str,
start_date: datetime, end_date: datetime):
"""
ดึงข้อมูล Trade แบบ Real-time จาก Tardis
รองรับ Binance, Bybit, OKX และ Exchange อื่นๆ
"""
channel = Channels.trades(exchange=exchange, symbol=symbol)
trades_data = []
# วนลูปดึงข้อมูลตามช่วงเวลาที่กำหนด
current_date = start_date
while current_date <= end_date:
next_date = min(current_date + timedelta(days=1), end_date)
print(f"กำลังดึงข้อมูล: {current_date.strftime('%Y-%m-%d')}")
# สร้าง Enumerator สำหรับดึงข้อมูล
enumerator = self.client.create_dataEnumerator(
channels=[channel],
from_date=current_date.isoformat(),
to_date=next_date.isoformat(),
timeout=60
)
async for rec in enumerator:
trade = {
'timestamp': rec.timestamp,
'exchange': rec.exchange,
'symbol': rec.symbol,
'side': rec.side,
'price': float(rec.price),
'amount': float(rec.amount),
'cost': float(rec.cost),
'id': rec.id
}
trades_data.append(trade)
current_date = next_date
return trades_data
def save_to_csv(self, data: list, filename: str,
add_indicators: bool = True):
"""
บันทึกข้อมูลเป็นไฟล์ CSV พร้อมเพิ่ม Technical Indicators
"""
df = pd.DataFrame(data)
# แปลง timestamp เป็น datetime
if 'timestamp' in df.columns:
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
df = df.sort_values('timestamp')
if add_indicators:
# เพิ่ม Technical Indicators พื้นฐาน
df['price_sma_20'] = df['price'].rolling(window=20).mean()
df['price_sma_50'] = df['price'].rolling(window=50).mean()
df['price_std_20'] = df['price'].rolling(window=20).std()
df['volatility'] = df['price_std_20'] / df['price_sma_20']
df['volume_ma_20'] = df['amount'].rolling(window=20).mean()
# บันทึกเป็น CSV
df.to_csv(filename, index=False, compression='gzip')
print(f"บันทึกไฟล์สำเร็จ: {filename}")
print(f"จำนวน Rows: {len(df):,}")
return df
ตัวอย่างการใช้งาน
async def main():
exporter = TardisToCSVExporter(api_key=os.getenv('TARDIS_API_KEY'))
# กำหนดช่วงเวลาที่ต้องการ
end_date = datetime.now()
start_date = end_date - timedelta(days=30)
# ดึงข้อมูล BTC/USDT จาก Binance
trades = await exporter.fetch_realtime_trades(
exchange='binance',
symbol='btcusdt_perpetual_future',
start_date=start_date,
end_date=end_date
)
# บันทึกเป็น CSV
df = exporter.save_to_csv(
data=trades,
filename='btcusdt_trades_30d.csv',
add_indicators=True
)
return df
if __name__ == '__main__':
df = asyncio.run(main())
print(df.head())
การทำ Backtesting ด้วยข้อมูล CSV
หลังจากได้ข้อมูล CSV แล้ว ขั้นตอนต่อไปคือการสร้างระบบ Backtest ที่ใช้งานได้จริง ผมได้พัฒนา Framework ที่ครอบคลุมการทดสอบกลยุทธ์หลายรูปแบบ
import pandas as pd
import numpy as np
from typing import Dict, List, Tuple, Optional
from dataclasses import dataclass
from datetime import datetime
@dataclass
class TradeResult:
"""ผลลัพธ์ของการเทรดแต่ละครั้ง"""
entry_time: datetime
exit_time: datetime
entry_price: float
exit_price: float
size: float
side: str # 'long' หรือ 'short'
pnl: float
pnl_percent: float
class QuantitativeBacktester:
"""ระบบ Backtest สำหรับทดสอบกลยุทธ์การเทรด"""
def __init__(self, initial_capital: float = 100000):
self.initial_capital = initial_capital
self.capital = initial_capital
self.trades: List[TradeResult] = []
self.equity_curve = []
self.position = None
def load_data(self, csv_path: str) -> pd.DataFrame:
"""โหลดข้อมูลจาก CSV"""
df = pd.read_csv(csv_path, parse_dates=['timestamp'])
df = df.set_index('timestamp')
return df
def moving_average_crossover_strategy(self, df: pd.DataFrame,
fast_ma: int = 10,
slow_ma: int = 30) -> pd.DataFrame:
"""
กลยุทธ์ Moving Average Crossover
- ซื้อเมื่อ Fast MA ตัดเหนือ Slow MA
- ขายเมื่อ Fast MA ตัดใต้ Slow MA
"""
df = df.copy()
df['fast_ma'] = df['price'].rolling(window=fast_ma).mean()
df['slow_ma'] = df['price'].rolling(window=slow_ma).mean()
df['signal'] = 0
df.loc[df['fast_ma'] > df['slow_ma'], 'signal'] = 1
df.loc[df['fast_ma'] < df['slow_ma'], 'signal'] = -1
df['position'] = df['signal'].shift(1)
return df
def mean_reversion_strategy(self, df: pd.DataFrame,
lookback: int = 50,
std_multiplier: float = 2.0) -> pd.DataFrame:
"""
กลยุทธ์ Mean Reversion
- ซื้อเมื่อราคาต่ำกว่า Lower Band
- ขายเมื่อราคาสูงกว่า Upper Band
"""
df = df.copy()
df['sma'] = df['price'].rolling(window=lookback).mean()
df['std'] = df['price'].rolling(window=lookback).std()
df['upper_band'] = df['sma'] + (std_multiplier * df['std'])
df['lower_band'] = df['sma'] - (std_multiplier * df['std'])
df['signal'] = 0
df.loc[df['price'] < df['lower_band'], 'signal'] = 1 # ซื้อ
df.loc[df['price'] > df['upper_band'], 'signal'] = -1 # ขาย
df['position'] = df['signal'].shift(1)
return df
def momentum_strategy(self, df: pd.DataFrame,
lookback: int = 20,
threshold: float = 0.02) -> pd.DataFrame:
"""
กลยุทธ์ Momentum
- ซื้อเมื่อราคาเปลี่ยนแปลงมากกว่า Threshold ในทิศทางบวก
- ขายเมื่อราคาเปลี่ยนแปลงมากกว่า Threshold ในทิศทางลบ
"""
df = df.copy()
df['returns'] = df['price'].pct_change()
df['momentum'] = df['returns'].rolling(window=lookback).sum()
df['signal'] = 0
df.loc[df['momentum'] > threshold, 'signal'] = 1
df.loc[df['momentum'] < -threshold, 'signal'] = -1
df['position'] = df['signal'].shift(1)
return df
def run_backtest(self, df: pd.DataFrame, position_size: float = 0.1):
"""รัน Backtest กับข้อมูลที่ผ่านการประมวลผลแล้ว"""
self.capital = self.initial_capital
self.trades = []
self.equity_curve = []
entry_price = 0
entry_time = None
current_position = None
for idx, row in df.iterrows():
if pd.isna(row['position']):
continue
# คำนวณมูลค่าพอร์ต
self.equity_curve.append({
'timestamp': idx,
'capital': self.capital,
'position': current_position
})
# เปิด Position
if current_position is None and row['position'] == 1:
current_position = 'long'
entry_price = row['price']
entry_time = idx
elif current_position is None and row['position'] == -1:
current_position = 'short'
entry_price = row['price']
entry_time = idx
# ปิด Position
elif current_position == 'long' and row['position'] == -1:
pnl = (row['price'] - entry_price) * self.capital * position_size
pnl_percent = (row['price'] - entry_price) / entry_price * 100
self.trades.append(TradeResult(
entry_time=entry_time,
exit_time=idx,
entry_price=entry_price,
exit_price=row['price'],
size=self.capital * position_size,
side='long',
pnl=pnl,
pnl_percent=pnl_percent
))
self.capital += pnl
current_position = 'short'
entry_price = row['price']
entry_time = idx
elif current_position == 'short' and row['position'] == 1:
pnl = (entry_price - row['price']) * self.capital * position_size
pnl_percent = (entry_price - row['price']) / entry_price * 100
self.trades.append(TradeResult(
entry_time=entry_time,
exit_time=idx,
entry_price=entry_price,
exit_price=row['price'],
size=self.capital * position_size,
side='short',
pnl=pnl,
pnl_percent=pnl_percent
))
self.capital += pnl
current_position = 'long'
entry_price = row['price']
entry_time = idx
return self.calculate_metrics()
def calculate_metrics(self) -> Dict:
"""คำนวณ Metrics สำหรับประเมินผลกลยุทธ์"""
if not self.trades:
return {}
df_trades = pd.DataFrame([{
'pnl': t.pnl,
'pnl_percent': t.pnl_percent,
'side': t.side,
'duration': (t.exit_time - t.entry_time).total_seconds() / 3600
} for t in self.trades])
# คำนวณ Metrics หลัก
total_return = (self.capital - self.initial_capital) / self.initial_capital * 100
winning_trades = df_trades[df_trades['pnl'] > 0]
losing_trades = df_trades[df_trades['pnl'] <= 0]
win_rate = len(winning_trades) / len(df_trades) * 100 if len(df_trades) > 0 else 0
avg_win = winning_trades['pnl'].mean() if len(winning_trades) > 0 else 0
avg_loss = abs(losing_trades['pnl'].mean()) if len(losing_trades) > 0 else 0
profit_factor = (avg_win * len(winning_trades)) / (avg_loss * len(losing_trades)) if avg_loss > 0 else float('inf')
# Maximum Drawdown
equity_df = pd.DataFrame(self.equity_curve)
equity_df['peak'] = equity_df['capital'].cummax()
equity_df['drawdown'] = (equity_df['capital'] - equity_df['peak']) / equity_df['peak'] * 100
max_drawdown = abs(equity_df['drawdown'].min())
# Sharpe Ratio
returns = df_trades['pnl_percent'] / 100
sharpe_ratio = np.sqrt(252) * returns.mean() / returns.std() if returns.std() > 0 else 0
# Sortino Ratio
downside_returns = returns[returns < 0]
sortino_ratio = np.sqrt(252) * returns.mean() / downside_returns.std() if len(downside_returns) > 0 and downside_returns.std() > 0 else 0
return {
'total_return_percent': total_return,
'total_trades': len(self.trades),
'winning_trades': len(winning_trades),
'losing_trades': len(losing_trades),
'win_rate_percent': win_rate,
'avg_win': avg_win,
'avg_loss': avg_loss,
'profit_factor': profit_factor,
'max_drawdown_percent': max_drawdown,
'sharpe_ratio': sharpe_ratio,
'sortino_ratio': sortino_ratio,
'final_capital': self.capital,
'trades_df': df_trades
}
ตัวอย่างการใช้งาน
def run_full_backtest():
backtester = QuantitativeBacktester(initial_capital=100000)
# โหลดข้อมูลจาก CSV
df = backtester.load_data('btcusdt_trades_30d.csv.gz')
# ทดสอบกลยุทธ์ Moving Average Crossover
df_ma = backtester.moving_average_crossover_strategy(df, fast_ma=10, slow_ma=30)
metrics_ma = backtester.run_backtest(df_ma)
# ทดสอบกลยุทธ์ Mean Reversion
df_mr = backtester.mean_reversion_strategy(df, lookback=50, std_multiplier=2.0)
metrics_mr = backtester.run_backtest(df_mr)
# ทดสอบกลยุทธ์ Momentum
df_mo = backtester.momentum_strategy(df, lookback=20, threshold=0.02)
metrics_mo = backtester.run_backtest(df_mo)
# เปรียบเทียบผลลัพธ์
print("=" * 60)
print("ผลลัพธ์การ Backtest - เปรียบเทียบกลยุทธ์")
print("=" * 60)
for name, metrics in [('MA Crossover', metrics_ma),
('Mean Reversion', metrics_mr),
('Momentum', metrics_mo)]:
if metrics:
print(f"\n{name}:")
print(f" Total Return: {metrics['total_return_percent']:.2f}%")
print(f" Win Rate: {metrics['win_rate_percent']:.2f}%")
print(f" Profit Factor: {metrics['profit_factor']:.2f}")
print(f" Max Drawdown: {metrics['max_drawdown_percent']:.2f}%")
print(f" Sharpe Ratio: {metrics['sharpe_ratio']:.2f}")
if __name__ == '__main__':
run_full_backtest()
การใช้ HolySheep AI สำหรับประมวลผลข้อมูลเพิ่มเติม
ในการวิเคราะห์ข้อมูลเชิงลึกและสร้างรายงาน คุณสามารถใช้ HolySheep AI เพื่อวิเคราะห์ผลลัพธ์ Backtest และให้คำแนะนำในการปรับปรุงกลยุทธ์ ซึ่งมีความสะดวกและประหยัดกว่าการใช้งาน OpenAI โดยตรงถึง 85%
import requests
import json
from typing import Dict, List
class HolySheepAnalysis:
"""ใช้ HolySheep AI สำหรับวิเคราะห์ผลลัพธ์ Backtest"""
def __init__(self, api_key: str):
self.base_url = "https://api.holysheep.ai/v1"
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
def analyze_backtest_results(self, metrics: Dict,
strategy_name: str) -> str:
"""
วิเคราะห์ผลลัพธ์ Backtest และให้คำแนะนำ
"""
prompt = f"""
วิเคราะห์ผลการ Backtest ของกลยุทธ์ {strategy_name} และให้คำแนะนำ:
ผลลัพธ์:
- Total Return: {metrics.get('total_return_percent', 0):.2f}%
- Win Rate: {metrics.get('win_rate_percent', 0):.2f}%
- Profit Factor: {metrics.get('profit_factor', 0):.2f}
- Max Drawdown: {metrics.get('max_drawdown_percent', 0):.2f}%
- Sharpe Ratio: {metrics.get('sharpe_ratio', 0):.2f}
- Total Trades: {metrics.get('total_trades', 0)}
กรุณาให้คำแนะนำในการปรับปรุงกลยุทธ์
"""
payload = {
"model": "gpt-4.1",
"messages": [
{"role": "system", "content": "คุณเป็นผู้เชี่ยวชาญด้าน Quantitative Trading และ Backtesting"},
{"role": "user", "content": prompt}
],
"temperature": 0.7,
"max_tokens": 1000
}
response = requests.post(
f"{self.base_url}/chat/completions",
headers=self.headers,
json=payload
)
if response.status_code == 200:
return response.json()['choices'][0]['message']['content']
else:
raise Exception(f"API Error: {response.status_code} - {response.text}")
def generate_strategy_report(self, metrics_list: List[Dict],
strategy_names: List[str]) -> str:
"""
สร้างรายงานเปรียบเทียบกลยุทธ์หลายแบบ
"""
analysis_text = "\n\n".join([
f"กลยุทธ์ {name}: Return {m.get('total_return_percent', 0):.2f}%, "
f"Win Rate {m.get('win_rate_percent', 0):.2f}%"
for name, m in zip(strategy_names, metrics_list)
])
prompt = f"""
เปรียบเทียบและวิเคราะห์กลยุทธ์การเทรดดังต่อไปนี้:
{analysis_text}
1. กลยุทธ์ใดมีประสิทธิภาพดีที่สุด เพราะอะไร?
2. ควรเลือกใช้กลยุทธ์ใดสำหรับตลาดปัจจุบัน?
3. มีข้อเสนอแนะในการปรับปรุงกลยุทธ์อย่างไร?
"""
payload = {
"model": "gpt-4.1",
"messages": [
{"role": "system", "content": "คุณเป็นผู้เชี่ยวชาญด้าน Quantitative Trading ที่มีประสบการณ์มากกว่า 10 ปี"},
{"role": "user", "content": prompt}
],
"temperature": 0.5,
"max_tokens": 1500
}
response = requests.post(
f"{self.base_url}/chat/completions",
headers=self.headers,
json=payload
)
if response.status_code == 200:
return response.json()['choices'][0]['message']['content']
else:
raise Exception(f"API Error: {response.status_code}")
ตัวอย่างการใช้งาน
def main():
# สร้าง instance สำหรับวิเคราะห์
analyzer = HolySheepAnalysis(api_key="YOUR_HOL