Bài viết gần đây

| Phân tích kỹ thuật auto trading với Python: Hướng dẫn toàn diện cho người mới bắt đầu

Được viết bởi thanhdt vào ngày 16/11/2025 lúc 10:42 | 9 lượt xem

Phân tích kỹ thuật với Python

Phân tích kỹ thuật là phương pháp phân tích thị trường tài chính bằng cách sử dụng các mô hình giá cả lịch sử, khối lượng giao dịch và các chỉ báo kỹ thuật khác để dự đoán biến động giá trong tương lai. Python, với các thư viện phân tích dữ liệu mạnh mẽ như Pandas, NumPy, và Matplotlib, là công cụ lý tưởng để thực hiện phân tích kỹ thuật một cách chuyên nghiệp.

Phân tích kỹ thuật là gì?

Phân tích kỹ thuật là một phương pháp dự đoán hướng giá của tài sản tài chính dựa trên việc nghiên cứu các dữ liệu giao dịch trong quá khứ, đặc biệt là giá và khối lượng. Khác với phân tích cơ bản (fundamental analysis) tập trung vào các yếu tố kinh tế và tài chính của công ty, phân tích kỹ thuật dựa trên giả định rằng:

  • Giá phản ánh tất cả thông tin
  • Giá di chuyển theo xu hướng
  • Lịch sử có xu hướng lặp lại

Tại sao sử dụng Python cho phân tích kỹ thuật?

Python là ngôn ngữ lập trình lý tưởng cho phân tích kỹ thuật vì:

  • Thư viện phong phú: Pandas, NumPy, Matplotlib, yfinance, TA-Lib
  • Xử lý dữ liệu mạnh mẽ: Dễ dàng đọc và xử lý dữ liệu giá từ nhiều nguồn
  • Trực quan hóa tốt: Tạo biểu đồ nến, biểu đồ đường, và các chỉ báo kỹ thuật
  • Tự động hóa: Xây dựng hệ thống phân tích và giao dịch tự động
  • Cộng đồng lớn: Nhiều tài liệu và ví dụ có sẵn

Cài đặt các thư viện cần thiết

Trước khi bắt đầu, bạn cần cài đặt các thư viện Python sau:

# Cài đặt các thư viện cơ bản
pip install pandas numpy matplotlib

# Thư viện lấy dữ liệu tài chính
pip install yfinance

# Thư viện tính toán chỉ báo kỹ thuật
pip install ta-lib

# Thư viện vẽ biểu đồ nến
pip install mplfinance

Lấy dữ liệu giá từ thị trường

Sử dụng yfinance

yfinance là thư viện phổ biến để lấy dữ liệu giá từ Yahoo Finance:

import yfinance as yf
import pandas as pd

# Lấy dữ liệu giá cổ phiếu Apple (AAPL)
ticker = yf.Ticker("AAPL")
data = ticker.history(period="1y")  # Lấy dữ liệu 1 năm

# Hiển thị 5 dòng đầu tiên
print(data.head())

# Lấy dữ liệu Bitcoin
btc = yf.download("BTC-USD", period="6mo", interval="1d")
print(btc.head())

Lấy dữ liệu từ Binance API

Nếu bạn muốn lấy dữ liệu từ Binance, có thể sử dụng API:

import requests
import pandas as pd

def get_binance_data(symbol, interval='1d', limit=500):
    """
    Lấy dữ liệu giá từ Binance API

    Parameters:
    symbol: Cặp giao dịch (ví dụ: 'BTCUSDT')
    interval: Khung thời gian ('1m', '5m', '1h', '1d', ...)
    limit: Số lượng nến cần lấy
    """
    url = f"https://api.binance.com/api/v3/klines"
    params = {
        'symbol': symbol,
        'interval': interval,
        'limit': limit
    }

    response = requests.get(url, params=params)
    data = response.json()

    # Chuyển đổi sang DataFrame
    df = pd.DataFrame(data, columns=[
        'timestamp', 'open', 'high', 'low', 'close', 'volume',
        'close_time', 'quote_volume', 'trades', 'taker_buy_base',
        'taker_buy_quote', 'ignore'
    ])

    # Chuyển đổi kiểu dữ liệu
    df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
    for col in ['open', 'high', 'low', 'close', 'volume']:
        df[col] = df[col].astype(float)

    df.set_index('timestamp', inplace=True)
    return df[['open', 'high', 'low', 'close', 'volume']]

# Lấy dữ liệu BTC/USDT
btc_data = get_binance_data('BTCUSDT', interval='1d', limit=365)
print(btc_data.head())

Vẽ biểu đồ giá

Biểu đồ đường đơn giản

import matplotlib.pyplot as plt
import pandas as pd

# Lấy dữ liệu
ticker = yf.Ticker("AAPL")
data = ticker.history(period="6mo")

# Vẽ biểu đồ giá đóng cửa
plt.figure(figsize=(12, 6))
plt.plot(data.index, data['Close'], linewidth=2)
plt.title('Giá cổ phiếu Apple (AAPL)', fontsize=16, fontweight='bold')
plt.xlabel('Ngày')
plt.ylabel('Giá (USD)')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

Biểu đồ nến (Candlestick Chart)

import mplfinance as mpf

# Vẽ biểu đồ nến
mpf.plot(data, 
         type='candle',
         style='yahoo',
         volume=True,
         title='Biểu đồ nến AAPL',
         figsize=(14, 8))

Các chỉ báo kỹ thuật phổ biến

Moving Average (Đường trung bình động)

Moving Average là một trong những chỉ báo kỹ thuật cơ bản nhất:

def calculate_ma(data, period=20):
    """
    Tính đường trung bình động đơn giản (SMA)
    """
    return data['Close'].rolling(window=period).mean()

# Tính SMA 20 và SMA 50
data['SMA_20'] = calculate_ma(data, 20)
data['SMA_50'] = calculate_ma(data, 50)

# Vẽ biểu đồ với SMA
plt.figure(figsize=(14, 8))
plt.plot(data.index, data['Close'], label='Giá đóng cửa', linewidth=2)
plt.plot(data.index, data['SMA_20'], label='SMA 20', linewidth=1.5)
plt.plot(data.index, data['SMA_50'], label='SMA 50', linewidth=1.5)
plt.title('Giá cổ phiếu với Moving Average', fontsize=16, fontweight='bold')
plt.xlabel('Ngày')
plt.ylabel('Giá (USD)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

Exponential Moving Average (EMA)

EMA cho trọng số cao hơn cho các giá trị gần đây:

def calculate_ema(data, period=20):
    """
    Tính đường trung bình động hàm mũ (EMA)
    """
    return data['Close'].ewm(span=period, adjust=False).mean()

# Tính EMA 12 và EMA 26
data['EMA_12'] = calculate_ema(data, 12)
data['EMA_26'] = calculate_ema(data, 26)

RSI (Relative Strength Index)

RSI đo lường sức mạnh của xu hướng giá:

def calculate_rsi(data, period=14):
    """
    Tính chỉ báo RSI (Relative Strength Index)
    """
    delta = 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

# Tính RSI
data['RSI'] = calculate_rsi(data, 14)

# Vẽ biểu đồ RSI
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 10), sharex=True)

# Biểu đồ giá
ax1.plot(data.index, data['Close'], label='Giá đóng cửa', linewidth=2)
ax1.set_title('Giá cổ phiếu', fontsize=14, fontweight='bold')
ax1.set_ylabel('Giá (USD)')
ax1.legend()
ax1.grid(True, alpha=0.3)

# Biểu đồ RSI
ax2.plot(data.index, data['RSI'], label='RSI', linewidth=2, color='purple')
ax2.axhline(y=70, color='r', linestyle='--', label='Overbought (70)')
ax2.axhline(y=30, color='g', linestyle='--', label='Oversold (30)')
ax2.set_title('RSI Indicator', fontsize=14, fontweight='bold')
ax2.set_xlabel('Ngày')
ax2.set_ylabel('RSI')
ax2.set_ylim(0, 100)
ax2.legend()
ax2.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

MACD (Moving Average Convergence Divergence)

MACD là chỉ báo xu hướng mạnh mẽ:

def calculate_macd(data, fast=12, slow=26, signal=9):
    """
    Tính chỉ báo MACD
    """
    ema_fast = calculate_ema(data, fast)
    ema_slow = calculate_ema(data, slow)

    macd_line = ema_fast - ema_slow
    signal_line = macd_line.ewm(span=signal, adjust=False).mean()
    histogram = macd_line - signal_line

    return macd_line, signal_line, histogram

# Tính MACD
data['MACD'], data['MACD_Signal'], data['MACD_Hist'] = calculate_macd(data)

# Vẽ biểu đồ MACD
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 10), sharex=True)

# Biểu đồ giá
ax1.plot(data.index, data['Close'], label='Giá đóng cửa', linewidth=2)
ax1.set_title('Giá cổ phiếu', fontsize=14, fontweight='bold')
ax1.set_ylabel('Giá (USD)')
ax1.legend()
ax1.grid(True, alpha=0.3)

# Biểu đồ MACD
ax2.plot(data.index, data['MACD'], label='MACD', linewidth=2)
ax2.plot(data.index, data['MACD_Signal'], label='Signal', linewidth=2)
ax2.bar(data.index, data['MACD_Hist'], label='Histogram', alpha=0.3)
ax2.set_title('MACD Indicator', fontsize=14, fontweight='bold')
ax2.set_xlabel('Ngày')
ax2.set_ylabel('MACD')
ax2.legend()
ax2.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

Bollinger Bands

Bollinger Bands giúp xác định biến động giá:

def calculate_bollinger_bands(data, period=20, std_dev=2):
    """
    Tính Bollinger Bands
    """
    sma = calculate_ma(data, period)
    std = data['Close'].rolling(window=period).std()

    upper_band = sma + (std * std_dev)
    lower_band = sma - (std * std_dev)

    return upper_band, lower_band, sma

# Tính Bollinger Bands
data['BB_Upper'], data['BB_Lower'], data['BB_Middle'] = calculate_bollinger_bands(data)

# Vẽ biểu đồ Bollinger Bands
plt.figure(figsize=(14, 8))
plt.plot(data.index, data['Close'], label='Giá đóng cửa', linewidth=2)
plt.plot(data.index, data['BB_Upper'], label='Upper Band', linestyle='--', alpha=0.7)
plt.plot(data.index, data['BB_Lower'], label='Lower Band', linestyle='--', alpha=0.7)
plt.plot(data.index, data['BB_Middle'], label='Middle Band (SMA)', linestyle='--', alpha=0.7)
plt.fill_between(data.index, data['BB_Upper'], data['BB_Lower'], alpha=0.1)
plt.title('Bollinger Bands', fontsize=16, fontweight='bold')
plt.xlabel('Ngày')
plt.ylabel('Giá (USD)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

Xây dựng chiến lược giao dịch đơn giản

Chiến lược Moving Average Crossover

Chiến lược này mua khi SMA ngắn hạn cắt lên trên SMA dài hạn và bán khi ngược lại:

def ma_crossover_strategy(data, short_period=20, long_period=50):
    """
    Chiến lược giao dịch dựa trên Moving Average Crossover
    """
    # Tính SMA
    data['SMA_Short'] = calculate_ma(data, short_period)
    data['SMA_Long'] = calculate_ma(data, long_period)

    # Tạo tín hiệu
    data['Signal'] = 0
    data['Signal'][short_period:] = np.where(
        data['SMA_Short'][short_period:] > data['SMA_Long'][short_period:], 1, 0
    )

    # Tạo lệnh mua/bán
    data['Position'] = data['Signal'].diff()

    return data

# Áp dụng chiến lược
data = ma_crossover_strategy(data)

# Vẽ biểu đồ với tín hiệu
plt.figure(figsize=(14, 8))
plt.plot(data.index, data['Close'], label='Giá đóng cửa', linewidth=2)
plt.plot(data.index, data['SMA_20'], label='SMA 20', linewidth=1.5)
plt.plot(data.index, data['SMA_50'], label='SMA 50', linewidth=1.5)

# Đánh dấu điểm mua
buy_signals = data[data['Position'] == 1]
plt.scatter(buy_signals.index, buy_signals['Close'], 
           marker='^', color='green', s=100, label='Tín hiệu MUA', zorder=5)

# Đánh dấu điểm bán
sell_signals = data[data['Position'] == -1]
plt.scatter(sell_signals.index, sell_signals['Close'], 
           marker='v', color='red', s=100, label='Tín hiệu BÁN', zorder=5)

plt.title('Chiến lược Moving Average Crossover', fontsize=16, fontweight='bold')
plt.xlabel('Ngày')
plt.ylabel('Giá (USD)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

Backtesting chiến lược

Backtesting giúp đánh giá hiệu quả của chiến lược trên dữ liệu lịch sử:

def backtest_strategy(data, initial_capital=10000):
    """
    Backtest chiến lược giao dịch
    """
    capital = initial_capital
    position = 0  # Số lượng cổ phiếu đang nắm giữ
    trades = []

    for i in range(len(data)):
        if data['Position'].iloc[i] == 1:  # Tín hiệu mua
            if position == 0:  # Chưa có vị thế
                position = capital / data['Close'].iloc[i]
                capital = 0
                trades.append({
                    'date': data.index[i],
                    'action': 'BUY',
                    'price': data['Close'].iloc[i],
                    'shares': position
                })

        elif data['Position'].iloc[i] == -1:  # Tín hiệu bán
            if position > 0:  # Đang có vị thế
                capital = position * data['Close'].iloc[i]
                trades.append({
                    'date': data.index[i],
                    'action': 'SELL',
                    'price': data['Close'].iloc[i],
                    'shares': position
                })
                position = 0

    # Tính toán lợi nhuận cuối cùng
    if position > 0:
        final_capital = position * data['Close'].iloc[-1]
    else:
        final_capital = capital

    total_return = ((final_capital - initial_capital) / initial_capital) * 100

    return {
        'initial_capital': initial_capital,
        'final_capital': final_capital,
        'total_return': total_return,
        'trades': trades
    }

# Chạy backtest
results = backtest_strategy(data)
print(f"Vốn ban đầu: ${results['initial_capital']:,.2f}")
print(f"Vốn cuối cùng: ${results['final_capital']:,.2f}")
print(f"Lợi nhuận: {results['total_return']:.2f}%")
print(f"Số lần giao dịch: {len(results['trades'])}")

Ví dụ hoàn chỉnh: Phân tích cổ phiếu với nhiều chỉ báo

Dưới đây là một ví dụ hoàn chỉnh kết hợp nhiều chỉ báo kỹ thuật:

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

# Lấy dữ liệu
ticker = yf.Ticker("AAPL")
data = ticker.history(period="1y")

# Tính các chỉ báo
data['SMA_20'] = calculate_ma(data, 20)
data['SMA_50'] = calculate_ma(data, 50)
data['RSI'] = calculate_rsi(data, 14)
data['MACD'], data['MACD_Signal'], data['MACD_Hist'] = calculate_macd(data)
data['BB_Upper'], data['BB_Lower'], data['BB_Middle'] = calculate_bollinger_bands(data)

# Vẽ biểu đồ tổng hợp
fig = plt.figure(figsize=(16, 12))

# Biểu đồ giá với Moving Average và Bollinger Bands
ax1 = plt.subplot(3, 1, 1)
ax1.plot(data.index, data['Close'], label='Giá đóng cửa', linewidth=2)
ax1.plot(data.index, data['SMA_20'], label='SMA 20', linewidth=1.5)
ax1.plot(data.index, data['SMA_50'], label='SMA 50', linewidth=1.5)
ax1.fill_between(data.index, data['BB_Upper'], data['BB_Lower'], alpha=0.1)
ax1.set_title('Phân tích kỹ thuật AAPL', fontsize=16, fontweight='bold')
ax1.set_ylabel('Giá (USD)')
ax1.legend()
ax1.grid(True, alpha=0.3)

# Biểu đồ RSI
ax2 = plt.subplot(3, 1, 2)
ax2.plot(data.index, data['RSI'], label='RSI', linewidth=2, color='purple')
ax2.axhline(y=70, color='r', linestyle='--', label='Overbought (70)')
ax2.axhline(y=30, color='g', linestyle='--', label='Oversold (30)')
ax2.set_ylabel('RSI')
ax2.set_ylim(0, 100)
ax2.legend()
ax2.grid(True, alpha=0.3)

# Biểu đồ MACD
ax3 = plt.subplot(3, 1, 3)
ax3.plot(data.index, data['MACD'], label='MACD', linewidth=2)
ax3.plot(data.index, data['MACD_Signal'], label='Signal', linewidth=2)
ax3.bar(data.index, data['MACD_Hist'], label='Histogram', alpha=0.3)
ax3.set_xlabel('Ngày')
ax3.set_ylabel('MACD')
ax3.legend()
ax3.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

Kết luận

Phân tích kỹ thuật với Python là một công cụ mạnh mẽ để phân tích thị trường tài chính. Với các thư viện như Pandas, NumPy, Matplotlib, và yfinance, bạn có thể:

  • Lấy và xử lý dữ liệu giá từ nhiều nguồn
  • Tính toán các chỉ báo kỹ thuật phổ biến
  • Vẽ biểu đồ trực quan và chuyên nghiệp
  • Xây dựng và backtest các chiến lược giao dịch
  • Tự động hóa quy trình phân tích

Để tìm hiểu thêm về các thư viện Python trong giao dịch, bạn có thể xem bài viết Giới thiệu về Pandas hoặc Làm Bot Giao Dịch Backtest với Pandas. Nếu bạn muốn xây dựng chiến lược giao dịch định lượng hoàn chỉnh, hãy tham khảo bài viết Làm thế nào để sử dụng Python xây dựng chiến lược giao dịch định lượng.

Tài liệu tham khảo