การทำ Backtesting ด้วย Backtrader ในรูปแบบ Multi-Timeframe เป็นเทคนิคขั้นสูงที่ช่วยให้นักเทรดสามารถวิเคราะห์กลยุทธ์ได้อย่างมีประสิทธิภาพมากขึ้น ในบทความนี้เราจะมาเรียนรู้วิธีการเขียนโค้ด Python สำหรับการทำ Multi-Timeframe Strategy Backtesting ตั้งแต่พื้นฐานจนถึงขั้นสูง พร้อมทั้งแนะนำวิธีการประหยัดค่าใช้จ่ายด้วย HolySheep AI ที่มีราคาประหยัดกว่า 85%

ทำไมต้องใช้ Multi-Timeframe Strategy

การใช้หลาย Timeframe ในการวิเคราะห์ช่วยให้เราสามารถ:

ราคา AI APIs 2026: เปรียบเทียบค่าใช้จ่ายสำหรับ 10M Tokens/เดือน

โมเดล ราคา/MTok ค่าใช้จ่าย 10M Tokens Latency
DeepSeek V3.2 $0.42 $4,200 <50ms
Gemini 2.5 Flash $2.50 $25,000 <100ms
GPT-4.1 $8.00 $80,000 <200ms
Claude Sonnet 4.5 $15.00 $150,000 <250ms

หมายเหตุ: ค่าใช้จ่ายคำนวณจาก Input + Output tokens รวมกัน ณ ราคาปี 2026

การติดตั้ง Backtrader และเตรียม Environment

# ติดตั้ง Package ที่จำเป็น
pip install backtrader pandas numpy yfinance

สร้างไฟล์ requirements.txt

backtrader==1.9.78.123

pandas==2.0.3

numpy==1.24.3

yfinance==0.2.28

โครงสร้างพื้นฐาน Multi-Timeframe Strategy

import backtrader as bt
import yfinance as yf
from datetime import datetime

class MultiTimeFrameStrategy(bt.Strategy):
    """
    Multi-Timeframe Strategy โดยใช้ SMA Crossover
    - Timeframe ใหญ่: Daily  -> กำหนด Trend
    - Timeframe เล็ก: 1 Hour  -> หาจุดเข้า-ออก
    """
    
    params = (
        ('sma_short', 10),      # SMA ระยะสั้น
        ('sma_long', 50),       # SMA ระยะยาว
        ('atr_period', 14),     # ATR สำหรับ Stop Loss
        ('atr_multiplier', 2.0), # Stop Loss Distance
    )
    
    def __init__(self):
        # Data Feeds จากหลาย Timeframe
        # self.daily  = self.datas[0]  # Daily TF (Trend)
        # self.hourly = self.datas[1]  # Hourly TF (Entry)
        
        # Indicators สำหรับ Daily (Trend Direction)
        self.sma_daily_short = bt.indicators.SMA(
            self.datas[0].close, period=self.params.sma_short
        )
        self.sma_daily_long = bt.indicators.SMA(
            self.datas[0].close, period=self.params.sma_long
        )
        
        # Indicators สำหรับ Hourly (Entry Signals)
        self.sma_hourly_short = bt.indicators.SMA(
            self.datas[1].close, period=self.params.sma_short
        )
        self.sma_hourly_long = bt.indicators.SMA(
            self.datas[1].close, period=self.params.sma_long
        )
        
        # ATR สำหรับ Position Sizing
        self.atr = bt.indicators.ATR(self.datas[1], period=self.params.atr_period)
        
        # Crossover Signals
        self.crossover_up = bt.indicators.CrossOver(
            self.sma_hourly_short, self.sma_hourly_long
        )
        self.crossover_down = bt.indicators.CrossOver(
            self.sma_hourly_short, self.sma_hourly_long
        )
        
    def next(self):
        # ตรวจสอบ Trend จาก Daily
        trend_bullish = self.sma_daily_short[0] > self.sma_daily_long[0]
        trend_bearish = self.sma_daily_short[0] < self.sma_daily_long[0]
        
        # เงื่อนไข Long: Uptrend + Golden Cross
        if not self.position:
            if trend_bullish and self.crossover_up > 0:
                stop_price = self.datas[1].close[0] - (self.atr[0] * self.params.atr_multiplier)
                self.buy_bracket(
                    limitprice=self.datas[1].close[0] * 1.05,
                    stopprice=stop_price
                )
        
        # เงื่อนไข Short: Downtrend + Death Cross
        elif not self.position:
            if trend_bearish and self.crossover_down < 0:
                stop_price = self.datas[1].close[0] + (self.atr[0] * self.params.atr_multiplier)
                self.sell_bracket(
                    limitprice=self.datas[1].close[0] * 0.95,
                    stopprice=stop_price
                )

การดึงข้อมูลและ Setup Cerebro

import backtrader as bt
import yfinance as yf
from datetime import datetime, timedelta

def fetch_multi_timeframe_data(ticker, start_date, end_date):
    """
    ดึงข้อมูลราคาหลาย Timeframe จาก Yahoo Finance
    """
    # ข้อมูล Daily (ใช้เป็น Trend)
    daily_data = yf.download(ticker, start=start_date, end=end_date, interval='1d')
    
    # ข้อมูล Hourly (ใช้เป็น Entry)
    hourly_data = yf.download(ticker, start=start_date, end=end_date, interval='1h')
    
    return daily_data, hourly_data

def run_backtest():
    # สร้าง Cerebro Engine
    cerebro = bt.Cerebro(optreturn=False)
    
    # กำหนดข้อมูล
    ticker = 'AAPL'
    end_date = datetime.now()
    start_date = end_date - timedelta(days=365)  # 1 ปี
    
    # ดึงข้อมูล
    daily_df, hourly_df = fetch_multi_timeframe_data(ticker, start_date, end_date)
    
    # สร้าง Data Feed
    data_daily = bt.feeds.PandasData(dataname=daily_df)
    data_hourly = bt.feeds.PandasData(dataname=hourly_df)
    
    # เพิ่ม Data Feeds - ต้องเรียงลำดับจาก TF ใหญ่ไปเล็ก
    cerebro.adddata(data_daily, name='daily')
    cerebro.adddata(data_hourly, name='hourly')
    
    # กำหนด Strategy
    cerebro.addstrategy(MultiTimeFrameStrategy)
    
    # กำหนด Broker
    cerebro.broker.setcash(100000.0)  # $100,000
    cerebro.broker.setcommission(commission=0.001)  # 0.1% commission
    
    # เพิ่ม Position Sizing
    cerebro.addsizer(bt.sizers.PercentSizer, percents=10)  # 10% ต่อออร์เดอร์
    
    # กำหนด Analyzer
    cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe')
    cerebro.addanalyzer(bt.analyzers.DrawDown, _name='drawdown')
    cerebro.addanalyzer(bt.analyzers.Returns, _name='returns')
    
    print(f'เงินเริ่มต้น: ${cerebro.broker.getvalue():,.2f}')
    
    # Run Backtest
    results = cerebro.run()
    
    print(f'เงินสุดท้าย: ${cerebro.broker.getvalue():,.2f}')
    print(f'ผลตอบแทน: {((cerebro.broker.getvalue() / 100000.0) - 1) * 100:.2f}%')
    
    return results

if __name__ == '__main__':
    results = run_backtest()

การใช้งานร่วมกับ AI APIs สำหรับวิเคราะห์สัญญาณ

นอกจากการใช้ Technical Indicators แล้ว เรายังสามารถใช้ AI ช่วยวิเคราะห์สัญญาณเพิ่มเติมได้ ด้วย HolySheep AI ที่มีราคาประหยัดมากและรองรับโมเดลหลากหลาย:

import requests
import json
from typing import Dict, List, Optional

class AISignalAnalyzer:
    """
    ใช้ AI API สำหรับวิเคราะห์สัญญาณการเทรด
    รองรับหลาย Provider ผ่าน HolySheep AI
    """
    
    BASE_URL = "https://api.holysheep.ai/v1"
    
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.model = "deepseek-v3.2"  # โมเดลที่ประหยัดที่สุด
        
    def analyze_trade_signal(
        self,
        symbol: str,
        price_data: Dict,
        indicators: Dict
    ) -> Optional[Dict]:
        """
        วิเคราะห์สัญญาณการเทรดด้วย AI
        """
        prompt = f"""
        วิเคราะห์สัญญาณการเทรดสำหรับ {symbol}:
        
        ราคาปัจจุบัน: ${price_data.get('close', 0):.2f}
        RSI (14): {indicators.get('rsi', 0):.2f}
        MACD: {indicators.get('macd', 0):.4f}
        MACD Signal: {indicators.get('macd_signal', 0):.4f}
        Volume: {indicators.get('volume', 0):,.0f}
        
        ให้คะแนนความมั่นใจ (0-100) และแนะนำ:
        - BUY / SELL / HOLD
        - ราคาเป้าหมาย
        - Stop Loss
        """
        
        payload = {
            "model": self.model,
            "messages": [
                {"role": "system", "content": "คุณเป็นผู้เชี่ยวชาญด้านการวิเคราะห์ทางเทคนิค"},
                {"role": "user", "content": prompt}
            ],
            "temperature": 0.3,
            "max_tokens": 500
        }
        
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        try:
            response = requests.post(
                f"{self.BASE_URL}/chat/completions",
                headers=headers,
                json=payload,
                timeout=30
            )
            response.raise_for_status()
            
            result = response.json()
            return {
                'signal': result['choices'][0]['message']['content'],
                'model': self.model,
                'usage': result.get('usage', {})
            }
        except requests.exceptions.RequestException as e:
            print(f"API Error: {e}")
            return None
    
    def batch_analyze(self, signals: List[Dict]) -> List[Dict]:
        """
        วิเคราะห์หลายสัญญาณพร้อมกัน
        """
        results = []
        for signal in signals:
            result = self.analyze_trade_signal(
                symbol=signal['symbol'],
                price_data=signal['price'],
                indicators=signal['indicators']
            )
            if result:
                results.append({**signal, 'analysis': result})
        return results

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

if __name__ == '__main__': api_key = "YOUR_HOLYSHEEP_API_KEY" analyzer = AISignalAnalyzer(api_key) sample_signal = { 'symbol': 'BTC-USD', 'price': {'close': 67500.00}, 'indicators': { 'rsi': 68.5, 'macd': 450.25, 'macd_signal': 380.10, 'volume': 25000000000 } } result = analyzer.analyze_trade_signal( symbol=sample_signal['symbol'], price_data=sample_signal['price'], indicators=sample_signal['indicators'] ) if result: print(f"สัญญาณ: {result['signal']}") print(f"โมเดล: {result['model']}")

ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข

1. ปัญหา: "Data feed has no bars" หรือ Timeframe ไม่ตรงกัน

สาเหตุ: ข้อมูลจาก Yahoo Finance มี Timeframe ที่ไม่ตรงกัน หรือข้อมูลว่างเปล่าในบางช่วง

# วิธีแก้ไข: ตรวจสอบและ Resample ข้อมูลให้ตรงกัน

import backtrader as bt

class ResampledData(bt.feeds.PandasData):
    """Data Feed ที่รองรับการ Resample"""
    params = (
        ('datetime', None),
        ('open', 0),
        ('high', 1),
        ('low', 2),
        ('close', 3),
        ('volume', 4),
        ('openinterest', -1),
    )

def prepare_data_with_resample(ticker, start, end):
    """เตรียมข้อมูลโดย Resample Hourly เป็น Daily"""
    # ดึงข้อมูล Hourly
    hourly_df = yf.download(ticker, start=start, end=end, interval='1h')
    
    # Resample เป็น Daily (OHLCV)
    daily_df = hourly_df.resample('D').agg({
        'Open': 'first',
        'High': 'max',
        'Low': 'min',
        'Close': 'last',
        'Volume': 'sum'
    })
    
    # Drop NA values
    daily_df = daily_df.dropna()
    
    # ตรวจสอบข้อมูล
    print(f"Daily data shape: {daily_df.shape}")
    print(f"Hourly data shape: {hourly_df.shape}")
    
    return daily_df, hourly_df

ใช้ Cerebro พร้อม Replay

cerebro = bt.Cerebro(optreturn=False)

เพิ่ม Data Feed แบบ Replay

data_hourly = bt.feeds.PandasData(dataname=hourly_df) data_replayed = bt.data.TimeScaleData( dataname=data_hourly, timeframe=bt.TimeFrame.Minutes, compression=60 # 60 นาที = 1 ชั่วโมง )

2. ปัญหา: สัญญาณซ้ำซ้อนหรือไม่ตรงกันระหว่าง Timeframe

สาเหตุ: ใช้ close[0] ซึ่งเป็น Current Bar ที่ยังไม่เสถียร ในขณะที่ Indicators อาจมาจาก Closed Bar

# วิธีแก้ไข: ใช้ตัวแปร Index ที่ถูกต้อง

class FixedMultiTimeFrameStrategy(bt.Strategy):
    def __init__(self):
        # กำหนด Alias สำหรับ Data Feeds
        self.data_daily = self.datas[0]
        self.data_hourly = self.datas[1]
        
        # Indicators ใช้ -1 สำหรับ Closed Bar
        self.sma_daily = bt.indicators.SMA(self.data_daily.close, period=20)
        
        # ตัวแปรสำหรับเก็บสัญญาณ
        self.last_signal = None
        self.bar_count = 0
        
    def next(self):
        # ใช้ -1 สำหรับ Closed Bar (ปลอดภัยกว่า)
        daily_close = self.data_daily.close[-1]
        hourly_close = self.data_hourly.close[-1]
        
        # SMA จาก Closed Bar
        sma_d = self.sma_daily[-1]
        
        # ถ้าใช้ Current Bar ให้ระวังเรื่อง Repainting
        # ใช้เฉพาะเมื่อแน่ใจว่าต้องการ Near-Realtime
        
        # ตรวจสอบ Trend เฉพาะเมื่อมี Bar เพียงพอ
        self.bar_count += 1
        if self.bar_count < 50:  # Warm-up period
            return
        
        trend = 'bullish' if daily_close > sma_d else 'bearish'
        
        # Entry Logic
        if self.last_signal != 'long' and trend == 'bullish':
            self.last_signal = 'long'
            self.buy()
        elif self.last_signal != 'short' and trend == 'bearish':
            self.last_signal = 'short'
            self.sell()

3. ปัญหา: Memory Error เมื่อใช้ข้อมูลขนาดใหญ่

สาเหตุ: ข้อมูลหลาย Timeframe ทำให้ Memory เพิ่มขึ้นมาก

# วิธีแก้ไข: ใช้ Data Feeds แบบ Efficient และ Limit ข้อมูล

class EfficientDataFeed(bt.feeds.PandasData):
    """Data Feed ที่ประหยัด Memory"""
    params = (
        ('datetime', 0),
        ('open', 1),
        ('high', 2),
        ('low', 3),
        ('close', 4),
        ('volume', 5),
        ('openinterest', -1),
    )

def run_efficient_backtest():
    """Backtest แบบประหยัด Memory"""
    cerebro = bt.Cerebro(optreturn=False)
    
    # ดึงข้อมูลเฉพาะที่จำเป็น
    ticker = 'SPY'
    start = '2023-01-01'
    end = '2024-12-31'
    
    # ใช้ columns เฉพาะที่ต้องการ
    df = yf.download(ticker, start=start, end=end, interval='1d')
    df = df[['Open', 'High', 'Low', 'Close', 'Volume']]  # ลด Memory
    
    # Limit จำนวน Rows
    max_bars = 500  # หรือใช้ timeframe ใหญ่ขึ้น
    df = df.tail(max_bars)
    
    data = EfficientDataFeed(dataname=df)
    cerebro.adddata(data)
    
    # ใช้ preload=False เพื่อประหยัด Memory
    cerebro.addstrategy(MyStrategy, preload=False)
    
    # ลด default ใน Cerebro
    cerebro._dopreload = False
    
    results = cerebro.run()
    return results

เพิ่ม Memory Cleanup

import gc def cleanup(): """ทำความสะอาด Memory หลังใช้งาน""" gc.collect() print("Memory cleaned")

เหมาะกับใคร / ไม่เหมาะกับใคร

เหมาะกับ ไม่เหมาะกับ
นักเทรดที่มีประสบการณ์ Python ขั้นพื้นฐาน ผู้เริ่มต้นที่ไม่เคยเขียนโค้ดมาก่อน
Quantitative Traders ที่ต้องการทำ Backtesting อย่างเป็นระบบ นักเทรดที่ใช้อารมณ์และ intuition เป็นหลัก
นักพัฒนา AI/ML ที่ต้องการรวม Technical Analysis ผู้ที่ต้องการผลลัพธ์ทันทีโดยไม่ทำความเข้าใจ
Portfolio Managers ที่ต้องการทดสอบหลายกลยุทธ์ นักเทรดรายวันที่ต้องการ Trade ทันที

ราคาและ ROI

สำหรับการใช้งาน AI ในการวิเคราะห์สัญญาณ คุณสามารถประหยัดได้มากด้วย HolySheep AI:

Provider ราคา/MTok ค่าใช้จ่าย 100K tokens/วัน ค่าใช้จ่าย 3M tokens/เดือน ประหยัด vs OpenAI
HolySheep DeepSeek V3.2 $0.42 $42 $1,260 ประหยัด 95%
HolySheep Gemini 2.5 Flash $2.50 $250 $7,500 ประหยัด 69%
OpenAI GPT-4.1 $8.00 $800 $24,000 -
Anthropic Claude Sonnet 4.5 $15.00 $1,500 $45,000 แพงกว่า 88%

ทำไมต้องเลือก HolySheep

สรุปและแนวทางถัดไป

การทำ Multi-Timeframe Strategy Backtesting ด้วย Backtrader เป็นเครื่องมือทรงพลังสำหรับนักเทรดและนัก