Logo FinLensFinLens Docs

Ví dụ thực chiến — 17 notebook Python

17 Jupyter notebook dùng thư viện finlens phân tích chứng khoán Việt Nam: dashboard thị trường, screener định giá, screener tín hiệu kỹ thuật và backtest.

Kho ví dụ finlens-python-examples gồm 17 Jupyter notebook đi từ lời gọi API đầu tiên tới bốn sản phẩm dùng được hằng ngày. Mọi notebook chạy trên dữ liệu thật, đã thực thi từ đầu tới cuối và commit kèm kết quả — không có số bịa, không có file .csv mẫu.

Chạy thử trong ba phút

Tải kho về và dựng môi trường:

git clone https://github.com/manhhung0221/finlens-python-examples.git
cd finlens-python-examples
python -m venv venv
venv\Scripts\activate
pip install -r requirements.txt

Đặt khoá API — xem Cài đặt và khoá API cho cả bốn cách:

set FINLENS_API_KEY=flk_...

Mở notebook đầu tiên:

jupyter lab notebooks/

Bắt đầu ở notebooks/00-bat-dau/00_bat_dau.ipynb. Notebook tự tìm thư mục gốc để nạp module dùng chung — không cần pip install -e ., không cần đặt PYTHONPATH.

Bốn sản phẩm hoàn chỉnh

Đây là những notebook chạy được hằng ngày, không phải bài tập minh hoạ.

Sản phẩmNotebookLàm gì
Dashboard thị trường14_dashboard_hang_ngayBáo cáo một trang sau phiên ATC — chỉ số, thanh khoản, độ rộng, dòng tiền ngoại, top biến động. Xuất HTML tự chứa, dùng 8 lời gọi API
Screener định giá23_screener_dinh_giaChấm điểm toàn sàn HOSE trên bốn trục, z-score trong từng ngành, xuất Excel
Screener tín hiệu33_screener_tin_hieuQuét 6 tín hiệu kỹ thuật toàn sàn, kèm đo hiệu quả lịch sử từng tín hiệu
Dashboard vĩ mô44_vi_mo_va_thi_truongCPI, GDP, tín dụng, tỷ giá, OMO, xuất nhập khẩu đặt cạnh VNINDEX

Năm nhóm notebook

Notebook chia thành năm thư mục theo chủ đề, mỗi thư mục có mục lục riêng.

Track 0 — Bắt đầu

00_bat_dau — khoá API, whoami()limits(), lời gọi đầu tiên, đơn vị dữ liệu và df.attrs, cây ngoại lệ FinLensError, tham số on_error, cache. Đây là điều kiện tiên quyết cho 16 notebook còn lại.

Track 1 — Thị trường và dòng tiền

OHLCV nhiều mã trong một request · interval · giá điều chỉnh so với giá thô · cây ngành ICB · sức mạnh 19 ngành · độ rộng thị trường · khối ngoại và tự doanh · dòng tiền theo ngành. Kết thúc bằng dashboard thị trường.

Track 2 — Phân tích cơ bản và định giá

statement() dạng long và cây chỉ tiêu · common-size · 181 chỉ tiêu tính sẵn với formulahigher_is_better · DuPont ba và năm tầng · screener định giá · deep-dive 28 ngân hàng niêm yết (NIM, nợ xấu, bao phủ, CIR, LDR).

Track 3 — Phân tích kỹ thuật và backtest

Hai tầng chỉ báo df.finlens.*finlens.ta.* · warm-up và NaN lan · 61 mẫu nến · screener tín hiệu toàn sàn · backtest vectorised tránh look-ahead với CAGR/MDD/Sharpe.

Track 4 — Intraday, phái sinh, vĩ mô

Dữ liệu tick và ba giá trị của side · VWAP · basis VN30F1M · chứng quyền và bẫy đơn vị · 3.348 chuỗi vĩ mô đặt cạnh VNINDEX.

Năm cạm bẫy được đo bằng số

Các notebook không kể lại cạm bẫy — chúng chạy cả cách sai lẫn cách đúng rồi in ra độ lệch. Đây là những con số đo được trên dữ liệu thật:

1. Đơn vị sai âm thầm. Giá cổ phiếu tính bằng nghìn VND, giá chứng quyền bằng VND thô. Sau pd.concat, HPG hiện ra 22.1 nằm cạnh chứng quyền 1630.0 trong cùng một cột close — cả hai đều hợp lệ, và df.attrs mang đơn vị đã biến mất. Đọc df.attrs["finlens"]["units"] trước khi ghép frame.

2. Chỉ báo kỹ thuật trên frame nhiều mã. talib.RSI(df["close"]) lấy 13 giá cuối của mã trước để tính cửa sổ đầu của mã sau. Đo trên frame HPG + VCB 500 dòng: mã đầu đúng hoàn toàn, mã thứ hai sai 174/250 dòng, lệch tới 18 điểm RSI — và mọi giá trị sai đều nằm trong khoảng 0–100 hợp lệ. Dùng df.finlens.rsi(14), nó tự tách nhóm theo symbol.

3. Kỳ của chỉ số tài chính khác nhau theo loại hình doanh nghiệp. Trong period="quarterly", peeps luôn tính trên 4 quý gần nhất, còn roeroa thì tuỳ loại hình: CT phi tài chính cho giá trị riêng quý đó (Q4 ÷ năm ≈ 0,27), NH/CK/BH cho giá trị đã quy về năm (≈ 1,00). Hệ quả: xếp hạng ROE quý đặt VCB ở 18,0% và FPT ở 6,3%, trong khi ROE năm của FPT là 21,4% — cao hơn VCB. Dùng period="annual" cho mọi phép so cắt ngang.

4. Bốn nhóm nhà đầu tư chi tiết cộng lại bằng 0. Mua ròng của nhóm này chính là bán ròng của nhóm kia. Đo trên 114 phiên HPG: tổng bốn nhóm lệch tối đa 2 VND. Cộng chúng với nhóm foreign là đếm hai lần.

5. Backtest không đo giả định của chính nó. Cùng một chiến lược đà tăng cho CAGR −5,70% khi đo đúng và +3,04% khi mắc ba lỗi phổ biến: nhìn trước ở bộ lọc vũ trụ, khớp lệnh cùng phiên tín hiệu, và bỏ qua chi phí giao dịch. Khoảng cách 8,7 điểm phần trăm đó là phương pháp, không phải chiến lược.

Môi trường đã kiểm chứng

Thành phầnPhiên bản
finlens1.3.0
pandas3.0.5
plotly6.x
Python3.12 (thư viện yêu cầu 3.11 trở lên)
Extension VS CodeFinLens.finlens 0.2.7

Toàn bộ 17 notebook đã chạy sạch từ đầu tới cuối bằng jupyter nbconvert --to notebook --execute, không lỗi nào.

Kho ví dụ là dự án riêng, phát hành dưới giấy phép MIT. Notebook không phải khuyến nghị đầu tư: screener thu hẹp danh sách từ 400 mã xuống 20, hai mươi mã đó vẫn cần được đọc từng cái một.

Câu hỏi thường gặp

Có ví dụ code mẫu nào cho thư viện Python finlens không?

Có. Kho `finlens-python-examples` trên GitHub gồm 17 Jupyter notebook chạy trên dữ liệu thật, chia thành năm nhóm theo chủ đề: bắt đầu, thị trường và dòng tiền, phân tích cơ bản và định giá, phân tích kỹ thuật và backtest, rồi intraday cùng vĩ mô. Mỗi notebook đã được thực thi từ đầu tới cuối bằng `jupyter nbconvert --to notebook --execute` và commit kèm kết quả, nên đọc trên GitHub là thấy ngay đầu ra thật chứ không phải chỉ thấy code. Tải về, đặt biến môi trường `FINLENS_API_KEY` rồi mở `notebooks/00-bat-dau/00_bat_dau.ipynb` là chạy lại được toàn bộ.

Làm dashboard thị trường chứng khoán Việt Nam bằng Python thế nào?

Notebook `14_dashboard_hang_ngay` trong kho ví dụ dựng một báo cáo thị trường một trang chỉ bằng 8 lời gọi API: chỉ số VNINDEX và VN30, thanh khoản toàn sàn so với bình quân 20 phiên, độ rộng thị trường (phần trăm số mã nằm trên MA50 cùng số mã tăng giảm), dòng tiền khối ngoại theo ngành ICB, và top biến động đã lọc thanh khoản. Kết quả xuất ra một file HTML tự chứa, mở được không cần mạng vì thư viện plotly.js chỉ nhúng một lần cho cả ba biểu đồ. Chạy được bằng dòng lệnh nên đặt vào Task Scheduler hay cron là có báo cáo tự động mỗi chiều sau phiên ATC.

Viết screener cổ phiếu Việt Nam bằng Python cần lưu ý gì?

Kho ví dụ có hai screener. `23_screener_dinh_gia` chấm điểm toàn sàn HOSE trên bốn trục định giá, sinh lời, tăng trưởng và an toàn tài chính, với ba nguyên tắc: chuẩn hoá z-score trong từng ngành chứ không trên toàn thị trường vì P/E ngân hàng và P/E công nghệ không so được với nhau, cắt đuôi trước khi tính z-score để một mã P/B cực đoan không đè bẹp cả thang, và lấy chiều tốt hay xấu từ cột `higher_is_better` của `indicator_catalog()` thay vì viết tay. `33_screener_tin_hieu` quét sáu tín hiệu kỹ thuật toàn sàn và đo hiệu quả lịch sử từng tín hiệu kèm sai số chuẩn.

Backtest chiến lược chứng khoán bằng Python cần tránh lỗi gì?

Notebook `34_backtest_chien_luoc` đo giá của ba lỗi phổ biến nhất bằng cách chạy cùng một chiến lược theo cả cách đúng lẫn cách sai. Thiên lệch nhìn trước ở bộ lọc vũ trụ xảy ra khi lọc thanh khoản bằng dữ liệu cả kỳ thay vì cửa sổ trượt kết thúc trước ngày ra quyết định. Khớp lệnh cùng phiên tín hiệu giả định mua được ở phiên mà tín hiệu chỉ xuất hiện lúc nó đóng cửa. Bỏ qua chi phí giao dịch biến một chiến lược quay vòng cao thành một chiến lược khác hẳn. Kết quả đo được: cùng chiến lược cho CAGR âm 5,70 phần trăm khi đo đúng và dương 3,04 phần trăm khi mắc cả ba lỗi.

Vì sao không nên dùng talib trực tiếp trên DataFrame nhiều mã?

Vì hàm TA-Lib không biết cột `symbol`. Một DataFrame dạng long chứa nhiều mã xếp chồng lên nhau, nên `talib.RSI(df["close"], 14)` sẽ lấy 13 giá cuối của mã đứng trước để tính cửa sổ đầu tiên của mã đứng sau. Đo trên frame HPG cộng VCB 500 dòng: mã đầu tiên đúng hoàn toàn, mã thứ hai sai 174 trên 250 dòng, lệch tới 18 điểm RSI, và mọi giá trị sai đều nằm trong khoảng 0 đến 100 hợp lệ nên không phép kiểm tự động nào bắt được. Cách đúng là dùng tầng `df.finlens.rsi(14)` — nó tự tách nhóm theo mã và cảnh báo khi dữ liệu chưa sắp xếp.

Cập nhật lần cuối

Nội dung trang