| Python Quản Lý Danh Mục Cổ Phiếu: Tính Sharpe Ratio, Beta, Tương Quan Tự Động

Quản lý danh mục đầu tư không chỉ là chọn cổ phiếu — mà là tối ưu tỷ trọng để tối đa lợi nhuận với rủi ro tối thiểu. Python giúp bạn làm điều này trong vài phút thay vì vài giờ với Excel.

1. Tải Dữ Liệu Đa Cổ Phiếu

from vnstock import stock_historical_data
import pandas as pd
import numpy as np

# Danh mục mẫu: 5 cổ phiếu blue-chip VN
portfolio = ['VNM', 'VIC', 'HPG', 'TCB', 'FPT']
START = "2023-01-01"
END   = "2026-06-01"

prices = {}
for sym in portfolio:
    df = stock_historical_data(sym, START, END, "1D")
    df.index = pd.to_datetime(df['time'])
    prices[sym] = df['close']

price_df = pd.DataFrame(prices)
price_df.dropna(inplace=True)
print(price_df.tail())
print(f"n{len(price_df)} phiên, {len(portfolio)} cổ phiếu")

2. Tính Lợi Nhuận Hàng Ngày

# Tỷ suất sinh lời hàng ngày
returns = price_df.pct_change().dropna()

# Thống kê cơ bản
annual_return = returns.mean() * 252 * 100  # % mỗi năm
annual_vol    = returns.std()  * np.sqrt(252) * 100

print("n=== Lợi nhuận & Rủi ro hàng năm ===")
for sym in portfolio:
    print(f"{sym}: {annual_return[sym]:.1f}%/năm | Biến động: {annual_vol[sym]:.1f}%")

3. Ma Trận Tương Quan

import matplotlib.pyplot as plt
import seaborn as sns

corr = returns.corr()
print("n=== Ma trận tương quan ===")
print(corr.round(2))

# Vẽ heatmap
fig, ax = plt.subplots(figsize=(8, 6))
sns.heatmap(corr, annot=True, fmt='.2f', cmap='RdYlGn',
            center=0, ax=ax)
ax.set_title('Tương quan giữa các cổ phiếu trong danh mục')
plt.tight_layout()
plt.savefig('correlation_matrix.png', dpi=150)
plt.show()

Tại sao quan trọng: Nếu 2 cổ phiếu tương quan > 0.8 — chúng di chuyển cùng chiều, không giảm được rủi ro khi nắm cả 2. Lý tưởng là chọn cổ phiếu tương quan < 0.5.

4. Tính Beta (Độ Nhạy Với Thị Trường)

from vnstock import stock_historical_data

# Lấy VNIndex làm benchmark
vnindex = stock_historical_data("VNINDEX", START, END, "1D", type="index")
vnindex.index = pd.to_datetime(vnindex['time'])
market_ret = vnindex['close'].pct_change()

# Tính Beta cho từng cổ phiếu
print("n=== Beta (so với VNIndex) ===")
for sym in portfolio:
    stock_ret = returns[sym]
    # Align index
    combined = pd.DataFrame({'stock': stock_ret, 'market': market_ret}).dropna()
    cov = combined.cov().iloc[0, 1]
    var = combined['market'].var()
    beta = cov / var
    print(f"{sym}: Beta = {beta:.2f}  {'(nhạy cảm cao)' if beta > 1.2 else '(ổn định)' if beta < 0.8 else '(trung bình)'}")

5. Sharpe Ratio Từng Cổ Phiếu

RISK_FREE_RATE = 0.045  # Lãi suất phi rủi ro VN ~4.5%/năm

print("n=== Sharpe Ratio ===")
for sym in portfolio:
    ann_ret = returns[sym].mean() * 252
    ann_std = returns[sym].std()  * np.sqrt(252)
    sharpe  = (ann_ret - RISK_FREE_RATE) / ann_std
    print(f"{sym}: Sharpe = {sharpe:.2f}  {'✅ Tốt' if sharpe > 1.0 else '⚠️ Trung bình' if sharpe > 0.5 else '❌ Kém'}")

6. Tối Ưu Hóa Danh Mục (Markowitz)

from scipy.optimize import minimize

def portfolio_stats(weights, returns, rf=0.045):
    w = np.array(weights)
    ret = np.sum(returns.mean() * w) * 252
    vol = np.sqrt(np.dot(w.T, np.dot(returns.cov() * 252, w)))
    sharpe = (ret - rf) / vol
    return ret, vol, sharpe

def neg_sharpe(weights, returns, rf=0.045):
    return -portfolio_stats(weights, returns, rf)[2]

n = len(portfolio)
constraints = ({'type': 'eq', 'fun': lambda w: np.sum(w) - 1})
bounds = tuple((0.05, 0.50) for _ in range(n))  # mỗi cổ phiếu 5%–50%
init_w = [1/n] * n

result = minimize(neg_sharpe, init_w,
                  args=(returns,),
                  method='SLSQP',
                  bounds=bounds,
                  constraints=constraints)

opt_weights = result.x
ret, vol, sharpe = portfolio_stats(opt_weights, returns)

print("n=== Danh mục tối ưu (Max Sharpe) ===")
for sym, w in zip(portfolio, opt_weights):
    print(f"{sym}: {w*100:.1f}%")
print(f"nLợi nhuận kỳ vọng: {ret*100:.1f}%/năm")
print(f"Rủi ro:            {vol*100:.1f}%/năm")
print(f"Sharpe Ratio:      {sharpe:.2f}")

Kết Luận

Với Python, việc phân tích và tối ưu danh mục cổ phiếu — từ tương quan đến Markowitz Optimization — chỉ mất vài phút. Điều này giúp bạn đưa ra quyết định phân bổ tài sản dựa trên dữ liệu thay vì cảm tính.


📌 Muốn ứng dụng Python vào phân tích và giao dịch tài chính thực chiến?
Khóa Python Fintech — Phân Tích Dữ Liệu Lớn & Tự Động Hóa Giao Dịch tại Hướng Nghiệp Dữ Liệu giúp bạn thực hành với dữ liệu VnIndex, Binance API thật — không dạy lý thuyết hàn lâm.
📞 Hotline/Zalo: 0927 909 257

admin

admin

Biên tập viên, Hướng Nghiệp Dữ Liệu
713 Bài viết
15.4k Người theo dõi
120k+ Lượt đọc

Biên tập viên nội dung tại Hướng Nghiệp Dữ Liệu, phụ trách tổng hợp và biên soạn các bài viết về lập trình Python, dữ liệu và công nghệ.