ในโลกของการเทรดคริปโต กลยุทธ์ Market Making เป็นหนึ่งในวิธีการที่ทำกำไรได้อย่างต่อเนื่อง แต่การพัฒนาและทดสอบกลยุทธ์เหล่านี้ต้องอาศัยข้อมูล Order Book ที่มีคุณภาพสูง ในบทความนี้เราจะสอนวิธีสร้าง Order Book Depth Data Reconstruction ตั้งแต่เริ่มต้น พร้อมโค้ด Python ที่พร้อมใช้งานจริง

ทำไมต้องสร้าง Order Book Data เอง?

ข้อมูล Order Book จาก Exchange มักมีข้อจำกัดหลายประการ ทั้งความล่าช้าในการอัปเดต ข้อมูลที่ไม่สมบูรณ์ และค่าใช้จ่ายในการเข้าถึง API ระดับ professional การสร้าง Order Book simulation ด้วยตัวเองช่วยให้เราสามารถควบคุมทุกปัจจัยได้อย่างเต็มที่

เปรียบเทียบต้นทุน AI API สำหรับ Data Processing 2026

ก่อนเริ่มต้นโปรเจกต์ มาดูต้นทุนของ AI API ที่ใช้ในการประมวลผลข้อมูลและสร้างโมเดลวิเคราะห์:

โมเดล ราคา/ล้าน tokens ต้นทุนสำหรับ 10M tokens/เดือน
DeepSeek V3.2 $0.42 $4.20
Gemini 2.5 Flash $2.50 $25.00
GPT-4.1 $8.00 $80.00
Claude Sonnet 4.5 $15.00 $150.00

จะเห็นได้ว่า DeepSeek V3.2 ผ่าน HolySheep AI มีต้นทุนต่ำกว่า Claude ถึง 35 เท่า เหมาะสำหรับการประมวลผลข้อมูลจำนวนมากในกลยุทธ์ Market Making

โครงสร้างพื้นฐานของ Order Book Simulation

import numpy as np
import pandas as pd
from dataclasses import dataclass
from typing import List, Dict, Tuple
from collections import deque
import time

@dataclass
class Order:
    """โครงสร้างข้อมูล Order เดียว"""
    order_id: str
    price: float
    quantity: float
    side: str  # 'bid' หรือ 'ask'
    timestamp: float
    is_maker: bool = True

class OrderBookLevel:
    """Level เดียวใน Order Book"""
    def __init__(self, price: float):
        self.price = price
        self.orders: List[Order] = []
        self.total_quantity: float = 0.0
    
    def add_order(self, order: Order):
        self.orders.append(order)
        self.total_quantity += order.quantity
    
    def remove_order(self, order_id: str) -> bool:
        for i, order in enumerate(self.orders):
            if order.order_id == order_id:
                self.total_quantity -= order.quantity
                self.orders.pop(i)
                return True
        return False
    
    def get_depth(self) -> float:
        return self.total_quantity

class SimulatedOrderBook:
    """
    Order Book ที่สร้างขึ้นสำหรับ Backtesting
    รองรับ Level 1 และ Level 2 data
    """
    def __init__(self, max_levels: int = 50):
        self.bids: Dict[float, OrderBookLevel] = {}  # price -> level
        self.asks: Dict[float, OrderBookLevel] = {}
        self.max_levels = max_levels
        self.spread: float = 0.0
        self.mid_price: float = 0.0
        self.timestamp: float = time.time()
        self.order_counter: int = 0
        
    def _generate_order_id(self) -> str:
        self.order_counter += 1
        return f"ORD_{self.timestamp}_{self.order_counter}"

การสร้าง Order Book Depth Data พร้อม Market Impact

import hashlib
import json

class MarketMakerOrderBookBuilder:
    """
    สร้าง Order Book depth data สำหรับ Market Making
    รวมถึงการจำลอง Order Flow และ Market Impact
    """
    
    def __init__(self, 
                 volatility: float = 0.02,
                 tick_size: float = 0.01,
                 lot_size: float = 0.001,
                 base_spread: float = 0.0005):
        self.volatility = volatility
        self.tick_size = tick_size
        self.lot_size = lot_size
        self.base_spread = base_spread
        self.order_history: deque = deque(maxlen=100000)
        
        # พารามิเตอร์สำหรับ Order Book shape
        self.bid_depth_params = {'alpha': 0.3, 'beta': 2.5}
        self.ask_depth_params = {'alpha': 0.35, 'beta': 2.3}
        
    def generate_order_book_snapshot(
        self, 
        mid_price: float,
        timestamp: float,
        intensity_bid: float = 10.0,
        intensity_ask: float = 10.0
    ) -> Dict:
        """
        สร้าง Order Book snapshot ณ เวลาที่กำหนด
        
        Args:
            mid_price: ราคากลางของ asset
            timestamp: Unix timestamp
            intensity_bid: ความเข้มข้นของ Bid orders
            intensity_ask: ความเข้มข้นของ Ask orders
        
        Returns:
            Dictionary ที่มี bids, asks และ metadata
        """
        bids = []
        asks = []
        
        # สร้าง Bid levels
        for i in range(50):
            price_offset = self._calculate_depth_offset(
                i, self.bid_depth_params, self.base_spread, is_bid=True
            )
            price = round(mid_price * (1 - price_offset), 
                         int(-np.log10(self.tick_size)))
            
            # คำนวณ quantity ด้วย exponential decay
            base_quantity = self._calculate_quantity(
                i, intensity_bid, self.bid_depth_params
            )
            
            # เพิ่ม noise เพื่อความสมจริง
            quantity = base_quantity * (1 + np.random.normal(0, 0.1))
            quantity = max(self.lot_size, round(quantity, 8))
            
            bids.append({
                'price': price,
                'quantity': quantity,
                'order_count': np.random.poisson(5) + 1,
                'is_maker': True
            })
        
        # สร้าง Ask levels
        for i in range(50):
            price_offset = self._calculate_depth_offset(
                i, self.ask_depth_params, self.base_spread, is_bid=False
            )
            price = round(mid_price * (1 + price_offset), 
                         int(-np.log10(self.tick_size)))
            
            base_quantity = self._calculate_quantity(
                i, intensity_ask, self.ask_depth_params
            )
            quantity = base_quantity * (1 + np.random.normal(0, 0.1))
            quantity = max(self.lot_size, round(quantity, 8))
            
            asks.append({
                'price': price,
                'quantity': quantity,
                'order_count': np.random.poisson(5) + 1,
                'is_maker': True
            })
        
        # คำนวณ spread และ mid price
        best_bid = bids[0]['price'] if bids else 0
        best_ask = asks[0]['price'] if asks else 0
        spread = (best_ask - best_bid) / mid_price if mid_price > 0 else 0
        
        snapshot = {
            'timestamp': timestamp,
            'mid_price': mid_price,
            'best_bid': best_bid,
            'best_ask': best_ask,
            'spread_bps': spread * 10000,
            'bids': bids,
            'asks': asks,
            'depth_10_bps': self._calculate_cumulative_depth(bids, asks, 0.001),
            'depth_50_bps': self._calculate_cumulative_depth(bids, asks, 0.005),
            'imbalance': self._calculate_order_imbalance(bids, asks)
        }
        
        return snapshot
    
    def _calculate_depth_offset(
        self, 
        level: int, 
        params: Dict, 
        base_spread: float,
        is_bid: bool
    ) -> float:
        """
        คำนวณ price offset สำหรับ level ที่กำหนด
        ใช้ power law distribution
        """
        alpha = params['alpha']
        beta = params['beta']
        
        if is_bid:
            return base_spread + alpha * (level ** beta) / 1000
        else:
            return base_spread + alpha * (level ** beta) / 1000
    
    def _calculate_quantity(
        self, 
        level: int, 
        intensity: float,
        params: Dict
    ) -> float:
        """
        คำนวณ quantity ที่ level ที่กำหนด
        ใช้ exponential decay พร้อม random variation
        """
        base_qty = intensity * np.exp(-level * 0.15)
        return base_qty * (0.8 + 0.4 * np.random.random())
    
    def _calculate_cumulative_depth(
        self, 
        bids: List, 
        asks: List, 
        depth_pct: float
    ) -> Dict[str, float]:
        """คำนวณ cumulative depth ที่ระยะทาง % จาก mid price"""
        mid = (bids[0]['price'] + asks[0]['price']) / 2 if bids and asks else 0
        
        bid_depth = sum(
            b['quantity'] for b in bids 
            if b['price'] >= mid * (1 - depth_pct)
        )
        ask_depth = sum(
            a['quantity'] for a in asks 
            if a['price'] <= mid * (1 + depth_pct)
        )
        
        return {'bid_depth': bid_depth, 'ask_depth': ask_depth}
    
    def _calculate_order_imbalance(self, bids: List, asks: List) -> float:
        """
        คำนวณ Order Imbalance Ratio
        OIR = (Bid Volume - Ask Volume) / (Bid Volume + Ask Volume)
        """
        bid_vol = sum(b['quantity'] for b in bids[:10])
        ask_vol = sum(a['quantity'] for a in asks[:10])
        
        if bid_vol + ask_vol == 0:
            return 0.0
        
        return (bid_vol - ask_vol) / (bid_vol + ask_vol)

ระบบ Backtest สำหรับ Market Making Strategy

import matplotlib.pyplot as plt
from typing import Optional
import sqlite3

class MarketMakingBacktester:
    """
    ระบบ Backtest สำหรับ Market Making Strategy
    รองรับการใช้งานกับ Order Book data ที่สร้างขึ้น
    """
    
    def __init__(self, 
                 initial_balance: float = 100000.0,
                 maker_fee: float = 0.001,
                 taker_fee: float = 0.002):
        self.initial_balance = initial_balance
        self.balance = initial_balance
        self.positions: List[Dict] = []
        self.trades: List[Dict] = []
        self.pnl_history: List[float] = []
        self.maker_fee = maker_fee
        self.taker_fee = taker_fee
        
        # Strategy parameters
        self.spread_multiplier = 1.5
        self.order_size_pct = 0.01  # 1% ของ balance
        self.rebalance_threshold = 0.1  # 10% position drift
        
    def generate_synthetic_data(
        self, 
        days: int = 30,
        ticks_per_day: int = 86400,
        volatility: float = 0.02
    ) -> pd.DataFrame:
        """
        สร้าง synthetic price data สำหรับ backtesting
        
        Args:
            days: จำนวนวันที่ต้องการ
            ticks_per_day: จำนวน ticks ต่อวัน
            volatility: ความผันผวนรายวัน (annualized)
        
        Returns:
            DataFrame พร้อม price series และ Order Book snapshots
        """
        n_ticks = days * ticks_per_day
        dt = 1 / ticks_per_day
        
        # Geometric Brownian Motion
        drift = 0
        sigma = volatility * np.sqrt(dt)
        
        prices = [100.0]  # Starting price
        for _ in range(n_ticks - 1):
            dW = np.random.normal(0, 1)
            dS = prices[-1] * (drift * dt + sigma * dW)
            new_price = prices[-1] + dS
            prices.append(max(0.01, new_price))
        
        timestamps = np.linspace(0, days * 86400, n_ticks)
        
        # สร้าง Order Book สำหรับแต่ละ tick
        builder = MarketMakerOrderBookBuilder(volatility=volatility)
        
        data = []
        for i, (ts, price) in enumerate(zip(timestamps, prices)):
            if i % 100 == 0:  # Sample every 100 ticks
                snapshot = builder.generate_order_book_snapshot(
                    mid_price=price,
                    timestamp=ts,
                    intensity_bid=10.0 + 5.0 * np.sin(ts / 86400),
                    intensity_ask=10.0 + 5.0 * np.cos(ts / 86400)
                )
                data.append({
                    'timestamp': ts,
                    'price': price,
                    'order_book': snapshot,
                    'spread': snapshot['spread_bps'],
                    'imbalance': snapshot['imbalance']
                })
        
        return pd.DataFrame(data)
    
    def run_backtest(self, price_data: pd.DataFrame) -> Dict:
        """
        Run backtest กับ price data
        
        Returns:
            Dictionary พร้อม metrics และ trade history
        """
        self.balance = self.initial_balance
        self.positions = []
        self.trades = []
        self.pnl_history = []
        
        for idx, row in price_data.iterrows():
            current_price = row['price']
            ob = row['order_book']
            
            # คำนวณ optimal spread
            optimal_spread = self._calculate_optimal_spread(
                current_price, 
                ob['imbalance'],
                row['spread']
            )
            
            # Place maker orders
            bid_price = current_price * (1 - optimal_spread / 2)
            ask_price = current_price * (1 + optimal_spread / 2)
            
            order_size = self.balance * self.order_size_pct / current_price
            
            # Simulate fill
            bid_fill_prob = self._calculate_fill_probability(
                bid_price, current_price, ob, 'bid'
            )
            ask_fill_prob = self._calculate_fill_probability(
                ask_price, current_price, ob, 'ask'
            )
            
            # Execute trades
            if np.random.random() < bid_fill_prob:
                self._execute_buy(bid_price, order_size, is_maker=True)
            
            if np.random.random() < ask_fill_prob:
                self._execute_sell(ask_price, order_size, is_maker=True)
            
            # Calculate PnL
            unrealized_pnl = self._calculate_unrealized_pnl(current_price)
            total_pnl = self.balance + unrealized_pnl - self.initial_balance
            self.pnl_history.append(total_pnl)
            
            # Rebalance if needed
            self._check_rebalance(current_price, ob)
        
        return self._generate_performance_report()
    
    def _calculate_optimal_spread(
        self, 
        price: float, 
        imbalance: float,
        market_spread: float
    ) -> float:
        """คำนวณ optimal spread ตาม Avellaneda-Stoikov model"""
        gamma = 0.1  # Risk aversion
        T = 1.0  # Time to end of day
        
        # Inventory penalty
        inventory_penalty = gamma * imbalance * price * 0.01
        
        # Spread adjustment based on imbalance
        spread_adj = abs(imbalance) * 0.0001
        
        optimal = (market_spread / 10000 + inventory_penalty + spread_adj) * \
                  self.spread_multiplier
        
        return max(optimal, market_spread / 10000)
    
    def _calculate_fill_probability(
        self,
        order_price: float,
        market_price: float,
        order_book: Dict,
        side: str
    ) -> float:
        """คำนวณ probability ของ order fill"""
        levels = order_book['bids'] if side == 'bid' else order_book['asks']
        
        for i, level in enumerate(levels[:5]):
            if (side == 'bid' and level['price'] <= order_price) or \
               (side == 'ask' and level['price'] >= order_price):
                return max(0.01, 0.9 - i * 0.15)
        
        return 0.05  # Low probability for far orders
    
    def _execute_buy(self, price: float, quantity: float, is_maker: bool):
        """Execute buy order"""
        fee = self.maker_fee if is_maker else self.taker_fee
        cost = price * quantity * (1 + fee)
        
        if cost <= self.balance:
            self.balance -= cost
            self.positions.append({
                'side': 'long',
                'entry_price': price,
                'quantity': quantity,
                'fee': price * quantity * fee
            })
            self.trades.append({
                'type': 'buy',
                'price': price,
                'quantity': quantity,
                'fee': price * quantity * fee,
                'is_maker': is_maker
            })
    
    def _execute_sell(self, price: float, quantity: float, is_maker: bool):
        """Execute sell order"""
        fee = self.maker_fee if is_maker else self.taker_fee
        
        # Find matching long position
        for i, pos in enumerate(self.positions):
            if pos['side'] == 'long':
                sell_qty = min(quantity, pos['quantity'])
                proceeds = price * sell_qty * (1 - fee)
                self.balance += proceeds
                pos['quantity'] -= sell_qty
                
                self.trades.append({
                    'type': 'sell',
                    'price': price,
                    'quantity': sell_qty,
                    'fee': price * sell_qty * fee,
                    'is_maker': is_maker
                })
                
                if pos['quantity'] <= 0:
                    self.positions.pop(i)
                break
    
    def _calculate_unrealized_pnl(self, current_price: float) -> float:
        """คำนวณ unrealized PnL"""
        return sum(
            (current_price - pos['entry_price']) * pos['quantity']
            for pos in self.positions if pos['side'] == 'long'
        )
    
    def _check_rebalance(self, price: float, order_book: Dict):
        """Check และ execute rebalance หากจำเป็น"""
        if not self.positions:
            return
        
        total_position = sum(pos['quantity'] for pos in self.positions)
        position_value = total_position * price
        position_pct = position_value / self.initial_balance
        
        # If position exceeds threshold, reduce
        if abs(position_pct) > self.rebalance_threshold:
            target_qty = self.rebalance_threshold * self.initial_balance / price
            if total_position > target_qty:
                sell_qty = total_position - target_qty
                # Execute at mid price
                self._execute_sell(price, sell_qty, is_maker=True)
    
    def _generate_performance_report(self) -> Dict:
        """สร้าง performance report"""
        trades_df = pd.DataFrame(self.trades)
        
        if len(trades_df) == 0:
            return {'error': 'No trades executed'}
        
        maker_trades = trades_df[trades_df['is_maker'] == True]
        taker_trades = trades_df[trades_df['is_maker'] == False]
        
        total_pnl = self.pnl_history[-1] if self.pnl_history else 0
        roi = (total_pnl / self.initial_balance) * 100
        
        # Calculate Sharpe Ratio
        returns = pd.Series(self.pnl_history).pct_change().dropna()
        sharpe = returns.mean() / returns.std() * np.sqrt(252 * 86400) if returns.std() > 0 else 0
        
        # Calculate Max Drawdown
        cumulative = pd.Series(self.pnl_history)
        running_max = cumulative.expanding().max()
        drawdown = (cumulative - running_max) / running_max
        max_drawdown = drawdown.min() * 100
        
        return {
            'total_pnl': total_pnl,
            'roi_pct': roi,
            'sharpe_ratio': sharpe,
            'max_drawdown_pct': max_drawdown,
            'total_trades': len(trades_df),
            'maker_trades': len(maker_trades),
            'taker_trades': len(taker_trades),
            'maker_ratio': len(maker_trades) / len(trades_df) * 100,
            'final_balance': self.balance,
            'pnl_history': self.pnl_history,
            'trades': trades_df
        }

ตัวอย่างการใช้งาน

if __name__ == "__main__": # สร้าง synthetic data backtester = MarketMakingBacktester(initial_balance=100000) data = backtester.generate_synthetic_data(days=30, volatility=0.02) # Run backtest results = backtester.run_backtest(data) print(f"Total PnL: ${results['total_pnl']:.2f}") print(f"ROI: {results['roi_pct']:.2f}%") print(f"Sharpe Ratio: {results['sharpe_ratio']:.2f}") print(f"Max Drawdown: {results['max_drawdown_pct']:.2f}%") print(f"Maker Ratio: {results['maker_ratio']:.1f}%")

การใช้ AI API สำหรับ Strategy Optimization

เมื่อมีผลลัพธ์จาก backtest แล้ว เราสามารถใช้ AI API เพื่อวิเคราะห์และ optimize กลยุทธ์ได้ ด้วยต้นทุนที่เหมาะสม:

import requests
import json

class StrategyOptimizer:
    """
    ใช้ AI API สำหรับวิเคราะห์และ optimize Market Making strategy
    รองรับ HolySheep AI พร้อม cost optimization
    """
    
    def __init__(self, api_key: str = "YOUR_HOLYSHEEP_API_KEY"):
        self.api_key = api_key
        self.base_url = "https://api.holysheep.ai/v1"
        self.model_costs = {
            'deepseek-v3': 0.42,      # $ per million tokens
            'gpt-4.1': 8.0,
            'claude-sonnet-4.5': 15.0,
            'gemini-2.5-flash': 2.50
        }
    
    def analyze_strategy_results(self, backtest_results: Dict, market_data: Dict) -> Dict:
        """
        ใช้ AI วิเคราะห์ผลลัพธ์ backtest และให้คำแนะนำ
        
        Args:
            backtest_results: ผลลัพธ์จาก MarketMakingBacktester
            market_data: ข้อมูลตลาดที่เกี่ยวข้อง
        
        Returns:
            Optimization recommendations
        """
        prompt = f"""
        วิเคราะห์ผลลัพธ์ Market Making Strategy Backtest:
        
        Performance Metrics:
        - Total PnL: ${backtest_results.get('total_pnl', 0):.2f}
        - ROI: {backtest_results.get('roi_pct', 0):.2f}%
        - Sharpe Ratio: {backtest_results.get('sharpe_ratio', 0):.2f}
        - Max Drawdown: {backtest_results.get('max_drawdown_pct', 0):.2f}%
        - Maker Ratio: {backtest_results.get('maker_ratio', 0):.1f}%
        - Total Trades: {backtest_results.get('total_trades', 0)}
        
        Market Data:
        - Volatility: {market_data.get('volatility', 'N/A')}
        - Average Spread: {market_data.get('avg_spread', 'N/A')} bps
        
        วิเคราะห์และให้คำแนะนำ:
        1. จุดแข็งและจุดอ่อนของกลยุทธ์
        2. พารามิเตอร์ที่ควรปรับ
        3. ความเสี่ยงที่ต้องจัดการ
        4. กลยุทธ์เสริมที่แนะนำ
        """
        
        # ใช้ DeepSeek V3.2 สำหรับ analysis (cost-effective)
        response = self._call_ai_model(
            model='deepseek-v3',
            prompt=prompt,
            max_tokens=2000
        )
        
        return {
            'analysis': response,
            'model_used': 'deepseek-v3',
            'estimated_cost': self._estimate_cost('deepseek-v3', len(prompt) / 4, 2000)
        }
    
    def optimize_parameters(
        self, 
        base_results: Dict,
        param_ranges: Dict
    ) -> Dict:
        """
        Optimize strategy parameters โดยใช้ AI
        
        Args:
            base_results: ผลลัพธ์เริ่มต้น
            param_ranges: ช่วงของพารามิเตอร์ที่จะ optimize
        """
        prompt = f"""
        Optimize these Market Making parameters:
        
        Current Best Results:
        - Sharpe: {base_results.get('sharpe_ratio', 0):.3f}
        - Max DD: {base_results.get('max_drawdown_pct', 0):.2f}%
        - ROI: {base_results.get('roi_pct', 0):.2f}%
        
        Parameter Ranges:
        {json.dumps(param_ranges, indent=2)}
        
        คำนวณ optimal parameters ที่ maximize Sharpe ratio
        โดยคำนึงถึง risk management
        
        ส่งคืนเป็น JSON format พร้อม optimized values
        """
        
        response = self._call_ai_model(
            model='deepseek-v3',
            prompt=prompt,
            max_tokens=1500
        )
        
        return self._parse_optimization_response(response)
    
    def generate_strategy_report(self, results: Dict) -> str:
        """
        สร้างรายงานกลยุทธ์แบบครบถ้วน
        """
        prompt = f"""
        สร้างรายงาน Strategy Report สำหรับ Market Making:
        
        {json.dumps(results, indent=2, default=str)}
        
        รายงานต้องประกอบด้วย:
        1. Executive Summary
        2. Key Performance Indicators
        3. Risk Analysis
        4. Recommendations
        5. Next Steps
        """
        
        # ใช้ Gemini Flash สำหรับ report generation (เร็วและถูก)
        response = self._call_ai_model(
            model='gemini-2.5-flash',
            prompt=prompt,
            max_tokens=3000
        )
        
        return response
    
    def _call_ai_model(
        self, 
        model: str, 
        prompt: str,
        max_tokens: int = 1000
    ) -> str:
        """
        เรียก AI model �