| Tự Code Thư Viện Chỉ Báo Kỹ Thuật (SMA, EMA, RSI) Bằng Pandas

Được viết bởi thanhdt vào ngày 15/06/2026 lúc 21:01 | 43 lượt xem

Khi phát triển Robot giao dịch tự động (Trading Bot) bằng Python, một trong những khó khăn lớn nhất của người mới bắt đầu là cài đặt thư viện TA-Lib. Đây là thư viện viết bằng C++ và yêu cầu cấu hình trình biên dịch phức tạp trên môi trường Windows.

Thực tế, bạn hoàn toàn có thể tự xây dựng một thư viện tính toán các chỉ báo kỹ thuật phổ biến như SMA, EMA, và RSI chỉ bằng Pandas — thư viện xử lý dữ liệu mạnh mẽ của Python. Tự viết chỉ báo giúp bạn:
– Làm chủ 100% thuật toán tính toán.
– Dễ dàng tối ưu hiệu năng và tích hợp vào hệ thống Bot Modular.
– Không bị phụ thuộc vào các thư viện bên thứ ba phức tạp.


🗺️ Quy Trình Tính Toán Chỉ Báo (Workflow)

Dưới đây là sơ đồ luồng dữ liệu biến đổi dữ liệu thô (OHLCV) thành tín hiệu chỉ báo kỹ thuật:

┌─────────────────────────┐
│ Dữ liệu giá thô (OHLCV) │ (Nhận từ API sàn qua Binance / Bitget / SSI)
└────────────┬────────────┘
             │
             ▼
┌─────────────────────────┐
│     Pandas DataFrame    │ (Định dạng cột: Close, Open, High, Low, Volume)
└────────────┬────────────┘
             │
     ┌───────┼───────┐
     │       │       │
     ▼       ▼       ▼
  [ SMA ] [ EMA ] [ RSI ]   (Tính toán song song bằng Vectorization)
     │       │       │
     └───────┼───────┘
             │
             ▼
┌─────────────────────────┐
│    DataFrame Mở Rộng    │ (Có thêm các cột: 'sma_20', 'ema_50', 'rsi_14')
└─────────────────────────┘

1. Simple Moving Average (SMA) – Đường Trung Bình Động Đơn Giản

SMA là trung bình cộng của giá đóng cửa trong một khoảng thời gian (chu kỳ) nhất định.

Công thức:
$$SMA_t = frac{sum_{i=0}^{N-1} Price_{t-i}}{N}$$

Trong Pandas, ta sử dụng phương thức .rolling(window) kết hợp với .mean() để tính toán cực kỳ nhanh chóng:

import pandas as pd

def calculate_sma(df: pd.DataFrame, period: int = 20, column: str = 'close') -> pd.Series:
    """Tính toán Simple Moving Average (SMA)"""
    return df[column].rolling(window=period).mean()

2. Exponential Moving Average (EMA) – Đường Trung Bình Động Lũy Thừa

Khác với SMA gán trọng số bằng nhau cho mọi ngày, EMA đặt trọng số lớn hơn cho những phiên giao dịch gần nhất, giúp chỉ báo phản ứng nhanh hơn với biến động giá.

Trong Pandas, chúng ta sử dụng hàm .ewm(span, adjust=False):

def calculate_ema(df: pd.DataFrame, period: int = 50, column: str = 'close') -> pd.Series:
    """Tính toán Exponential Moving Average (EMA)"""
    return df[column].ewm(span=period, adjust=False).mean()

3. Relative Strength Index (RSI) – Chỉ Số Sức Mạnh Tương Đối

RSI là chỉ báo đo lường tốc độ và sự thay đổi của biến động giá, dao động trong khoảng từ 0 đến 100. Thuật toán RSI chuẩn của J. Welles Wilder sử dụng phương pháp trung bình mượt lũy thừa (Smoothed Moving Average) cho các phiên tăng và giảm giá.

Quy trình tính RSI bằng Pandas:
1. Tính mức chênh lệch giá giữa phiên sau và phiên trước (diff).
2. Tách biệt mức tăng (gain) và giảm (loss).
3. Tính trung bình mượt lũy thừa của Gain và Loss bằng phương pháp của Wilder.
4. Tính tỷ lệ sức mạnh tương đối $RS = frac{Gain}{Loss}$.
5. Tính $RSI = 100 – frac{100}{1 + RS}$.

def calculate_rsi(df: pd.DataFrame, period: int = 14, column: str = 'close') -> pd.Series:
    """Tính toán Relative Strength Index (RSI) chuẩn Wilder"""
    # 1. Tính hiệu số giá đóng cửa
    delta = df[column].diff()

    # 2. Tách Gain và Loss
    gain = delta.clip(lower=0)
    loss = -delta.clip(upper=0)

    # 3. Tính trung bình mượt lũy thừa (Wilder Exponential Moving Average)
    # Wilder sử dụng alpha = 1 / period
    avg_gain = gain.ewm(alpha=1/period, adjust=False).mean()
    avg_loss = loss.ewm(alpha=1/period, adjust=False).mean()

    # 4. Tính RS và RSI
    rs = avg_gain / (avg_loss + 1e-10) # Thêm epsilon nhỏ tránh chia cho 0
    rsi = 100 - (100 / (1 + rs))

    return rsi

4. Đóng Gói Thành Thư Viện Tiện Ích indicators.py

Hãy tạo một module chứa toàn bộ các chỉ báo để tái sử dụng trong dự án Bot Trading:

# indicators.py
import pandas as pd

class TechnicalIndicators:
    @staticmethod
    def sma(df: pd.DataFrame, period: int, column: str = 'close') -> pd.Series:
        return df[column].rolling(window=period).mean()

    @staticmethod
    def ema(df: pd.DataFrame, period: int, column: str = 'close') -> pd.Series:
        return df[column].ewm(span=period, adjust=False).mean()

    @staticmethod
    def rsi(df: pd.DataFrame, period: int = 14, column: str = 'close') -> pd.Series:
        delta = df[column].diff()
        gain = delta.clip(lower=0)
        loss = -delta.clip(upper=0)

        avg_gain = gain.ewm(alpha=1/period, adjust=False).mean()
        avg_loss = loss.ewm(alpha=1/period, adjust=False).mean()

        rs = avg_gain / (avg_loss + 1e-10)
        return 100 - (100 / (1 + rs))

Cách sử dụng trong mã nguồn Bot chính:

from indicators import TechnicalIndicators as ta
import pandas as pd

# Giả sử df_candles chứa cột 'close' lấy từ API sàn
df_candles = pd.read_csv("historical_candles.csv")

# Tính toán chỉ báo
df_candles['sma_20'] = ta.sma(df_candles, 20)
df_candles['ema_50'] = ta.ema(df_candles, 50)
df_candles['rsi_14'] = ta.rsi(df_candles, 14)

print(df_candles.tail())

Kết Luận

Bằng cách tự viết chỉ báo kỹ thuật qua Pandas, bạn đã tối ưu hóa được tốc độ chạy của Bot nhờ cơ chế tính toán Vectorization, đồng thời loại bỏ được rủi ro lỗi môi trường cài đặt khi deploy Bot lên Cloud VPS.

Bạn muốn học cách viết trọn vẹn một Bot Trading Modular chuyên nghiệp?
Hãy tham gia khóa học Vibe Code Lập trình Bot Auto Trading Python để làm chủ toàn bộ pipeline từ Lấy dữ liệu API $rightarrow$ Tính toán Chỉ báo $rightarrow$ Đưa ra Tín hiệu $rightarrow$ Quản lý vốn $rightarrow$ Khớp lệnh tự động.