เคสเริ่มต้น: เมื่อบอท Arbitrage ของผมพลาดกำไร 12.4% ต่อเดือน

เรื่องนี้เกิดขึ้นเมื่อต้นปี 2026 ผมกำลังรันบอทเทรดข้ามกระดูกสำหรับสัญญา BTC Perpetual โดยอาศัยความแตกต่างของ Funding Rate ระหว่าง Binance, OKX และ Bybit ตอนแรกใช้แค่ WebSocket แบบ Real-time ผลปรากฏว่าในช่วงที่ตลาด sideways บอททำกำไรได้ประมาณ 4.1% ต่อเดือน แต่พอตลาดผันผวนหนัก บอทพลาดโอกาสไปเกือบ 12.4% ของ APR เพราะไม่มีข้อมูลย้อนหลังมากพอจะ backtest หาจังหวะ threshold ที่เหมาะสม และที่สำคัญคือข่าว macro ไม่ได้ถูกนำมาประกอบการตัดสินใจเลย ผมจึงตัดสินใจต่อยอดระบบด้วย Tardis.dev สำหรับข้อมูลย้อนหลัง และใช้ HolySheep AI เป็นโมดูลวิเคราะห์ข่าวเพราะ latency ต่ำกว่า 50 ms และราคาถูกกว่าการยิง OpenAI ตรงๆ ถึง 85%

พื้นฐาน Funding Rate ที่ต้องเข้าใจก่อนเขียนโค้ด

Funding Rate คือค่าธรรมเนียมที่ฝั่ง Long และ Short จ่ายให้กันเองทุก 8 ชั่วโมง (00:00, 08:00, 16:00 UTC) มีจุดประสงค์เพื่อให้ราคา Futures ไม่หลุดจาก Spot มากเกินไป ปกติค่าจะอยู่ที่ ±0.01% ต่อรอบ แต่ในช่วงที่ตลาดคาดว่าราคาจะขึ้น กระดูกหนึ่งอาจจ่าย 0.05% ขณะที่อีกกระดูกจ่าย 0.015% ตรงนี้แหละคือช่องว่างให้เรา short ฝั่งที่จ่ายสูง แล้ว long ฝั่งที่จ่ายต่ำ รอจน spread กลับมา converge ก็ปิด position

โครงสร้างระบบ Arbitrage ข้ามกระดูก

  1. Data Layer: ดึงข้อมูลย้อนหลังจาก Tardis เพื่อหา threshold ที่เหมาะสม
  2. Signal Layer: คำนวณ spread ระหว่างกระดูก + ใช้ LLM วิเคราะห์ข่าวเสริม
  3. Execution Layer: ส่งคำสั่งผ่าน API ของแต่ละกระดูก (Binance Futures, OKX V5, Bybit V5)
  4. Risk Layer: ตรวจ margin, slippage และ funding rate ที่อาจเปลี่ยนกะทันหัน

ขั้นตอนที่ 1: ดึงข้อมูลย้อนหลังจาก Tardis

# ติดตั้งก่อนใช้งาน: pip install tardis-dev pandas pyarrow requests
from tardis_dev import datasets
from datetime import datetime
import os

API_KEY = os.environ["TARDIS_API_KEY"]  # สมัครฟรีที่ tardis.dev

exchanges = ["binance", "okx", "bybit"]
symbol    = "btcusdt"
start     = datetime(2024, 7, 1)
end       = datetime(2025, 6, 30)

for ex in exchanges:
    print(f"กำลังโหลดข้อมูล {ex} ...")
    datasets.get(
        exchange=ex,
        symbols=symbol,
        data_types="derivative_ticker",
        from_date=start,
        to_date=end,
        download_dir="./tardis_data",
        api_key=API_KEY,
    )
print("ดาวน์โหลดเสร็จ ตรวจสอบโฟลเดอร์ tardis_data")

ขั้นตอนที่ 2: คำนวณ Spread และสร้างสัญญาณ

import pandas as pd
import numpy as np

def load(ex, base="./tardis_data"):
    df = pd.read_parquet(f"{base}/{ex}/derivative_ticker/btcusdt/")
    df["timestamp"] = pd.to_datetime(df["timestamp"], unit="ms", utc=True)
    return df[["timestamp", "funding_rate", "mark_price"]].sort_values("timestamp")

binance = load("binance").rename(columns={"funding_rate": "fr_b"})
okx     = load("okx").rename(columns={"funding_rate": "fr_o"})
bybit   = load("bybit").rename(columns={"funding_rate": "fr_y"})

ใช้ merge_asof เพราะ timestamp ของแต่ละ exchange อาจคลาดกัน 1-3 วินาที

m = pd.merge_asof(binance, okx, on="timestamp", direction="nearest", tolerance=pd.Timedelta("60s")) m = pd.merge_asof(m, bybit, on="timestamp", direction="nearest", tolerance=pd.Timedelta("60s")) m["spread_OB"] = m["fr_o"] - m["fr_b"] m["spread_YB"] = m["fr_y"] - m["fr_b"]

Threshold 0.03% ต่อรอบ (≈ 0.09% ต่อวัน) ถือว่าคุ้มค่าธรรมเนียม

TH = 0.0003 m["signal"] = np.select( [m["spread_OB"] > TH, m["spread_YB"] > TH, m["spread_OB"] < -TH, m["spread_YB"] < -TH], ["short_okx_long_binance", "short_bybit_long_binance", "long_okx_short_binance", "long_bybit_short_binance"], default="hold" ) print(m["signal"].value