Bài viết gần đây
-
FSM Là Gì? Ứng Dụng FSM Trong Robot MT5 (MetaTrader 5) Thực Chiến
Tháng 6 28, 2026 -
Quản Lý Basket TP Target Hiệu Quả Trong Bot Auto Trading Thực Chiến
Tháng 6 28, 2026 -
Khắc Phục Tình Trạng Kẹt Lệnh Bằng State_Recovery Trên MT5
Tháng 6 28, 2026
| Python Tính Monte Carlo Simulation: Dự Báo Danh Mục Đầu Tư 1 Năm Tới
Monte Carlo Simulation là kỹ thuật mạnh để dự báo phân phối kết quả của danh mục đầu tư — thay vì đưa ra 1 con số, nó cho bạn thấy phạm vi có thể xảy ra và xác suất tương ứng. Đây là công cụ quan trọng trong quản lý rủi ro tài chính.
Ý Tưởng Cơ Bản
Thay vì dự báo “danh mục sẽ đạt X%”, Monte Carlo chạy 10,000 kịch bản ngẫu nhiên dựa trên phân phối lợi nhuận lịch sử và cho biết:
- Xác suất đạt lợi nhuận dương là bao nhiêu?
- Worst case (5% tệ nhất) là bao nhiêu?
- Cần bao nhiêu vốn đệm để không bị margin call?
Bước 1: Lấy Dữ Liệu Danh Mục
from vnstock import stock_historical_data
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Danh mục: 40% VNM, 30% HPG, 30% FPT
portfolio = {
'VNM': 0.40,
'HPG': 0.30,
'FPT': 0.30
}
prices = {}
for sym in portfolio:
df = stock_historical_data(sym, "2022-01-01", "2026-06-01", "1D")
df.index = pd.to_datetime(df['time'])
prices[sym] = df['close']
price_df = pd.DataFrame(prices).dropna()
returns = price_df.pct_change().dropna()
print(f"Dữ liệu: {len(returns)} phiên giao dịch")
print("nThống kê lợi nhuận ngày:")
print(returns.describe())
Bước 2: Tính Tham Số Phân Phối
# Lợi nhuận danh mục = weighted average
weights = np.array(list(portfolio.values()))
port_ret = (returns * weights).sum(axis=1)
# Tham số phân phối lợi nhuận ngày
mu = port_ret.mean() # Trung bình
sigma = port_ret.std() # Độ lệch chuẩn
print(f"nLợi nhuận trung bình/ngày: {mu*100:.4f}%")
print(f"Độ lệch chuẩn/ngày: {sigma*100:.4f}%")
print(f"Lợi nhuận kỳ vọng/năm: {mu*252*100:.1f}%")
print(f"Volatility/năm: {sigma*np.sqrt(252)*100:.1f}%")
Bước 3: Chạy Monte Carlo
np.random.seed(42)
N_SIMULATIONS = 10_000
N_DAYS = 252 # 1 năm giao dịch
INITIAL_VALUE = 1_000_000_000 # 1 tỷ VND
# Ma trận tương quan để tạo returns có tương quan thực tế
cov_matrix = returns.cov()
# Simulate với correlated returns
simulations = np.zeros((N_DAYS, N_SIMULATIONS))
simulations[0] = INITIAL_VALUE
for t in range(1, N_DAYS):
# Sinh random returns có tương quan
rand_returns = np.random.multivariate_normal(
mean=returns.mean(),
cov=returns.cov(),
size=N_SIMULATIONS
)
# Lợi nhuận danh mục
port_rand = (rand_returns * weights).sum(axis=1)
simulations[t] = simulations[t-1] * (1 + port_rand)
final_values = simulations[-1]
final_returns = (final_values / INITIAL_VALUE - 1) * 100
print(f"n=== Kết quả Monte Carlo ({N_SIMULATIONS:,} kịch bản) ===")
print(f"Giá trị trung bình sau 1 năm: {np.mean(final_values)/1e9:.2f} tỷ")
print(f"Lợi nhuận trung bình: {np.mean(final_returns):.1f}%")
Bước 4: Tính VaR và CVaR
CONFIDENCE = 0.95 # 95% confidence level
# Value at Risk (VaR): mức lỗ tệ nhất ở 5% xác suất
var_95 = np.percentile(final_returns, 5)
print(f"nVaR (95%): {var_95:.1f}%")
print(f" → Có 5% khả năng lỗ hơn {abs(var_95):.1f}% trong 1 năm")
print(f" → Tương đương: {abs(var_95)/100 * INITIAL_VALUE/1e9:.2f} tỷ VND")
# Conditional VaR (CVaR / Expected Shortfall): trung bình của 5% tệ nhất
cvar_95 = final_returns[final_returns 0).mean() * 100
prob_loss_20 = (final_returns 20%: {prob_loss_20:.1f}%")
Bước 5: Vẽ Biểu Đồ
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# Biểu đồ 1: 100 simulation paths
ax1 = axes[0]
for i in range(min(100, N_SIMULATIONS)):
ax1.plot(simulations[:, i] / 1e9, alpha=0.05, color='blue', linewidth=0.5)
ax1.plot(np.median(simulations, axis=1) / 1e9, color='red', linewidth=2, label='Trung vị')
ax1.set_xlabel('Ngày giao dịch')
ax1.set_ylabel('Giá trị danh mục (tỷ VND)')
ax1.set_title('Monte Carlo: 100 kịch bản')
ax1.legend()
# Biểu đồ 2: Phân phối kết quả cuối năm
ax2 = axes[1]
ax2.hist(final_returns, bins=100, color='steelblue', alpha=0.7, edgecolor='white')
ax2.axvline(var_95, color='red', linestyle='--', label=f'VaR 95%: {var_95:.1f}%')
ax2.axvline(cvar_95, color='orange', linestyle='--', label=f'CVaR 95%: {cvar_95:.1f}%')
ax2.axvline(0, color='black', linestyle='-', linewidth=2)
ax2.set_xlabel('Lợi nhuận 1 năm (%)')
ax2.set_ylabel('Số kịch bản')
ax2.set_title('Phân phối lợi nhuận sau 1 năm')
ax2.legend()
plt.tight_layout()
plt.savefig('monte_carlo.png', dpi=150)
plt.show()
Kết Luận
Monte Carlo cho bạn cái nhìn thực tế hơn về rủi ro — thay vì chỉ nhìn lợi nhuận kỳ vọng, bạn biết phân phối đầy đủ của kết quả có thể xảy ra. Đây là công cụ tiêu chuẩn tại các quỹ đầu tư chuyên nghiệp và ngân hàng khi quản lý danh mục lớn.
📌 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
Weekly Digest — Nhận Bản Tin Hàng Tuần
Nhận các bài viết phân tích kỹ thuật chuyên sâu, thuật toán giao dịch tự động (Trading Bot) và các giải pháp công nghệ mới nhất từ Hướng Nghiệp Dữ Liệu.
admin
Biên tập viên, Hướng Nghiệp Dữ LiệuBiê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ệ.