Giới Thiệu Python và Dữ Liệu Tài Chính

Python đã trở thành ngôn ngữ lập trình phổ biến nhất trong lĩnh vực tài chính nhờ vào tính đơn giản, dễ học và bộ thư viện phong phú. Trong bài viết này, chúng ta sẽ tìm hiểu về Python và cách sử dụng nó trong phân tích dữ liệu tài chính.
1. Giới thiệu về Python và ứng dụng trong phân tích tài chính
1.1. Tại sao chọn Python?
Python có nhiều ưu điểm khiến nó trở thành lựa chọn hàng đầu cho phân tích tài chính:
- Dễ học và dễ sử dụng: Cú pháp đơn giản, dễ đọc
- Thư viện phong phú: pandas, numpy, matplotlib, scikit-learn,...
- Cộng đồng lớn: Nhiều tài liệu, hỗ trợ và chia sẻ
- Hiệu suất cao: Xử lý dữ liệu lớn nhanh chóng
- Tích hợp tốt: Kết nối với nhiều nguồn dữ liệu tài chính
1.2. Ứng dụng trong tài chính
Python được sử dụng rộng rãi trong:
- Phân tích dữ liệu thị trường
- Xây dựng mô hình dự báo
- Giao dịch tự động
- Quản lý rủi ro
- Tối ưu hóa danh mục đầu tư
2. Cài đặt môi trường Python và IDE
2.1. Cài đặt Python
-
Tải Python:
- Truy cập python.org
- Tải phiên bản mới nhất (hiện tại là Python 3.11)
-
Cài đặt:
- Windows: Chạy file .exe và đánh dấu "Add Python to PATH"
- macOS: Sử dụng Homebrew:
brew install python3 - Linux:
sudo apt-get install python3
2.2. Cài đặt IDE
Các IDE phổ biến cho Python:
-
Visual Studio Code:
- Tải từ code.visualstudio.com
- Cài extension Python
- Ưu điểm: Nhẹ, nhanh, nhiều extension
-
PyCharm:
- Tải từ jetbrains.com/pycharm
- Có phiên bản Community (miễn phí) và Professional
- Ưu điểm: Tính năng phong phú, debug mạnh mẽ
-
Jupyter Notebook:
pip install jupyter
jupyter notebook- Ưu điểm: Tương tác tốt, phù hợp cho phân tích dữ liệu
-
Spyder:
- Cài đặt với Anaconda
- Ưu điểm: Giao diện giống MATLAB, phù hợp cho tính toán

2.3. Cài đặt các thư viện cần thiết
# Cài đặt các thư viện cơ bản
pip install pandas numpy matplotlib seaborn jupyter
# Cài đặt các thư viện cho phân tích tài chính
pip install yfinance scikit-learn ta-lib ccxt backtrader
3. Cú pháp cơ bản và biến trong Python
3.1. Biến và kiểu dữ liệu
Python có nhiều kiểu dữ liệu cơ bản:

# Số nguyên
price = 100
volume = 1000
# Số thực
price_change = -2.5
return_rate = 0.15
# Chuỗi
stock_name = "AAPL"
market = "NASDAQ"
# Boolean
is_trading = True
is_market_open = False
# In ra màn hình
print(f"Stock: {stock_name}, Price: ${price}")
3.2. Cấu trúc dữ liệu
# List (Danh sách)
prices = [100, 102, 98, 105, 103]
print(f"First price: {prices[0]}")
print(f"Last price: {prices[-1]}")
# Dictionary (Từ điển)
stock_info = {
"symbol": "AAPL",
"name": "Apple Inc.",
"price": 150.25,
"volume": 1000000
}
print(f"Stock: {stock_info['name']}")
# Tuple (Bộ)
price_data = (100, 102, 98, 105, 103)
3.3. Cấu trúc điều khiển

# If-else
price = 100
if price > 100:
print("Price is high")
elif price < 90:
print("Price is low")
else:
print("Price is normal")
# For loop
prices = [100, 102, 98, 105, 103]
for price in prices:
print(f"Price: ${price}")
# While loop
count = 0
while count < 5:
print(f"Count: {count}")
count += 1
3.4. Hàm và Module
# Định nghĩa hàm
def calculate_return(initial_price, final_price):
"""Tính toán tỷ suất lợi nhuận"""
return (final_price - initial_price) / initial_price * 100
# Sử dụng hàm
return_rate = calculate_return(100, 110)
print(f"Return rate: {return_rate:.2f}%")
# Import module
import math
import random
from datetime import datetime
4. Bài tập thực hành: Viết chương trình Python đầu tiên
4.1. Chương trình tính lợi nhuận đầu tư
def calculate_return(initial_price, final_price):
"""Tính toán tỷ suất lợi nhuận"""
return (final_price - initial_price) / initial_price * 100
# Nhập dữ liệu
initial_price = float(input("Nhập giá mua: "))
final_price = float(input("Nhập giá bán: "))
# Tính toán và hiển thị kết quả
return_rate = calculate_return(initial_price, final_price)
print(f"Tỷ suất lợi nhuận: {return_rate:.2f}%")
4.2. Chương trình phân tích giá cổ phiếu
import pandas as pd
import matplotlib.pyplot as plt
# Tạo dữ liệu mẫu
dates = pd.date_range(start='2023-01-01', periods=30)
prices = [100 + i + np.random.normal(0, 2) for i in range(30)]
df = pd.DataFrame({'Price': prices}, index=dates)
# Tính toán các chỉ số
df['MA5'] = df['Price'].rolling(window=5).mean()
df['MA20'] = df['Price'].rolling(window=20).mean()
# Vẽ biểu đồ
plt.figure(figsize=(10, 6))
plt.plot(df.index, df['Price'], label='Giá')
plt.plot(df.index, df['MA5'], label='MA5')
plt.plot(df.index, df['MA20'], label='MA20')
plt.title('Phân tích giá cổ phiếu')
plt.xlabel('Ngày')
plt.ylabel('Giá')
plt.legend()
plt.show()
4.3. Bài tập thực hành thêm
- Tính toán chỉ số RSI:
def calculate_rsi(prices, period=14):
"""Tính toán chỉ số RSI (Relative Strength Index)"""
delta = prices.diff()
gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
rs = gain / loss
return 100 - (100 / (1 + rs))
- Phân tích khối lượng giao dịch:
def analyze_volume(volume_data):
"""Phân tích khối lượng giao dịch"""
avg_volume = volume_data.mean()
max_volume = volume_data.max()
min_volume = volume_data.min()
print(f"Khối lượng trung bình: {avg_volume:,.0f}")
print(f"Khối lượng cao nhất: {max_volume:,.0f}")
print(f"Khối lượng thấp nhất: {min_volume:,.0f}")
5. Tổng kết
Trong bài viết này, chúng ta đã tìm hiểu:
- Tại sao Python phù hợp cho phân tích tài chính
- Cách cài đặt môi trường Python và IDE
- Cú pháp cơ bản và biến trong Python
- Viết chương trình Python đầu tiên
Trong các bài tiếp theo, chúng ta sẽ đi sâu vào:
- Phân tích dữ liệu tài chính với pandas
- Trực quan hóa dữ liệu với matplotlib
- Xây dựng chiến lược giao dịch
- Và nhiều chủ đề thú vị khác!
Nguồn dữ liệu tài chính — chọn nguồn nào?
Trước khi viết dòng code nào, bạn cần biết dữ liệu đến từ đâu. Đây là bảng so sánh các nguồn phổ biến:
| Nguồn | Dữ liệu | Có API? | Chi phí | Phù hợp |
|---|---|---|---|---|
Yahoo Finance (yfinance) | Cổ phiếu, ETF, forex, crypto | Có (không chính thức) | Miễn phí | Học tập, nghiên cứu |
| Alpha Vantage | Cổ phiếu, forex, crypto | Có | Miễn phí 25 request/ngày | Thử nghiệm nhỏ |
| Binance / Coinbase | Crypto | Có (REST + WebSocket) | Miễn phí | Crypto, realtime |
| CCXT | 100+ sàn crypto | Có (thống nhất) | Miễn phí | Đa sàn |
| VNStock / SSI | Chứng khoán Việt Nam | Có | Miễn phí có giới hạn | Thị trường VN |
| Vnstock, Fiin | Chứng khoán VN | Có | Trả phí | Dữ liệu chuyên sâu VN |
| tushare | Chứng khoán Trung Quốc | Có | Miễn phí/trả phí | Thị trường TQ |
| FMP / Polygon | Cổ phiếu Mỹ | Có | Trả phí | Production |
⚠️ Lưu ý về
yfinance: đây là thư viện không chính thức, được duy trì bởi cộng đồng. Nó có thể ngừng hoạt động bất cứ lúc nào khi Yahoo đổi API. Tuyệt đối không dùng cho hệ thống giao dịch thật — chỉ dùng để học và nghiên cứu.
Lấy dữ liệu thật — ví dụ với yfinance
import yfinance as yf
import pandas as pd
def lay_du_lieu(ma: str, tu_ngay: str, den_ngay: str) -> pd.DataFrame:
"""Tải dữ liệu OHLCV và chuẩn hoá cột."""
df = yf.download(ma, start=tu_ngay, end=den_ngay,
interval="1d", progress=False, auto_adjust=True)
if df.empty:
raise ValueError(f"Không có dữ liệu cho {ma} trong khoảng đã chọn")
# yfinance trả về MultiIndex khi tải nhiều mã — làm phẳng cho 1 mã
if isinstance(df.columns, pd.MultiIndex):
df.columns = df.columns.get_level_values(0)
df = df.rename(columns={
"Open": "open", "High": "high", "Low": "low",
"Close": "close", "Volume": "volume",
})
df.index.name = "ngay"
return df[['open', 'high', 'low', 'close', 'volume']]
df = lay_du_lieu("FPT.VN", "2023-01-01", "2026-10-01")
print(df.head())
print(f"\n{len(df)} phiên | từ {df.index[0].date()} đến {df.index[-1].date()}")
Cấu trúc dữ liệu OHLCV — hiểu từng cột
| Cột | Ý nghĩa | Lưu ý quan trọng |
|---|---|---|
open | Giá mở cửa phiên | Không phải giá đóng phiên trước |
high | Giá cao nhất trong phiên | Dùng cho ATR, breakout |
low | Giá thấp nhất trong phiên | Dùng cho ATR, stop loss |
close | Giá đóng cửa | Quan trọng nhất — hầu hết chỉ báo dùng cột này |
volume | Khối lượng giao dịch | Xác nhận độ tin cậy của biến động giá |
adj_close | Giá đã điều chỉnh chia tách/cổ tức | Phải dùng cái này cho phân tích dài hạn |
⚠️ Lỗi nghiêm trọng nhiều người mắc: dùng
closethay vìadj_closekhi phân tích cổ phiếu qua nhiều năm có chia tách hoặc trả cổ tức. Kết quả sẽ sai hoàn toàn — bạn sẽ thấy "lợi nhuận" khổng lồ chỉ vì giá được điều chỉnh chia tách.
Kiểm tra chất lượng dữ liệu — bước không được bỏ
Dữ liệu tài chính miễn phí luôn có vấn đề. Hãy kiểm tra trước khi phân tích:
import numpy as np
def kiem_tra_du_lieu(df: pd.DataFrame, ma: str) -> None:
"""Chạy 8 kiểm tra chất lượng và in báo cáo."""
print(f"\n{'=' * 55}\nKIỂM TRA DỮ LIỆU: {ma}\n{'=' * 55}")
# 1. Khoảng thời gian
print(f"1. Khoảng: {df.index[0].date()} → {df.index[-1].date()}")
print(f" Số phiên: {len(df)}")
# 2. Khoảng trống thời gian — dữ liệu bị thiếu
khoang_cach = df.index.to_series().diff().dt.days
nghi = khoang_cach[khoang_cach > 5]
print(f"2. Khoảng trống > 5 ngày: {len(nghi)}")
if len(nghi):
print(f" Lớn nhất: {nghi.max():.0f} ngày")
# 3. Giá trị thiếu
thieu = df.isna().sum()
print(f"3. Giá trị thiếu: {thieu.sum()} "
f"({thieu.sum() / df.size:.2%})")
# 4. Giá <= 0 — luôn là lỗi
gia_vo_ly = (df[['open', 'high', 'low', 'close']] <= 0).sum().sum()
print(f"4. Giá <= 0: {gia_vo_ly} {'⚠️ LỖI' if gia_vo_ly else '✅'}")
# 5. High/Low không nhất quán — dấu hiệu dữ liệu bẩn
sai = ((df['high'] < df['low']) |
(df['high'] < df['open']) |
(df['high'] < df['close']) |
(df['low'] > df['open']) |
(df['low'] > df['close'])).sum()
print(f"5. OHLC không nhất quán: {sai} {'⚠️ LỖI' if sai else '✅'}")
# 6. Phiên không giao dịch (volume = 0)
kl_zero = (df['volume'] == 0).sum()
print(f"6. Phiên volume = 0: {kl_zero}")
# 7. Biến động bất thường — nghi lỗi dữ liệu hoặc chia tách
bien_dong = df['close'].pct_change().abs()
dot_bien = bien_dong[bien_dong > 0.15]
print(f"7. Biến động > 15%/phiên: {len(dot_bien)}")
for ngay in dot_bien.index[:3]:
print(f" {ngay.date()}: {bien_dong[ngay]:.1%}")
# 8. Trùng lặp index
print(f"8. Index trùng: {df.index.duplicated().sum()}")
print()
kiem_tra_du_lieu(df, "FPT.VN")
Vì sao kiểm tra high < low lại quan trọng: đây là dấu hiệu chắc chắn của dữ liệu hỏng. Nếu bạn đưa dữ liệu này vào tính ATR hay Bollinger Bands, kết quả sẽ vô nghĩa và bạn có thể vào lệnh dựa trên tín hiệu sai.
Cài đặt môi trường làm việc
# Tạo môi trường ảo — KHÔNG BAO GIỜ cài trực tiếp vào Python hệ thống
python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate
# Các thư viện nền tảng cho phân tích tài chính
pip install pandas numpy matplotlib seaborn plotly
yfinance jupyter ipykernel pandas-datareader
# Lưu lại phiên bản để tái lập kết quả
pip freeze > requirements.txt
💡 Vì sao phải dùng môi trường ảo: nếu bạn cài trực tiếp vào Python hệ thống, các dự án khác nhau sẽ tranh chấp phiên bản thư viện. Một dự án cần
pandas==2.0, dự án khác cầnpandas==2.2— và bạn không thể có cả hai. Môi trường ảo giải quyết triệt để vấn đề này.
Lưu dữ liệu đúng cách
| Định dạng | Ưu điểm | Nhược điểm | Nên dùng khi |
|---|---|---|---|
| Parquet | Nhỏ, nhanh, giữ kiểu dữ liệu | Khó đọc bằng mắt | Mặc định cho mọi dữ liệu |
| CSV | Đọc được mọi nơi | Lớn, mất kiểu dữ liệu | Trao đổi với người khác |
| Excel | Quen thuộc | Rất chậm với dữ liệu lớn | Báo cáo cho sếp |
| Database | Truy vấn linh hoạt | Cần setup | Dữ liệu lớn, nhiều người dùng |
# Lưu dữ liệu lớn: Parquet
import numpy as np
for f, mo_ta in [("thu-nghiem.parquet", "Parquet"), ("thu-nghiem.csv", "CSV")]:
import os, time
df.to_parquet(f) if f.endswith("parquet") else df.to_csv(f)
t = time.perf_counter()
_ = pd.read_parquet(f) if f.endswith("parquet") else pd.read_csv(f, index_col=0, parse_dates=True)
print(f"{mo_ta}: đọc mất {time.perf_counter() - t:.3f}s | "
f"dung lượng {os.path.getsize(f) / 1024:.0f} KB")
Bốn sai lầm phổ biến nhất khi mới bắt đầu
- Không dùng
parse_dateskhi đọc file → cột ngày là chuỗi, không resample được. - Không
set_indextheo ngày → không dùng được.loc["2026-01"], không resample được. - Bỏ qua kiểm tra chất lượng → kết luận sai vì dữ liệu hỏng.
- Dùng
closethayadj_close→ phân tích cổ phiếu dài hạn hoàn toàn sai lệch.
# Đúng cách đọc dữ liệu đã lưu
df = pd.read_csv(
"du-lieu.csv",
index_col=0,
parse_dates=True, # ← bắt buộc
dtype={"volume": "int64"},
)
df.index = pd.to_datetime(df.index)
df = df.sort_index() # ← luôn sắp xếp theo thời gian