Nếu bạn đang tìm kiếm cách lấy dữ liệu lịch sử từ Binance và xây dựng hệ thống backtesting cho chiến lược trading, bài viết này sẽ hướng dẫn bạn từ A đến Z. Trước khi bắt đầu, hãy cùng tôi so sánh chi phí khi sử dụng AI để phân tích dữ liệu và xây dựng chiến lược:

So Sánh Chi Phí AI Models Cho Phân Tích Dữ Liệu 2026

Model Giá/MTok 10M Tokens/tháng Tỷ lệ tiết kiệm
DeepSeek V3.2 (HolySheep) $0.42 $4.20 Tiết kiệm 85%+
Gemini 2.5 Flash (HolySheep) $2.50 $25.00 Tiết kiệm 70%+
GPT-4.1 (HolySheep) $8.00 $80.00 Chính hãng
Claude Sonnet 4.5 (HolySheep) $15.00 $150.00 Chính hãng
DeepSeek V3 (OpenAI) $2.80 $28.00

Như bạn thấy, HolySheep AI cung cấp giá cực kỳ cạnh tranh với tỷ giá ¥1=$1 và thanh toán qua WeChat/Alipay. Đặc biệt, DeepSeek V3.2 chỉ $0.42/MTok — rẻ hơn 85% so với các nhà cung cấp khác. Độ trễ dưới 50ms đảm bảo trải nghiệm mượt mà khi xây dựng hệ thống backtesting của bạn.

Binance K线数据 là gì và Tại sao quan trọng

K线 (Candlestick) là biểu đồ nến thể hiện biến động giá theo thời gian. Mỗi cây nến chứa 4 thông tin quan trọng: Open (giá mở cửa), High (giá cao nhất), Low (giá thấp nhất), Close (giá đóng cửa). Đây là nền tảng của phân tích kỹ thuật và xây dựng chiến lược trading tự động.

Cài đặt môi trường và thư viện

pip install python-binance pandas numpy matplotlib backtrader requests

Trước khi bắt đầu, bạn cần Python 3.8+ và API key từ Binance. Nếu chưa có, hãy đăng ký tại binance.com và tạo API key trong phần Account > API Management.

Lấy Dữ Liệu K线 từ Binance bằng Python

import requests
import pandas as pd
from datetime import datetime, timedelta
import time

class BinanceKlineFetcher:
    """
    Lớp lấy dữ liệu K-line từ Binance API
    Author: HolySheep AI - https://www.holysheep.ai
    """
    
    BASE_URL = "https://api.binance.com/api/v3"
    
    def __init__(self, api_key=None, secret_key=None):
        self.api_key = api_key
        self.secret_key = secret_key
    
    def get_klines(self, symbol, interval, start_str, end_str=None, limit=1000):
        """
        Lấy dữ liệu K-line
        
        Args:
            symbol: Cặp tiền (VD: 'BTCUSDT')
            interval: Khung thời gian ('1m', '5m', '1h', '1d', '1w')
            start_str: Thời gian bắt đầu (timestamp hoặc ISO string)
            end_str: Thời gian kết thúc (tùy chọn)
            limit: Số lượng nến tối đa (1-1000)
        
        Returns:
            DataFrame với dữ liệu K-line
        """
        params = {
            'symbol': symbol.upper(),
            'interval': interval,
            'startTime': self._parse_time(start_str),
            'limit': limit
        }
        
        if end_str:
            params['endTime'] = self._parse_time(end_str)
        
        url = f"{self.BASE_URL}/klines"
        response = requests.get(url, params=params)
        response.raise_for_status()
        
        data = response.json()
        return self._process_klines(data)
    
    def _parse_time(self, time_str):
        """Chuyển đổi thời gian sang timestamp milliseconds"""
        if isinstance(time_str, int):
            return time_str
        elif isinstance(time_str, str):
            dt = datetime.fromisoformat(time_str.replace('Z', '+00:00'))
            return int(dt.timestamp() * 1000)
        elif isinstance(time_str, datetime):
            return int(time_str.timestamp() * 1000)
        return time_str
    
    def _process_klines(self, data):
        """Xử lý dữ liệu K-line thành DataFrame"""
        columns = ['Open time', 'Open', 'High', 'Low', 'Close', 'Volume', 
                   'Close time', 'Quote asset volume', 'Number of trades',
                   'Taker buy base', 'Taker buy quote', 'Ignore']
        
        df = pd.DataFrame(data, columns=columns)
        
        # Chuyển đổi kiểu dữ liệu
        numeric_cols = ['Open', 'High', 'Low', 'Close', 'Volume']
        for col in numeric_cols:
            df[col] = pd.to_numeric(df[col], errors='coerce')
        
        df['Open time'] = pd.to_datetime(df['Open time'], unit='ms')
        df['Close time'] = pd.to_datetime(df['Close time'], unit='ms')
        
        return df

Sử dụng

fetcher = BinanceKlineFetcher()

Lấy dữ liệu BTCUSDT khung 1 giờ trong 30 ngày gần đây

end_time = datetime.now() start_time = end_time - timedelta(days=30) df = fetcher.get_klines( symbol='BTCUSDT', interval='1h', start_str=start_time.isoformat(), end_str=end_time.isoformat() ) print(f"Đã lấy {len(df)} nến từ {df['Open time'].min()} đến {df['Open time'].max()}") print(df.head())

Tải Dữ Liệu Lớn (Nhiều Tháng) Với Chunking

import pandas as pd
from datetime import datetime, timedelta

class BinanceHistoricalData:
    """
    Lớp tải dữ liệu lịch sử dài hạn từ Binance
    Sử dụng chunking để tránh giới hạn API
    """
    
    BASE_URL = "https://api.binance.com/api/v3"
    CHUNK_DAYS = 30  # Mỗi lần lấy 30 ngày
    
    def get_historical_klines(self, symbol, interval, start_date, end_date):
        """
        Tải dữ liệu K-line trong khoảng thời gian dài
        
        Args:
            symbol: Cặp tiền
            interval: Khung thời gian
            start_date: Ngày bắt đầu
            end_date: Ngày kết thúc
        
        Returns:
            DataFrame với toàn bộ dữ liệu
        """
        all_klines = []
        current_start = pd.to_datetime(start_date)
        end = pd.to_datetime(end_date)
        
        while current_start < end:
            chunk_end = min(current_start + timedelta(days=self.CHUNK_DAYS), end)
            
            print(f"Đang tải: {current_start.date()} -> {chunk_end.date()}")
            
            try:
                import requests
                params = {
                    'symbol': symbol.upper(),
                    'interval': interval,
                    'startTime': int(pd.Timestamp(current_start).timestamp() * 1000),
                    'endTime': int(pd.Timestamp(chunk_end).timestamp() * 1000),
                    'limit': 1000
                }
                
                response = requests.get(f"{self.BASE_URL}/klines", params=params)
                data = response.json()
                
                if data:
                    all_klines.extend(data)
                
                # Delay để tránh rate limit
                import time
                time.sleep(0.5)
                
                current_start = chunk_end
                
            except Exception as e:
                print(f"Lỗi khi tải chunk: {e}")
                import time
                time.sleep(2)
        
        # Chuyển đổi thành DataFrame
        columns = ['Open time', 'Open', 'High', 'Low', 'Close', 'Volume',
                   'Close time', 'Quote volume', 'Trades', 'Taker buy base',
                   'Taker buy quote', 'Ignore']
        
        df = pd.DataFrame(all_klines, columns=columns)
        
        # Xử lý dữ liệu
        numeric_cols = ['Open', 'High', 'Low', 'Close', 'Volume', 'Quote volume']
        for col in numeric_cols:
            df[col] = pd.to_numeric(df[col], errors='coerce')
        
        df['Open time'] = pd.to_datetime(df['Open time'], unit='ms')
        df['Close time'] = pd.to_datetime(df['Close time'], unit='ms')
        
        # Loại bỏ duplicate
        df = df.drop_duplicates(subset=['Open time']).sort_values('Open time')
        
        return df.reset_index(drop=True)

Tải 2 năm dữ liệu BTCUSDT khung 1 ngày

loader = BinanceHistoricalData() df_2years = loader.get_historical_klines( symbol='BTCUSDT', interval='1d', start_date='2022-01-01', end_date='2024-01-01' )

Lưu vào CSV

df_2years.to_csv('btcusdt_2years_daily.csv', index=False) print(f"Đã lưu {len(df_2years)} nến vào btcusdt_2years_daily.csv") print(df_2years.tail())

Xây Dựng Hệ Thống Backtesting Chiến Lược RSI

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

class RSIBacktester:
    """
    Backtest chiến lược trading dựa trên RSI
    RSI > 70: Overbought -> Sell
    RSI < 30: Oversold -> Buy
    """
    
    def __init__(self, data):
        self.data = data.copy()
        self.signals = pd.DataFrame(index=data.index)
        self.trades = []
        self.initial_capital = 10000
        self.capital = self.initial_capital
        self.position = 0
        
    def calculate_rsi(self, period=14):
        """Tính RSI"""
        delta = self.data['Close'].diff()
        gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
        loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
        
        rs = gain / loss
        rsi = 100 - (100 / (1 + rs))
        return rsi
    
    def calculate_sma(self, period):
        """Tính SMA"""
        return self.data['Close'].rolling(window=period).mean()
    
    def generate_signals(self, rsi_period=14, oversold=30, overbought=70,
                        use_sma_filter=True, sma_period=200):
        """Tạo tín hiệu trading"""
        
        self.data['RSI'] = self.calculate_rsi(rsi_period)
        
        if use_sma_filter:
            self.data['SMA200'] = self.calculate_sma(sma_period)
        else:
            self.data['SMA200'] = self.data['Close']  # Không lọc
        
        self.signals['Signal'] = 0
        self.signals['RSI'] = self.data['RSI']
        
        # Tín hiệu mua: RSI < oversold và giá > SMA200
        buy_condition = (
            (self.data['RSI'] < oversold) & 
            (self.data['Close'] > self.data['SMA200'])
        )
        
        # Tín hiệu bán: RSI > overbought hoặc giá < SMA200
        sell_condition = (
            (self.data['RSI'] > overbought) | 
            (self.data['Close'] < self.data['SMA200'])
        )
        
        self.signals.loc[buy_condition, 'Signal'] = 1
        self.signals.loc[sell_condition, 'Signal'] = -1
        
        return self.signals
    
    def run_backtest(self):
        """Chạy backtest"""
        
        self.trades = []
        position = 0
        entry_price = 0
        entry_date = None
        
        for i, (date, row) in enumerate(self.data.iterrows()):
            signal = self.signals.loc[date, 'Signal']
            
            if signal == 1 and position == 0:  # Mua
                position = self.capital / row['Close']
                entry_price = row['Close']
                entry_date = date
                self.trades.append({
                    'type': 'BUY',
                    'date': date,
                    'price': entry_price,
                    'quantity': position,
                    'capital': self.capital
                })
                
            elif signal == -1 and position > 0:  # Bán
                exit_price = row['Close']
                self.capital = position * exit_price
                profit = self.capital - entry_price * position
                self.trades.append({
                    'type': 'SELL',
                    'date': date,
                    'price': exit_price,
                    'quantity': position,
                    'capital': self.capital,
                    'profit': profit,
                    'profit_pct': (exit_price - entry_price) / entry_price * 100
                })
                position = 0
        
        self.final_capital = self.capital if position == 0 else position * self.data['Close'].iloc[-1]
        return self.calculate_metrics()
    
    def calculate_metrics(self):
        """Tính các chỉ số hiệu suất"""
        
        trades_df = pd.DataFrame(self.trades)
        winning_trades = trades_df[trades_df['type'] == 'SELL']
        
        metrics = {
            'Initial Capital': self.initial_capital,
            'Final Capital': self.final_capital,
            'Total Return': (self.final_capital - self.initial_capital) / self.initial_capital * 100,
            'Total Trades': len(winning_trades),
            'Winning Trades': len(winning_trades[winning_trades['profit'] > 0]) if len(winning_trades) > 0 else 0,
            'Losing Trades': len(winning_trades[winning_trades['profit'] <= 0]) if len(winning_trades) > 0 else 0,
        }
        
        if len(winning_trades) > 0:
            metrics['Win Rate'] = len(winning_trades[winning_trades['profit'] > 0]) / len(winning_trades) * 100
            metrics['Avg Profit'] = winning_trades[winning_trades['profit'] > 0]['profit'].mean()
            metrics['Avg Loss'] = winning_trades[winning_trades['profit'] <= 0]['profit'].mean()
            
            if metrics['Avg Loss'] != 0:
                metrics['Profit Factor'] = abs(metrics['Avg Profit'] / metrics['Avg Loss'])
        
        return metrics
    
    def plot_results(self):
        """Vẽ biểu đồ kết quả"""
        
        fig, axes = plt.subplots(2, 2, figsize=(16, 10))
        
        # Biểu đồ giá và tín hiệu
        ax1 = axes[0, 0]
        ax1.plot(self.data.index, self.data['Close'], label='Giá', alpha=0.7)
        ax1.plot(self.data.index, self.data['SMA200'], label='SMA200', alpha=0.5)
        
        buy_signals = self.data[self.signals['Signal'] == 1]
        sell_signals = self.data[self.signals['Signal'] == -1]
        
        ax1.scatter(buy_signals.index, buy_signals['Close'], 
                   marker='^', color='green', s=100, label='Mua')
        ax1.scatter(sell_signals.index, sell_signals['Close'], 
                   marker='v', color='red', s=100, label='Bán')
        ax1.set_title('Biểu đồ Giá và Tín hiệu Trading')
        ax1.legend()
        ax1.grid(True, alpha=0.3)
        
        # Biểu đồ RSI
        ax2 = axes[0, 1]
        ax2.plot(self.data.index, self.data['RSI'], label='RSI', color='purple')
        ax2.axhline(y=70, color='red', linestyle='--', label='Overbought (70)')
        ax2.axhline(y=30, color='green', linestyle='--', label='Oversold (30)')
        ax2.fill_between(self.data.index, 70, 100, alpha=0.1, color='red')
        ax2.fill_between(self.data.index, 0, 30, alpha=0.1, color='green')
        ax2.set_title('RSI Indicator')
        ax2.legend()
        ax2.grid(True, alpha=0.3)
        
        # Biểu đồ Equity
        ax3 = axes[1, 0]
        equity = [self.initial_capital]
        for trade in self.trades:
            if trade['type'] == 'SELL':
                equity.append(trade['capital'])
        ax3.plot(equity, color='blue', linewidth=2)
        ax3.axhline(y=self.initial_capital, color='gray', linestyle='--')
        ax3.set_title('Equity Curve')
        ax3.set_ylabel('Vốn ($)')
        ax3.grid(True, alpha=0.3)
        
        # Biểu đồ Drawdown
        ax4 = axes[1, 1]
        equity_series = pd.Series(equity)
        running_max = equity_series.expanding().max()
        drawdown = (equity_series - running_max) / running_max * 100
        ax4.fill_between(range(len(drawdown)), drawdown, 0, alpha=0.3, color='red')
        ax4.plot(drawdown, color='red')
        ax4.set_title('Drawdown')
        ax4.set_ylabel('Drawdown (%)')
        ax4.grid(True, alpha=0.3)
        
        plt.tight_layout()
        plt.savefig('backtest_results.png', dpi=150)
        plt.show()
        
        return fig

Chạy backtest

Đọc dữ liệu đã lưu

df = pd.read_csv('btcusdt_2years_daily.csv', parse_dates=['Open time']) df.set_index('Open time', inplace=True)

Khởi tạo và chạy backtest

backtester = RSIBacktester(df) backtester.generate_signals( rsi_period=14, oversold=30, overbought=70, use_sma_filter=True, sma_period=200 ) metrics = backtester.run_backtest() print("=" * 50) print("KẾT QUẢ BACKTEST") print("=" * 50) for key, value in metrics.items(): if isinstance(value, float): print(f"{key}: {value:.2f}") else: print(f"{key}: {value}") print("=" * 50)

Vẽ biểu đồ

backtester.plot_results()

Sử Dụng Backtrader Cho Backtesting Nâng Cao

import backtrader as bt
import pandas as pd

class RSIStrategy(bt.Strategy):
    """Chiến lược RSI với Backtrader"""
    
    params = (
        ('rsi_period', 14),
        ('oversold', 30),
        ('overbought', 70),
        ('sma_period', 200),
        ('use_sma_filter', True),
    )
    
    def __init__(self):
        # Tính RSI
        self.rsi = bt.indicators.RSI(
            self.data.close, 
            period=self.params.rsi_period
        )
        
        # Tính SMA
        self.sma = bt.indicators.SMA(
            self.data.close,
            period=self.params.sma_period
        )
        
        # Cross-over signal
        self.crossover = bt.indicators.CrossOver(self.rsi, self.sma)
        
        # Log kết quả
        self.order = None
        
    def log(self, txt, dt=None):
        dt = dt or self.datas[0].datetime.date(0)
        print(f'{dt.isoformat()} {txt}')
        
    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            return
        
        if order.status in [order.Completed]:
            if order.isbuy():
                self.log(f'BUY EXECUTED, Price: {order.executed.price:.2f}')
            elif order.issell():
                self.log(f'SELL EXECUTED, Price: {order.executed.price:.2f}')
                
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            self.log('Order Canceled/Margin/Rejected')
            
        self.order = None
        
    def next(self):
        if self.order:
            return
            
        # Kiểm tra điều kiện SMA filter
        if self.params.use_sma_filter:
            if self.data.close < self.sma:
                if self.position:
                    self.close()
                return
        
        # Mua khi RSI < oversold
        if not self.position and self.rsi < self.params.oversold:
            self.log(f'BUY CREATE, RSI: {self.rsi[0]:.2f}')
            self.order = self.buy()
            
        # Bán khi RSI > overbought
        elif self.position and self.rsi > self.params.overbought:
            self.log(f'SELL CREATE, RSI: {self.rsi[0]:.2f}')
            self.order = self.sell()


def run_backtest():
    """Chạy backtest với Backtrader"""
    
    # Khởi tạo Cerebro
    cerebro = bt.Cerebro()
    
    # Thêm chiến lược
    cerebro.addstrategy(
        RSIStrategy,
        rsi_period=14,
        oversold=30,
        overbought=70,
        sma_period=200,
        use_sma_filter=True
    )
    
    # Đọc dữ liệu
    df = pd.read_csv('btcusdt_2years_daily.csv')
    df['Open time'] = pd.to_datetime(df['Open time'])
    df.set_index('Open time', inplace=True)
    df = df[['Open', 'High', 'Low', 'Close', 'Volume']]
    df.columns = ['open', 'high', 'low', 'close', 'volume']
    
    # Tạo data feed
    data = bt.feeds.PandasData(dataname=df)
    cerebro.adddata(data)
    
    # Cài đặt broker
    cerebro.broker.setcash(10000.0)
    cerebro.broker.setcommission(commission=0.001)  # 0.1% commission
    
    # Thêm analyzer
    cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe')
    cerebro.addanalyzer(bt.analyzers.DrawDown, _name='drawdown')
    cerebro.addanalyzer(bt.analyzers.Returns, _name='returns')
    cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name='trades')
    
    # In số dư ban đầu
    print(f'Starting Portfolio Value: {cerebro.broker.getvalue():.2f}')
    
    # Chạy backtest
    results = cerebro.run()
    
    # In số dư cuối cùng
    final_value = cerebro.broker.getvalue()
    print(f'Final Portfolio Value: {final_value:.2f}')
    print(f'Total Return: {(final_value - 10000) / 10000 * 100:.2f}%')
    
    # Lấy kết quả analyzer
    strat = results[0]
    
    print('\n' + '=' * 50)
    print('PHÂN TÍCH CHI TIẾT')
    print('=' * 50)
    
    # Sharpe Ratio
    sharpe = strat.analyzers.sharpe.get_analysis()
    if sharpe['sharperatio']:
        print(f'Sharpe Ratio: {sharpe["sharperatio"]:.2f}')
    
    # Drawdown
    dd = strat.analyzers.drawdown.get_analysis()
    print(f'Max Drawdown: {dd["max"]["drawdown"]:.2f}%')
    print(f'Max Drawdown Duration: {dd["max"]["len"]} days')
    
    # Returns
    ret = strat.analyzers.returns.get_analysis()
    print(f'Annual Return: {ret["rnorm100"]:.2f}%')
    
    # Trades
    trades = strat.analyzers.trades.get_analysis()
    print(f'Total Trades: {trades.total.total}')
    print(f'Winning Trades: {trades.won.total}')
    print(f'Losing Trades: {trades.lost.total}')
    if trades.won.total + trades.lost.total > 0:
        print(f'Win Rate: {trades.won.total / (trades.won.total + trades.lost.total) * 100:.2f}%')
    
    # Vẽ biểu đồ
    cerebro.plot(style='candlestick', volume=False)
    
    return results

Chạy backtest

results = run_backtest()

Sử Dụng AI Để Phân Tích Kết Quả Backtest

Sau khi có kết quả backtest, bạn có thể sử dụng AI để phân tích chi tiết và đề xuất cải thiện chiến lược. Với HolySheep AI, chi phí cho việc phân tích này cực kỳ thấp:

import requests
import json

Sử dụng HolySheep AI để phân tích kết quả backtest

HolySheep API - Base URL: https://api.holysheep.ai/v1

def analyze_backtest_with_ai(metrics, trades_data): """ Sử dụng AI để phân tích kết quả backtest và đề xuất cải thiện chiến lược """ prompt = f""" Phân tích kết quả backtest chiến lược RSI cho BTCUSDT: Metrics: {json.dumps(metrics, indent=2)} Hãy đề xuất: 1. Đánh giá tổng quan hiệu suất chiến lược 2. Các điểm yếu cần cải thiện 3. Thay đổi tham số đề xuất 4. Chiến lược bổ sung có thể kết hợp """ messages = [ {"role": "system", "content": "Bạn là chuyên gia phân tích tài chính và trading với 15 năm kinh nghiệm."}, {"role": "user", "content": prompt} ] response = requests.post( 'https://api.holysheep.ai/v1/chat/completions', headers={ 'Authorization': 'Bearer YOUR_HOLYSHEEP_API_KEY', 'Content-Type': 'application/json' }, json={ 'model': 'deepseek-chat', # $0.42/MTok - Rẻ nhất 'messages': messages, 'temperature': 0.7, 'max_tokens': 2000 } ) if response.status_code == 200: result = response.json() analysis = result['choices'][0]['message']['content'] print("PHÂN TÍCH TỪ AI:") print("=" * 50) print(analysis) return analysis else: print(f"Lỗi API: {response.status_code}") print(response.text) return None

Ví dụ metrics từ backtest

example_metrics = { 'Initial Capital': 10000, 'Final Capital': 12450, 'Total Return': 24.5, 'Total Trades': 15, 'Winning Trades': 10, 'Losing Trades': 5, 'Win Rate': 66.67, 'Max Drawdown': 12.5, 'Sharpe Ratio': 1.2 }

Phân tích với DeepSeek V3.2 ($0.42/MTok)

analysis = analyze_backtest_with_ai(example_metrics, [])

Hoặc sử dụng Claude để phân tích chuyên sâu hơn

def analyze_with_claude(metrics, code): """Sử dụng Claude Sonnet 4.5 để phân tích mã chiến lược""" prompt = f""" Review và tối ưu hóa mã chiến lược RSI backtest: ``{code}`` Metrics hiện tại: {metrics} Hãy đề xuất các cải tiến cụ thể. """ response = requests.post( 'https://api.holysheep.ai/v1/chat/completions', headers={ 'Authorization': 'Bearer YOUR_HOLYSHEEP_API_KEY', 'Content-Type': 'application/json' }, json={ 'model': 'claude-sonnet-4-20250514', 'messages': [ {"role": "system", "content": "Bạn là senior quantitative developer với 10 năm kinh nghiệm."}, {"role": "user", "content": prompt} ], 'temperature': 0.3, 'max_tokens': 3000 } ) return response.json() if response.status_code == 200 else None print("\nChi phí ước tính cho phân tích AI:") print("- DeepSeek V3.2 ($0.42/MTok): ~$0.001 cho 2000 tokens") print("- Claude Sonnet 4.5 ($15/MTok): ~$0.03 cho 2000 tokens") print("- Gemini 2.5 Flash ($2.50/MTok): ~$0.005 cho 2000 tokens")

Lỗi Thường Gặp và Cách Khắc Phục

1. Lỗi Rate Limit khi tải dữ liệu

# VẤN ĐỀ:

{"code":-1003,"msg":"Too much request weight used; current limit is 1200 request weight

per minute! Please use the endpoint for less request weight."}

GIẢI PHÁP:

import time import requests def safe_get_klines_with_retry(symbol, interval, start_time, end_time, max_retries=3): """ Lấy dữ liệu K-line an toàn với retry và rate limiting """ base_url = "https://api.binance.com/api/v3/klines" for attempt in range(max_retries): try: params = { 'symbol': symbol.upper(), 'interval': interval