Cài đặt thư viện Python finlens và lấy khoá API
Cài finlens bằng pip trên Python 3.11+, tạo khoá API dạng flk_, đặt biến môi trường FINLENS_API_KEY và chạy truy vấn đầu tiên với client.eod.stock.ohlcv().
Trang này đi từ máy chưa có gì tới lúc bạn cầm trong tay một DataFrame giá cổ
phiếu: cài gói, lấy khoá API, chạy truy vấn đầu tiên, và kiểm chứng rằng
mình đã cài đúng bản.
Cài đặt
Kiểm tra phiên bản Python
Thư viện yêu cầu Python 3.11 trở lên.
python --versionĐây là ràng buộc kéo theo từ pandas 3.0 — dòng pandas này chỉ phát hành wheel cho Python 3.11 đến 3.14.
Cài từ PyPI
pip install finlensLệnh này kéo theo đúng ba phụ thuộc: pandas (từ 3.0), httpx và
packaging. Nếu dùng môi trường ảo, nhớ kích hoạt trước khi cài.
Lấy khoá API
Đăng nhập finlens.vn → Cài đặt tài khoản → mục API Key → bấm Tạo API Key.
Khoá của bản 1.x có dạng flk_....
Đặt khoá vào biến môi trường
# Linux / macOS
export FINLENS_API_KEY="flk_..."# Windows PowerShell
$env:FINLENS_API_KEY = "flk_..."Đây là cách được khuyến nghị — nhờ nó mà mã nguồn của bạn không bao giờ chứa khoá.
Chạy truy vấn đầu tiên
import finlens
client = finlens.client() # đọc FINLENS_API_KEY
df = client.eod.stock.ohlcv("HPG", start="2026-01-01", end="2026-01-05")
print(df) symbol date open high low close volume
0 HPG 2026-01-05 23.57 23.70 22.94 23.17 59427911.0Giá tính bằng nghìn đồng: 23.17 nghĩa là 23.170 VND.
Khoá API chỉ hiện một lần
Sau khi tạo, khoá chỉ hiển thị đúng một lần. Sao chép và cất giữ ngay — mất thì
phải tạo khoá mới. Máy chủ về sau chỉ trả lại 12 ký tự đầu của khoá
(client.whoami()["key"]["prefix"]), không bao giờ trả lại khoá đầy đủ.
Ba cách đưa khoá vào client
Cấu hình được ghép từ nhiều tầng, ưu tiên từ cao xuống thấp: tham số truyền
vào → biến môi trường FINLENS_* → file finlens.toml → mặc định.
import finlens
# 1. Truyền thẳng — tiện khi thử nhanh, đừng commit
client = finlens.client(api_key="flk_...")
# 2. Biến môi trường FINLENS_API_KEY — khuyến nghị
client = finlens.client()
# 3. File cấu hình, khi bạn có nhiều môi trường
client = finlens.client(profile="staging")File cấu hình được tìm ở ./finlens.toml trước, rồi tới thư mục cấu hình của
người dùng (%APPDATA%\finlens\config.toml trên Windows,
~/.config/finlens/config.toml trên Linux và macOS):
[default]
api_key = "flk_..."
[profile.staging]
api_key = "flk_..."Tên profile cũng đọc được từ biến môi trường FINLENS_PROFILE.
Thư viện không tự đọc file `.env`
Một thư viện tự nạp .env của bạn là một tác dụng phụ bất ngờ: nó đọc một file
bạn không hề yêu cầu, và có thể ghi đè biến môi trường bạn đặt có chủ đích. Bản
1.x đã bỏ hẳn hành vi đó. Ai muốn nó thì tự gọi load_dotenv() trong ứng dụng
của mình — một dòng, và là lựa chọn của họ.
Giữ khoá API an toàn
Đừng viết thẳng khoá vào mã nguồn rồi đẩy lên Git. Nếu buộc phải đọc khoá trong code, hãy đọc từ môi trường:
import os
import finlens
client = finlens.client(api_key=os.environ["FINLENS_API_KEY"])Trong notebook dùng chung, finlens.client() không tham số là an toàn nhất:
khoá không xuất hiện ở bất kỳ cell nào, nên nó cũng không nằm trong file .ipynb
bạn gửi đi.
Nếu dùng file finlens.toml trong thư mục dự án, thêm nó vào .gitignore.
Kiểm tra cài đặt thành công
Bốn dòng dưới đây trả lời bốn câu hỏi khác nhau. Chạy hết chúng trước khi kết luận là "cài xong".
import finlens
finlens.__version__ # '1.1.1' — phải bắt đầu bằng số 1
client = finlens.client() # khoá có đúng định dạng không (không chạm mạng)
client.status() # service có sống không
client.whoami() # khoá có thật sự dùng được khôngclient.whoami() là lời gọi đầu tiên thật sự đi ra mạng. Nó trả về gói dịch vụ,
tình trạng khoá và hạn mức:
client.whoami()["account"]["tier"] # 'pro'
client.limits()["requests_remaining"] # 4783
client.limits()["max_symbols_per_request"]Kiểm `finlens.__version__` chứ đừng tin lệnh cài
Trên Python 3.10 hoặc cũ hơn, pip install finlens không báo lỗi — nó lặng
lẽ lùi về một bản 0.1.x cũ, vốn còn nhận Python 3.10. Bản đó có tên hàm khác,
tên cột khác và đơn vị khác, nên mọi ví dụ trong bộ tài liệu này sẽ hỏng theo
những cách khó đoán.
Nếu finlens.__version__ không bắt đầu bằng 1., hãy nâng Python lên 3.11+ rồi
cài lại bằng pip install -U finlens.
client.status() không cần khoá hợp lệ — nó vẫn trả lời khi khoá sai hoặc
đã hết hạn, nên đây là cách phân biệt "service đang có vấn đề" với "khoá của tôi
có vấn đề".
Tạo client không chạm mạng
finlens.client() chỉ kiểm định dạng khoá tại chỗ; việc xác thực thật xảy
ra ở lời gọi dữ liệu đầu tiên. Nhờ vậy đặt nó ở cell đầu notebook hay trong
__init__ của một lớp không bao giờ hỏng vì một trục trặc mạng.
Muốn phát hiện khoá sai ngay lúc khởi động ứng dụng thì gọi connect() — nó chủ
động chạy handshake:
client = finlens.client()
client.connect() # ném lỗi ngay tại đây nếu khoá hỏngĐóng client đúng cách
Client giữ một pool kết nối và một event loop chạy nền. Cả hai được đóng tự động lúc thoát interpreter, nên phần lớn script không phải làm gì. Khi muốn giải phóng sớm, dùng context manager:
import finlens
with finlens.client() as client:
df = client.eod.stock.ohlcv(["HPG", "VCB"], start="2026-01-01")
# Đã đóng, không cần gọi client.close()Bản bất đồng bộ bắt buộc dùng async with (hoặc await client.connect()
trước lời gọi đầu tiên), vì engine phải được tạo trên chính event loop của bạn:
import finlens
async def main():
async with finlens.AsyncClient() as client:
df = await client.eod.stock.ohlcv("HPG")Tuỳ chỉnh client
Mọi tham số đều bỏ trống được, và mỗi cái đều có biến môi trường tương ứng.
| Tham số | Biến môi trường | Ý nghĩa |
|---|---|---|
api_key | FINLENS_API_KEY | Khoá API |
timeout | FINLENS_TIMEOUT | Thời gian chờ tối đa của một request HTTP, tính bằng giây |
deadline | FINLENS_DEADLINE | Ngân sách thời gian cho cả lời gọi, kể cả các lần thử lại |
max_concurrency | FINLENS_MAX_CONCURRENCY | Số request song song tối đa |
max_retries | FINLENS_MAX_RETRIES | Số lần thử lại tối đa cho mỗi request |
profile | FINLENS_PROFILE | Profile trong finlens.toml |
ca_bundle | FINLENS_CA_BUNDLE | Đường dẫn tới CA bundle của tổ chức bạn |
max_concurrency bị kẹp xuống theo giới hạn của gói dịch vụ sau lần handshake
đầu tiên: sự thật của server thắng phỏng đoán của client.
deadline tồn tại vì một lý do rất cụ thể — không có nó, 50 mã × 3 lần thử ×
backoff có thể treo hàng chục phút trong một cell notebook.
Khi có gì đó không chạy
| Triệu chứng | Nguyên nhân thường gặp | Cách xử lý |
|---|---|---|
ConfigurationError: Thiếu API key | Chưa đặt FINLENS_API_KEY, hoặc đã đặt nhưng chưa mở lại terminal | Truyền finlens.client(api_key=...) để kiểm chứng nhanh |
ConfigurationError: API key chứa khoảng trắng | Sao chép khoá từ email hoặc terminal bị ngắt dòng | Dán lại khoá, bỏ mọi khoảng trắng |
InvalidApiKeyError | Khoá sai hoặc đã bị thu hồi | Tạo khoá mới trong tài khoản |
ApiKeyExpiredError / AccountExpiredError | Khoá hoặc gói dịch vụ hết hạn | Kiểm client.whoami()["account"]["expires_at"] |
TlsVerificationError | Máy nằm sau proxy kiểm tra TLS hoặc phần mềm diệt virus | Trỏ tới CA bundle của tổ chức: finlens.client(ca_bundle="/đường/dẫn/ca.pem") hoặc đặt FINLENS_CA_BUNDLE |
AttributeError ở client.eod.market | Đang làm theo tài liệu 0.1.x | Namespace chỉ số nay tên là client.eod.index |
KeyError: 'Date' | Đang làm theo tài liệu 0.1.x | Tên cột nay viết thường: date |
Không có tuỳ chọn tắt xác thực TLS, và đó là chủ ý: tắt nó để sửa một lỗi cấu hình là đổi một phút phiền phức lấy một lỗ hổng vĩnh viễn — trong khi chính khoá API của bạn đi qua đúng kết nối đó.
Danh sách đầy đủ các lớp ngoại lệ và mã lỗi FL_* nằm ở
Xử lý lỗi.
Tiếp theo
Dữ liệu cuối ngày (EOD)
Giá OHLCV của cổ phiếu, chỉ số, phái sinh, chứng quyền, ngành ICB và dòng tiền theo nhóm nhà đầu tư.
Dữ liệu trong phiên
Thanh giá theo phút, từng lệnh khớp và giá trị mua bán chủ động.
Kiểu dữ liệu
Giá trị hợp lệ của từng tham số và hình dạng của client.whoami().
Nhật ký thay đổi
Cái gì vừa đổi, và những thay đổi phá vỡ tương thích khi lên 1.x.
Khi báo lỗi, gửi kèm kết quả của finlens.build_info() — phần lớn thư viện được
biên dịch, nên số phiên bản một mình không đủ để dựng lại đúng bản build bạn
đang chạy.
>>> finlens.build_info()
{'version': '1.1.1', 'commit': 'a1b2c3d', 'built_at': '...', 'cython': '3.2.9',
'python': '3.12', 'platform': 'windows-amd64'}Câu hỏi thường gặp
Cài đặt thư viện Python finlens bằng lệnh nào?
Cài từ PyPI bằng `pip install finlens`. Thư viện yêu cầu Python từ 3.11 trở lên, kiểm bằng `python --version` trước khi cài — ràng buộc này kéo theo từ pandas 3.0, dòng pandas chỉ phát hành wheel cho Python 3.11 đến 3.14. Lệnh cài chỉ thêm ba phụ thuộc: `pandas`, `httpx` và `packaging`. Nếu dùng môi trường ảo thì kích hoạt trước khi cài. Cài xong, kiểm `finlens.__version__` — nó phải bắt đầu bằng `1.`.
Khoá API của FinLens lấy ở đâu và có dạng như thế nào?
Đăng nhập finlens.vn, vào Cài đặt tài khoản, mở mục API Key rồi bấm Tạo API Key. Khoá của bản 1.x có tiền tố `flk_`. Khoá chỉ hiển thị đúng một lần sau khi tạo nên phải sao chép và cất giữ ngay; làm mất thì tạo khoá mới. Về sau máy chủ chỉ trả lại 12 ký tự đầu của khoá, đọc bằng `client.whoami()["key"]["prefix"]`, chứ không bao giờ trả lại khoá đầy đủ.
Nên lưu khoá API thế nào cho an toàn khi viết code Python?
Đừng viết thẳng khoá vào mã nguồn rồi đẩy lên Git. Với thư viện Python finlens, cách được khuyến nghị là đặt khoá vào biến môi trường `FINLENS_API_KEY` rồi gọi `finlens.client()` không tham số — khoá không xuất hiện ở cell nào nên cũng không nằm trong file `.ipynb` bạn gửi đi. Trên Linux và macOS dùng `export FINLENS_API_KEY="flk_..."`, trên Windows PowerShell dùng `$env:FINLENS_API_KEY = "flk_..."`. Nếu dùng file `finlens.toml` trong thư mục dự án thì thêm nó vào `.gitignore`.
Làm sao kiểm tra đã cài đúng bản và khoá API còn dùng được?
Chạy bốn dòng của thư viện Python finlens, mỗi dòng trả lời một câu hỏi khác nhau: `finlens.__version__` phải bắt đầu bằng `1.`; `finlens.client()` kiểm định dạng khoá tại chỗ mà không chạm mạng; `client.status()` cho biết dịch vụ có sống không và trả lời được cả khi khoá sai hoặc hết hạn; `client.whoami()` là lời gọi thật đầu tiên, trả về gói dịch vụ, tình trạng khoá và hạn mức. Hạn mức còn lại đọc bằng `client.limits()["requests_remaining"]`.
Vì sao pip lại cài về một bản finlens 0.1.x cũ?
Vì máy đang chạy Python 3.10 hoặc cũ hơn. Bản 1.x khai `requires-python >= 3.11`, nên trên Python cũ `pip install finlens` không báo lỗi mà lặng lẽ lùi về một bản 0.1.x — bản đó có tên hàm khác, tên cột khác và đơn vị khác, nên mọi ví dụ trong bộ tài liệu này sẽ hỏng theo những cách khó đoán. Kiểm bằng `finlens.__version__`; nếu nó không bắt đầu bằng `1.` thì nâng Python lên 3.11+ rồi chạy `pip install -U finlens`.
Cập nhật lần cuối