# FinLens Docs — Toàn văn tài liệu > Tài liệu hướng dẫn hệ sinh thái FinLens: nền tảng web finlens.vn, thư viện Python finlens và FinLens MCP cho trợ lý AI. Dữ liệu chứng khoán Việt Nam cho nhà đầu tư và lập trình viên. --- # Báo cáo phân tích CTCK & giá mục tiêu đồng thuận bằng AI URL: https://docs.finlens.vn/mcp/bao-cao-ctck Mô tả: Hỏi AI để tra báo cáo phân tích từ 20+ CTCK như SSI, VND, MBS, đọc tóm tắt PDF và xem đồng thuận giá mục tiêu, upside %, tỷ lệ MUA/NẮM GIỮ/BÁN của từng mã. Tóm tắt: FinLens MCP cho phép nhà đầu tư Việt Nam hỏi Claude, ChatGPT hoặc Gemini để tra cứu báo cáo phân tích từ hơn 20 công ty chứng khoán như SSI, VND, MBS, BSC, VPS, ACBS, Yuanta, Mirae Asset và KB Securities, gồm cả báo cáo theo mã, theo ngành lẫn vĩ mô. Ba công cụ đảm nhận việc này: `research_list_reports` tìm báo cáo theo mã, theo CTCK phát hành, theo khoảng thời gian hoặc theo từ khóa chủ đề; `research_read_report` đọc tối đa 10 trang PDF để AI tóm tắt luận điểm, giá mục tiêu, rủi ro và catalyst; `research_get_analyst_consensus` tổng hợp giá mục tiêu trung vị, cao nhất, thấp nhất, upside % so giá hiện tại và phân bổ khuyến nghị MUA/NẮM GIỮ/BÁN. Tính năng đọc báo cáo CTCK yêu cầu gói FinLens Pro. Sản phẩm: mcp ⏱ Đọc 8 phút · 🟢 Mọi cấp độ · 🔧 Yêu cầu: FinLens Pro ## Giá trị của báo cáo CTCK — tại sao cần đọc? [#giá-trị-của-báo-cáo-ctck--tại-sao-cần-đọc] Báo cáo phân tích từ CTCK cung cấp những thông tin mà dữ liệu tài chính thô không có: * **Luận điểm đầu tư** — lý do cụ thể tại sao cổ phiếu đáng mua hoặc bán * **Cập nhật tin tức ngành** — xu hướng cung cầu, chính sách, đối thủ cạnh tranh * **Mô hình định giá** — cách CTCK tính giá mục tiêu (DCF, P/E tương đối…) * **Rủi ro cụ thể** — những gì có thể làm luận điểm sai * **Đồng thuận thị trường** — sentiment của cộng đồng phân tích chuyên nghiệp Tổng hợp từ 20+ CTCK lớn như SSI, VND, MBS, BSC, VPS, ACBS, VNDS, Yuanta, Mirae Asset, KB Securities… cả báo cáo mã, ngành lẫn vĩ mô/thị trường chung. ## Tìm báo cáo theo mã cổ phiếu [#tìm-báo-cáo-theo-mã-cổ-phiếu] **Có báo cáo phân tích nào về MWG mới nhất không? Tóm tắt luận điểm chính và giá mục tiêu từ các CTCK** → research_list_reports: ticker=MWG, sort=newest — danh sách báo cáo + tóm tắt tiêu đề **Cho tôi xem các báo cáo của SSI Research về HPG trong 3 tháng gần nhất — họ đã thay đổi quan điểm như thế nào?** → list_reports: ticker=HPG, source=SSI, period=3mo — thấy quá trình thay đổi khuyến nghị **Tìm báo cáo nào gần đây đề cập đến "lãi suất" và "ngân hàng" — tổng hợp quan điểm về triển vọng nhóm ngân hàng** → list_reports: query="lãi suất ngân hàng", scope=industry — tổng hợp nhiều báo cáo ## Đọc nội dung PDF báo cáo [#đọc-nội-dung-pdf-báo-cáo] Công cụ `research_read_report` đọc nội dung tối đa 10 trang PDF và để AI tóm tắt — tiết kiệm thời gian đọc hàng chục trang: **Đọc báo cáo mới nhất của VND Research về VIC — tóm tắt: luận điểm chính, giá mục tiêu, rủi ro và catalyst ngắn hạn** → list_reports (lấy ID) → read_report (đọc PDF) → AI tóm tắt 4 mục **So sánh quan điểm của SSI và MBS về cổ phiếu HPG — ai lạc quan hơn? Lý do khác biệt chủ yếu là gì?** → đọc 2 báo cáo khác nhau, tổng hợp điểm giống/khác về luận điểm, định giá và rủi ro **Trong báo cáo của KB Securities về FPT, họ dự báo doanh thu và lợi nhuận năm 2025 là bao nhiêu? Giả định nào họ dùng?** → read_report: trích xuất bảng dự báo và giả định định giá từ PDF ## Đồng thuận giá mục tiêu [#đồng-thuận-giá-mục-tiêu] Công cụ `research_get_analyst_consensus` tổng hợp từ tất cả khuyến nghị đang hiệu lực: * **Giá mục tiêu**: trung vị, cao nhất, thấp nhất * **Upside %**: khoảng cách từ giá hiện tại đến giá mục tiêu trung vị * **Phân bổ khuyến nghị**: số lượng MUA / NẮM GIỮ / BÁN * **Cập nhật mới nhất**: khi nào khuyến nghị cuối được đưa ra Nếu cổ phiếu đã chia tách hoặc trả cổ tức bằng cổ phiếu SAU ngày báo cáo phát hành, giá mục tiêu in trong báo cáo nằm ở thang giá cũ — so thẳng với giá hôm nay sẽ thổi phồng upside. Công cụ tự quy đổi về thang giá hiện tại theo hệ số điều chỉnh của **phiên giao dịch gần nhất tính đến ngày phát hành** (báo cáo ra thứ Bảy/Chủ nhật hoặc ngày nghỉ lễ thì lùi về phiên liền trước). Con số nguyên bản trong báo cáo vẫn được giữ ở trường `target_price_reported` để bạn đối chiếu. **Giá mục tiêu đồng thuận của VCB từ các CTCK là bao nhiêu? Upside so giá hiện tại là bao nhiêu %? Bao nhiêu CTCK đang khuyến nghị MUA?** → research_get_analyst_consensus: VCB — trung vị/cao/thấp, upside %, phân bổ MUA/NẮM GIỮ/BÁN **So sánh đồng thuận CTCK giữa VCB, BID và CTG — mã ngân hàng nào đang được kỳ vọng upside nhiều nhất?** → consensus cho 3 mã, xếp hạng theo upside % và tỷ lệ MUA **Trong 1 tháng qua, các CTCK có nâng hay hạ giá mục tiêu HPG? Sentiment đang cải thiện hay xấu đi?** → list_reports 1 tháng + consensus — phát hiện xu hướng revision tăng/giảm giá mục tiêu ## Báo cáo ngành & vĩ mô [#báo-cáo-ngành--vĩ-mô] **Có báo cáo nào gần đây về ngành bất động sản không? Tóm tắt các luận điểm chính về triển vọng phục hồi** → list_reports: scope=industry, query="bất động sản" — có thể nhiều báo cáo từ nhiều CTCK **Các CTCK đang nhận định thị trường VN cuối năm 2025 thế nào? Tổng hợp quan điểm về VNINDEX và nhóm cổ phiếu được ưa thích** → list_reports: scope=market — báo cáo chiến lược thị trường, tổng hợp quan điểm chung ## Kết hợp báo cáo CTCK với phân tích tự làm [#kết-hợp-báo-cáo-ctck-với-phân-tích-tự-làm] **Phân tích toàn diện VNM: 1. Chỉ tiêu tài chính cơ bản (ROE, FCF, định giá) 2. Chất lượng kế toán (fundamental\_quality\_scan) 3. Đồng thuận CTCK — giá mục tiêu và upside 4. Tóm tắt báo cáo mới nhất — luận điểm chính 5. So sánh quan điểm của tôi với đồng thuận CTCK** → AI tích hợp dữ liệu tài chính + báo cáo CTCK + consensus thành bài phân tích đa chiều Khi 80%+ CTCK khuyến nghị MUA một mã, thị trường thường đã phản ánh rồi. Ngược lại, mã bị nhiều CTCK bán nhưng đang cải thiện cơ bản có thể là cơ hội bị bỏ qua. ## Bài liên quan [#bài-liên-quan] Làm phân tích của mình trước khi đọc quan điểm CTCK — tránh anchoring bias. Xem dòng tiền thực tế sau khi có quan điểm từ CTCK. Chuỗi đầy đủ FinLens MCP. ### Câu hỏi thường gặp **Xem giá mục tiêu đồng thuận của cổ phiếu ở đâu?** Công cụ `research_get_analyst_consensus` của FinLens MCP tổng hợp toàn bộ khuyến nghị đang hiệu lực của một mã và trả về giá mục tiêu trung vị, cao nhất, thấp nhất, upside % so với giá hiện tại, phân bổ số lượng khuyến nghị MUA/NẮM GIỮ/BÁN và thời điểm khuyến nghị gần nhất. Nhà đầu tư chỉ cần hỏi Claude, ChatGPT hoặc Gemini theo dạng: "Giá mục tiêu đồng thuận của VCB là bao nhiêu, upside so giá hiện tại bao nhiêu %?". Có thể hỏi nhiều mã cùng lúc để xếp hạng theo upside và tỷ lệ khuyến nghị MUA, ví dụ so sánh VCB, BID và CTG. **AI có tóm tắt được báo cáo phân tích dạng PDF không?** Công cụ `research_read_report` của FinLens MCP đọc tối đa 10 trang nội dung PDF của báo cáo, sau đó AI tóm tắt luận điểm chính, giá mục tiêu, rủi ro và catalyst ngắn hạn. Quy trình thông thường là dùng `research_list_reports` để lấy ID báo cáo cần đọc rồi chuyển sang `research_read_report`. Cách này cũng dùng được để trích xuất bảng dự báo doanh thu, lợi nhuận và các giả định định giá nằm trong báo cáo, hoặc để so sánh quan điểm của hai CTCK về cùng một mã. **FinLens MCP có báo cáo phân tích của những công ty chứng khoán nào?** FinLens MCP tổng hợp báo cáo từ hơn 20 công ty chứng khoán lớn tại Việt Nam, trong đó có SSI, VND, MBS, BSC, VPS, ACBS, VNDS, Yuanta, Mirae Asset và KB Securities. Kho báo cáo gồm cả báo cáo theo mã cổ phiếu, báo cáo ngành và báo cáo vĩ mô/chiến lược thị trường chung. Công cụ `research_list_reports` cho phép lọc theo mã, theo CTCK phát hành, theo khoảng thời gian hoặc theo từ khóa chủ đề. Tính năng đọc báo cáo CTCK yêu cầu gói FinLens Pro. **Giá mục tiêu trong báo cáo cũ có bị lệch khi cổ phiếu chia tách không?** Nếu cổ phiếu chia tách hoặc trả cổ tức bằng cổ phiếu sau ngày báo cáo phát hành, giá mục tiêu in trong báo cáo nằm ở thang giá cũ, nên so thẳng với giá hôm nay sẽ thổi phồng upside. FinLens MCP tự quy đổi giá mục tiêu về thang giá hiện tại theo hệ số điều chỉnh của phiên giao dịch gần nhất tính đến ngày phát hành; báo cáo ra thứ Bảy, Chủ nhật hoặc ngày nghỉ lễ thì lùi về phiên liền trước. Con số nguyên bản trong báo cáo vẫn được giữ ở trường `target_price_reported` để nhà đầu tư đối chiếu. --- # Kết nối FinLens MCP với Claude AI và ChatGPT dưới 2 phút URL: https://docs.finlens.vn/mcp/bat-dau Mô tả: Hướng dẫn kết nối FinLens MCP vào Claude Desktop, Claude.ai và ChatGPT qua OAuth trong dưới 2 phút để hỏi AI về giá và báo cáo tài chính cổ phiếu Việt Nam. Tóm tắt: FinLens MCP là MCP server cung cấp dữ liệu chứng khoán Việt Nam cho Claude Desktop, Claude.ai và ChatGPT thông qua URL https://mcp.finlens.vn/mcp và xác thực OAuth, phủ hơn 1.700 cổ phiếu HOSE/HNX/UPCOM. Quy trình kết nối gồm thêm custom connector trong Claude Desktop hoặc Integrations trên Claude.ai, tạo ứng dụng OAuth trong phần Cài đặt → Ứng dụng của ChatGPT, sau đó gửi một câu hỏi kiểm tra để AI gọi stocks_get_latest_quote và stocks_get_profile. Việc kết nối yêu cầu tài khoản FinLens Pro hoặc Premium, thường mất dưới 2 phút, và mỗi tài khoản chỉ duy trì đồng thời 1 phiên Claude và 1 phiên ChatGPT. Sản phẩm: mcp ⏱ Đọc 8 phút · 🟢 Dành cho người mới bắt đầu · 🔧 Yêu cầu: tài khoản FinLens Pro hoặc Premium ## MCP là gì và tại sao dùng? [#mcp-là-gì-và-tại-sao-dùng] **MCP (Model Context Protocol)** là chuẩn mở cho phép các AI như Claude hay ChatGPT kết nối trực tiếp với nguồn dữ liệu bên ngoài theo thời gian thực — thay vì chỉ dựa vào kiến thức cũ trong tập huấn luyện. Khi bạn kết nối **FinLens MCP**, trợ lý AI của bạn sẽ có thể: * Truy xuất **giá, khối lượng, báo cáo tài chính** của 1.700+ cổ phiếu HOSE/HNX/UPCOM * Theo dõi **dòng tiền khối ngoại, smart money** và dòng tiền chủ động trong phiên * Đọc **báo cáo phân tích từ 20+ CTCK**, tóm tắt và so sánh khuyến nghị * Chạy **backtest chiến lược**, tối ưu tham số và phân tích danh mục * Xem **số liệu kinh tế vĩ mô GSO** và dữ liệu xuất nhập khẩu Hải quan Không có MCP, AI chỉ biết dữ liệu đến ngày huấn luyện (thường là năm ngoái). Với FinLens MCP, AI biết giá hôm nay, BCTC quý mới nhất và dòng tiền đang diễn ra trong phiên. ## Yêu cầu trước khi bắt đầu [#yêu-cầu-trước-khi-bắt-đầu] * **Tài khoản FinLens Pro hoặc Premium** — [Xem bảng giá tại đây](https://finlens.vn/pricing). Gói Pro gồm phân tích cơ bản, dòng tiền và báo cáo CTCK. Gói Premium thêm backtest, tối ưu danh mục và tín hiệu kỹ thuật. * **Ứng dụng AI hỗ trợ MCP:** Claude Desktop (Mac/Windows), Claude.ai (web) hoặc ChatGPT (free & Plus đều được). * **Trình duyệt** để hoàn tất xác thực OAuth khi kết nối lần đầu. Mỗi tài khoản FinLens chỉ được kết nối **1 Claude** và **1 ChatGPT** đồng thời. Nếu kết nối thiết bị mới, phiên cũ sẽ tự ngắt — bảo vệ tài khoản khỏi chia sẻ trái phép. ## Kết nối với Claude [#kết-nối-với-claude] Xem video hướng dẫn kết nối FinLens với Claude, hoặc làm theo các bước bên dưới: ### Cách A: Claude Desktop (khuyến nghị) [#cách-a-claude-desktop-khuyến-nghị] ### Tải Claude Desktop [#tải-claude-desktop] Tải tại [claude.ai/download](https://claude.ai/download) (Mac hoặc Windows). Đăng nhập tài khoản Anthropic (gói Pro hoặc Max). ### Mở Settings → Connectors → Add Custom [#mở-settings--connectors--add-custom] Vào **Settings** (bánh răng góc trên phải) → **Connectors** → **Add custom connector**. Dán URL: `https://mcp.finlens.vn/mcp` Đặt tên tuỳ ý, ví dụ: *FinLens VN* ### Đăng nhập FinLens [#đăng-nhập-finlens] Trình duyệt sẽ mở trang xác thực **finlens.vn/connect**. Đăng nhập tài khoản FinLens → Chọn **"Đồng ý & Kết nối"**. Tự động quay lại Claude. ### Kiểm tra connector xuất hiện [#kiểm-tra-connector-xuất-hiện] Trong chat mới, nhìn góc dưới phải — biểu tượng FinLens (F xanh) sẽ hiện trong phần *Tools*. Vậy là xong! ### Cách B: Claude.ai (trên web) [#cách-b-claudeai-trên-web] Vào [claude.ai](https://claude.ai) → menu trái → **Integrations** → **Add integration** → Dán URL `https://mcp.finlens.vn/mcp` → làm theo hướng dẫn xác thực. ## Kết nối với ChatGPT [#kết-nối-với-chatgpt] Xem video hướng dẫn kết nối FinLens với ChatGPT, hoặc làm theo các bước bên dưới: ### Vào Cài đặt → Ứng dụng → Tạo ứng dụng [#vào-cài-đặt--ứng-dụng--tạo-ứng-dụng] Mở [chatgpt.com](https://chatgpt.com), click avatar → **Cài đặt** → chọn tab **Ứng dụng** → bấm **Thêm nhiều hơn** → **Tạo ứng dụng**. ### Điền thông tin & chọn OAuth [#điền-thông-tin--chọn-oauth] Điền tên ứng dụng (vd: *FinLens*), dán URL kết nối: `https://mcp.finlens.vn/mcp`, chọn phương thức Xác thực **OAuth**, tích chọn "Tôi hiểu và muốn tiếp tục" rồi bấm **Tạo**. ### Đăng nhập & xác thực FinLens [#đăng-nhập--xác-thực-finlens] ChatGPT hiện màn xác nhận — bấm **Đăng nhập bằng FinLens**. Trình duyệt mở trang xác thực FinLens: đăng nhập tài khoản, đồng ý cấp quyền → quay lại ChatGPT. ### Làm mới để kích hoạt [#làm-mới-để-kích-hoạt] Sau khi kết nối xong, vào **Thông tin** của ứng dụng vừa tạo → bấm nút **Làm mới**. Đợi ChatGPT báo trạng thái thành công — FinLens xuất hiện trong danh sách ứng dụng đã kích hoạt là hoàn tất. ## Kiểm tra kết nối [#kiểm-tra-kết-nối] Gửi câu hỏi đơn giản để xác nhận kết nối hoạt động: **Cho tôi biết giá hiện tại và thông tin cơ bản của VNM** AI sẽ gọi stocks_get_latest_quote + stocks_get_profile. Nếu ra kết quả thật = kết nối thành công ✓ Nếu AI trả lời "Tôi không có công cụ để xem giá cổ phiếu" → kết nối chưa thành công. Kiểm tra lại URL và thử đăng xuất rồi kết nối lại. ## 5 câu hỏi đầu tiên nên thử [#5-câu-hỏi-đầu-tiên-nên-thử] **Giá đóng cửa hôm nay của HPG là bao nhiêu? Thay đổi so với hôm qua?** **P/E và ROE hiện tại của FPT là bao nhiêu? So với ngành viễn thông thế nào?** **Khối ngoại đang mua hay bán ròng VCB trong 10 phiên gần nhất?** **Các CTCK đang khuyến nghị MWG gì? Giá mục tiêu đồng thuận là bao nhiêu?** **Phân tích toàn diện cổ phiếu HPG: tài chính 5 năm, DuPont, chất lượng kế toán và so sánh với ngành thép** ## Câu hỏi thường gặp [#câu-hỏi-thường-gặp] Thường dưới 2 phút — chủ yếu là thời gian đăng nhập và xác nhận OAuth. Gói Free không hỗ trợ MCP. Cần ít nhất gói **Pro** để kết nối. Xem [bảng giá](https://finlens.vn/pricing). Mỗi nền tảng (Claude hoặc ChatGPT) chỉ duy trì 1 phiên active. Kết nối thiết bị mới sẽ tự ngắt thiết bị cũ cùng nền tảng. Vào [finlens.vn](https://finlens.vn) → Hồ sơ → mục **Kết nối AI** để xem và thu hồi từng phiên. Cửa sổ Cài đặt tài khoản trên finlens.vn, mục Kết nối AI hiển thị phiên Claude đang hoạt động kèm nút Thu hồi Mục **Kết nối AI** trong Cài đặt tài khoản — xem phiên đang hoạt động và bấm **Thu hồi** để ngắt quyền truy cập. ## Bài liên quan [#bài-liên-quan] 7 nhóm KPI, báo cáo tài chính TTM, thẩm định chất lượng kế toán. Theo dõi tiền vào/ra của từng nhóm nhà đầu tư theo thời gian thực. Từ kỹ thuật, danh mục, báo cáo CTCK đến kinh tế vĩ mô. ### Câu hỏi thường gặp **Làm sao cho ChatGPT hoặc Claude xem được giá cổ phiếu Việt Nam theo thời gian thực?** Trợ lý AI chỉ biết những gì có trong dữ liệu huấn luyện, nên không tự xem được giá cổ phiếu Việt Nam hôm nay. Cách nối là thêm một MCP server vào phần connector của trợ lý — với thị trường Việt Nam là FinLens MCP tại https://mcp.finlens.vn/mcp — rồi đăng nhập qua OAuth. Sau bước đó, hỏi "Giá VNM hôm nay bao nhiêu?" thì AI gọi công cụ stocks_get_latest_quote và trả về giá thật của phiên gần nhất trên HOSE, HNX hoặc UPCOM. **Làm sao kết nối FinLens MCP với Claude Desktop?** Trong Claude Desktop, vào Settings → Connectors → Add custom connector, dán URL https://mcp.finlens.vn/mcp và đặt tên tuỳ ý. Trình duyệt sẽ mở trang xác thực finlens.vn/connect để đăng nhập tài khoản FinLens và bấm "Đồng ý & Kết nối", sau đó tự động quay lại Claude. Khi biểu tượng FinLens xuất hiện trong phần Tools ở khung chat mới là đã kết nối xong. Trên Claude.ai bản web, làm tương tự qua menu trái → Integrations → Add integration với cùng URL đó. **Kết nối FinLens MCP với ChatGPT như thế nào?** Mở chatgpt.com, click avatar → Cài đặt → tab Ứng dụng → Thêm nhiều hơn → Tạo ứng dụng. Điền tên ứng dụng, dán URL kết nối https://mcp.finlens.vn/mcp, chọn phương thức xác thực OAuth rồi bấm Tạo; tiếp đó bấm "Đăng nhập bằng FinLens" và đồng ý cấp quyền trên trình duyệt. Cuối cùng vào mục Thông tin của ứng dụng vừa tạo và bấm nút Làm mới để kích hoạt. Cả ChatGPT bản Free và Plus đều kết nối được. **Gói Free của FinLens có dùng được MCP không?** Gói Free không hỗ trợ MCP, cần tối thiểu gói Pro để kết nối FinLens MCP với Claude hoặc ChatGPT. Gói Pro gồm phân tích cơ bản, dòng tiền và báo cáo phân tích từ hơn 20 công ty chứng khoán; gói Premium bổ sung backtest chiến lược, tối ưu danh mục và tín hiệu kỹ thuật. Bảng giá được công bố tại finlens.vn/pricing. **Làm sao biết FinLens MCP đã kết nối thành công?** Gửi cho AI câu kiểm tra: "Cho tôi biết giá hiện tại và thông tin cơ bản của VNM". Nếu kết nối thành công, AI sẽ gọi hai công cụ stocks_get_latest_quote và stocks_get_profile rồi trả về số liệu thật. Nếu AI trả lời rằng không có công cụ để xem giá cổ phiếu thì kết nối chưa hoàn tất — kiểm tra lại URL https://mcp.finlens.vn/mcp, đăng xuất rồi kết nối lại. Các phiên đã kết nối có thể xem và thu hồi tại finlens.vn → Hồ sơ → mục Kết nối AI. --- # Cẩm nang 107 công cụ FinLens MCP phân tích chứng khoán URL: https://docs.finlens.vn/mcp/cam-nang-cong-cu Mô tả: Danh sách đầy đủ 107 công cụ FinLens MCP theo 12 nhóm: giá, báo cáo tài chính, dòng tiền, kỹ thuật, chứng quyền, vĩ mô, cổ tức, tin tức — kèm câu hỏi mẫu. Tóm tắt: Cẩm nang công cụ FinLens MCP trình bày 12 nhóm công cụ phân tích chính cùng bảng tra cứu đầy đủ 107 công cụ kèm tham số: tìm kiếm và hồ sơ doanh nghiệp (stocks_search, stocks_get_profile, stocks_get_latest_quote), phân tích tài chính cơ bản (fundamental_get_key_metrics, fundamental_dupont, fundamental_compare_peers), dòng tiền khối ngoại và tự doanh (flows_get_stock_flow), báo cáo công ty chứng khoán, tín hiệu kỹ thuật và backtest (signals_screen, signals_backtest), danh mục đầu tư, chứng quyền, vĩ mô và xuất nhập khẩu, cổ tức, quỹ đầu tư, trái phiếu doanh nghiệp và tin tức phân tích bằng AI. FinLens MCP là MCP server kết nối Claude và ChatGPT với dữ liệu hơn 1.700 mã cổ phiếu trên HOSE, HNX và UPCOM, cho phép nhà đầu tư Việt Nam hỏi bằng tiếng Việt tự nhiên và nhận số liệu thực thay vì ước lượng. Tài liệu kèm hơn 30 câu hỏi mẫu copy-dán được, hướng dẫn kết nối qua URL https://mcp.finlens.vn/mcp và các lưu ý về dữ liệu EOD. Sản phẩm: mcp ## Cách sử dụng [#cách-sử-dụng] Không cần học lệnh, không cần code. Chỉ cần hỏi bằng tiếng Việt tự nhiên. ### Đặt câu hỏi [#đặt-câu-hỏi] Nhập câu hỏi tự nhiên về cổ phiếu, ngành, hay thị trường. Ví dụ: *"Phân tích tài chính HPG 5 năm gần nhất"* ### AI xử lý & gọi tool [#ai-xử-lý--gọi-tool] FinLens MCP tự động nhận diện yêu cầu, gọi đúng công cụ và lấy dữ liệu thực từ thị trường. ### Nhận phân tích [#nhận-phân-tích] Kết quả được trình bày rõ ràng kèm bảng, biểu đồ, và nhận định — không phải dữ liệu thô khó đọc. ### Hỏi thêm & đào sâu [#hỏi-thêm--đào-sâu] Tiếp tục đặt câu hỏi follow-up trong cùng cuộc trò chuyện để phân tích ngày càng sâu hơn. ## Kết nối FinLens MCP với Claude & ChatGPT [#kết-nối-finlens-mcp-với-claude--chatgpt] Mỗi nền tảng có video hướng dẫn riêng — chọn đúng trợ lý AI bạn dùng và làm theo các bước bên dưới. Kết nối một lần, dùng mãi mãi. 1. Tải **Claude Desktop** ([claude.ai/download](https://claude.ai/download)) hoặc mở **Claude.ai** trên web, đăng nhập gói Pro/Max. 2. Vào **Settings → Connectors → Add custom connector** (Claude.ai: **Integrations → Add integration**). Dán URL: `https://mcp.finlens.vn/mcp` 3. Trình duyệt mở **finlens.vn/connect** — đăng nhập FinLens rồi chọn **"Đồng ý & Kết nối"**, tự động quay lại Claude. 4. Connector FinLens hiện ra là xong — thử hỏi ngay *"VNM giá bao nhiêu?"*. 1. Mở [chatgpt.com](https://chatgpt.com) → avatar → **Cài đặt → tab Ứng dụng → Thêm nhiều hơn → Tạo ứng dụng**. 2. Điền tên (vd *FinLens*), dán URL, chọn Xác thực **OAuth**, tích "Tôi hiểu và muốn tiếp tục" rồi bấm **Tạo**: `https://mcp.finlens.vn/mcp` 3. Bấm **"Đăng nhập bằng FinLens"** — đăng nhập & đồng ý cấp quyền, quay lại ChatGPT. 4. Vào **Thông tin** ứng dụng vừa tạo → bấm **Làm mới**, chờ báo thành công là hoàn tất. 💡 Cần hướng dẫn chi tiết kèm ảnh chụp màn hình và xử lý sự cố? Xem [**Bài 1 · Bắt đầu**](/mcp/bat-dau). Mỗi tài khoản FinLens kết nối đồng thời 1 Claude và 1 ChatGPT; gói Free của cả hai nền tảng chưa hỗ trợ MCP. *** ## 12 nhóm công cụ phân tích [#12-nhóm-công-cụ-phân-tích] Mỗi nhóm bao gồm nhiều công cụ chuyên biệt, tự động được AI lựa chọn phù hợp với câu hỏi của bạn. ### Tìm kiếm & Hồ sơ doanh nghiệp [#tìm-kiếm--hồ-sơ-doanh-nghiệp] Tra cứu thông tin cơ bản và giá mới nhất của bất kỳ mã nào trên HOSE/HNX/UPCOM | Công cụ | Chức năng | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------- | | `stocks_search` | Tìm mã theo tên hoặc mã cổ phiếu | | `stocks_get_profile` | Hồ sơ doanh nghiệp: sàn, ngành ICB, số CP lưu hành | | `stocks_get_latest_quote` | Giá EOD mới nhất: OHLCV, giá trị giao dịch | | `stocks_get_price_history` | Chuỗi lịch sử giá (tối đa 500 phiên) để phân tích kỹ thuật | | `stocks_session_recap` | Diễn biến MỘT mã trong phiên: giá/VWAP/gap, hình dạng phiên, dòng tiền chủ động, KL so trung bình (pro-rate), khối ngoại | | `stocks_supply_demand` | Cung-cầu ĐẶT lệnh theo phiên: bên nào áp đảo, lệnh to hay nhỏ, phát hiện phân kỳ "cung/cầu bị che" (lệnh đặt ≠ lệnh khớp) | ### Phân tích tài chính cơ bản [#phân-tích-tài-chính-cơ-bản] Báo cáo tài chính, chỉ tiêu định giá, sinh lợi, dòng tiền — từng quý và từng năm | Công cụ | Chức năng | | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `fundamental_get_key_metrics` | 7 nhóm KPI: định giá, sinh lợi, hiệu quả, thanh khoản, dòng tiền, tăng trưởng, đòn bẩy — cả 4 nhóm (phi tài chính, ngân hàng, chứng khoán, bảo hiểm) LUÔN kèm khối TTM (lũy kế 4 quý, khử mùa vụ) | | `fundamental_get_statement` | BCTC đầy đủ: CĐKT, KQKD, LCTT (cây line-item) | | `fundamental_dupont` | Phân rã ROE theo 3 nhân tố: biên LN × vòng quay × đòn bẩy | | `fundamental_quality_scan` | Thẩm định 8 mục chất lượng tài chính + phát hiện red flags | | `fundamental_get_metric_history` | Chuỗi thời gian một chỉ tiêu (vd. ROE 8 năm) | | `fundamental_compare_peers` | So sánh với toàn bộ doanh nghiệp cùng ngành ICB | ### Phân tích dòng tiền giao dịch [#phân-tích-dòng-tiền-giao-dịch] Theo dõi tiền vào/ra của từng nhóm nhà đầu tư: khối ngoại, tự doanh, tổ chức, cá nhân | Công cụ | Chức năng | | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `flows_get_stock_flow` | Dòng tiền theo mã (chọn focus): smart money = khối ngoại + tự doanh + tổ chức trong nước (cá nhân = retail, KHÔNG thuộc smart money; nhóm nội chốt sau \~18h, tự neo kỳ lũy kế vào phiên đủ dữ liệu) · khối ngoại riêng · dòng tiền chủ động (mua-bán chủ động — CHIỀU KHÁC, không phải smart money; cập nhật trong phiên → trả lời ngay). Kèm tín hiệu tích lũy/phân phối, room ngoại | | `flows_sector_flow` | Dòng tiền chủ động theo ngành ICB (cập nhật trong phiên) — ngành nào đang được mua/bán chủ động ròng | | `flows_top_net` | Top mã mua/bán ròng nhiều nhất theo nhóm NĐT trong N phiên | ### Báo cáo CTCK & Đồng thuận [#báo-cáo-ctck--đồng-thuận] Tổng hợp và đọc báo cáo phân tích từ các công ty chứng khoán hàng đầu | Công cụ | Chức năng | | -------------------------------- | ----------------------------------------------------------------------------------------- | | `research_list_reports` | Liệt kê báo cáo gần nhất theo mã, ngành, vĩ mô hoặc tổng quan thị trường | | `research_read_report` | Đọc nội dung báo cáo PDF (tối đa 10 trang) dưới dạng văn bản để AI tóm tắt | | `research_get_analyst_consensus` | Đồng thuận khuyến nghị: giá mục tiêu trung vị/cao/thấp, % upside, phân bổ MUA/NẮM GIỮ/BÁN | | `research_download_report` | Tải file PDF báo cáo về để phân tích chuyên sâu hơn | ### Thị trường & Ngành [#thị-trường--ngành] Tổng quan chỉ số thị trường và phân loại ngành theo chuẩn ICB quốc tế | Công cụ | Chức năng | | ------------------------ | ----------------------------------------------------------------------------------------------------------------------- | | `market_list_indices` | Liệt kê các chỉ số thị trường: VNINDEX, VN30, HNX, UPCOM... | | `market_list_sectors` | Cây phân loại ngành ICB 4 cấp: từ ngành lớn đến phân ngành chi tiết | | `market_sector_strength` | Xếp hạng sức mạnh ngành theo RS momentum (1-100) — ngành nào đang trend, kèm breadth & phát hiện dẫn dắt hẹp | | `market_today` | Ảnh chụp thị trường trong phiên: chỉ số, độ rộng tăng/giảm/ trần/sàn, dòng tiền chủ động, khối ngoại, top kéo/đè chỉ số | ### Quản lý kỳ dữ liệu [#quản-lý-kỳ-dữ-liệu] Tra cứu các kỳ BCTC khả dụng trước khi phân tích theo quý hoặc năm | Công cụ | Chức năng | | -------------------------- | ----------------------------------------------------------------------------------------------------- | | `fundamental_list_periods` | Liệt kê đầy đủ các quý/năm có sẵn dữ liệu BCTC của một mã — hữu ích khi muốn phân tích theo kỳ cụ thể | ### Tối ưu hóa danh mục đầu tư [#tối-ưu-hóa-danh-mục-đầu-tư] Tính tỷ trọng tối ưu, backtest so VNINDEX và đo lường rủi ro danh mục nhiều mã | Công cụ | Chức năng | | ------------------------------ | ------------------------------------------------------------------------------------------------- | | `portfolio_optimize` | Tỷ trọng tối ưu theo 5 phương pháp: max Sharpe, rủi ro thấp nhất, chia đều, nghịch biến động, HRP | | `portfolio_backtest` | Mô phỏng danh mục với tái cân bằng tháng/quý — so hiệu suất với VNINDEX | | `portfolio_analyze` | Bộ chỉ số rủi ro đầy đủ: VaR/CVaR, win rate, beta/alpha, lợi nhuận theo tháng | | `portfolio_efficient_frontier` | Đường biên hiệu quả Markowitz — chọn danh mục theo khẩu vị rủi ro | ### Tín hiệu kỹ thuật & Backtest chiến lược [#tín-hiệu-kỹ-thuật--backtest-chiến-lược] Xây dựng chiến lược từ chỉ báo kỹ thuật, quét tín hiệu trên universe, backtest và tối ưu tham số | Công cụ | Chức năng | | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `signals_list_indicators` | Danh mục 141 chỉ báo: 9 native (MA, RSI, MACD, BBANDS, STOCH, ATR, ADX, OBV, SUPERTREND) + 132 TA-Lib | | `signals_indicator_values` | Giá trị THỰC của chỉ báo cho 1 mã — hỏi "RSI/MFI/MACD của HPG đang bao nhiêu?": chuỗi N phiên gần nhất + giá trị mới nhất, tính trên giá điều chỉnh đủ warmup | | `signals_detect_patterns` | Soi MẪU HÌNH GIÁ trên 1 mã: 2 đỉnh/2 đáy, vai-đầu-vai, cốc tay cầm, tam giác, cờ... (\~15 mẫu đặt tên sẵn + template tùy ý) — trả ngày xuất hiện, độ khớp 0-1, cờ "đang hình thành" | | `signals_candle_patterns` | Quét cả \~61 mẫu NẾN Nhật TA-Lib trên 1 mã (Búa, Nhấn chìm, Sao Mai/Sao Hôm, Doji...) — trả mẫu có tín hiệu N phiên gần nhất, tên tiếng Việt + hướng bullish/bearish | | `signals_event_study` | Thống kê SAU TÍN HIỆU: mỗi lần tín hiệu/mẫu hình xuất hiện trong quá khứ, 5/10/20 phiên sau giá thay đổi thế nào (win rate, trung bình, tốt/xấu nhất) so với baseline mua bất kỳ | | `signals_market_structure` | Xu hướng hiện tại + HỖ TRỢ/KHÁNG CỰ từ đỉnh/đáy pivot, các pivot gần đây, đỉnh/đáy 52 tuần và % khoảng cách | | `signals_screen` | Quét tín hiệu trên 1.700 mã: lọc theo sàn/ngành/thanh khoản + điều kiện cơ bản (ROE, P/E, tăng trưởng) + sức mạnh tương đối RS (mã/ngành/leader) + rule kỹ thuật, tìm mã có tín hiệu trong N phiên gần nhất | | `signals_backtest` | Backtest long-only: 1–10 mã, 1–15 năm, tính Sharpe/Sortino/max DD/win rate, so với buy-hold; 1 mã kèm danh sách lệnh với giá trị chỉ báo tại phiên vào/thoát + chuỗi indicator N phiên cuối; tùy chọn t\_plus mô phỏng chu kỳ thanh toán T+2.5 của VN | | `signals_optimize` | Grid search tham số chỉ báo (≤200 tổ hợp), train/test split 70/30, top-K với IS + OOS metrics, cảnh báo overfit | ### Chứng quyền có bảo đảm (CW) [#chứng-quyền-có-bảo-đảm-cw] Tra cứu điều khoản, định giá, lịch sử giá & thanh khoản và so sánh chứng quyền — điểm hoà vốn, premium, đòn bẩy, Greeks Black-Scholes và hạng thanh khoản | Công cụ | Chức năng | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `warrants_search` | Tìm chứng quyền theo mã CK cơ sở / tổ chức phát hành / từ khoá — trả điều khoản tóm tắt (giá thực hiện, tỷ lệ chuyển đổi, ngày đáo hạn) | | `warrants_get_info` | Định giá đầy đủ một CW: điểm hoà vốn, premium %, giá trị nội tại/thời gian, ITM/ATM/OTM, đòn bẩy đơn & hiệu dụng, Greeks Black-Scholes (IV/delta/gamma/theta) + giá lý thuyết | | `warrants_price_history` | Lịch sử giá EOD của CW (OHLC, khối lượng, giá trị, VWAP, khối ngoại ròng) kèm tổng hợp thanh khoản: giá trị khớp TB/phiên, số phiên KL=0, hạng thanh khoản, xu hướng — giá CW theo VND thô | | `warrants_compare` | So sánh mọi CW trên cùng mã cơ sở — xếp theo premium thấp nhất / đòn bẩy hiệu dụng cao nhất / còn nhiều phiên nhất / thanh khoản cao nhất, kèm cột thanh khoản để tránh CW kẹt hàng | ### Kinh tế vĩ mô & Thương mại XNK [#kinh-tế-vĩ-mô--thương-mại-xnk] Số liệu KINH TẾ VĨ MÔ Việt Nam (FinLens): GDP, CPI, IIP, bán lẻ, FDI, XNK, tín dụng, M2, PMI cộng dữ liệu THEO NGÀY (tỷ giá, lãi suất, lợi suất TPCP, giá vàng/dầu) + cầu nối vĩ mô → cổ phiếu; cộng thương mại XNK Hải quan theo nước & mặt hàng | Công cụ | Chức năng | | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `fin_dashboard` | Ảnh chụp VĨ MÔ top-down theo 5 bloc (tăng trưởng / lạm phát / đối ngoại / tiền tệ / lãi suất-tỷ giá): giá trị mới nhất + điểm trước + chiều — định khung trước khi soi cổ phiếu/trái phiếu | | `fin_list_topics` | Liệt kê 24 NHÓM CHỦ ĐỀ kinh tế (FDI, XNK, GDP, CPI, IIP, tỷ giá, lãi suất, lợi suất TPCP, tín dụng, M2, PMI, giá hàng hoá…) — điểm vào định hướng | | `fin_browse` | Duyệt CÂY chỉ tiêu 1 cấp; phân biệt node CHỦ ĐỀ (không có chuỗi) vs node LÁ query được — không bao giờ hỏi giá trị nhầm node cha | | `fin_search` | Tìm chỉ tiêu theo TÊN tiếng Việt; mặc định chỉ trả node lá query được (gọi thẳng fin\_get\_series), kèm đường về chủ đề | | `fin_list_key_indicators` | Danh mục \~23 chỉ tiêu CHÍNH (CPI/GDP/IIP/bán lẻ/XNK/FDI/lãi suất/tỷ giá…) — lối tắt thay vì duyệt cả cây, kèm ngày dữ liệu mới nhất | | `fin_get_series` | Chuỗi thời gian của MỘT chỉ tiêu lá; giá trị sẵn sàng theo đơn vị (CPI 5.6%, USD/VND 25189); lọc theo ngày — Daily/Monthly/ Quarterly/Yearly | | `fin_compare` | So sánh một chỉ tiêu giữa hai kỳ: giá trị từng kỳ, chênh lệch và % thay đổi (tự khớp kỳ theo tần suất) | | `fin_data_status` | Độ tươi dữ liệu: kỳ mới nhất theo từng tần suất & từng chủ đề — gọi trước khi hỏi một kỳ cụ thể | | `fin_macro_context` | Cầu nối cổ phiếu → vĩ mô: từ mã → ngành ICB → các động lực kinh tế tác động (chiều tailwind/headwind/cost\_input + giá trị + hàm ý). Gợi ý liên hệ, KHÔNG phải khuyến nghị | | `fin_sector_macro_link` | Cầu nối ngành → vĩ mô: từ tên ngành → động lực kinh tế + vài mã cổ phiếu tiêu biểu. Gợi ý liên hệ, KHÔNG phải khuyến nghị | | `fin_rate_outlook` | Bức tranh LÃI SUẤT & LẠM PHÁT: lãi suất liên NH/huy động/cho vay + lợi suất TPCP 1y–10y THỰC TẾ, cùng CPI; kèm nhận định & hàm ý cho trái phiếu/ngân hàng/BĐS/chứng khoán | | `gso_trade` | Thương mại XNK Hải quan (cập nhật theo tháng): top mặt hàng / nước đối tác / tỉnh, hoặc đào sâu (cơ cấu mặt hàng của 1 nước; nước nào mua/bán 1 mặt hàng). Có phân khúc khối FDI khi xếp hạng mặt hàng | | `gso_trade_series` | Chuỗi trị giá XNK theo tháng của 1 mặt hàng / nước / tỉnh — xem xu hướng & momentum (chỉ báo sớm trước GDP và lợi nhuận quý ngành xuất khẩu) | | `gso_trade_stocks` | Cầu nối XNK → cổ phiếu: ánh xạ mặt hàng sang ngành + danh sách mã VN tiêu biểu, kèm trị giá lũy kế & %YoY mới nhất. Là gợi ý ngành liên quan, KHÔNG phải khuyến nghị đầu tư | ### Cổ tức & Sự kiện quyền [#cổ-tức--sự-kiện-quyền] Lịch chia cổ tức (GDKHQ) sắp tới, lịch sử cổ tức theo mã và phân tích chính sách cổ tức (lợi suất, payout, độ đều, tăng trưởng) cho nhà đầu tư theo phong cách nhận cổ tức | Công cụ | Chức năng | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `dividends_upcoming` | Lịch sự kiện chia cổ tức / quyền SẮP TỚI (GDKHQ ≥ hôm nay) toàn thị trường, sắp theo ngày — lọc theo loại (tiền / thưởng CP / quyền), sàn, danh sách mã, lợi suất tiền tối thiểu; cổ tức tiền kèm lợi suất theo giá hiện tại | | `dividends_get_history` | Lịch sử cổ tức & sự kiện quyền của 1 mã trong N năm: từng đợt (tiền VND/CP, tỷ lệ thưởng CP, giá phát hành quyền) + gộp theo năm + sự kiện sắp tới gần nhất | | `dividends_analyze_policy` | Phân tích chính sách cổ tức: lợi suất tiền hiện tại (TTM ÷ giá), tỷ lệ chi trả (payout = cổ tức / EPS), số năm trả + chuỗi liên tiếp, CAGR cổ tức 3/5 năm, thiên tiền mặt hay thưởng CP, số lần phát hành quyền (pha loãng) + hồ sơ cổ tức & cờ cảnh báo. TRUNG LẬP, không phải khuyến nghị | ### Tin tức phân tích bằng AI [#tin-tức-phân-tích-bằng-ai] Tin chứng khoán Việt Nam được AI đọc và phân tích sẵn mỗi \~10 phút: tóm tắt 2–4 câu, sentiment theo tác động giá dự kiến, mã liên quan kèm trọng số, ngành ICB, loại sự kiện, độ quan trọng 1–5 và bảng số liệu trọng yếu — cầu nối tin tức ↔ cổ phiếu/ngành | Công cụ | Chức năng | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `news_market_brief` | Điểm tin trọng yếu theo cửa sổ morning (16:00 phiên làm việc trước → 09:00; thứ Hai gộp trọn cuối tuần) / today / last24h: tin quan trọng nhất, vĩ mô & chính sách, quốc tế, điểm tin phiên, mã được nhắc nhiều nhất và độ nóng theo ngành | | `news_get_for_stock` | Tin theo MÃ + sentiment tổng hợp cả cửa sổ (có điểm trung bình theo trọng số liên quan). Mặc định chỉ tin VỀ mã; bật include\_mentions=true để quét cả bài điểm tin có nhắc mã | | `news_get_for_sector` | Tin theo NGÀNH ICB cấp 2 + sentiment ngành. Nhận cả mã ngành cấp 4 từ hồ sơ doanh nghiệp (tự quy về cấp 2, vd 8355 → 8300) | | `news_search` | Tìm tin theo từ khoá (tiêu đề/tóm tắt), theo mã, theo loại tin (doanh nghiệp / ngành / điểm tin / vĩ mô / quốc tế), theo loại sự kiện (KQKD, M\&A, cổ tức, nhân sự, pháp lý, tăng vốn, kế hoạch, dự án, số liệu vĩ mô) và độ quan trọng tối thiểu | | `news_get_article` | Chi tiết 1 bài: TOÀN BỘ mã liên quan kèm lý do, danh sách ngành, từ khoá, sapo gốc và bảng số liệu trọng yếu (doanh thu, lợi nhuận, %tăng trưởng, giá mục tiêu…) trích từ bài | *** ## Thử các câu hỏi này [#thử-các-câu-hỏi-này] Copy và dán trực tiếp vào chat — AI sẽ tự chọn đúng công cụ và trả lời. **Phân tích toàn diện cổ phiếu HPG: tài chính 5 năm, DuPont, dòng tiền tự do** Kết hợp fundamental_get_key_metrics + fundamental_dupont + fundamental_get_statement **So sánh HPG với các doanh nghiệp cùng ngành thép về P/E, ROE và tăng trưởng** Dùng fundamental_compare_peers để xếp hạng và tính percentile **Thẩm định chất lượng kế toán của VHM — có red flag nào không?** Dùng fundamental_quality_scan: kiểm tra 8 mục, cho điểm Equity/Credit **Khối ngoại đang mua hay bán ròng FPT trong 20 phiên qua?** flows_get_stock_flow với days=20 **Top 10 mã được khối ngoại mua ròng nhiều nhất tuần này** flows_top_net với flow_type=foreign, days=5 **Ngành nào đang nhận dòng tiền nhiều nhất trên HOSE 10 phiên gần nhất?** flows_sector_flow — xem luân chuyển vốn giữa các ngành **Tóm tắt các báo cáo phân tích mới nhất về MWG từ các CTCK** research_list_reports + research_read_report để đọc nội dung **Giá mục tiêu đồng thuận của VCB theo các CTCK là bao nhiêu? Upside là bao nhiêu %?** research_get_analyst_consensus: trung vị, cao, thấp và phân bổ khuyến nghị **Có báo cáo nào về ngành ngân hàng gần đây không? Tóm tắt luận điểm chính** research_list_reports với scope=industry, query=ngân hàng **Giá hiện tại và thông tin cơ bản của TCB** stocks_get_latest_quote + stocks_get_profile **Vẽ xu hướng ROE của VNM từ 2016 đến nay theo năm** fundamental_get_metric_history với metric=roe, limit=8 **Tìm tất cả cổ phiếu thuộc nhóm khu công nghiệp, so sánh P/B và ROE** market_list_sectors + fundamental_compare_peers để lọc và xếp hạng **Tôi muốn đầu tư vào HPG, FPT, VNM, MWG — phân bổ tỷ trọng thế nào là tối ưu?** portfolio_optimize với max_sharpe / min_volatility, kèm max_weight chống tập trung **Backtest danh mục 40% HPG, 30% FPT, 30% VNM trong 2 năm qua — có thắng VNINDEX không?** portfolio_backtest với rebalance theo quý, so CAGR/Sharpe/drawdown với VNINDEX **Danh mục của tôi rủi ro đến mức nào? VaR, tháng xấu nhất và max drawdown là bao nhiêu?** portfolio_analyze + portfolio_efficient_frontier để định vị khẩu vị rủi ro **HPG có đang hình thành mẫu hình 2 đáy không? Quét luôn các mẫu hình khác nếu có** signals_detect_patterns — so khớp hình dáng với thư viện ~15 mẫu, trả độ khớp + thời điểm **VNM tuần này xuất hiện mẫu nến gì? Có tín hiệu đảo chiều không?** signals_candle_patterns — quét cả 61 mẫu nến TA-Lib, trả tên tiếng Việt + hướng **Sau khi HPG xuất hiện mẫu hình 2 đáy thì 20 phiên sau thường tăng hay giảm?** signals_event_study — lợi nhuận 5/10/20 phiên sau mỗi lần sự kiện, win rate, so baseline **Xu hướng hiện tại của FPT thế nào? Hỗ trợ và kháng cự gần nhất ở đâu?** signals_market_structure — trend từ pivot, mức S/R kèm khoảng cách %, đỉnh/đáy 52 tuần **Cho tôi biết MFI, OBV, MACD của mã cổ phiếu HPG đang là bao nhiêu?** signals_indicator_values trả giá trị thực N phiên gần nhất — AI không tự ước lượng **Quét các cổ phiếu HOSE có RSI \< 30 và giá cắt lên MA20 trong 5 phiên gần nhất, lọc thêm ROE > 15% và P/E \< 15** signals_screen với rule sequence + bộ lọc cơ bản (ROE, P/E) **Backtest chiến lược MA20/50 cross trên HPG, FPT, VNM trong 5 năm — so với mua-hold từng mã** signals_backtest trên nhiều mã, tính Sharpe/drawdown/win rate, so buyhold return **Tối ưu tham số chỉ báo MA (window 10–50) × RSI (window 7–28) trên FPT 3 năm, chia train/test 70/30, báo cảnh báo overfit** signals_optimize grid search, in-sample vs out-of-sample side-by-side, best_spec dùng ngay cho backtest **Phân tích chứng quyền CFPT2613: điểm hoà vốn, premium, đòn bẩy và Greeks là bao nhiêu?** warrants_get_info — điều khoản + định giá đầy đủ kèm IV/delta/theta, thanh khoản gần đây, giá CW theo VND **Có những chứng quyền nào trên FPT? Mã nào premium thấp và đòn bẩy hợp lý nhất?** warrants_search rồi warrants_compare — xếp hạng CW cùng cơ sở theo premium / đòn bẩy / thanh khoản **Chứng quyền CHPG2607 thanh khoản thế nào? Giá và khối lượng khớp 30 phiên gần nhất, có phiên nào không giao dịch không?** warrants_price_history — OHLC + VWAP + giá trị khớp TB/phiên, số phiên KL=0 và hạng thanh khoản **Lạm phát (CPI) Việt Nam 12 tháng qua diễn biến thế nào?** fin_search → fin_get_series — chuỗi CPI (FinLens) theo tháng **Tóm tắt tình hình kinh tế - xã hội tháng gần nhất: CPI, sản xuất công nghiệp, FDI, xuất nhập khẩu** fin_dashboard cho ảnh chụp vĩ mô top-down + fin_compare để so cùng kỳ **Xuất khẩu thủy sản đang tăng hay giảm? Có những mã cổ phiếu nào thuộc ngành liên quan?** gso_trade_stocks bắc cầu mặt hàng → ngành + mã (VHC, ANV, MPC…) kèm trị giá & %YoY **Top mặt hàng xuất khẩu lớn nhất và các đối tác thương mại chính của Việt Nam là gì?** gso_trade với by=commodity rồi by=country — kèm trị giá lũy kế và % tỷ trọng **Cán cân thương mại tháng gần nhất thế nào? Khối FDI chiếm bao nhiêu % xuất khẩu?** gso_trade (Hải quan) cho cán cân XK/NK + fin_dashboard cho khối đối ngoại & FDI **Điểm tin sáng nay có gì đáng chú ý? Mã nào đang được nhắc nhiều nhất?** news_market_brief(window=morning) — tin trọng yếu + vĩ mô + mã nóng + độ nóng ngành **HPG tháng qua có tin gì? Tin tức đang nghiêng tích cực hay tiêu cực?** news_get_for_stock — tóm tắt AI + sentiment tổng hợp; drill bài quan trọng bằng news_get_article **VNM có phải cổ phiếu cổ tức tốt không? Lợi suất, tỷ lệ chi trả và độ đều của cổ tức 7 năm qua?** dividends_analyze_policy — yield, payout, streak, CAGR + hồ sơ & cờ cảnh báo (trung lập) **Sắp tới có mã nào trên HOSE chốt quyền trả cổ tức tiền lợi suất trên 5% không?** dividends_upcoming với kind=cash, exchange=HOSE, min_cash_yield=5 — sắp theo ngày GDKHQ *** ## Chuỗi bài viết từng chủ đề [#chuỗi-bài-viết-từng-chủ-đề] 18 bài hướng dẫn chi tiết — câu hỏi mẫu, giải thích khái niệm và prompt sẵn dùng cho từng nhóm công cụ. Bài 1 · Bắt đầu — Từng bước kết nối MCP, kiểm tra và 5 câu hỏi đầu tiên nên thử. Bài 2 · Tài chính cơ bản — 7 nhóm KPI, phân tích chất lượng kế toán và so sánh peers ngành. Bài 3 · Dòng tiền — Phân biệt smart money vs dòng tiền chủ động, độ trễ dữ liệu và cách đọc tín hiệu. Bài 4 · Kỹ thuật & Backtest — Chỉ báo THỰC tế, quét tín hiệu, mẫu giá, mẫu nến và backtest mô phỏng thanh toán VN. Bài 5 · Danh mục — 5 phương pháp tối ưu, backtest tái cân bằng và đo lường rủi ro đầy đủ. Bài 6 · Báo cáo CTCK — Tìm, đọc tóm tắt PDF và xem giá mục tiêu đồng thuận từ nhiều CTCK. Bài 7 · Chứng quyền — Black-Scholes đầy đủ: điểm hòa vốn, premium, đòn bẩy hiệu dụng và so sánh CW cùng mã. Bài 8 · Vĩ mô — Dashboard 7 nhóm, 4910 chỉ tiêu, tương quan/lead-lag, đường cong TPCP, XNK & tiền tệ SBV → cầu nối cổ phiếu. Bài 9 · Cổ tức — Lịch GDKHQ sắp tới, lịch sử cổ tức, phân tích chính sách (yield, payout, độ đều) cho NĐT cổ tức. Bài 10 · Nâng cao — Kỹ thuật chia nhỏ câu hỏi từng bước, kết hợp nhiều tool để soi một cổ phiếu từ mọi góc độ. Bài 11 · Quỹ đầu tư — 185 quỹ: danh mục nắm giữ, NAV & dòng tiền, xếp hạng hiệu suất và cầu nối cổ phiếu → quỹ nào đang gom/xả. Bài 12 · Công ty thường — Bóc tách chi phí, cơ cấu nợ vay, vốn lưu động và định giá nội tại DCF chuyên sâu cho doanh nghiệp phi tài chính. Bài 13 · Ngân hàng — Bộ công cụ chuyên ngành ngân hàng: chất lượng tài sản, cơ cấu huy động CASA và cơ cấu thu nhập, hiệu quả CIR & PPOP. Bài 14 · Chứng khoán — Danh mục tự doanh (FVTPL/AFS/HTM), cơ cấu doanh thu, tài sản khách hàng giữ hộ và chỉ báo tâm lý thị trường toàn ngành. Bài 15 · Sức mạnh ngành — Xếp hạng ngành theo RS momentum (1–100), phát hiện dẫn dắt hẹp và lọc cổ phiếu leader trong ngành đang trend theo O'Neil. Bài 16 · Diễn biến trong phiên — Ảnh chụp thị trường & nhịp phiên từng mã từ dữ liệu 1 phút: độ rộng, VWAP, khối ngoại, dòng tiền ròng chủ động (cách đọc chuẩn) và cung-cầu ĐẶT lệnh (lệnh to/nhỏ, phân kỳ cung/cầu bị che). Bài 17 · Tin tức AI — Điểm tin mỗi sáng, sentiment theo tác động giá, trọng số mã liên quan — và 4 cạm bẫy phải tránh khi đọc tin bằng AI. Xem tất cả hướng dẫn → *** ## Toàn bộ 107 công cụ [#toàn-bộ-107-công-cụ] Danh sách đầy đủ với nhóm chức năng, mã tool và mô tả ngắn gọn. | Tool | Nhóm | Chức năng | Tham số chính | | ----------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------- | | `stocks_search` | Cổ phiếu | Tìm mã theo tên hoặc ticker | `query, limit` | | `stocks_get_profile` | Cổ phiếu | Hồ sơ DN: sàn, ngành ICB, số CP lưu hành | `ticker` | | `stocks_get_latest_quote` | Cổ phiếu | Giá EOD mới nhất + OHLCV + giá trị khớp | `ticker` | | `stocks_get_price_history` | Cổ phiếu | Chuỗi giá lịch sử EOD (tối đa 500 phiên) | `ticker, start, end, limit` | | `stocks_session_recap` | Cổ phiếu | Diễn biến 1 mã trong phiên: giá/VWAP/gap, dòng tiền chủ động, KL so TB (pro-rate), khối ngoại | `ticker` | | `stocks_supply_demand` | Cổ phiếu | Cung-cầu ĐẶT lệnh theo phiên: imbalance/size\_diff, kích cỡ lệnh TB, nhãn phân kỳ cung/cầu bị che | `ticker, days` | | `fundamental_get_key_metrics` | Cơ bản | 7 nhóm KPI: định giá, sinh lợi, hiệu quả, thanh khoản, dòng tiền, tăng trưởng, đòn bẩy. Cả 4 nhóm (phi tài chính, ngân hàng, chứng khoán, bảo hiểm) luôn kèm khối TTM (lũy kế 4 quý) | `ticker, groups, period_type (annual/quarter/ttm), limit` | | `fundamental_get_statement` | Cơ bản | BCTC dạng cây: CĐKT / KQKD / LCTT | `ticker, statement, period_type, limit` | | `fundamental_dupont` | Cơ bản | Phân rã ROE theo 3 nhân tố qua từng kỳ | `ticker, period_type, limit` | | `fundamental_quality_scan` | Cơ bản | Thẩm định 8 mục chất lượng kế toán + red flags + điểm Equity/Credit | `ticker, limit, period_type` | | `fundamental_get_metric_history` | Cơ bản | Chuỗi thời gian một chỉ tiêu (roe, pe, fcf...) | `ticker, metric, period_type, limit` | | `fundamental_compare_peers` | Cơ bản | So sánh với peers cùng ngành ICB, kèm xếp hạng và percentile | `ticker, metrics, icb_level, limit` | | `fundamental_list_periods` | Cơ bản | Liệt kê kỳ BCTC có sẵn của một mã | `ticker, statement, period_type` | | `flows_get_stock_flow` | Dòng tiền | Dòng tiền theo mã: nhóm NĐT, tín hiệu, room ngoại | `ticker, days` | | `flows_sector_flow` | Dòng tiền | Dòng tiền vào/ra các ngành ICB trong N phiên | `days, top` | | `flows_top_net` | Dòng tiền | Top mã mua/bán ròng nhiều nhất của một nhóm NĐT | `flow_type, days, direction, exchange, limit` | | `research_list_reports` | Nghiên cứu | Báo cáo CTCK: theo mã / ngành / vĩ mô / thị trường | `scope, ticker, query, limit` | | `research_read_report` | Nghiên cứu | Đọc nội dung PDF báo cáo (≤10 trang) thành markdown | `report_id, max_pages` | | `research_get_analyst_consensus` | Nghiên cứu | Đồng thuận giá mục tiêu, upside, phân bổ MUA/NẮM/BÁN | `ticker, limit` | | `research_download_report` | Nghiên cứu | Tải file PDF báo cáo về server để phân tích | `report_id` | | `market_list_indices` | Thị trường | Danh sách chỉ số: VNINDEX, VN30, HNX, UPCOM... | — | | `market_list_sectors` | Thị trường | Cây ngành ICB 4 cấp với mã và tên tiếng Việt | `level, limit` | | `market_sector_strength` | Thị trường | Xếp hạng ngành theo RS momentum 1-100, kèm breadth & độ phân kỳ (dẫn dắt hẹp) | `level, limit` | | `market_today` | Thị trường | Ảnh chụp thị trường trong phiên: chỉ số, độ rộng tăng/giảm/trần/sàn, dòng tiền chủ động, khối ngoại | `top_n` | | `portfolio_optimize` | Danh mục | Tỷ trọng tối ưu (max\_sharpe, min\_volatility, equal\_weight, inverse\_volatility, hrp) + lợi nhuận/biến động kỳ vọng | `tickers, method, lookback, max_weight` | | `portfolio_backtest` | Danh mục | Backtest tỷ trọng cố định hoặc tái tối ưu định kỳ — so với VNINDEX | `weights \| method, rebalance, lookback` | | `portfolio_analyze` | Danh mục | Chỉ số rủi ro đầy đủ: Sharpe, Sortino, VaR/CVaR, beta/alpha, lợi nhuận tháng | `weights, lookback, rebalance` | | `portfolio_efficient_frontier` | Danh mục | Đường biên hiệu quả Markowitz + 2 danh mục then chốt theo khẩu vị rủi ro | `tickers, lookback, n_points` | | `signals_list_indicators` | Tín hiệu | Danh mục 141 chỉ báo kỹ thuật + cú pháp DSL rule (strict/within/sequence) + ví dụ spec | `source, query` | | `signals_candle_patterns` | Tín hiệu | Quét cả 61 mẫu nến Nhật trên 1 mã: tên tiếng Việt, hướng, ngày xuất hiện | `ticker, days` | | `signals_event_study` | Tín hiệu | Thống kê lợi nhuận 5/10/20 phiên sau mỗi lần tín hiệu/mẫu hình xuất hiện, so baseline | `strategy, ticker, years, horizons` | | `signals_market_structure` | Tín hiệu | Xu hướng + hỗ trợ/kháng cự pivot + đỉnh/đáy 52 tuần của một mã | `ticker, years, threshold` | | `signals_detect_patterns` | Tín hiệu | Soi mẫu hình giá 1 mã (2 đáy, vai-đầu-vai, cốc tay cầm...): ngày xuất hiện + độ khớp + đang hình thành | `ticker, patterns, years, min_similarity` | | `signals_indicator_values` | Tín hiệu | Giá trị thực của chỉ báo (MFI, OBV, MACD...) cho 1 mã: chuỗi N phiên gần nhất + giá trị mới nhất | `ticker, indicators, days` | | `signals_screen` | Tín hiệu | Quét tín hiệu kỹ thuật trên universe: lọc sàn/ngành/cơ bản, tìm tín hiệu trong N phiên | `strategy, exchanges, fundamental_conditions, signal_within_days` | | `signals_backtest` | Tín hiệu | Backtest chiến lược long-only: 1–10 mã, 1–15 năm, Sharpe/Sortino/drawdown vs buy-hold, kèm giá trị chỉ báo tại lệnh | `strategy, tickers, years, fees, sl_stop, tp_stop, t_plus` | | `signals_optimize` | Tín hiệu | Tối ưu tham số: grid search ≤200 combos, train/test 70/30, top-K IS+OOS metrics, cảnh báo overfit | `strategy, ticker, objective, years, train_ratio, t_plus` | | `warrants_search` | Chứng quyền | Tìm CW theo mã CK cơ sở / tổ chức phát hành / từ khoá; trả điều khoản tóm tắt | `underlying, issuer, query, active_only, limit` | | `warrants_get_info` | Chứng quyền | Định giá đầy đủ 1 CW: hoà vốn, premium, nội tại/thời gian, ITM/ATM/OTM, đòn bẩy, Greeks BS | `code` | | `warrants_price_history` | Chứng quyền | Lịch sử giá EOD của CW (OHLC, KL, giá trị, VWAP, khối ngoại) + tổng hợp thanh khoản (giá trị khớp TB/phiên, phiên KL=0, hạng thanh khoản); giá CW theo VND thô | `code, start, end, limit` | | `warrants_compare` | Chứng quyền | So sánh mọi CW cùng mã cơ sở — xếp theo premium / đòn bẩy / kỳ hạn / thanh khoản, kèm cột thanh khoản | `underlying, sort_by, active_only, limit` | | `fin_dashboard` | Vĩ mô | Ảnh chụp vĩ mô top-down theo 5 bloc + chiều tăng/giảm | `as_of` | | `fin_list_topics` | Vĩ mô | 24 nhóm chủ đề kinh tế — điểm vào định hướng | `—` | | `fin_browse` | Vĩ mô | Duyệt cây 1 cấp; phân biệt node chủ đề vs node lá query được | `indicator_id, query, top` | | `fin_search` | Vĩ mô | Tìm chỉ tiêu theo tên tiếng Việt (mặc định chỉ node lá) | `query, queryable_only, top` | | `fin_list_key_indicators` | Vĩ mô | \~23 chỉ tiêu chính (CPI/GDP/IIP/lãi suất/tỷ giá…) — lối tắt | `bloc` | | `fin_get_series` | Vĩ mô | Chuỗi thời gian 1 chỉ tiêu lá; giá trị sẵn theo đơn vị | `indicator_id, from_date, to_date, top` | | `fin_compare` | Vĩ mô | So sánh 1 chỉ tiêu giữa 2 kỳ: giá trị, chênh lệch, % | `indicator_id, period_a, period_b` | | `fin_data_status` | Vĩ mô | Độ tươi dữ liệu theo tần suất & chủ đề | `—` | | `fin_macro_context` | Vĩ mô | Cầu nối cổ phiếu → động lực vĩ mô của ngành (+ chiều, hàm ý) | `ticker` | | `fin_sector_macro_link` | Vĩ mô | Cầu nối ngành → động lực vĩ mô + mã tiêu biểu | `sector` | | `fin_rate_outlook` | Vĩ mô | Lãi suất & lợi suất TPCP thật + CPI + hàm ý | `—` | | `gso_trade` | XNK | Thương mại XNK Hải quan: top / đào sâu theo mặt hàng, nước đối tác hoặc tỉnh (có khối FDI) | `flow, by, period, key, segment, top` | | `gso_trade_series` | XNK | Chuỗi trị giá XNK theo tháng của 1 mặt hàng / nước / tỉnh — xu hướng & momentum | `by, key, flow, segment, from_period, to_period` | | `gso_trade_stocks` | XNK | Cầu nối mặt hàng XNK → ngành + mã cổ phiếu VN tiêu biểu, kèm trị giá lũy kế & %YoY | `commodity_or_keyword, flow, period` | | `dividends_upcoming` | Cổ tức | Lịch GDKHQ sắp tới toàn thị trường, kèm lợi suất tiền theo giá hiện tại | `days_ahead, kind, exchange, symbols, min_cash_yield, limit` | | `dividends_get_history` | Cổ tức | Lịch sử cổ tức/quyền 1 mã, gộp theo năm + sự kiện sắp tới | `ticker, years` | | `dividends_analyze_policy` | Cổ tức | Phân tích chính sách: lợi suất, payout, độ đều, CAGR, hồ sơ + cờ cảnh báo (trung lập) | `ticker` | | `fundamental_list_notes` | Cơ bản | Tra cứu danh mục mục thuyết minh BCTC bóc tách được (CT/NH/CK) | `ticker, query, com_type` | | `fundamental_get_notes` | Cơ bản | Bóc tách 1 mục thuyết minh: tỷ trọng (composition %) + YoY, theo Năm/Quý/TTM | `ticker, section, period_type` | | `fundamental_cost_structure` | Cơ bản | Cơ cấu chi phí theo yếu tố — đòn bẩy hoạt động (cố định vs biến đổi), DN phi tài chính | `ticker, period_type` | | `fundamental_debt_structure` | Cơ bản | Cơ cấu nợ vay ST/LT, % nợ DH đến hạn 12 tháng, trái phiếu phát hành (CT) | `ticker, period_type` | | `fundamental_working_capital` | Cơ bản | Phải thu khác + cơ cấu tồn kho, cờ tồn kho thành phẩm (CT) | `ticker, period_type` | | `fundamental_revenue_breakdown` | Cơ bản | Doanh thu theo dòng + giảm trừ + giá vốn + biên LN gộp (CT) | `ticker, period_type` | | `fundamental_bank_asset_quality` | Cơ bản · NH | Chất lượng tài sản NH: NPL (nhóm 3-5), nợ nhóm 2 (SML), bao phủ dự phòng (LLR) | `ticker, period_type` | | `fundamental_bank_funding` | Cơ bản · NH | Cơ cấu huy động NH: CASA (tiền gửi không kỳ hạn), tỷ trọng có kỳ hạn | `ticker, period_type` | | `fundamental_bank_income` | Cơ bản · NH | Cơ cấu thu nhập NH: NII, TOI, CIR, PPOP, tỷ trọng NII vs thu ngoài lãi | `ticker, period_type` | | `fundamental_securities_portfolio` | Cơ bản · CK | Danh mục tự doanh CTCK: FVTPL/AFS/HTM, lãi/lỗ chưa thực hiện, dư nợ margin | `ticker, period_type` | | `fundamental_securities_income` | Cơ bản · CK | Cơ cấu doanh thu CTCK: tự doanh / margin / môi giới / IB / tư vấn | `ticker, period_type` | | `fundamental_securities_client_assets` | Cơ bản · CK | Tài sản KH giữ hộ (ngoại bảng): franchise, thâm nhập margin, nợ xử lý | `ticker, period_type` | | `fundamental_securities_market_sentiment` | Cơ bản · CK | Tâm lý thị trường: margin & tiền gửi toàn ngành CTCK (đòn bẩy / dry powder) | `period_type, limit` | | `fundamental_valuation_history` | Cơ bản | Dải P/E·P/B·P/S lịch sử của chính mã + percentile re-rating (đắt/rẻ vs quá khứ) | `ticker, metric, lookback_years` | | `fundamental_intrinsic_value` | Cơ bản | Định giá nội tại DCF/FCFF, WACC tự tính theo CAPM + kịch bản bull/base/bear (CT) | `ticker, wacc, equity_risk_premium` | | `fin_markets` | Vĩ mô | Ảnh chụp ngày: tỷ giá, vàng, dầu + đường cong lợi suất TPCP 1y–10y | `—` | | `fin_relate` | Vĩ mô | Tương quan & lead-lag giữa các chỉ tiêu vĩ mô (vd dầu dẫn trước CPI) | `indicator_ids, transform` | | `fin_omo_overview` | Vĩ mô | Tổng quan nghiệp vụ thị trường mở SBV: lãi suất điều hành + bơm/hút ròng | `frequency` | | `fin_omo_liquidity` | Vĩ mô | Chuỗi bơm/hút ròng OMO theo thời gian (>0 = nới, \<0 = thắt) | `frequency, top` | | `fin_omo_rates` | Vĩ mô | Lãi suất điều hành + đường cong lãi suất liên ngân hàng (qua đêm → 9M) | `frequency` | | `fin_trade_overview` | XNK | Cán cân XNK mới nhất: xuất/nhập/cán cân + FDI vs nội địa, %YoY | `data_type` | | `fin_trade_balance_series` | XNK | Xu hướng xuất siêu / nhập siêu theo thời gian | `data_type` | | `fin_trade_top` | XNK | Top mặt hàng hoặc đối tác xuất/nhập khẩu + mức tập trung | `flow, dimension, top` | | `fin_trade_matrix` | XNK | Ma trận mặt hàng × quốc gia ("VN xuất gạo nhiều nhất sang đâu") | `flow, product\|partner` | | `fund_search` | Quỹ | Tìm quỹ theo loại/cấu trúc/công ty QLQ, sắp xếp theo AUM/rating | `fund_type, structure, sort` | | `fund_profile` | Quỹ | Hồ sơ quỹ: loại, công ty quản lý, AUM, phí, NAV/CCQ | `ticker` | | `fund_holdings` | Quỹ | Danh mục nắm giữ top + phân bổ ngành ICB + thay đổi mua/bán kỳ trước | `ticker` | | `fund_performance` | Quỹ | Hiệu suất 1M/3M/6M/1Y/YTD + dòng tiền vào/ra + ETF discount | `ticker` | | `fund_rank` | Quỹ | Xếp hạng quỹ theo hiệu suất / dòng tiền / AUM, lọc theo loại quỹ | `metric, fund_type` | | `fund_stock_ownership` | Quỹ | Đảo chiều smart money: 1 cổ phiếu đang được quỹ nào nắm + đang gom hay xả | `ticker, min_funds` | | `fund_top_stocks` | Quỹ | Cổ phiếu được nhiều quỹ nắm nhất toàn thị trường (theo số quỹ/giá trị/tỷ trọng) | `metric, sector, fund_type` | | `bond_search` | Trái phiếu | Tìm trái phiếu DN theo nhiều tiêu chí (tổ chức, ngành, lãi suất, đáo hạn) | `filters, limit` | | `bond_get` | Trái phiếu | Chi tiết 1 trái phiếu: kỳ hạn, lãi suất, tài sản đảm bảo, lịch trả | `bond_code` | | `bond_list_issuers` | Trái phiếu | Danh sách tổ chức phát hành trái phiếu + dư nợ | `filters` | | `bond_issuer_profile` | Trái phiếu | Hồ sơ phát hành 1 tổ chức + cầu nối sang cổ phiếu niêm yết | `issuer / ticker` | | `bond_market_overview` | Trái phiếu | Tổng quan thị trường trái phiếu DN: quy mô, phát hành, đáo hạn | `—` | | `bond_maturity_wall` | Trái phiếu | Lịch đáo hạn ("maturity wall") — áp lực trả nợ theo thời gian/ngành | `filters` | | `bond_sector_debt` | Trái phiếu | Dư nợ trái phiếu theo ngành — tập trung rủi ro | `—` | | `bond_issuance_trend` | Trái phiếu | Xu hướng phát hành trái phiếu theo thời gian | `—` | | `bond_coupon_landscape` | Trái phiếu | Phân bố lãi suất coupon trên thị trường | `—` | | `bond_convertible` | Trái phiếu | Trái phiếu chuyển đổi — điều khoản & pha loãng tiềm năng | `filters` | | `bond_lookup_column` | Trái phiếu | Tra cứu trường/cột dữ liệu trái phiếu khả dụng | `query` | | `news_market_brief` | Tin tức | Điểm tin trọng yếu: tin quan trọng + vĩ mô + quốc tế + điểm tin phiên + mã nóng + độ nóng ngành | `window, date, min_importance, limit` | | `news_get_for_stock` | Tin tức | Tin theo mã + sentiment tổng hợp (có trọng số liên quan) | `ticker, days, include_mentions, min_relevance, limit` | | `news_get_for_sector` | Tin tức | Tin theo ngành ICB cấp 2 + sentiment ngành (nhận cả mã cấp 4) | `icb_code, days, limit` | | `news_search` | Tin tức | Tìm tin theo từ khoá / mã / loại tin / loại sự kiện / độ quan trọng | `query, ticker, days, news_type, event_type, min_importance` | | `news_get_article` | Tin tức | Chi tiết 1 bài: đủ mã liên quan + lý do, ngành, từ khoá, bảng số liệu trọng yếu | `article_id` | | `gso_rank_regions` | Vùng/Tỉnh | Xếp hạng tỉnh/vùng theo chỉ tiêu kinh tế - xã hội | `metric` | | `gso_province_profile` | Vùng/Tỉnh | Hồ sơ kinh tế - xã hội của một tỉnh/thành | `province` | *** ## Tối ưu hoá cuộc trò chuyện [#tối-ưu-hoá-cuộc-trò-chuyện] Một vài gợi ý để nhận được phân tích chính xác và hữu ích nhất. Luôn dùng mã viết hoa chuẩn (HPG, VCB, FPT). Nếu không nhớ mã, hỏi AI để tìm: *"Mã cổ phiếu của Hòa Phát là gì?"* Thêm "5 năm gần nhất", "theo quý", "từ Q1/2022" để AI chọn đúng kỳ dữ liệu và không lấy quá nhiều/ít. AI nhớ ngữ cảnh trong suốt cuộc trò chuyện. Sau khi hỏi về HPG, bạn có thể nói *"so sánh với HSG"* mà không cần nhắc lại. Thêm *"trình bày dưới dạng bảng"*, *"vẽ biểu đồ so sánh"*, hoặc *"tóm tắt trong 5 điểm"* để kiểm soát output. Giá lịch sử và báo cáo tài chính là dữ liệu **cuối ngày (EOD)**. Riêng diễn biến phiên có nhóm công cụ riêng: chỉ số và độ rộng thị trường, dòng tiền chủ động, khối ngoại, sổ lệnh đặt và nến 1 phút từng mã — xem [Thị trường hôm nay](/mcp/phien-truc-tiep). Dữ liệu nhóm nhà đầu tư nội (tự doanh, tổ chức, cá nhân) về sau khi kết phiên. Công cụ thẩm định tự nhận diện loại doanh nghiệp và áp bộ tiêu chí riêng: DN thường, ngân hàng (nợ xấu, CAR, NIM), chứng khoán (margin, tự doanh, LN chưa thực hiện), bảo hiểm (nghiệp vụ, dự phòng, đầu tư). Bắt đầu bằng *"liệt kê ngành khu công nghiệp ICB"* → rồi *"top mã theo ROE trong ngành đó"* để sàng lọc đúng cách. Hỏi *"xuất khẩu gỗ đang phục hồi không, mã nào liên quan?"* — AI dùng *gso\_trade\_stocks* để ra ngành + mã (vd PTB), rồi bạn nối tiếp *"phân tích tài chính PTB"*. Danh sách mã là gợi ý ngành, không phải khuyến nghị. Các tín hiệu tích lũy/phân phối từ flows là công cụ hỗ trợ phân tích — không phải khuyến nghị mua/bán. Luôn kết hợp với phân tích cơ bản. Sau khi nhận tỷ trọng từ *portfolio\_optimize*, hãy yêu cầu backtest so với VNINDEX để kiểm chứng — tỷ trọng "tối ưu" trên quá khứ không đảm bảo tương lai. Chiến lược giữ lệnh ngắn ngày nên backtest với *t\_plus=2* hoặc *3*: tín hiệu bán và cắt lỗ/chốt lời trong lúc cổ phiếu chưa về tài khoản sẽ được dời tới phiên hợp lệ đầu tiên — sát thực tế VN hơn. Mặc định t\_plus=0 (khớp ngay). Công cụ danh mục cần tối thiểu 2 mã với ≥120 phiên lịch sử chung. Mã mới niêm yết sẽ bị loại tự động. Lần gọi đầu tiên có thể chậm \~10–30 giây. *** Mọi phân tích, chỉ tiêu, tín hiệu và thông tin do FinLens MCP cung cấp **chỉ mang tính tham khảo**, không phải khuyến nghị đầu tư. Quyết định mua/bán chứng khoán là trách nhiệm cá nhân của nhà đầu tư. FinLens không chịu trách nhiệm về tổn thất phát sinh từ việc sử dụng thông tin trên nền tảng. Dữ liệu tài chính được tổng hợp từ nguồn công khai và có thể có sai sót hoặc độ trễ. *** ## FAQ [#faq] Những thắc mắc phổ biến khi sử dụng FinLens MCP. FinLens MCP bao phủ toàn bộ thị trường chứng khoán Việt Nam — hơn 1.700 mã trên cả 3 sàn HOSE, HNX và UPCOM. Bạn có thể dùng `stocks_search` để tìm kiếm bất kỳ mã nào. Giá cổ phiếu và dữ liệu giao dịch được cập nhật theo phiên giao dịch (EOD — cuối ngày). Riêng dòng tiền **tự doanh, tổ chức và cá nhân trong nước** về dữ liệu sau \~18h hằng ngày — nếu hỏi trước thời điểm đó, các tool dòng tiền tự neo kỳ lũy kế vào phiên gần nhất ĐỦ dữ liệu và tách riêng phần khối ngoại của phiên mới (luôn ghi rõ kỳ dữ liệu trong câu trả lời). Báo cáo tài chính được cập nhật sau khi doanh nghiệp công bố chính thức. Báo cáo CTCK được cập nhật liên tục khi có báo cáo mới phát hành. Có — đầy đủ. Ngoài giá, hồ sơ, dòng tiền và báo cáo CTCK, các công cụ phân tích cơ bản (`fundamental_quality_scan`, `fundamental_get_key_metrics`, `fundamental_compare_peers`) tự nhận diện loại hình và dùng bộ chỉ tiêu chuyên biệt: ngân hàng (NIM, nợ xấu, bao phủ, CAR, LDR), chứng khoán (dư nợ margin vs trần 2× vốn, tự doanh, lợi nhuận thực hiện vs đánh giá lại), bảo hiểm (tỷ lệ bồi thường, dự phòng nghiệp vụ, tái bảo hiểm, danh mục đầu tư) — kèm so sánh trung bình ngành và điểm chất lượng riêng từng nhóm. Không. FinLens MCP là công cụ phân tích — nó cung cấp dữ liệu, tính toán chỉ tiêu, tóm tắt báo cáo và trình bày tín hiệu dòng tiền. Quyết định đầu tư cuối cùng luôn thuộc về bạn. Tín hiệu "tích lũy" hay "phân phối" là mô tả hành vi dòng tiền, không phải lời khuyên giao dịch. Có. Bạn có thể hỏi AI so sánh trực tiếp: *"So sánh HPG, HSG và NKG về ROE, P/E và tăng trưởng doanh thu"*. AI sẽ gọi `fundamental_compare_peers` hoặc lần lượt lấy dữ liệu từng mã rồi tổng hợp thành bảng so sánh. FinLens tổng hợp báo cáo từ các công ty chứng khoán lớn tại Việt Nam bao gồm SSI, VCSC, MBS, ACBS, HSC, FPTS và nhiều CTCK khác. Mỗi lần truy vấn trả về tối đa 10 báo cáo trong vòng 3 tháng gần nhất. Có. FinLens nay có dữ liệu vĩ mô TRỰC TIẾP theo tháng từ Tổng cục Thống kê (nhóm `gso_*`): CPI/lạm phát, sản xuất công nghiệp (IIP), bán lẻ, FDI, xuất nhập khẩu, GDP, doanh nghiệp, vận tải, du lịch… Hỏi kiểu "CPI 12 tháng qua thế nào?" hay "Tóm tắt KT-XH tháng gần nhất" — AI sẽ lấy số liệu thật. Ngoài ra vẫn có báo cáo vĩ mô từ CTCK (`research_list_reports` với `scope=macro`) cho góc nhìn phân tích. Lưu ý: số liệu mang tính lũy kế từ đầu năm với một số chỉ tiêu, và có thể được điều chỉnh ở các kỳ sau (sơ bộ → chính thức). Có. FinLens tích hợp số liệu **xuất nhập khẩu của Tổng cục Hải quan** theo **nước × mặt hàng**, theo tỉnh và riêng khối FDI — kịp thời theo tháng (số sơ bộ ra sớm, trước cả GDP và lợi nhuận quý). Dùng nhóm tool `gso_trade*`: hỏi "Top mặt hàng xuất khẩu và đối tác lớn nhất?", "Trung Quốc nhập gì nhiều nhất từ Việt Nam?", hay xem chuỗi xu hướng một mặt hàng. Điểm độc đáo là **cầu nối XNK → cổ phiếu** (`gso_trade_stocks`): từ một mặt hàng (vd "thủy sản") suy ra ngành và danh sách mã VN tiêu biểu (VHC, ANV, MPC…) kèm trị giá lũy kế & %YoY — biến số liệu vĩ mô thành ý tưởng nghiên cứu ngành. **Lưu ý:** danh sách mã chỉ là gợi ý ngành liên quan, KHÔNG phải khuyến nghị đầu tư. Có. Đưa cho AI danh sách 2–30 mã bạn quan tâm, AI sẽ dùng `portfolio_optimize` để tính tỷ trọng tối ưu theo nhiều phương pháp (Sharpe cao nhất, rủi ro thấp nhất, HRP...), vẽ `portfolio_efficient_frontier` để bạn chọn khẩu vị rủi ro, rồi `portfolio_backtest` kiểm chứng so với VNINDEX và `portfolio_analyze` đo lường rủi ro (VaR, drawdown, beta/alpha). Lưu ý: tỷ trọng được tính từ dữ liệu giá quá khứ — đây là công cụ phân tích định lượng, **không phải khuyến nghị đầu tư**. **max\_sharpe** — tối đa hóa lợi nhuận trên mỗi đơn vị rủi ro (thường tập trung vào ít mã); **min\_volatility** — biến động thấp nhất, phù hợp khẩu vị an toàn; **equal\_weight** — chia đều, đơn giản và bền vững; **inverse\_volatility** — mã càng biến động mạnh tỷ trọng càng thấp; **hrp** — phân cụm phân tầng theo tương quan, cân bằng giữa đa dạng hóa và ổn định. Có thể thêm `max_weight` (vd 0.3) để chống tập trung quá mức vào một mã. ### Câu hỏi thường gặp **FinLens MCP có bao nhiêu công cụ phân tích chứng khoán?** FinLens MCP cung cấp 107 công cụ, được giới thiệu theo 12 nhóm phân tích chính: tìm kiếm và hồ sơ doanh nghiệp, phân tích tài chính cơ bản, dòng tiền giao dịch, báo cáo công ty chứng khoán và đồng thuận, thị trường và ngành, quản lý kỳ dữ liệu, tối ưu danh mục, tín hiệu kỹ thuật và backtest, chứng quyền, vĩ mô và thương mại xuất nhập khẩu, cổ tức, tin tức phân tích bằng AI. Bảng tra cứu đầy đủ còn có các nhóm quỹ đầu tư (fund_*), trái phiếu doanh nghiệp (bond_*) và dữ liệu tỉnh/vùng (gso_*). Người dùng không cần nhớ tên công cụ hay viết code — AI tự chọn công cụ phù hợp với câu hỏi tiếng Việt. **Làm sao hỏi giá và thông tin cơ bản của một mã cổ phiếu bằng AI?** Chỉ cần hỏi bằng tiếng Việt tự nhiên, ví dụ "Giá hiện tại và thông tin cơ bản của TCB". FinLens MCP sẽ gọi stocks_get_latest_quote để lấy giá EOD mới nhất kèm OHLCV và giá trị giao dịch, cùng stocks_get_profile để lấy sàn niêm yết, ngành ICB và số cổ phiếu lưu hành. Nếu chưa nhớ mã, dùng stocks_search để tìm theo tên doanh nghiệp; dữ liệu bao phủ hơn 1.700 mã trên HOSE, HNX và UPCOM. **FinLens MCP có backtest chiến lược kỹ thuật được không?** Có. Công cụ signals_backtest chạy backtest long-only cho 1–10 mã trong 1–15 năm, tính Sharpe, Sortino, max drawdown và win rate so với mua-nắm giữ, kèm tùy chọn t_plus mô phỏng chu kỳ thanh toán T+2.5 của thị trường Việt Nam. Công cụ signals_optimize chạy grid search tối đa 200 tổ hợp tham số với train/test 70/30 và cảnh báo overfit, còn signals_screen quét tín hiệu trên 1.700 mã kèm bộ lọc cơ bản như ROE và P/E. **FinLens MCP có khuyến nghị mua bán cổ phiếu không?** Không. FinLens MCP là công cụ phân tích: cung cấp dữ liệu, tính toán chỉ tiêu, tóm tắt báo cáo và trình bày tín hiệu dòng tiền. Các tín hiệu "tích lũy" hay "phân phối" chỉ mô tả hành vi dòng tiền, không phải lời khuyên giao dịch. Mọi phân tích chỉ mang tính tham khảo và quyết định mua/bán chứng khoán thuộc trách nhiệm cá nhân của nhà đầu tư. --- # Phân tích cổ phiếu chứng khoán bằng AI: tự doanh, margin URL: https://docs.finlens.vn/mcp/chung-khoan Mô tả: Dùng AI phân tích cổ phiếu công ty chứng khoán: bóc tách danh mục tự doanh, cơ cấu doanh thu, tài sản khách hàng giữ hộ và margin toàn ngành. Tóm tắt: FinLens MCP có bốn công cụ chuyên biệt để phân tích cổ phiếu công ty chứng khoán Việt Nam: fundamental_securities_portfolio (danh mục tự doanh FVTPL/AFS/HTM và cho vay, giá gốc so với giá thị trường, lãi/lỗ chưa thực hiện), fundamental_securities_income (tỷ trọng doanh thu tự doanh, cho vay margin, môi giới, IB, tư vấn), fundamental_securities_client_assets (chứng khoán lưu ký của nhà đầu tư, tiền gửi khách hàng, thâm nhập margin, nợ khó đòi đã xử lý) và fundamental_securities_market_sentiment (dư nợ margin cùng tiền gửi khách hàng toàn ngành theo quý, không cần nhập mã cổ phiếu). Nhà đầu tư Việt Nam đặt câu hỏi tiếng Việt tự nhiên cho Claude, ChatGPT hoặc Gemini — ví dụ "Danh mục tự doanh của SSI đang lãi hay lỗ chưa thực hiện?" — và AI gọi trực tiếp các công cụ này rồi tổng hợp kết quả. Bốn công cụ chuyên ngành chứng khoán nêu trên thuộc gói FinLens Pro. Sản phẩm: mcp ⏱ Đọc 13 phút · 🟡 Trung cấp – Nâng cao · 🔧 Yêu cầu: FinLens Pro ## Vì sao công ty chứng khoán đặc biệt? [#vì-sao-công-ty-chứng-khoán-đặc-biệt] Lợi nhuận một CTCK đến từ ba nguồn rất khác nhau về bản chất rủi ro: **tự doanh** (đánh chứng khoán bằng vốn của chính mình — nhạy thị trường), **cho vay margin** (lãi cho vay ký quỹ — nhạy lãi suất & thanh khoản), và **môi giới** (phí giao dịch — nhạy thanh khoản thị trường). FinLens tách bạch ba mảng này để bạn biết một CTCK đang "đặt cược" vào đâu. FVTPL/AFS/HTM, giá gốc vs thị trường, lãi/lỗ chưa thực hiện Tự doanh vs margin vs môi giới vs IB Quy mô tệp khách hàng, thâm nhập margin, nợ xử lý Margin & tiền gửi toàn ngành = đòn bẩy & dry powder ## Danh mục tự doanh — giá gốc vs thị trường [#danh-mục-tự-doanh--giá-gốc-vs-thị-trường] `fundamental_securities_portfolio` bóc danh mục tự doanh theo lớp tài sản: **FVTPL** (ghi nhận qua lãi/lỗ), **AFS** (sẵn sàng để bán), **HTM** (giữ đến đáo hạn), và **cho vay & phải thu** (gồm dư nợ margin). Mỗi lớp có giá gốc và giá thị trường → **lãi/lỗ CHƯA thực hiện** (mark-to-market) trên các lớp được đánh giá lại. FVTPL/AFS được mark-to-market; còn cho vay margin & HTM giữ ở giá gốc (không có "lỗ ảo"). FinLens xử lý đúng việc này — bạn nhận con số lãi/lỗ chưa thực hiện chính xác, không bị méo bởi phần danh mục giữ ở giá gốc. **Danh mục tự doanh của SSI: cơ cấu FVTPL/AFS/HTM/cho vay ra sao, đang lãi hay lỗ chưa thực hiện, và dư nợ margin chiếm bao nhiêu danh mục?** → securities_portfolio(SSI) — cost vs market theo lớp + unrealized_pnl + margin_balance ## Cơ cấu doanh thu — mô hình kinh doanh [#cơ-cấu-doanh-thu--mô-hình-kinh-doanh] `fundamental_securities_income` tách doanh thu hoạt động thành: **tự doanh** (lãi bán + đánh giá lại + cổ tức/lãi), **cho vay margin**, **môi giới**, **IB** (bảo lãnh/phát hành), **tư vấn**, và khác — mỗi mảng kèm tỷ trọng + YoY. Đây là cách nhanh nhất để biết một CTCK đang nghiêng về đâu. CTCK nghiêng **tự doanh + margin** cao → lợi nhuận RẤT nhạy với thị trường & lãi suất (rủi ro/lợi nhuận cao, dễ biến động mạnh theo VN-Index). CTCK nghiêng **môi giới + IB** → ổn định hơn nhưng phụ thuộc thanh khoản thị trường. AI tự đọc và diễn giải mức tập trung này. **Cơ cấu doanh thu của VND: tự doanh, cho vay margin và môi giới chiếm bao nhiêu mỗi mảng? Mô hình này nhạy với thị trường đến mức nào?** → securities_income(VND) — tỷ trọng từng mảng + signal mức nhạy thị trường ## Tài sản khách hàng giữ hộ — franchise & rủi ro margin [#tài-sản-khách-hàng-giữ-hộ--franchise--rủi-ro-margin] `fundamental_securities_client_assets` khai thác phần NGOẠI BẢNG — tài sản khách hàng mà bảng cân đối không thể hiện, nhưng đo trực tiếp quy mô **franchise môi giới**: * **Chứng khoán lưu ký của nhà đầu tư** = quy mô tệp khách hàng thật. * **Tiền gửi khách hàng** = "dry powder" (tiền chờ giải ngân). * **Thâm nhập margin** = dư nợ margin ÷ chứng khoán niêm yết của khách → mức cho vay tích cực hay thận trọng. * **Nợ khó đòi đã xử lý ÷ vốn chủ** = vân tay rủi ro quản trị margin trong quá khứ (các đợt call margin/blow-up). **Tài sản khách hàng giữ hộ của HCM: quy mô tệp khách hàng (CK lưu ký), CTCK này cho vay margin tích cực đến mức nào, và có vết nợ margin xấu trong quá khứ không?** → securities_client_assets(HCM) — client_securities, margin_penetration, bad_debt_to_equity ## ⭐ Tâm lý thị trường toàn ngành — chỉ báo độc nhất [#-tâm-lý-thị-trường-toàn-ngành--chỉ-báo-độc-nhất] `fundamental_securities_market_sentiment` KHÔNG cần ticker — nó cộng dồn ngoại bảng của **TOÀN BỘ công ty chứng khoán** theo quý để dựng một chỉ báo tâm lý cấp thị trường mà ít nơi có: * **Tổng tiền gửi khách hàng** (dry powder) — nhà đầu tư đang thủ tiền chờ hay đã giải ngân? * **Tổng dư nợ margin** — đòn bẩy toàn thị trường đang phình hay co? * **Margin / chứng khoán lưu ký** — mức đòn bẩy trên tệp khách hàng toàn ngành. **Margin tăng + tiền mặt giảm** = nhà đầu tư đang giải ngân đòn bẩy — thường ở giai đoạn cuối sóng tăng (cảnh giác). **Tiền gửi tăng** = thủ tiền/thận trọng (tích lũy dry powder). Đây là lớp phủ vĩ mô tuyệt vời để bổ trợ phân tích dòng tiền & cấu trúc thị trường — tương tự series "margin debt" của thị trường Mỹ. **Tâm lý thị trường chứng khoán hiện tại qua lăng kính margin toàn ngành: dư nợ margin và tiền gửi khách hàng 6 quý gần nhất đang diễn biến ra sao? Thị trường đang hưng phấn dùng đòn bẩy hay thận trọng thủ tiền?** → securities_market_sentiment(quarter, 6) — chuỗi margin/cash/custody toàn ngành + signal diễn giải ## Prompt phân tích CTCK toàn diện [#prompt-phân-tích-ctck-toàn-diện] **Phân tích chuyên sâu cổ phiếu chứng khoán SSI: 1. Danh mục tự doanh — cơ cấu & lãi/lỗ chưa thực hiện 2. Cơ cấu doanh thu — nghiêng tự doanh/margin hay môi giới, mức nhạy thị trường 3. Tài sản khách hàng giữ hộ — quy mô franchise & thâm nhập margin 4. Bối cảnh: tâm lý margin toàn ngành đang ở đâu trong chu kỳ? 5. Định giá P/B vs lịch sử & kết luận điểm mạnh/yếu** → AI gọi securities_portfolio + securities_income + securities_client_assets + securities_market_sentiment + valuation_history(pb), tổng hợp Kết hợp với [Bài 3 — Dòng tiền](/mcp/dong-tien) (smart money) và [Bài 8 — Vĩ mô](/mcp/vi-mo) (lãi suất, thanh khoản OMO) để có bức tranh đầy đủ về môi trường vận hành của CTCK. Xem thêm [Bài 12](/mcp/cong-ty-thuong) và [Bài 13](/mcp/ngan-hang) cho hai nhóm doanh nghiệp còn lại. ## Bài liên quan [#bài-liên-quan] Cơ cấu chi phí, nợ vay, vốn lưu động và định giá nội tại. Chất lượng tài sản, huy động và cơ cấu thu nhập ngân hàng. Ghép tâm lý margin toàn ngành với dòng tiền thực tế của cá mập. ### Câu hỏi thường gặp **Làm sao biết công ty chứng khoán đang lãi hay lỗ ở danh mục tự doanh?** Công cụ fundamental_securities_portfolio của FinLens MCP bóc danh mục tự doanh theo từng lớp tài sản: FVTPL (ghi nhận qua lãi/lỗ), AFS (sẵn sàng để bán), HTM (giữ đến đáo hạn) và cho vay & phải thu (gồm dư nợ margin). Mỗi lớp có giá gốc và giá thị trường, chênh lệch chính là lãi/lỗ chưa thực hiện theo mark-to-market. Lưu ý chỉ FVTPL và AFS được đánh giá lại; cho vay margin và HTM giữ ở giá gốc nên không phát sinh lỗ ảo, và FinLens MCP xử lý đúng khác biệt này khi tính toán. **Dư nợ margin toàn thị trường chứng khoán Việt Nam đang tăng hay giảm?** Công cụ fundamental_securities_market_sentiment cộng dồn số liệu ngoại bảng của toàn bộ công ty chứng khoán theo quý để dựng chuỗi tổng tiền gửi khách hàng, tổng dư nợ margin và tỷ lệ margin trên chứng khoán lưu ký; công cụ này không cần nhập mã cổ phiếu. Cách đọc: margin tăng kèm tiền mặt giảm cho thấy nhà đầu tư đang giải ngân đòn bẩy, thường xuất hiện ở giai đoạn cuối sóng tăng; ngược lại tiền gửi tăng phản ánh tâm lý thận trọng, tích lũy dry powder. Đây là lớp phủ vĩ mô tương tự series margin debt của thị trường Mỹ. **Cơ cấu doanh thu của công ty chứng khoán gồm những mảng nào?** Công cụ fundamental_securities_income tách doanh thu hoạt động của công ty chứng khoán thành tự doanh (lãi bán, đánh giá lại, cổ tức và lãi), cho vay margin, môi giới, IB (bảo lãnh và phát hành), tư vấn và các khoản khác, mỗi mảng kèm tỷ trọng và tăng trưởng so với cùng kỳ. Công ty chứng khoán nghiêng nhiều về tự doanh và margin có lợi nhuận rất nhạy với biến động thị trường và lãi suất, dễ dao động mạnh theo VN-Index. Công ty nghiêng về môi giới và IB thì ổn định hơn nhưng phụ thuộc thanh khoản thị trường. **Làm sao đánh giá quy mô khách hàng và rủi ro margin của một công ty chứng khoán?** Công cụ fundamental_securities_client_assets khai thác phần ngoại bảng mà bảng cân đối kế toán không thể hiện: chứng khoán lưu ký của nhà đầu tư (quy mô tệp khách hàng thật), tiền gửi khách hàng (dry powder chờ giải ngân), thâm nhập margin (dư nợ margin chia chứng khoán niêm yết của khách) và nợ khó đòi đã xử lý trên vốn chủ sở hữu. Thâm nhập margin cho biết công ty cho vay tích cực hay thận trọng, còn nợ khó đòi đã xử lý là vân tay rủi ro quản trị margin trong quá khứ, chẳng hạn các đợt call margin. --- # Chứng quyền có bảo đảm (CW): Định giá & So sánh bằng AI URL: https://docs.finlens.vn/mcp/chung-quyen Mô tả: Định giá chứng quyền có bảo đảm bằng AI: điểm hòa vốn, premium, đòn bẩy hiệu dụng, Greeks và IV, so sánh mọi CW trên cùng mã cơ sở để chọn mã tối ưu. Tóm tắt: FinLens MCP định giá chứng quyền có bảo đảm (CW) của thị trường chứng khoán Việt Nam theo mô hình Black-Scholes: điểm hòa vốn, premium, trạng thái ITM/ATM/OTM, đòn bẩy đơn và đòn bẩy hiệu dụng, Greeks (delta, gamma, theta, vega) cùng Implied Volatility. Bốn công cụ liên quan gồm warrants_search (tìm CW theo mã cơ sở hoặc CTCK phát hành), warrants_get_info (định giá đầy đủ một mã CW, giá lý thuyết so với giá thị trường), warrants_price_history (giá EOD, VWAP, giá trị khớp trung bình mỗi phiên, số phiên khối lượng bằng 0) và warrants_compare (xếp hạng toàn bộ CW trên cùng cổ phiếu cơ sở theo premium, đòn bẩy hoặc thanh khoản). Nhà đầu tư Việt Nam gọi các công cụ này bằng câu hỏi tiếng Việt trong Claude, ChatGPT hoặc Gemini; tính năng chứng quyền yêu cầu gói FinLens Pro. Sản phẩm: mcp ⏱ Đọc 10 phút · 🟡 Trung cấp · 🔧 Yêu cầu: FinLens Pro ## Chứng quyền có bảo đảm là gì? [#chứng-quyền-có-bảo-đảm-là-gì] **Chứng quyền có bảo đảm (Covered Warrant — CW)** là sản phẩm phái sinh do CTCK phát hành, cho phép người nắm giữ quyền (không phải nghĩa vụ) mua cổ phiếu cơ sở tại một giá định sẵn (giá thực hiện) trước ngày đáo hạn. CW phù hợp với nhà đầu tư muốn: * **Đòn bẩy cao** — bỏ ít vốn, khuếch đại lợi nhuận (và rủi ro) so cổ phiếu cơ sở * **Giới hạn lỗ tối đa** = giá mua CW (khác với margin) * **Phòng ngừa rủi ro** danh mục cổ phiếu đang nắm giữ Nếu cổ phiếu cơ sở không vượt giá thực hiện trước ngày đáo hạn, CW hết giá trị và nhà đầu tư mất toàn bộ vốn đã bỏ ra. Hiểu rõ rủi ro trước khi đầu tư. ## Các khái niệm quan trọng trước khi dùng tool [#các-khái-niệm-quan-trọng-trước-khi-dùng-tool] Điểm hòa vốn Giá cổ phiếu cơ sở cần đạt để nhà đầu tư không lãi không lỗ khi đáo hạn = Giá thực hiện + (Giá CW × Tỷ lệ chuyển đổi). Premium % Phần trả thêm so với mua thẳng cổ phiếu = (Điểm hòa vốn − Giá cổ phiếu) / Giá cổ phiếu × 100. Premium cao = tốn kém hơn. ITM / ATM / OTM In-the-money: cổ phiếu > giá thực hiện (có giá trị nội tại). At-the-money: bằng nhau. Out-of-the-money: cổ phiếu \< giá thực hiện. Đòn bẩy hiệu dụng Tỷ lệ % thay đổi giá CW / % thay đổi giá cổ phiếu = Delta × Đòn bẩy đơn. Phản ánh mức khuếch đại thực tế. Delta (δ) CW tăng bao nhiêu VND khi cổ phiếu tăng 1 VND. Delta gần 1 (ITM sâu) = CW phản ứng mạnh. Delta gần 0 (OTM xa) = ít phản ứng. Theta (θ) Giá trị CW giảm bao nhiêu mỗi ngày do thời gian trôi qua. Theta cao = CW hao giá trị nhanh khi đến gần đáo hạn. Implied Volatility (IV) Biến động ngụ ý của cổ phiếu cơ sở theo giá CW hiện tại. IV cao = thị trường kỳ vọng biến động lớn. So với HV để đánh giá CW đắt hay rẻ. Tỷ lệ chuyển đổi Cần bao nhiêu CW để đổi lấy 1 cổ phiếu cơ sở khi thực hiện quyền. Ví dụ: ratio=5 → 5 CW đổi 1 cổ phiếu. Giá trị thời gian Phần giá CW cao hơn giá trị nội tại — phụ thuộc vào thời gian còn lại và IV. Giảm dần theo thời gian (time decay). Thanh khoản & VWAP Giá trị khớp bình quân mỗi phiên (VND) cho biết CW dễ mua/bán đến đâu. Nhiều CW chỉ khớp vài chục triệu/phiên, CW gần đáo hạn có thể "trắng" thanh khoản (phiên KL=0). VWAP = giá trị / khối lượng = giá khớp bình quân thực tế. ## Tìm CW theo mã cổ phiếu cơ sở [#tìm-cw-theo-mã-cổ-phiếu-cơ-sở] **Tìm tất cả chứng quyền đang giao dịch trên cổ phiếu HPG — điều khoản tóm tắt, giá thực hiện, tỷ lệ chuyển đổi và ngày đáo hạn** → warrants_search: underlying=HPG — danh sách CW, CTCK phát hành, điều khoản cơ bản **Liệt kê các chứng quyền do SSI phát hành đang còn hạn — mã nào có thời gian còn lại nhiều nhất?** → warrants_search: issuer=SSI, filter=active — sort theo days_to_expiry giảm dần ## Định giá đầy đủ một CW cụ thể [#định-giá-đầy-đủ-một-cw-cụ-thể] **Định giá chi tiết chứng quyền CHPG2408 — điểm hòa vốn, premium, ITM/OTM, đòn bẩy hiệu dụng, và toàn bộ Greeks (delta, gamma, theta, vega, IV)** → warrants_get_info: đầy đủ Black-Scholes + giá lý thuyết vs giá thị trường **Implied Volatility của CVHM2309 đang là bao nhiêu? So với historical volatility của VHM thì CW này đang đắt hay rẻ?** → warrants_get_info: IV + gọi stocks_get_price_history để tính HV, so sánh IV vs HV **CFPT2312 còn bao nhiêu ngày đến đáo hạn? Theta đang ở mức bao nhiêu — mỗi ngày CW mất bao nhiêu giá trị vì time decay?** → warrants_get_info: days_to_expiry + theta (VND/ngày) + cảnh báo nếu còn ít ngày ## Giá & thanh khoản CW [#giá--thanh-khoản-cw] Thanh khoản là yếu tố **sống còn** với CW: một mã premium thấp, đòn bẩy đẹp nhưng mỗi phiên chỉ khớp vài triệu đồng thì rất khó vào/ra đúng giá. Dùng `warrants_price_history` để xem chuỗi giá EOD (OHLC, khối lượng, giá trị, VWAP, khối ngoại) kèm tổng hợp thanh khoản — tất cả giá CW theo VND thô. **Chứng quyền CHPG2607 thanh khoản thế nào? Cho tôi giá trị khớp trung bình mỗi phiên, có phiên nào không giao dịch không, và xếp hạng thanh khoản** → warrants_price_history: avg_daily_value + zero_volume_days + liquidity_tier (Rất thấp → Rất cao) **Lịch sử giá 30 phiên gần nhất của CVHM2607 — giá mở/cao/thấp/đóng, VWAP và khối lượng khớp mỗi phiên, thanh khoản đang tăng hay giảm?** → warrants_price_history: OHLC (VND thô) + VWAP = giá trị/khối lượng + xu hướng thanh khoản gần đây Càng gần ngày giao dịch cuối, nhiều CW càng ít người mua/bán — giá trị khớp rớt mạnh và xuất hiện phiên KL=0. Luôn kiểm tra `liquidity_tier` và `zero_volume_days` trước khi đặt lệnh để tránh kẹt hàng dù định giá có đẹp. ## So sánh tất cả CW trên cùng mã cơ sở [#so-sánh-tất-cả-cw-trên-cùng-mã-cơ-sở] **So sánh tất cả chứng quyền trên HPG đang giao dịch — xếp hạng theo premium thấp nhất và đòn bẩy hiệu dụng cao nhất. Tôi muốn CW có thời gian còn lại ít nhất 3 tháng** → warrants_compare: underlying=HPG, sort_by=premium/leverage/liquidity — bảng so sánh kèm cột thanh khoản (giá trị khớp TB/phiên, số phiên KL=0) **Trên VNM, CW nào có tỷ lệ cân bằng tốt nhất giữa premium thấp và đòn bẩy hợp lý? Loại trừ CW gần đáo hạn dưới 2 tháng** → warrants_compare: underlying=VNM, filter_min_days=60 — gợi ý CW "ngọt nhất" với cả 2 tiêu chí **So sánh CW trên FPT và xếp theo thanh khoản cao nhất — tôi muốn mã dễ mua bán, tránh CW có nhiều phiên không khớp lệnh** → warrants_compare: underlying=FPT, sort_by=liquidity — CW có giá trị khớp TB/phiên cao lên đầu, kèm số phiên KL=0 ## Hướng dẫn chọn CW phù hợp [#hướng-dẫn-chọn-cw-phù-hợp] **1. Premium thấp** — phần trả thêm ít hơn = vào lệnh hiệu quả hơn. Dưới 5% là lý tưởng. **2. Thời gian còn lại đủ dài** — tối thiểu 3–6 tháng để có thời gian cho luận điểm đúng. **3. Đòn bẩy hiệu dụng vừa phải** — 5–15× thường an toàn hơn 30–50× (dễ bị xoá sạch vốn). **4. IV không quá cao** — CW với IV >> HV đang bị định giá đắt bởi thị trường. **5. Thanh khoản đủ tốt** — ưu tiên CW có giá trị khớp TB/phiên cao và không có phiên KL=0; CW kẹt thanh khoản rất khó thoát hàng dù định giá đẹp. **Tôi đang bullish HPG trong 3–4 tháng tới. So sánh tất cả CW trên HPG và tư vấn CW nào phù hợp nhất với: premium dưới 8%, đòn bẩy hiệu dụng 8–15 lần, còn ít nhất 3 tháng đến đáo hạn và Delta ít nhất 0.3** → warrants_compare + filter đa tiêu chí — AI giải thích trade-off và đề xuất cụ thể ## Bài liên quan [#bài-liên-quan] Xác nhận luận điểm dùng CW với tín hiệu dòng tiền thực tế của cổ phiếu cơ sở. Xác định điểm vào CW dựa trên mức hỗ trợ và tín hiệu kỹ thuật. Chuỗi đầy đủ FinLens MCP. ### Câu hỏi thường gặp **Chứng quyền có bảo đảm (CW) là gì?** Chứng quyền có bảo đảm (Covered Warrant — CW) là sản phẩm phái sinh do công ty chứng khoán phát hành, cho phép người nắm giữ quyền (không phải nghĩa vụ) mua cổ phiếu cơ sở tại một giá định sẵn là giá thực hiện, trước ngày đáo hạn. CW hấp dẫn nhờ đòn bẩy cao và khoản lỗ tối đa chỉ bằng đúng số tiền bỏ ra mua CW, khác với giao dịch margin. Đổi lại, nếu cổ phiếu cơ sở không vượt giá thực hiện trước ngày đáo hạn, CW hết giá trị và nhà đầu tư mất toàn bộ vốn đã bỏ ra. **Làm sao biết một chứng quyền đang đắt hay rẻ?** So sánh Implied Volatility (IV) của chứng quyền với historical volatility của cổ phiếu cơ sở: IV cao hơn HV nhiều nghĩa là CW đang bị thị trường định giá đắt. Công cụ warrants_get_info của FinLens MCP trả về IV cùng giá lý thuyết Black-Scholes đặt cạnh giá thị trường, còn stocks_get_price_history cung cấp chuỗi giá cổ phiếu để tính HV. Premium % — phần trả thêm so với mua thẳng cổ phiếu, tính bằng (điểm hòa vốn − giá cổ phiếu)/giá cổ phiếu — cũng là thước đo chi phí, dưới 5% được xem là lý tưởng. **Chọn chứng quyền nên dựa vào tiêu chí nào?** Năm tiêu chí chọn chứng quyền có bảo đảm gồm: premium thấp (dưới 5% là lý tưởng), thời gian còn lại tối thiểu 3–6 tháng, đòn bẩy hiệu dụng vừa phải (5–15 lần thường an toàn hơn 30–50 lần), IV không cao hơn HV quá nhiều, và thanh khoản đủ tốt. Công cụ warrants_compare của FinLens MCP xếp hạng toàn bộ CW trên cùng một cổ phiếu cơ sở theo premium, đòn bẩy hoặc thanh khoản, kèm bộ lọc số ngày còn lại đến đáo hạn, để lọc ra mã đáp ứng đủ các tiêu chí trên. **Cách kiểm tra thanh khoản chứng quyền trước khi mua?** Công cụ warrants_price_history của FinLens MCP trả về giá trị khớp trung bình mỗi phiên (avg_daily_value), số phiên không có giao dịch (zero_volume_days) và xếp hạng thanh khoản theo thang từ Rất thấp đến Rất cao, kèm chuỗi giá EOD với OHLC, khối lượng và VWAP. Chứng quyền càng gần ngày giao dịch cuối càng dễ cạn thanh khoản, giá trị khớp rớt mạnh và xuất hiện phiên khối lượng bằng 0. Cần kiểm tra hai chỉ số này trước khi đặt lệnh để tránh kẹt hàng, dù định giá của CW có hấp dẫn đến đâu. --- # Phân tích cổ tức bằng AI: lợi suất, payout, lịch GDKHQ URL: https://docs.finlens.vn/mcp/co-tuc Mô tả: Phân tích cổ tức bằng AI với FinLens MCP: tra lịch chốt quyền (GDKHQ) sắp tới, xem lịch sử cổ tức từng mã, đánh giá lợi suất, tỷ lệ chi trả và độ đều. Tóm tắt: FinLens MCP cho phép nhà đầu tư Việt Nam hỏi trợ lý AI như Claude bằng tiếng Việt về cổ tức cổ phiếu niêm yết, với ba công cụ: `dividends_upcoming` (lịch chốt quyền sắp tới toàn thị trường, lọc theo sàn, danh sách mã, lợi suất tối thiểu và số ngày tới), `dividends_get_history` (lịch sử từng đợt và gộp theo năm của một mã) và `dividends_analyze_policy` (lợi suất TTM, tỷ lệ chi trả, số năm trả và chuỗi liên tiếp, CAGR 3/5 năm, hồ sơ cổ tức, cờ cảnh báo). Các công cụ này trả dữ liệu trung lập, không đưa khuyến nghị Mua/Bán, và có thể ghép với `fundamental_get_key_metrics`, `fundamental_compare_peers`, `research_get_analyst_consensus` để kiểm tra tính bền vững của cổ tức. FinLens MCP còn có lệnh tắt `/phan_tich_co_tuc ` chạy tự động chuỗi phân tích chính sách cổ tức, lịch sử, cơ bản, so sánh cùng ngành và quan điểm công ty chứng khoán; tính năng cổ tức yêu cầu gói FinLens Pro. Sản phẩm: mcp ⏱ Đọc 9 phút · 🟢 Cơ bản → Trung cấp · 🔧 Yêu cầu: FinLens Pro ## 3 loại "chia" — đừng nhầm lẫn [#3-loại-chia--đừng-nhầm-lẫn] Khi doanh nghiệp "chia" cho cổ đông, có **ba loại sự kiện hoàn toàn khác bản chất**. Nhầm lẫn giữa chúng là sai lầm phổ biến nhất của nhà đầu tư cổ tức: Cổ tức TIỀN Tiền mặt thật vào tài khoản (VND/cổ phiếu). Đây mới là **thu nhập** — thứ nhà đầu tư cổ tức quan tâm. Thưởng CỔ PHIẾU Nhận thêm cổ phiếu (vd 100:21). KHÔNG tạo tiền — chỉ tăng số lượng CP, giá tham chiếu điều chỉnh giảm tương ứng. Tổng giá trị không đổi. Quyền MUA Phát hành thêm cho cổ đông hiện hữu (vd 2:1 @10.000đ). **Pha loãng** — nhà đầu tư phải BỎ THÊM tiền, không phải nhận. Đây không phải cổ tức. Vào ngày giao dịch không hưởng quyền (GDKHQ / ex-date), giá tham chiếu của cổ phiếu bị **điều chỉnh giảm đúng bằng cổ tức**. Bạn nhận tiền nhưng giá cổ phiếu giảm tương ứng — lợi ích thực đến từ việc doanh nghiệp tạo ra dòng tiền bền vững, không phải từ bản thân việc chia. ## Các khái niệm cốt lõi [#các-khái-niệm-cốt-lõi] Lợi suất cổ tức Dividend yield = Cổ tức tiền 12 tháng / Giá hiện tại × 100. Vd 2.000đ/CP trên giá 50.000 = 4%. Thay đổi khi giá đổi. Tỷ lệ chi trả Payout ratio = Cổ tức tiền / EPS. Đo phần lợi nhuận đem chia. >100% = chia nhiều hơn kiếm được → khó bền. GDKHQ (ex-date) Ngày giao dịch không hưởng quyền. Phải SỞ HỮU cổ phiếu TRƯỚC ngày này (mua trước ≥ T+2) mới được nhận đợt cổ tức đó. Độ đều / Streak Số năm liên tiếp trả cổ tức tiền. Streak dài = chính sách ổn định, dễ dự báo dòng tiền tương lai. CAGR cổ tức Tốc độ tăng cổ tức tiền/CP qua các năm. Dương & ổn định = "dividend grower" — hấp dẫn dài hạn. Ngày chi trả Pay date — ngày tiền thực về tài khoản, thường sau GDKHQ vài tuần đến vài tháng. ## Lịch cổ tức sắp tới (toàn thị trường) [#lịch-cổ-tức-sắp-tới-toàn-thị-trường] **Sắp tới 30 ngày có mã nào chốt quyền trả cổ tức tiền không? Sắp xếp theo ngày, kèm lợi suất theo giá hiện tại** → dividends_upcoming: kind=cash, days_ahead=30 — danh sách GDKHQ + cash yield, sort theo ex_date **Có mã nào trên HOSE sắp chốt quyền trả cổ tức tiền lợi suất trên 6% trong 60 ngày tới không?** → dividends_upcoming: kind=cash, exchange=HOSE, min_cash_yield=6, days_ahead=60 **Trong các mã VNM, FPT, HPG, MWG, REE — mã nào sắp có sự kiện cổ tức/quyền trong quý này?** → dividends_upcoming: symbols=[VNM,FPT,HPG,MWG,REE], days_ahead=90, kind=all ## Lịch sử cổ tức của một mã [#lịch-sử-cổ-tức-của-một-mã] **Lịch sử cổ tức của REE 7 năm gần đây — mỗi năm trả tiền bao nhiêu, có thưởng cổ phiếu hay phát hành quyền gì không?** → dividends_get_history: ticker=REE, years=7 — từng đợt + gộp theo năm + sự kiện sắp tới **Cổ tức tiền của VNM đang tăng hay giảm qua các năm? Có năm nào cắt cổ tức không?** → dividends_get_history (by_year) — đọc chuỗi cổ tức/CP theo năm, phát hiện gián đoạn ## Phân tích chính sách cổ tức (công cụ lõi) [#phân-tích-chính-sách-cổ-tức-công-cụ-lõi] **VNM có phải cổ phiếu cổ tức tốt không? Cho tôi lợi suất hiện tại, tỷ lệ chi trả, độ đều và tăng trưởng cổ tức** → dividends_analyze_policy: yield + payout + years_paid/streak + CAGR 3/5 năm + dividend_profile + flags **Lợi suất TTM**, **payout ratio** (cờ đỏ nếu >100%), **số năm trả + chuỗi liên tiếp**, **CAGR 3/5 năm**, thiên tiền mặt hay thưởng CP, số lần phát hành quyền, một **"hồ sơ cổ tức"** (vd "Trả tiền đều, lợi suất cao" / "Tăng cổ tức đều" / "Thiên thưởng CP" / "Pha loãng nhiều"), và danh sách **cờ cảnh báo**. Công cụ **trung lập** — không nói Mua/Bán, AI sẽ tự tổng hợp khuyến nghị. **Cổ tức của mã X có bền không? Tỷ lệ chi trả so với lợi nhuận thế nào, có vay nợ để trả cổ tức không?** → dividends_analyze_policy (payout) + fundamental_get_key_metrics (LN, dòng tiền, đòn bẩy) ## Quy trình chọn cổ phiếu cổ tức (1 prompt) [#quy-trình-chọn-cổ-phiếu-cổ-tức-1-prompt] FinLens MCP có sẵn lệnh **/phan\_tich\_co\_tuc \** — tự động chạy chuỗi: phân tích chính sách → lịch sử → cơ bản → so ngành → quan điểm CTCK, rồi tổng hợp nhận định cho nhà đầu tư cổ tức. Trên Claude gõ `/phan_tich_co_tuc VNM`. **Tôi muốn mua cổ phiếu để nhận cổ tức đều dài hạn. Đánh giá REE giúp tôi: 1. Lợi suất cổ tức tiền hiện tại + lịch sử 7 năm (đều/tăng/giảm) 2. Tỷ lệ chi trả so với lợi nhuận & dòng tiền — cổ tức có bền không? 3. So sánh lợi suất/payout với các mã cùng ngành 4. Quan điểm CTCK về triển vọng & kế hoạch cổ tức 5. Rủi ro cần lưu ý (cắt cổ tức, pha loãng, payout cao)** → dividends_analyze_policy + dividends_get_history + fundamental_get_key_metrics + fundamental_compare_peers + research_get_analyst_consensus **1. Lợi suất hợp lý** — đủ hấp dẫn so với lãi tiết kiệm & cùng ngành, nhưng cảnh giác lợi suất quá cao (>12%) vì có thể do giá giảm mạnh. **2. Trả đều & lâu năm** — streak dài, không cắt cổ tức kể cả năm khó khăn. **3. Payout bền vững** — dưới 70–80% lợi nhuận, được dòng tiền thực (FCF) đỡ, không vay nợ để trả. **4. Cổ tức tăng dần** — CAGR dương cho thấy doanh nghiệp tăng trưởng & chia sẻ với cổ đông. Dữ liệu cổ tức tổng hợp từ nguồn công khai (lịch GDKHQ), có thể có độ trễ hoặc sai sót. Lợi suất thay đổi liên tục theo giá. Lịch sắp tới phụ thuộc thời điểm doanh nghiệp công bố. Mọi phân tích chỉ mang tính tham khảo, **không phải khuyến nghị đầu tư**. ## Bài liên quan [#bài-liên-quan] Lợi nhuận, dòng tiền tự do và đòn bẩy quyết định cổ tức có bền hay không. Báo cáo phân tích thường nêu kế hoạch & dự phóng cổ tức tương lai. Kết hợp cổ tức với cơ bản, dòng tiền, kỹ thuật để soi mã toàn diện. ### Câu hỏi thường gặp **Làm sao biết mã nào sắp chốt quyền trả cổ tức tiền?** Công cụ `dividends_upcoming` của FinLens MCP liệt kê các mã sắp giao dịch không hưởng quyền trên thị trường chứng khoán Việt Nam, kèm lợi suất tiền mặt tính theo giá hiện tại và sắp xếp theo ngày GDKHQ. Có thể lọc theo loại sự kiện (kind=cash cho cổ tức tiền), số ngày tới (days_ahead), sàn niêm yết (exchange=HOSE), lợi suất tối thiểu (min_cash_yield) hoặc một danh sách mã trong watchlist. Ví dụ câu hỏi: "Sắp tới 30 ngày có mã nào chốt quyền trả cổ tức tiền không, sắp xếp theo ngày kèm lợi suất?" Lịch sắp tới phụ thuộc thời điểm doanh nghiệp công bố nên có thể thay đổi. **Mua cổ phiếu trước ngày nào thì được nhận cổ tức?** Nhà đầu tư phải sở hữu cổ phiếu trước ngày giao dịch không hưởng quyền (GDKHQ, ex-date) mới được nhận đợt cổ tức đó, tức là phải mua trước ít nhất T+2 để giao dịch kịp hoàn tất. Ngày tiền thực về tài khoản là ngày chi trả (pay date), thường sau GDKHQ vài tuần đến vài tháng. Lưu ý vào ngày GDKHQ, giá tham chiếu của cổ phiếu bị điều chỉnh giảm đúng bằng mức cổ tức, nên cổ tức không phải "tiền cho không". **Lợi suất cổ tức và tỷ lệ chi trả tính như thế nào?** Lợi suất cổ tức (dividend yield) = cổ tức tiền 12 tháng chia cho giá hiện tại nhân 100; ví dụ cổ tức 2.000 đồng mỗi cổ phiếu trên giá 50.000 đồng cho lợi suất 4%, và con số này thay đổi mỗi khi giá đổi. Tỷ lệ chi trả (payout ratio) = cổ tức tiền chia EPS, đo phần lợi nhuận đem chia; payout trên 100% nghĩa là doanh nghiệp chia nhiều hơn số kiếm được nên khó bền. Công cụ `dividends_analyze_policy` của FinLens MCP trả về lợi suất TTM, payout ratio kèm cờ đỏ khi vượt 100%, số năm trả và chuỗi liên tiếp, CAGR cổ tức 3 và 5 năm cùng danh sách cờ cảnh báo. **Cổ tức tiền, thưởng cổ phiếu và quyền mua khác nhau thế nào?** Cổ tức tiền là tiền mặt thật vào tài khoản tính theo VND trên mỗi cổ phiếu, và đây mới là thu nhập mà nhà đầu tư cổ tức quan tâm. Thưởng cổ phiếu (ví dụ tỷ lệ 100:21) chỉ làm tăng số lượng cổ phiếu nắm giữ trong khi giá tham chiếu điều chỉnh giảm tương ứng, nên tổng giá trị không đổi và không tạo ra tiền. Quyền mua (ví dụ 2:1 giá 10.000 đồng) là phát hành thêm cho cổ đông hiện hữu, buộc nhà đầu tư bỏ thêm tiền và gây pha loãng, không phải cổ tức. Công cụ `dividends_get_history` của FinLens MCP tách rõ ba loại sự kiện này theo từng đợt và gộp theo năm cho một mã. --- # Thuyết minh BCTC, cơ cấu chi phí & định giá DCF bằng AI URL: https://docs.finlens.vn/mcp/cong-ty-thuong Mô tả: FinLens MCP giúp AI bóc tách thuyết minh BCTC doanh nghiệp phi tài chính: cơ cấu chi phí, nợ vay, vốn lưu động, doanh thu và định giá DCF tự tính WACC. Tóm tắt: FinLens MCP cung cấp 8 công cụ để Claude, ChatGPT và Gemini bóc tách thuyết minh báo cáo tài chính của doanh nghiệp phi tài chính niêm yết tại Việt Nam: `fundamental_list_notes` và `fundamental_get_notes` tra cứu từng mục thuyết minh kèm tỷ trọng và YoY, cùng bốn lăng kính diễn giải `fundamental_cost_structure`, `fundamental_debt_structure`, `fundamental_working_capital`, `fundamental_revenue_breakdown`. Hai công cụ định giá là `fundamental_valuation_history` (dải bội số P/E, P/B, P/S của chính mã qua nhiều năm kèm percentile hiện tại, median, vùng p25–75) và `fundamental_intrinsic_value` (DCF/FCFF hai giai đoạn, WACC tự tính theo CAPM, kèm ba kịch bản bull/base/bear và lưới sensitivity). Nhà đầu tư dùng nhóm công cụ này để trả lời các câu hỏi mà báo cáo tài chính tóm tắt không xử lý được, ví dụ chi phí cố định hay biến đổi chiếm ưu thế, bao nhiêu phần trăm nợ vay đến hạn trong 12 tháng tới, tồn kho thành phẩm có chất đống không và giá trị hợp lý mỗi cổ phiếu là bao nhiêu. Sản phẩm: mcp ⏱ Đọc 14 phút · 🟡 Trung cấp – Nâng cao · 🔧 Yêu cầu: FinLens Pro ## Vì sao chỉ P/E – ROE là chưa đủ? [#vì-sao-chỉ-pe--roe-là-chưa-đủ] Báo cáo tài chính tóm tắt cho bạn biết *CÁI GÌ* (doanh thu, lợi nhuận, ROE). Nhưng **thuyết minh BCTC** mới cho biết *VÌ SAO* và *CƠ CẤU* — chỗ một nhà phân tích chuyên sâu thực sự sống. FinLens bóc tách thuyết minh thành dữ liệu có cấu trúc để AI diễn giải thay vì để bạn lật từng trang PDF. Với **doanh nghiệp phi tài chính (CT)**, AI có thể trả lời những câu hỏi mà báo cáo tóm tắt chịu thua: *"Chi phí cố định hay biến đổi chiếm ưu thế?", "Bao nhiêu % nợ vay đến hạn trong 12 tháng tới?", "Tồn kho thành phẩm có đang chất đống?", "Doanh thu phụ thuộc một dòng sản phẩm đến mức nào?"* `list_notes` + `get_notes` (tra cứu & bóc tách mọi mục) · 4 lăng kính diễn giải sẵn: `cost_structure`, `debt_structure`, `working_capital`, `revenue_breakdown` · 2 công cụ định giá: `valuation_history` và `intrinsic_value` (DCF). ## Tra cứu & bóc tách mục thuyết minh [#tra-cứu--bóc-tách-mục-thuyết-minh] Bắt đầu bằng `fundamental_list_notes` để xem doanh nghiệp đó công bố những mục nào (kèm kỳ mới nhất), rồi `fundamental_get_notes` để lấy chi tiết. Mỗi dòng leaf kèm **tỷ trọng (composition %)** trên tổng mục và **YoY**. Hỗ trợ Năm / Quý / TTM (lũy kế 4 quý — tự quy về rời rạc nếu nguồn báo cáo lũy kế). **HPG công bố những mục thuyết minh nào có thể bóc tách? Tôi muốn soi cơ cấu hàng tồn kho và chi phí** → list_notes(HPG) liệt kê mục có data → get_notes(HPG, inventory / cost_by_element) **Bóc tách hàng tồn kho của HPG 4 quý gần nhất — NVL, dở dang, thành phẩm chiếm bao nhiêu % và biến động ra sao?** → get_notes(HPG, inventory, quarter) — composition % + YoY từng dòng ## Cơ cấu chi phí — đọc đòn bẩy hoạt động [#cơ-cấu-chi-phí--đọc-đòn-bẩy-hoạt-động] `fundamental_cost_structure` bóc chi phí SXKD theo yếu tố: NVL, nhân công, khấu hao, dịch vụ mua ngoài, chi khác — và tách **cố định** (nhân công + khấu hao) vs **biến đổi** (NVL + thuê ngoài + khác). Đây là chìa khóa hiểu vì sao biên lợi nhuận nhạy hay ổn với sản lượng. Ví dụ HPG: chi phí biến đổi \~90% (chủ yếu NVL) → **đòn bẩy hoạt động THẤP**: biên LN ít nhạy với sản lượng nhưng rất nhạy với giá đầu vào (giá quặng/than). Ngược lại doanh nghiệp khấu hao cao sau đầu tư lớn → đòn bẩy cao, biên LN khuếch đại theo sản lượng. **Phân tích cơ cấu chi phí của HPG — chi phí cố định hay biến đổi chiếm ưu thế? Đòn bẩy hoạt động đang tăng hay giảm so với năm trước?** → cost_structure — fixed_pct vs variable_pct + signal diễn giải ## Cơ cấu nợ vay & áp lực tái cấp vốn [#cơ-cấu-nợ-vay--áp-lực-tái-cấp-vốn] `fundamental_debt_structure` bóc nợ vay ngắn hạn vs dài hạn, **% nợ dài hạn đến hạn trong 12 tháng** (áp lực tái cấp vốn), cơ cấu công cụ (ngân hàng / trái phiếu / thuê tài chính) và số dư trái phiếu phát hành. Nếu có trái phiếu, AI bắc cầu sang nhóm `bond_*` để soi lịch đáo hạn. **Cơ cấu nợ vay của NVL: tỷ trọng ngắn hạn/dài hạn, bao nhiêu % đến hạn trong 12 tháng, và có trái phiếu nào sắp đáo hạn không?** → debt_structure → st_pct, refinance_due_pct, bonds_outstanding → bond_maturity_wall ## Chất lượng vốn lưu động [#chất-lượng-vốn-lưu-động] `fundamental_working_capital` soi phải thu ngắn hạn khác (gồm dấu hiệu bên liên quan) + cơ cấu tồn kho, với cờ **tỷ trọng thành phẩm/hàng hóa** (cao = cầu yếu/khó tiêu thụ). Cảnh báo sớm khi tồn kho thành phẩm chất đống hoặc phải thu khác tăng đột biến. **Chất lượng vốn lưu động của HPG: tồn kho thành phẩm có tăng tỷ trọng không, phải thu khác có dấu hiệu bất thường không?** → working_capital → finished_goods_pct + signal phải thu bên liên quan ## Cơ cấu doanh thu & biên lợi nhuận gộp [#cơ-cấu-doanh-thu--biên-lợi-nhuận-gộp] `fundamental_revenue_breakdown` cho doanh thu theo dòng (hàng hóa / dịch vụ / xây lắp), doanh thu thuần, giá vốn và biên LN gộp — đọc mức tập trung nguồn thu + xu hướng biên. Bóc tách này theo loại doanh thu kế toán (hàng hóa/dịch vụ/xây lắp), KHÔNG phải mảng kinh doanh hay phân tách địa lý nội địa/xuất khẩu. Cần cơ cấu theo mảng/segment thì hỏi AI đọc báo cáo phân tích CTCK (Bài 6). **Cơ cấu doanh thu HPG: phụ thuộc một dòng sản phẩm đến mức nào, biên lợi nhuận gộp đang cải thiện hay xói mòn?** → revenue_breakdown → composition theo dòng + gross_margin qua các kỳ ## Định giá lịch sử — đắt/rẻ vs chính nó (re-rating) [#định-giá-lịch-sử--đắtrẻ-vs-chính-nó-re-rating] `fundamental_valuation_history` dựng dải bội số **P/E, P/B hoặc P/S** của chính mã qua nhiều năm (point-in-time, tránh look-ahead) với **percentile hiện tại** (thấp = rẻ so với quá khứ chính nó), median và vùng p25–75. Thống kê BỀN với outlier — đọc percentile/median thay vì mean thô (P/E vọt cực đoan khi lợi nhuận ≈ 0). Kết hợp HAI khung re-rating: vs ngành (`fundamental_compare_peers`) và vs chính nó (`valuation_history`). "P/E 9x = dưới median 5 năm của chính nó (percentile 37) VÀ dưới median ngành thép" → rẻ thật. P/S hữu ích khi doanh nghiệp lỗ/chu kỳ làm P/E vô nghĩa. **Định giá hiện tại của MWG đắt hay rẻ so với chính nó 5 năm qua? Cho tôi percentile P/E và P/B, đang ở vùng nào của lịch sử?** → valuation_history(MWG, pe) + (MWG, pb) — percentile_now, median, p25–75 ## Định giá nội tại DCF — WACC tự tính CAPM + kịch bản [#định-giá-nội-tại-dcf--wacc-tự-tính-capm--kịch-bản] `fundamental_intrinsic_value` chạy **DCF/FCFF 2 giai đoạn**: FCFF cơ sở = trung vị 3 năm (CFO + lãi vay×(1−thuế) − capex), chiết khấu về giá trị doanh nghiệp → trừ nợ ròng → giá trị hợp lý mỗi cổ phiếu. Điểm đặc biệt: **WACC được tự tính theo CAPM** — không cần bạn nhập: * **Chi phí vốn chủ (Re)** = lãi suất phi rủi ro (lợi suất TPCP 10 năm) + beta × phần bù rủi ro vốn chủ * **Chi phí nợ (Rd)** = lãi vay / nợ vay, sau lá chắn thuế * **WACC** = trọng số theo vốn hóa thị trường & nợ vay Đầu ra kèm **phân rã WACC** (rf / beta / ERP / Re / Rd / cơ cấu vốn) và **3 kịch bản bull / base / bear** (thay đổi tăng trưởng & WACC), cùng lưới sensitivity — để AI dựng dải giá trị thay vì một con số đơn lẻ. Đừng tin một con số fair value duy nhất. AI luôn trả dải bull/base/bear + sensitivity và đối chiếu với định giá tương đối. Nếu FCFF cơ sở ≤ 0 (doanh nghiệp đầu tư nặng, dòng tiền âm — ví dụ giai đoạn xây nhà máy lớn) thì DCF không áp dụng được, AI sẽ chuyển sang định giá tương đối. **Định giá nội tại VNM bằng DCF — tự tính WACC giúp tôi. Cho tôi giá trị hợp lý, dải kịch bản bull/base/bear và giả định WACC đến từ đâu (beta, lãi suất phi rủi ro)?** → intrinsic_value(VNM) — fair value + wacc_breakdown + scenarios + upside vs giá hiện tại **Chạy lại DCF cho VNM với kịch bản thận trọng: phần bù rủi ro cao hơn (11%) và tăng trưởng thấp hơn — giá trị hợp lý thay đổi thế nào?** → intrinsic_value(VNM, equity_risk_premium=0.11, growth_stage1 thấp hơn) — ERP cao → WACC cao → định giá thấp hơn ## Prompt phân tích chuyên sâu toàn diện [#prompt-phân-tích-chuyên-sâu-toàn-diện] **Phân tích chuyên sâu HPG dưới góc độ nhà phân tích cơ bản: 1. Cơ cấu chi phí — đòn bẩy hoạt động cao hay thấp? 2. Cơ cấu nợ vay — áp lực tái cấp vốn 12 tháng? 3. Chất lượng vốn lưu động — tồn kho/phải thu có cờ nào? 4. Cơ cấu doanh thu & xu hướng biên gộp 5. Định giá: re-rating P/E·P/B vs chính nó + DCF với dải kịch bản 6. Kết luận điểm mạnh/yếu & mức định giá hợp lý** → AI lần lượt gọi cost_structure + debt_structure + working_capital + revenue_breakdown + valuation_history + intrinsic_value, tổng hợp thành bài phân tích Bài này nối tiếp [Bài 2 — Phân tích cơ bản](/mcp/phan-tich-co-ban) (KPI/DuPont/fundamental\_quality\_scan). Ngân hàng và chứng khoán có bộ công cụ chuyên ngành RIÊNG — xem [Bài 13 — Ngân hàng](/mcp/ngan-hang) và [Bài 14 — Chứng khoán](/mcp/chung-khoan). ## Bài liên quan [#bài-liên-quan] Nền tảng KPI và thẩm định chất lượng kế toán trước khi đi sâu thuyết minh. Bộ công cụ chuyên ngành cho nhóm ngân hàng — cấu trúc khác hẳn. Danh mục tự doanh, cơ cấu doanh thu và chỉ báo sentinel toàn ngành CTCK. ### Câu hỏi thường gặp **Làm sao biết chi phí của doanh nghiệp là cố định hay biến đổi?** Công cụ `fundamental_cost_structure` của FinLens MCP bóc chi phí sản xuất kinh doanh theo yếu tố (nguyên vật liệu, nhân công, khấu hao, dịch vụ mua ngoài, chi khác) rồi tách phần cố định (nhân công + khấu hao) khỏi phần biến đổi (nguyên vật liệu + thuê ngoài + khác). Đầu ra gồm fixed_pct, variable_pct và tín hiệu diễn giải, cho biết đòn bẩy hoạt động đang tăng hay giảm so với năm trước. Ví dụ với HPG, chi phí biến đổi chiếm khoảng 90% (chủ yếu nguyên vật liệu) nên đòn bẩy hoạt động thấp: biên lợi nhuận ít nhạy với sản lượng nhưng rất nhạy với giá đầu vào. **Định giá DCF cổ phiếu có phải tự nhập WACC không?** Không. Công cụ `fundamental_intrinsic_value` của FinLens MCP tự tính WACC theo mô hình CAPM: chi phí vốn chủ bằng lãi suất phi rủi ro (lợi suất trái phiếu chính phủ 10 năm) cộng beta nhân phần bù rủi ro vốn chủ, chi phí nợ bằng lãi vay chia nợ vay sau lá chắn thuế, trọng số theo vốn hóa thị trường và nợ vay. Mô hình chạy DCF/FCFF hai giai đoạn với FCFF cơ sở là trung vị 3 năm, trả về giá trị hợp lý mỗi cổ phiếu kèm phân rã WACC và ba kịch bản bull/base/bear. Người dùng vẫn có thể ghi đè giả định, ví dụ đặt equity_risk_premium = 0.11 để chạy kịch bản thận trọng. **Cổ phiếu đang đắt hay rẻ so với chính nó trong quá khứ?** Công cụ `fundamental_valuation_history` của FinLens MCP dựng dải bội số P/E, P/B hoặc P/S của chính mã cổ phiếu qua nhiều năm theo cách point-in-time để tránh look-ahead bias, kèm percentile hiện tại, median và vùng p25–75. Percentile thấp nghĩa là cổ phiếu đang rẻ so với chính lịch sử của nó. Nên đọc percentile và median thay vì trung bình thô vì P/E dễ vọt cực đoan khi lợi nhuận gần bằng 0; với doanh nghiệp lỗ hoặc mang tính chu kỳ thì P/S hữu ích hơn. **Làm sao kiểm tra áp lực trả nợ 12 tháng tới của một doanh nghiệp?** Công cụ `fundamental_debt_structure` của FinLens MCP bóc nợ vay ngắn hạn so với dài hạn, tỷ lệ phần trăm nợ dài hạn đến hạn trong 12 tháng (refinance_due_pct), cơ cấu công cụ nợ theo ngân hàng, trái phiếu, thuê tài chính và số dư trái phiếu đang lưu hành. Nếu doanh nghiệp có trái phiếu, AI bắc cầu sang nhóm công cụ `bond_*`, ví dụ `bond_maturity_wall`, để xem lịch đáo hạn cụ thể. Cách này trả lời trực tiếp câu hỏi về rủi ro kỳ hạn nợ và áp lực tái cấp vốn của các mã như NVL. --- # Tối ưu danh mục đầu tư bằng AI: Max Sharpe, HRP, VaR URL: https://docs.finlens.vn/mcp/danh-muc Mô tả: Hướng dẫn dùng FinLens MCP để tính tỷ trọng tối ưu theo Max Sharpe, Min Volatility, HRP, backtest danh mục so với VNINDEX và đo VaR, CVaR, max drawdown. Tóm tắt: FinLens MCP cho phép nhà đầu tư Việt Nam tối ưu tỷ trọng danh mục cổ phiếu bằng câu hỏi tiếng Việt đặt cho Claude, ChatGPT hoặc Gemini. Công cụ portfolio_optimize hỗ trợ 5 phương pháp phân bổ là Max Sharpe, Min Volatility, Equal Weight, Inverse Volatility và HRP; portfolio_backtest mô phỏng tái cân bằng hàng tháng hoặc hàng quý và so hiệu suất với VNINDEX; portfolio_analyze đo VaR, CVaR, max drawdown, beta/alpha và win rate tháng; portfolio_efficient_frontier vẽ đường biên hiệu quả Markowitz. Nhóm tính năng tối ưu danh mục của FinLens MCP yêu cầu gói FinLens Premium. Sản phẩm: mcp ⏱ Đọc 10 phút · 🔴 Nâng cao · 🔧 Yêu cầu: FinLens Premium ## 5 phương pháp tối ưu tỷ trọng [#5-phương-pháp-tối-ưu-tỷ-trọng] Max Sharpe Tối đa hóa tỷ lệ lợi nhuận/rủi ro. Tìm danh mục trên đường biên hiệu quả với Sharpe cao nhất. Phù hợp: mục tiêu lợi nhuận điều chỉnh rủi ro Min Volatility Tỷ trọng để volatility danh mục thấp nhất có thể. An toàn nhất, phù hợp thị trường biến động cao. Phù hợp: ưu tiên bảo toàn vốn Equal Weight Chia đều 1/N cho mỗi mã. Đơn giản, không phụ thuộc ước lượng lịch sử, chống overfit tốt. Phù hợp: baseline đơn giản, ít mã Inverse Volatility Mã biến động thấp hơn nhận tỷ trọng cao hơn — cân bằng rủi ro đóng góp. Ít nhạy cảm với overfit. Phù hợp: đa dạng hóa rủi ro HRP (Hierarchical Risk Parity) Phân cụm tương quan theo cây phân cấp, phân bổ rủi ro bằng nhau giữa các nhóm. Mạnh mẽ nhất khi nhiều mã. Phù hợp: danh mục 5+ mã, ổn định hơn Max Sharpe Thực tế: hãy chạy **tất cả 5 phương pháp** rồi so sánh tỷ trọng. Nếu các phương pháp đồng thuận trên một mã (đều phân bổ tỷ trọng cao) — đó là tín hiệu mạnh hơn. Tránh chỉ tin Max Sharpe vì dễ overfit lịch sử. ## Tối ưu tỷ trọng danh mục [#tối-ưu-tỷ-trọng-danh-mục] **Tôi muốn đầu tư vào HPG, FPT, VNM, MWG — tỷ trọng tối ưu theo Max Sharpe và Min Volatility là bao nhiêu? Dùng dữ liệu 3 năm** → portfolio_optimize: 4 mã, 2 phương pháp, lookback=3yr — so sánh tỷ trọng và expected return/risk **So sánh cả 5 phương pháp tối ưu cho danh mục HPG, VCB, FPT, TCB, VHM — phương pháp nào phân bổ HPG cao nhất? Mức tập trung tối đa là 30%/mã** → optimize 5 methods, max_weight=0.3 — bảng so sánh 5 tỷ trọng + expected Sharpe **Tối ưu HRP cho danh mục 8 mã: HPG, FPT, VNM, VCB, MWG, MSN, GAS, REE — tỷ trọng từng nhóm ngành là bao nhiêu?** → HRP phân cụm tương quan theo ngành, phân bổ rủi ro cân bằng hơn Max Sharpe ## Backtest danh mục — so với VNINDEX [#backtest-danh-mục--so-với-vnindex] **Backtest danh mục 40% HPG, 30% FPT, 30% VNM trong 3 năm qua với tái cân bằng hàng quý — CAGR, Sharpe và max drawdown so với VNINDEX là bao nhiêu?** → portfolio_backtest: tỷ trọng cố định, rebalance=quarterly, 3yr, benchmark=VNINDEX **Với danh mục HPG, FPT, VCB chia đều, tái cân bằng hàng tháng có tốt hơn hàng quý không? Chi phí giao dịch ảnh hưởng thế nào?** → 2 backtest: monthly vs quarterly rebalance, có thể kèm transaction cost **Backtest tỷ trọng Max Sharpe cho HPG, FPT, VNM, MWG từ 2020 đến nay — danh mục tối ưu có thắng VNINDEX không? Tháng nào xấu nhất?** → optimize → lấy tỷ trọng → backtest với tỷ trọng đó, kèm monthly return calendar ## Đo lường rủi ro danh mục [#đo-lường-rủi-ro-danh-mục] Công cụ `portfolio_analyze` cung cấp bộ chỉ số rủi ro đầy đủ: * **VaR (Value at Risk)**: tổn thất tối đa ở mức tin cậy 95% trong 1 tháng * **CVaR**: tổn thất kỳ vọng khi vượt VaR (tail risk) * **Max Drawdown**: mức sụt giảm đỉnh-đáy lớn nhất * **Beta/Alpha so VNINDEX**: độ nhạy cảm thị trường * **Win rate tháng**: tỷ lệ tháng dương * **Calmar Ratio**: CAGR / Max Drawdown **Phân tích rủi ro danh mục 50% HPG + 30% VCB + 20% FPT trong 2 năm qua: VaR, CVaR, max drawdown, beta và win rate tháng — danh mục này rủi ro bao nhiêu?** → portfolio_analyze — bộ chỉ số đầy đủ + monthly return calendar **So sánh rủi ro giữa danh mục tập trung (70% HPG, 30% FPT) và danh mục phân tán (5 mã chia đều) — phương án nào có tỷ lệ Sharpe/Drawdown tốt hơn?** ## Đường biên hiệu quả Markowitz [#đường-biên-hiệu-quả-markowitz] **Vẽ đường biên hiệu quả Markowitz cho danh mục HPG, FPT, VNM, VCB, MWG — tôi chấp nhận được drawdown tối đa 20%, danh mục nào phù hợp với khẩu vị rủi ro của tôi?** → portfolio_efficient_frontier — đường cong risk/return, gợi ý danh mục theo mức rủi ro chấp nhận ## Quy trình thực chiến — từ ý tưởng đến danh mục [#quy-trình-thực-chiến--từ-ý-tưởng-đến-danh-mục] **Tôi muốn xây danh mục cổ phiếu Việt Nam với 5–7 mã, ưu tiên ngành công nghệ và ngân hàng: 1. Gợi ý các mã tiềm năng trong 2 ngành (ROE > 15%, tăng trưởng tốt) 2. Tối ưu tỷ trọng HRP và Max Sharpe 3. Backtest 2 năm so VNINDEX 4. Phân tích rủi ro VaR và max drawdown 5. Kết luận nên chọn phương pháp nào?** → AI gọi tuần tự: fundamental_compare_peers (lọc mã) → optimize → backtest → analyze, tổng hợp khuyến nghị Tỷ trọng tối ưu hóa theo dữ liệu lịch sử có thể không tối ưu trong tương lai khi tương quan và volatility thay đổi. Dùng làm tham chiếu, không phải công thức cứng nhắc. ## Bài liên quan [#bài-liên-quan] Trước khi tối ưu danh mục, cần chọn được mã tốt về cơ bản. Kết hợp tỷ trọng tối ưu với điểm vào/ra theo tín hiệu kỹ thuật. Chuỗi đầy đủ từ cơ bản đến nâng cao. ### Câu hỏi thường gặp **Tối ưu tỷ trọng danh mục cổ phiếu Việt Nam bằng AI như thế nào?** Người dùng mô tả danh mục bằng tiếng Việt và AI gọi công cụ portfolio_optimize của FinLens MCP để tính tỷ trọng. Ví dụ câu hỏi: "Tôi muốn đầu tư vào HPG, FPT, VNM, MWG — tỷ trọng tối ưu theo Max Sharpe và Min Volatility là bao nhiêu? Dùng dữ liệu 3 năm". Có thể yêu cầu chạy đồng thời cả 5 phương pháp và đặt mức tập trung tối đa cho mỗi mã, ví dụ 30%, để nhận bảng so sánh tỷ trọng kèm expected return, risk và Sharpe. **Nên chọn Max Sharpe hay HRP khi phân bổ danh mục?** Cách thực tế là chạy cả 5 phương pháp rồi so sánh tỷ trọng: nếu nhiều phương pháp cùng phân bổ tỷ trọng cao cho một mã thì đó là tín hiệu mạnh hơn. Không nên chỉ tin Max Sharpe vì phương pháp này dễ overfit dữ liệu lịch sử. HRP phân cụm tương quan theo cây phân cấp và phân bổ rủi ro cân bằng giữa các nhóm, phù hợp danh mục từ 5 mã trở lên và ổn định hơn Max Sharpe; Min Volatility phù hợp khi ưu tiên bảo toàn vốn. **Làm sao backtest danh mục cổ phiếu và so sánh với VNINDEX?** Công cụ portfolio_backtest của FinLens MCP mô phỏng danh mục với tỷ trọng cố định, chu kỳ tái cân bằng hàng tháng hoặc hàng quý, khoảng thời gian tùy chọn và benchmark VNINDEX. Kết quả gồm CAGR, tỷ lệ Sharpe, max drawdown so với VNINDEX kèm lịch lợi nhuận theo tháng để biết tháng nào xấu nhất. Có thể so sánh hai kịch bản tái cân bằng tháng và quý, kèm ảnh hưởng của chi phí giao dịch. Lưu ý tỷ trọng tối ưu theo dữ liệu lịch sử có thể không còn tối ưu khi tương quan và volatility thay đổi. **VaR và CVaR của danh mục cổ phiếu là gì, đo bằng công cụ nào?** VaR (Value at Risk) là mức tổn thất tối đa ở độ tin cậy 95% trong 1 tháng, còn CVaR là tổn thất kỳ vọng khi vượt ngưỡng VaR, tức phần rủi ro đuôi. Công cụ portfolio_analyze của FinLens MCP trả về bộ chỉ số rủi ro đầy đủ gồm VaR, CVaR, max drawdown, beta/alpha so với VNINDEX, win rate tháng và Calmar Ratio (CAGR chia cho max drawdown), kèm lịch lợi nhuận theo tháng. --- # Dòng tiền smart money và khối ngoại: hỏi AI qua FinLens MCP URL: https://docs.finlens.vn/mcp/dong-tien Mô tả: Hỏi AI về smart money, khối ngoại, dòng tiền chủ động và dòng tiền theo ngành của cổ phiếu Việt Nam bằng công cụ flows_get_stock_flow của FinLens MCP. Tóm tắt: FinLens MCP cho phép hỏi Claude, ChatGPT hoặc Gemini về dòng tiền cổ phiếu Việt Nam bằng ba công cụ: flows_get_stock_flow (dòng tiền từng mã), flows_top_net (quét top mua/bán ròng toàn thị trường) và flows_sector_flow (luân chuyển vốn theo ngành ICB). FinLens MCP phân biệt hai khái niệm khác nhau: smart money là tổng hợp khối ngoại, tự doanh và tổ chức trong nước, còn dòng tiền chủ động (aggressor) là bên chủ động đặt lệnh trong từng lệnh khớp, không phân biệt loại nhà đầu tư. Hướng dẫn dành cho nhà đầu tư chứng khoán Việt Nam muốn theo dõi khối ngoại, room ngoại, tín hiệu tích lũy hay phân phối và rotation dòng tiền giữa các ngành bằng câu hỏi tiếng Việt. Sản phẩm: mcp ⏱ Đọc 10 phút · 🟡 Trung cấp · 🔧 Yêu cầu: FinLens Pro ## Hai khái niệm KHÔNG được nhầm lẫn [#hai-khái-niệm-không-được-nhầm-lẫn] FinLens theo dõi hai chiều phân tích dòng tiền hoàn toàn khác nhau. Nhầm lẫn chúng sẽ dẫn đến phân tích sai: #### 🐋 Smart Money (tiền thông minh) [#-smart-money-tiền-thông-minh] \= **Khối ngoại** + **Tự doanh** + **Tổ chức trong nước** Đây là tổng hợp của 3 nhóm được coi là "cá mập" — có thông tin và vốn lớn. **Cá nhân trong nước = RETAIL**, KHÔNG thuộc smart money (dù chiếm phần lớn thanh khoản). Dữ liệu về sau \~18h (nhóm nội). #### ⚡ Dòng tiền chủ động (Aggressor) [#-dòng-tiền-chủ-động-aggressor] \= Ai **chủ động đặt lệnh** — bên mua chủ động hay bán chủ động? Đây là chiều SÁNG KIẾN: lệnh mua khớp với bên bán đang chờ (mua chủ động), hoặc ngược lại. Không phân biệt loại nhà đầu tư. Cập nhật **trong phiên theo thời gian thực**. **Đừng** dùng dòng tiền chủ động để trả lời câu hỏi về smart money và ngược lại. Ví dụ: "dòng tiền chủ động đang mua ròng HPG" **KHÔNG có nghĩa** là khối ngoại hay tổ chức đang mua HPG. ## Độ trễ dữ liệu — quan trọng khi hỏi [#độ-trễ-dữ-liệu--quan-trọng-khi-hỏi] Mỗi nhóm dữ liệu có lịch cập nhật khác nhau. FinLens tự động điều chỉnh kỳ phân tích theo dữ liệu có sẵn: | Nhóm dữ liệu | Nguồn | Cập nhật | Phù hợp cho | | ---------------------------- | ------------------------- | ------------------ | ---------------------------- | | **Khối ngoại** | eod\_stock\_v2 | Trong phiên | focus="foreign" | | **Dòng tiền chủ động** | net\_value\_stock\_v2 | Trong phiên | focus="active" | | **Tự doanh** | eod\_stock\_v2 | \~18h sau đóng cửa | focus="smart\_money" | | **Tổ chức trong nước** | eod\_investor\_trades | \~18h sau đóng cửa | focus="smart\_money" | | **Cá nhân (retail)** | eod\_investor\_trades | \~18h sau đóng cửa | focus="smart\_money" / "all" | | **Dòng tiền chủ động ngành** | intraday\_icb\_agg\_daily | Trong phiên | flows\_sector\_flow | Bạn không cần lo lắng về thời điểm hỏi. Khi hỏi về smart money trước 18h, AI tự biết neo lũy kế vào phiên đã có đủ dữ liệu — ghi rõ trong kết quả trả về. ## Smart money theo mã cụ thể [#smart-money-theo-mã-cụ-thể] Dùng `flows_get_stock_flow` với `focus="smart_money"` để xem tổng hợp 3 nhóm cá mập: **Smart money đang mua hay bán ròng HPG trong 20 phiên qua?** → AI dùng focus="smart_money", days=20 — trả net_bil lũy kế, phân tách từng nhóm **Trong 10 phiên qua với HPG, tự doanh và tổ chức trong nước đang đi cùng chiều hay ngược chiều với khối ngoại?** → AI tách smart_net_bil, retail_net_bil, foreign_net_bil + signal tích lũy/phân phối **So sánh smart money 15 phiên qua của VCB, BID và CTG — ngân hàng nào đang được cá mập tích lũy hơn?** → Gọi flows_get_stock_flow lần lượt cho từng mã, tổng hợp smart_net_bil ## Khối ngoại riêng (cập nhật ngay trong phiên) [#khối-ngoại-riêng-cập-nhật-ngay-trong-phiên] Khi chỉ cần theo dõi **khối ngoại** — không đợi tự doanh/tổ chức về lúc 18h — dùng `focus="foreign"`: **Khối ngoại đang mua bán ròng VIC thế nào trong 5 phiên gần nhất? Còn room ngoại bao nhiêu?** → focus="foreign" — trả lời ngay, không đợi nhóm nội. Kèm tỷ lệ sở hữu nước ngoài hiện tại **VHM còn bao nhiêu % room ngoại? Khối ngoại có đang tiếp tục mua vào khi room sắp hết không?** → Kèm foreign_pct (tỷ lệ sở hữu hiện tại so room) và tín hiệu accumulation ## Dòng tiền chủ động (aggressor) — cập nhật trong phiên [#dòng-tiền-chủ-động-aggressor--cập-nhật-trong-phiên] Dùng `focus="active"` để xem bên nào đang CHỦ ĐỘNG trong từng lệnh khớp — đây là tín hiệu ngắn hạn về áp lực mua/bán: **Dòng tiền chủ động vào FPT trong 5 phiên gần nhất như thế nào? Bên mua hay bên bán đang chủ động hơn?** → focus="active" — net_value_stock_v2, cập nhật ngay phiên hôm nay **HPG hôm nay: smart money đang làm gì? Và dòng tiền chủ động trong phiên đang nghiêng về bên mua hay bán?** → AI gọi focus="smart_money" + focus="active" riêng, tổng hợp 2 chiều phân tích ## Top mã mua/bán ròng nhiều nhất [#top-mã-muabán-ròng-nhiều-nhất] Dùng `flows_top_net` để quét toàn thị trường — không cần biết trước mã cụ thể: **Top 10 mã được khối ngoại mua ròng nhiều nhất trong 5 phiên gần nhất** → flows_top_net, flow_type="foreign", days=5, direction="buy" **Top 15 mã smart money bán ròng nhiều nhất trong 20 phiên qua — ngành nào bị xả nhiều nhất?** → flow_type="smart_money", days=20, direction="sell" **Top mã có dòng tiền chủ động mua ròng lớn nhất hôm nay trên HOSE** → flow_type="active", days=1, exchange="HOSE" ## Luân chuyển vốn theo ngành [#luân-chuyển-vốn-theo-ngành] Dùng `flows_sector_flow` để xem tiền đang chạy vào/ra ngành nào — tín hiệu sớm về rotation thị trường: **Dòng tiền chủ động theo ngành trong 10 phiên gần nhất — ngành nào đang nhận vốn nhiều nhất? Ngành nào bị rút?** → flows_sector_flow — net lũy kế 10 phiên theo ICB, cập nhật trong phiên hôm nay **So sánh dòng tiền ngân hàng vs bất động sản vs thép trong 20 phiên gần nhất — có dấu hiệu rotation không?** → flows_sector_flow lọc theo sector_code, so sánh net_bil giữa các ngành ## Câu hỏi mẫu nâng cao [#câu-hỏi-mẫu-nâng-cao] **Phân tích toàn diện dòng tiền HPG trong tháng qua: smart money đang tích lũy hay phân phối? Khối ngoại và tổ chức có đồng chiều không? Dòng tiền chủ động gần đây thế nào? Kết hợp với xu hướng giá để đánh giá tín hiệu** **VNM vừa phá kháng cự — smart money và dòng tiền chủ động có xác nhận breakout này không? Khối ngoại mấy phiên gần đây đang mua hay bán?** ## Bài liên quan [#bài-liên-quan] Kết hợp phân tích dòng tiền với nền tảng tài chính vững chắc. Kết hợp dòng tiền với tín hiệu kỹ thuật để tăng độ chính xác. Đầy đủ chuỗi hướng dẫn FinLens MCP từ cơ bản đến nâng cao. ### Câu hỏi thường gặp **Smart money trong chứng khoán Việt Nam gồm những nhóm nào?** Trên FinLens MCP, smart money là tổng hợp ba nhóm: khối ngoại, tự doanh công ty chứng khoán và tổ chức trong nước. Nhà đầu tư cá nhân trong nước được xếp vào nhóm retail và không thuộc smart money, dù chiếm phần lớn thanh khoản. Để xem số liệu, dùng công cụ flows_get_stock_flow với focus="smart_money", kết quả tách riêng smart_net_bil, retail_net_bil và foreign_net_bil kèm tín hiệu tích lũy hay phân phối. **Dòng tiền chủ động khác gì dòng tiền khối ngoại?** Dòng tiền chủ động (aggressor) đo bên nào chủ động đặt lệnh trong từng lệnh khớp — mua chủ động hay bán chủ động — và không phân biệt loại nhà đầu tư; tra bằng flows_get_stock_flow với focus="active". Dòng tiền khối ngoại đo mua bán ròng của nhà đầu tư nước ngoài, tra bằng focus="foreign" và kèm tỷ lệ sở hữu nước ngoài hiện tại. Hai chiều này không thay thế nhau: dòng tiền chủ động mua ròng một mã không có nghĩa là khối ngoại hay tổ chức đang mua mã đó. **Làm sao xem top mã khối ngoại mua ròng nhiều nhất?** Công cụ flows_top_net của FinLens MCP quét toàn thị trường và xếp hạng các mã mua ròng hoặc bán ròng mạnh nhất, không cần biết trước mã nào. Ví dụ câu hỏi cho AI: "Top 10 mã được khối ngoại mua ròng nhiều nhất trong 5 phiên gần nhất", tương ứng flows_top_net với flow_type="foreign", days=5, direction="buy". Đổi flow_type sang "smart_money" hoặc "active" để xếp hạng theo smart money hay dòng tiền chủ động, và lọc sàn bằng exchange="HOSE". **Dữ liệu dòng tiền của FinLens MCP cập nhật lúc nào?** Khối ngoại và dòng tiền chủ động được cập nhật ngay trong phiên giao dịch, kể cả dòng tiền chủ động theo ngành. Số liệu tự doanh, tổ chức trong nước và nhà đầu tư cá nhân về khoảng 18h sau khi đóng cửa, nên bức tranh smart money đầy đủ chỉ có sau thời điểm đó. Khi được hỏi trước 18h, FinLens MCP tự neo kỳ lũy kế vào phiên đã có đủ dữ liệu và ghi rõ điều này trong kết quả trả về. --- # FinLens MCP: Phân tích chứng khoán Việt Nam bằng AI URL: https://docs.finlens.vn/mcp Mô tả: Tổng quan FinLens MCP: cách kết nối Claude và ChatGPT với dữ liệu tài chính Việt Nam, cùng 18 bài hướng dẫn phân tích cổ phiếu bằng AI theo chủ đề. Tóm tắt: FinLens MCP là máy chủ Model Context Protocol cho phép Claude, ChatGPT và Gemini truy vấn dữ liệu tài chính Việt Nam: giá cổ phiếu HOSE/HNX/UPCOM, báo cáo tài chính, dòng tiền khối ngoại, báo cáo phân tích của hơn 20 công ty chứng khoán, kinh tế vĩ mô, cổ tức, chứng quyền, trái phiếu doanh nghiệp và quỹ đầu tư. Nhà đầu tư đăng ký gói FinLens Pro hoặc Premium tại finlens.vn/pricing, thêm địa chỉ https://mcp.finlens.vn/mcp vào trợ lý AI rồi hỏi bằng tiếng Việt, ví dụ "Phân tích tài chính HPG 5 năm gần nhất". Bộ tài liệu FinLens MCP gồm 18 bài hướng dẫn theo chủ đề, từ kết nối ban đầu tới backtest chiến lược và tối ưu danh mục. Sản phẩm: mcp FinLens MCP nối trợ lý AI của bạn với dữ liệu chứng khoán Việt Nam theo thời gian thực. Bạn hỏi bằng tiếng Việt thông thường, AI tự chọn công cụ và trả về số liệu thật — không phải phỏng đoán từ trí nhớ huấn luyện. ## Bắt đầu trong 3 bước [#bắt-đầu-trong-3-bước] ### Đăng ký gói Pro hoặc Premium [#đăng-ký-gói-pro-hoặc-premium] Chọn gói tại [finlens.vn/pricing](https://finlens.vn/pricing). Gói Free không kết nối được MCP. ### Thêm vào Claude hoặc ChatGPT [#thêm-vào-claude-hoặc-chatgpt] Dán URL `https://mcp.finlens.vn/mcp` vào phần connector, rồi đăng nhập FinLens để xác thực. Mất khoảng 2 phút — [xem hướng dẫn từng bước](/mcp/bat-dau). ### Hỏi thử [#hỏi-thử] *"Phân tích tài chính HPG 5 năm gần nhất"* — nếu AI trả về số liệu thật là đã kết nối xong. Tra cứu toàn bộ công cụ theo 12 nhóm, kèm tham số và câu hỏi mẫu. Thêm vào Claude Desktop, Claude.ai hoặc ChatGPT qua OAuth. ## 18 bài hướng dẫn theo chủ đề [#18-bài-hướng-dẫn-theo-chủ-đề] ### Phân tích doanh nghiệp [#phân-tích-doanh-nghiệp] 7 nhóm KPI, báo cáo tài chính TTM, phân rã DuPont, so sánh cùng ngành. Thuyết minh BCTC, cơ cấu chi phí và nợ vay, định giá DCF theo kịch bản. NPL, CASA, NII và CIR — bộ chỉ tiêu riêng cho ngành ngân hàng. Danh mục tự doanh, dư nợ margin và chỉ báo tâm lý thị trường. ### Dòng tiền & thị trường [#dòng-tiền--thị-trường] Smart money, khối ngoại và dòng tiền chủ động theo từng mã, từng ngành. Xếp hạng RS ngành 1–100, độ rộng thị trường, lọc cổ phiếu dẫn dắt. Thị trường hôm nay, cung cầu theo bước giá, điểm lại phiên giao dịch. Tin được AI tóm tắt, gắn sentiment và trọng số liên quan theo mã. ### Công cụ đầu tư [#công-cụ-đầu-tư] 141 chỉ báo, quét tín hiệu 1.700 mã, backtest và tối ưu tham số. Max Sharpe, HRP, VaR, đường biên hiệu quả và backtest tái cân bằng. Định giá Black-Scholes, điểm hòa vốn, đòn bẩy, so sánh CW cùng mã cơ sở. Lịch GDKHQ sắp tới, lịch sử chi trả và phân tích chính sách cổ tức. 185 quỹ: danh mục nắm giữ, NAV, và quỹ nào đang gom hay xả một mã. Lịch đáo hạn, dư nợ theo ngành, hồ sơ phát hành và trái phiếu chuyển đổi. ### Nguồn tham khảo & kỹ thuật nâng cao [#nguồn-tham-khảo--kỹ-thuật-nâng-cao] Báo cáo từ hơn 20 công ty chứng khoán và đồng thuận giá mục tiêu. GDP, CPI, tỷ giá, lãi suất, xuất nhập khẩu — và cầu nối vĩ mô sang cổ phiếu. Bắc cầu nhiều công cụ, soi một cổ phiếu qua 6 lăng kính khác nhau. ## Công cụ MCP theo chủ đề [#công-cụ-mcp-theo-chủ-đề] Bảng tra nhanh khi bạn muốn biết AI sẽ gọi công cụ nào cho câu hỏi của mình. | Chủ đề | Công cụ chính | | -------------------------- | -------------------------------------------------------------------------------------------------------------------------- | | Hồ sơ & giá cổ phiếu | `stocks_search`, `stocks_get_profile`, `stocks_get_latest_quote` | | Tài chính cơ bản | `fundamental_get_key_metrics`, `fundamental_dupont`, `fundamental_compare_peers`, `fundamental_quality_scan` | | Doanh nghiệp phi tài chính | `fundamental_cost_structure`, `fundamental_debt_structure`, `fundamental_valuation_history`, `fundamental_intrinsic_value` | | Ngân hàng | `fundamental_bank_asset_quality`, `fundamental_bank_funding`, `fundamental_bank_income` | | Công ty chứng khoán | `fundamental_securities_portfolio`, `fundamental_securities_income`, `fundamental_securities_market_sentiment` | | Dòng tiền | `flows_get_stock_flow`, `flows_sector_flow`, `flows_top_net` | | Ngành & phiên giao dịch | `market_sector_strength`, `market_today`, `stocks_supply_demand` | | Kỹ thuật & backtest | `signals_screen`, `signals_backtest`, `signals_optimize`, `signals_candle_patterns` | | Danh mục đầu tư | `portfolio_optimize`, `portfolio_backtest`, `portfolio_analyze`, `portfolio_efficient_frontier` | | Chứng quyền | `warrants_search`, `warrants_get_info`, `warrants_price_history`, `warrants_compare` | | Cổ tức | `dividends_upcoming`, `dividends_get_history`, `dividends_analyze_policy` | | Quỹ đầu tư | `fund_stock_ownership`, `fund_holdings`, `fund_rank` | | Trái phiếu doanh nghiệp | `bond_search`, `bond_maturity_wall`, `bond_sector_debt`, `bond_issuer_profile` | | Báo cáo phân tích | `research_list_reports`, `research_read_report`, `research_get_analyst_consensus` | | Vĩ mô & xuất nhập khẩu | `fin_dashboard`, `fin_macro_context`, `fin_relate`, `fin_trade_matrix` | | Tin tức | `news_market_brief`, `news_get_for_stock`, `news_search` | Giá cổ phiếu và chỉ số trả về ở đơn vị **nghìn đồng** (23.4 nghĩa là 23.400 VND), còn giá chứng quyền ở **đồng** nguyên. Phải quy đổi trước khi so sánh hai loại với nhau — chi tiết tại [Quy ước dữ liệu FinLens](/platform). ### Câu hỏi thường gặp **Có MCP server nào cho thị trường chứng khoán Việt Nam không?** Có. FinLens MCP là máy chủ Model Context Protocol phục vụ riêng thị trường Việt Nam, địa chỉ https://mcp.finlens.vn/mcp. Sau khi thêm vào Claude, ChatGPT hoặc Gemini, trợ lý AI truy vấn được hơn 1.700 cổ phiếu trên HOSE, HNX và UPCOM cùng chỉ số VNINDEX, VN30, HNX-Index, kèm báo cáo tài chính, dòng tiền khối ngoại, trái phiếu doanh nghiệp và số liệu kinh tế vĩ mô. Câu hỏi đặt bằng tiếng Việt tự nhiên, không cần biết lập trình. **Làm sao để Claude hoặc ChatGPT đọc được dữ liệu tài chính Việt Nam?** Trợ lý AI không có sẵn dữ liệu thị trường Việt Nam và cũng không cập nhật theo thời gian thực, nên cần nối qua một MCP server. Cách làm là thêm địa chỉ https://mcp.finlens.vn/mcp vào phần connector của Claude Desktop, Claude.ai hoặc ChatGPT rồi đăng nhập bằng tài khoản FinLens qua OAuth, mất khoảng hai phút. Từ đó AI tự gọi công cụ để lấy số liệu thật thay vì phỏng đoán từ trí nhớ huấn luyện, và mỗi câu trả lời đều dựa trên dữ liệu có ngày tháng rõ ràng. **FinLens MCP là gì?** FinLens MCP là máy chủ MCP giúp trợ lý AI như Claude và ChatGPT truy vấn trực tiếp dữ liệu chứng khoán Việt Nam. Sau khi kết nối, AI gọi được các công cụ như flows_get_stock_flow (dòng tiền cổ phiếu), signals_screen (quét tín hiệu kỹ thuật), portfolio_optimize (tối ưu danh mục) hay news_market_brief (điểm tin thị trường) để trả lời câu hỏi bằng tiếng Việt. Địa chỉ máy chủ là https://mcp.finlens.vn/mcp. **Cách kết nối FinLens MCP với Claude và ChatGPT?** Kết nối FinLens MCP gồm ba bước: đăng ký gói FinLens Pro hoặc Premium tại finlens.vn/pricing, thêm địa chỉ https://mcp.finlens.vn/mcp vào Claude Desktop, Claude.ai hoặc ChatGPT, rồi đặt câu hỏi đầu tiên. Câu hỏi thử nghiệm gợi ý là "Phân tích tài chính HPG 5 năm gần nhất". Hướng dẫn từng bước kèm phần kiểm tra kết nối nằm ở bài Kết nối FinLens MCP với Claude AI & ChatGPT tại /mcp/bat-dau. **FinLens MCP phân tích được những gì?** FinLens MCP bao phủ các nhóm phân tích chính của thị trường Việt Nam: tài chính cơ bản (báo cáo tài chính, DuPont, so sánh cùng ngành), dòng tiền khối ngoại và smart money qua flows_get_stock_flow và flows_sector_flow, phân tích kỹ thuật với 141 chỉ báo cùng backtest qua signals_screen và signals_backtest, tối ưu danh mục qua portfolio_optimize, báo cáo phân tích từ hơn 20 công ty chứng khoán qua research_list_reports, kinh tế vĩ mô qua fin_dashboard, cổ tức qua dividends_upcoming, chứng quyền có bảo đảm qua warrants_compare, trái phiếu doanh nghiệp qua bond_maturity_wall và 185 quỹ đầu tư qua fund_stock_ownership. Diễn biến trong phiên và tin tức đã được AI đọc sẵn nằm ở market_today và news_market_brief. **Nên đọc bài hướng dẫn FinLens MCP nào trước?** Bộ tài liệu FinLens MCP có 18 bài hướng dẫn xếp từ cơ bản đến nâng cao, mỗi bài tập trung vào một nhóm công cụ. Nhà đầu tư mới nên đọc bài 1 về cách kết nối tại /mcp/bat-dau, sau đó là bài phân tích cơ bản tại /mcp/phan-tich-co-ban và bài dòng tiền tại /mcp/dong-tien. Người cần tra cứu nhanh toàn bộ công cụ có thể xem cẩm nang công cụ tại /mcp/cam-nang-cong-cu. --- # Phân tích kỹ thuật & backtest chiến lược chứng khoán bằng AI URL: https://docs.finlens.vn/mcp/ky-thuat-backtest Mô tả: Hướng dẫn dùng AI đọc 141 chỉ báo kỹ thuật, quét tín hiệu trên 1.700 mã, nhận diện 61 mẫu nến và backtest chiến lược với mô phỏng T+2.5 Việt Nam. Tóm tắt: FinLens MCP cho phép Claude, ChatGPT và Gemini phân tích kỹ thuật cổ phiếu Việt Nam bằng dữ liệu tính toán thực: signals_indicator_values đọc giá trị chỉ báo (RSI, MACD, MFI, OBV) trên giá điều chỉnh với đủ warmup, signals_screen quét tín hiệu trên 1.700 mã kèm bộ lọc cơ bản và 4 bộ lọc RS, signals_detect_patterns nhận dạng khoảng 15 mẫu hình giá, signals_candle_patterns quét 61 mẫu nến TA-Lib có tên tiếng Việt, signals_market_structure xác định xu hướng cùng các mức hỗ trợ và kháng cự. Nhà đầu tư kiểm chứng chiến lược bằng signals_event_study để đo win rate lịch sử sau mỗi tín hiệu, signals_backtest để mô phỏng giao dịch với tham số t_plus=2 theo quy tắc thanh toán T+2.5 của thị trường Việt Nam, và signals_optimize để tối ưu tham số với train/test split 70/30 kèm cảnh báo overfit. Nhóm công cụ tín hiệu này yêu cầu gói FinLens Premium. Sản phẩm: mcp ⏱ Đọc 14 phút · 🔴 Nâng cao · 🔧 Yêu cầu: FinLens Premium ## Đọc giá trị chỉ báo thực — đừng để AI đoán [#đọc-giá-trị-chỉ-báo-thực--đừng-để-ai-đoán] Thay vì để AI ước tính RSI hay MACD từ kiến thức chung, dùng `signals_indicator_values` để lấy **giá trị tính toán thực tế** trên giá điều chỉnh với đủ warmup period: **Cho tôi giá trị RSI(14), MACD(12,26,9) và MFI(14) của HPG hiện tại — và 10 phiên gần nhất để thấy xu hướng** → signals_indicator_values, N=10 — giá trị thực tính trên adjusted close, đủ warmup **OBV của FPT đang tăng hay giảm trong 20 phiên qua? Có xác nhận xu hướng giá không?** → indicator_values OBV + so sánh với price action ## Quét tín hiệu trên toàn thị trường [#quét-tín-hiệu-trên-toàn-thị-trường] Công cụ `signals_screen` quét toàn bộ 1.700 mã theo rule bạn định nghĩa — có thể kết hợp điều kiện kỹ thuật với bộ lọc cơ bản: **Tìm tất cả cổ phiếu HOSE có RSI \< 30 trong 3 phiên gần nhất và giá cắt lên MA20 — danh sách mã và chỉ báo kèm theo** → screen: exchange=HOSE, rules=[RSI<30, price_cross_up_MA20], days=3 **Quét mã có RSI vượt 50 từ bên dưới trong 5 phiên qua, lọc thêm ROE > 15% và P/E \< 20 và thanh khoản > 10 tỷ/ngày — mã nào phù hợp nhất?** → screen kỹ thuật + bộ lọc cơ bản đồng thời — tín hiệu kỹ thuật trên nền tảng tốt **Trong ngành ngân hàng, mã nào đang có MACD golden cross trong 5 phiên gần nhất và volume tăng bất thường?** → screen lọc sector + MACD cross + volume spike `signals_screen` có 4 bộ lọc RS: `min_rs_rating` (RS của mã), `min_rs_vs_industry` (leader trong ngành), `min_industry_rs` (breadth ngành) và `min_sector_rs` (momentum ngành) — kết quả trả kèm cả 4 giá trị. Ghép chúng để chỉ giữ mã mạnh trong ngành đang trend. Xem đầy đủ ở [Bài 15 · Sức mạnh ngành (RS)](/mcp/suc-manh-nganh). **Tìm mã có RSI cắt lên 50 trong 5 phiên qua, RS của mã ≥ 80 và là leader trong ngành (RS nội bộ ngành ≥ 75), thanh khoản > 10 tỷ/ngày** → screen: rule RSI + min_rs_rating=80 + min_rs_vs_industry=75 + min_avg_value_bil=10 ## Phát hiện mẫu hình giá [#phát-hiện-mẫu-hình-giá] Công cụ `signals_detect_patterns` nhận dạng \~15 mẫu hình đặt tên sẵn (hoặc mẫu tùy ý bạn định nghĩa), trả về ngày xuất hiện, độ khớp 0–1 và cờ "đang hình thành": **HPG có đang hình thành mẫu hình 2 đáy (double bottom) không? Quét thêm các mẫu hình tích cực khác nếu có** → detect_patterns: HPG, mẫu "double_bottom" + tất cả mẫu bullish **Kiểm tra xem VIC có mẫu hình vai-đầu-vai (head and shoulders) đang hình thành không — ngưỡng breakdown là đâu?** → detect_patterns "head_and_shoulders" — trả ngưỡng neckline + khoảng cách % tới breakdown ## Mẫu nến Nhật — tín hiệu đảo chiều ngắn hạn [#mẫu-nến-nhật--tín-hiệu-đảo-chiều-ngắn-hạn] Công cụ `signals_candle_patterns` quét cả 61 mẫu nến TA-Lib, trả tên tiếng Việt + hướng bullish/bearish: **VNM tuần này xuất hiện mẫu nến gì đáng chú ý? Có tín hiệu đảo chiều không?** → candle_patterns: VNM, days=5 — danh sách mẫu có tín hiệu + tên tiếng Việt **FPT có xuất hiện mẫu Búa (Hammer) hoặc Nhấn chìm tăng (Bullish Engulfing) trong 10 phiên qua không?** → lọc theo mẫu cụ thể + hướng bullish ## Cấu trúc giá — Hỗ trợ & Kháng cự [#cấu-trúc-giá--hỗ-trợ--kháng-cự] **Xu hướng hiện tại của HPG thế nào? Các mức hỗ trợ và kháng cự gần nhất ở đâu? Đang cách giá hiện tại bao nhiêu %?** → market_structure: trend từ pivot, S/R levels kèm khoảng cách %, đỉnh/đáy 52 tuần **FPT vừa phá vỡ kháng cự. Cấu trúc giá xác nhận breakout không? Mức kháng cự tiếp theo ở đâu?** → market_structure — pivot points, % cách mức S/R tiếp theo, xu hướng trending/ranging ## Thống kê sau tín hiệu — win rate thực tế [#thống-kê-sau-tín-hiệu--win-rate-thực-tế] Công cụ `signals_event_study` tổng hợp mỗi lần tín hiệu xuất hiện trong lịch sử — 5, 10, 20 phiên sau giá thay đổi thế nào, so với baseline mua ngẫu nhiên: **Mỗi khi RSI của HPG chạm dưới 30 rồi vượt lên lại, 20 phiên sau giá thường tăng bao nhiêu %? Win rate là bao nhiêu? So với mua ngẫu nhiên?** → event_study: mỗi event = RSI cross up 30, thống kê return 5/10/20 phiên + win rate + baseline ## Backtest chiến lược — mô phỏng T+2.5 VN [#backtest-chiến-lược--mô-phỏng-t25-vn] Tham số `t_plus=2` mô phỏng quy tắc thanh toán T+2.5 VN — tín hiệu bán chỉ thực hiện được sau khi cổ phiếu đủ ngày nắm giữ. Backtest sẽ thực tế hơn nhiều so với bỏ qua yếu tố này. **Backtest chiến lược MA20/50 cross trên HPG trong 5 năm — so với mua-hold HPG, Sharpe và max drawdown là bao nhiêu?** → backtest: HPG, rule=MA20 cross MA50, 5 năm, so buy-hold, kèm danh sách lệnh **Backtest RSI(14) \< 30 → mua, > 70 → bán trên HPG, FPT và VNM trong 3 năm qua với t\_plus=2 — mã nào chiến lược này hoạt động tốt nhất?** → backtest 3 mã cùng rule, t_plus=2 mô phỏng T+2.5, so sánh Sharpe/Sortino/drawdown ## Tối ưu tham số — tránh overfit [#tối-ưu-tham-số--tránh-overfit] FinLens tự động chia dữ liệu train/test 70/30 và cảnh báo khi Sharpe in-sample cao nhưng out-of-sample thấp — dấu hiệu overfit rõ ràng. Luôn kiểm tra OOS metrics trước khi dùng tham số tối ưu. **Tối ưu tham số MA short (5–30) × MA long (20–80) cho chiến lược cross trên FPT 3 năm — chia train/test 70/30, top 5 tổ hợp tốt nhất và cảnh báo overfit** → optimize: grid search ≤200 combo, IS/OOS Sharpe side-by-side, best_spec để dùng ngay trong backtest **Tối ưu chiến lược RSI(window 7–21) × MA(window 10–50) trên VCB trong 5 năm — tham số nào cho Sharpe OOS cao nhất?** → optimize 2 tham số đồng thời, lấy best_spec OOS-first (không phải IS-first) ## Bài liên quan [#bài-liên-quan] Lọc mã leader trong ngành đang trend bằng 4 bộ lọc RS của signals\_screen. Kết hợp tín hiệu kỹ thuật với xác nhận từ dòng tiền để tăng độ chính xác. Chuỗi đầy đủ từ cơ bản đến nâng cao. ### Câu hỏi thường gặp **Làm sao để backtest chiến lược chứng khoán Việt Nam bằng AI?** Công cụ signals_backtest của FinLens MCP chạy backtest long-only cho một hoặc nhiều mã theo rule do nhà đầu tư mô tả bằng ngôn ngữ tự nhiên, ví dụ MA20 cắt MA50 hoặc RSI(14) dưới 30 thì mua và trên 70 thì bán. Kết quả trả về so sánh với chiến lược mua và nắm giữ, kèm Sharpe, Sortino, max drawdown và danh sách lệnh đã khớp. Nhà đầu tư chỉ cần yêu cầu AI backtest chiến lược trên mã và khung thời gian mong muốn, không cần viết code. **Backtest của FinLens MCP có mô phỏng quy tắc T+2.5 của Việt Nam không?** Có. Tham số t_plus=2 trong signals_backtest mô phỏng quy tắc thanh toán T+2.5 của thị trường Việt Nam: tín hiệu bán chỉ được thực hiện sau khi cổ phiếu đủ ngày nắm giữ. Bật tham số này giúp kết quả backtest sát thực tế hơn nhiều so với việc bỏ qua độ trễ thanh toán, đặc biệt với các chiến lược giao dịch ngắn hạn. **Làm sao quét toàn thị trường tìm cổ phiếu có RSI dưới 30 hoặc MACD golden cross?** Công cụ signals_screen của FinLens MCP quét toàn bộ 1.700 mã theo rule kỹ thuật do người dùng định nghĩa, chẳng hạn RSI dưới 30 trong 3 phiên gần nhất, giá cắt lên MA20, hoặc MACD golden cross kèm volume tăng bất thường. Bộ lọc kỹ thuật có thể kết hợp đồng thời với tiêu chí cơ bản như ROE trên 15%, P/E dưới 20 và thanh khoản trên 10 tỷ đồng mỗi ngày. Ngoài ra còn có 4 bộ lọc sức mạnh tương đối là min_rs_rating, min_rs_vs_industry, min_industry_rs và min_sector_rs để chỉ giữ lại mã dẫn dắt trong ngành đang có xu hướng tăng. **Làm sao tránh overfit khi tối ưu tham số chiến lược giao dịch?** Công cụ signals_optimize của FinLens MCP chạy grid search tối đa 200 tổ hợp tham số và tự động chia dữ liệu train/test theo tỷ lệ 70/30, hiển thị Sharpe in-sample và out-of-sample cạnh nhau. Hệ thống cảnh báo khi Sharpe in-sample cao nhưng out-of-sample thấp, đây là dấu hiệu overfit rõ ràng. Nguyên tắc an toàn là chọn best_spec dựa trên kết quả out-of-sample thay vì in-sample, rồi đưa tham số đó vào signals_backtest để kiểm chứng lại. --- # Phân tích cổ phiếu đa góc nhìn: chia nhỏ prompt cho AI URL: https://docs.finlens.vn/mcp/nang-cao Mô tả: Hướng dẫn chia nhỏ prompt thành chuỗi bước và soi cổ phiếu qua 6 lăng kính — định giá, chất lượng, dòng tiền, kỹ thuật, cổ tức, ngành — với FinLens MCP. Tóm tắt: Tài liệu FinLens MCP hướng dẫn kỹ thuật chia nhỏ prompt: thay vì hỏi AI một câu tổng quát, nhà đầu tư gửi lần lượt các bước nhỏ, mỗi bước một mục tiêu và một bộ công cụ riêng, rồi bắc cầu kết quả bước trước sang bước sau. Nội dung gồm 5 nguyên tắc điều phối AI, 6 lăng kính soi một cổ phiếu (định giá & cơ bản, chất lượng & rủi ro, dòng tiền & cung-cầu, kỹ thuật & thời điểm, cổ tức & sự kiện, ngành · vĩ mô · CTCK), một phiên mẫu 8 bước phân tích HPG và một prompt điều phối chạy tuần tự. Các công cụ MCP được dùng gồm stocks_get_profile, fundamental_get_key_metrics, fundamental_quality_scan, fundamental_dupont, flows_get_stock_flow, signals_market_structure, signals_indicator_values, fundamental_compare_peers, research_get_analyst_consensus và gso_trade_stocks; quy trình này yêu cầu gói FinLens Pro. Sản phẩm: mcp ⏱ Đọc 12 phút · 🔴 Nâng cao · 🔧 Yêu cầu: FinLens Pro ## Vì sao nên chia nhỏ câu hỏi? [#vì-sao-nên-chia-nhỏ-câu-hỏi] Khi bạn hỏi một câu khổng lồ — *"Phân tích toàn bộ HPG và cho biết nên mua không"* — AI buộc phải gọi nhiều tool cùng lúc, tóm tắt vội và dễ bỏ sót. Ngược lại, khi bạn **chia thành chuỗi bước nhỏ**, mỗi bước: * Có **một mục tiêu rõ ràng** → AI chọn đúng 1–2 công cụ, trả lời kỹ. * Cho bạn **kiểm chứng từng mảnh** trước khi đi tiếp (số liệu, kỳ dữ liệu). * Tạo **ngữ cảnh tích lũy** — bước sau tận dụng phát hiện ở bước trước. * Giúp bạn **đào sâu chỗ bất thường** thay vì nhận một bản tóm tắt phẳng. Một phân tích đáng tin được xây từ **nhiều mảnh nhỏ đã kiểm chứng**, nhìn từ **nhiều góc độ độc lập**, rồi mới tổng hợp. Bạn là "đạo diễn" điều phối; AI là chuyên viên thực thi từng cảnh. ## 5 nguyên tắc vàng khi điều phối AI [#5-nguyên-tắc-vàng-khi-điều-phối-ai] 1 #### Một bước — một mục tiêu [#một-bước--một-mục-tiêu] Mỗi câu hỏi nhắm đúng một việc (định giá, hoặc chất lượng, hoặc dòng tiền…). Đừng trộn 5 mục tiêu vào 1 câu. 2 #### Bắc cầu kết quả [#bắc-cầu-kết-quả] Dùng phát hiện ở bước trước làm đầu vào bước sau: "Ngành của nó là gì?" → "So sánh nó với các mã cùng ngành đó". 3 #### Luôn hỏi "tính đến khi nào?" [#luôn-hỏi-tính-đến-khi-nào] Yêu cầu AI nêu rõ *as\_of* / kỳ dữ liệu (giá EOD, dòng tiền chốt 18h, BCTC quý nào). Dữ liệu khác mốc thời gian = kết luận khác. 4 #### Ép dùng SỐ THẬT, cấm phỏng đoán [#ép-dùng-số-thật-cấm-phỏng-đoán] "Dựa trên số liệu thật từ công cụ, đừng ước lượng". Nếu thiếu dữ liệu, yêu cầu AI nói rõ "không có" thay vì bịa. 5 #### Đào sâu & đối chiếu chéo [#đào-sâu--đối-chiếu-chéo] Gặp con số lạ → hỏi tiếp "vì sao". Bắt AI **đối chiếu** các góc nhìn: cơ bản tốt nhưng dòng tiền rút ra? CTCK khen nhưng kỹ thuật yếu? ## 6 lăng kính để soi một cổ phiếu [#6-lăng-kính-để-soi-một-cổ-phiếu] Một quyết định tốt cần nhìn cổ phiếu từ nhiều phía độc lập. Mỗi lăng kính là một bước (hoặc cụm bước) với bộ công cụ riêng: Doanh nghiệp đang đắt hay rẻ, sinh lời & tăng trưởng ra sao (ưu tiên TTM). `fundamental_get_key_metrics` `fundamental_dupont` `fundamental_get_statement` Lợi nhuận có thực không, dòng tiền & CĐKT có red flag không. `fundamental_quality_scan` `fundamental_get_metric_history` Smart money/khối ngoại đang mua hay bán, lực cầu chủ động ra sao. `flows_get_stock_flow` `flows_top_net` Xu hướng, hỗ trợ/kháng cự, tín hiệu & mẫu hình — để chọn điểm vào. `signals_market_structure` `signals_indicator_values` `signals_detect_patterns` Lợi suất, độ bền cổ tức, sự kiện quyền sắp tới (nếu là NĐT cổ tức). `dividends_analyze_policy` `dividends_upcoming` Vị thế so ngành, bối cảnh vĩ mô/XNK, và quan điểm phân tích viên. `fundamental_compare_peers` `research_get_analyst_consensus` `gso_trade_stocks` Tùy mục tiêu mà chọn lăng kính: đầu tư dài hạn → nặng ①②⑤⑥; lướt sóng → nặng ③④; săn cổ tức → ⑤①②. Điều quan trọng là **ý thức được mình đang bỏ qua góc nào**. ## Thực chiến: soi HPG qua 8 bước [#thực-chiến-soi-hpg-qua-8-bước] Dưới đây là một phiên phân tích mẫu. Gửi **lần lượt**, đọc câu trả lời mỗi bước rồi mới gửi bước sau (có thể chỉnh hướng giữa chừng): **HPG là doanh nghiệp gì, niêm yết sàn nào, thuộc ngành ICB nào? Vốn hoá hiện tại?** → stocks_get_profile + latest_quote — lấy TÊN NGÀNH để dùng ở bước 6 **Cho tôi P/E, P/B, ROE, biên LN ròng và tăng trưởng doanh thu/LN của HPG 5 năm gần nhất, ưu tiên số liệu TTM. Định giá đang ở vùng nào so với lịch sử?** → fundamental_get_key_metrics (limit=5) — nêu rõ kỳ TTM **Thẩm định chất lượng kế toán của HPG — lợi nhuận có được dòng tiền thực đỡ không, có red flag nào về tồn kho, phải thu hay nợ vay không?** → fundamental_quality_scan — 8 mục cross-check + cờ đỏ; đào sâu mục bất thường nếu có **Smart money và khối ngoại đang mua hay bán ròng HPG trong 20 phiên gần nhất? Nêu rõ kỳ dữ liệu.** → flows_get_stock_flow (focus=smart_money rồi foreign) — chú ý as_of/as_of_complete **Xu hướng hiện tại của HPG thế nào? Hỗ trợ/kháng cự gần nhất ở đâu, RSI và MACD đang bao nhiêu?** → signals_market_structure + signals_indicator_values (số thật, không ước lượng) **So sánh HPG với các mã cùng ngành thép về P/E, ROE, tăng trưởng. Giá mục tiêu đồng thuận của các CTCK là bao nhiêu, upside còn bao nhiêu %?** → fundamental_compare_peers + research_get_analyst_consensus — dùng tên ngành từ bước 1 **Tổng hợp 6 góc nhìn vừa rồi vào một bảng: góc nào TÍCH CỰC, góc nào TIÊU CỰC. Có mâu thuẫn nào không (vd cơ bản tốt nhưng dòng tiền rút ra, hoặc kỹ thuật yếu dù CTCK khen)?** → Không gọi tool mới — ép AI tổng hợp & chỉ ra xung đột giữa các lăng kính **Với nhà đầu tư dài hạn ưu tiên an toàn, điểm mạnh / điểm yếu / rủi ro chính của HPG là gì, và những mốc nào tôi cần theo dõi tiếp?** → Tổng hợp cuối, nêu rõ giả định & giới hạn dữ liệu + disclaimer ## Mẫu prompt "điều phối" (một lần) [#mẫu-prompt-điều-phối-một-lần] Khi đã quen, bạn có thể gói cả quy trình vào **một prompt đánh số** để AI tự chạy tuần tự — vừa nhanh, vừa giữ được tính đa góc nhìn: **Phân tích HPG đa góc nhìn, làm TUẦN TỰ và nêu rõ kỳ dữ liệu mỗi phần: 1. Hồ sơ + ngành (stocks\_get\_profile) 2. Định giá & sinh lời TTM (fundamental\_get\_key\_metrics) 3. Chất lượng & red flags (fundamental\_quality\_scan) 4. Dòng tiền smart money & khối ngoại 20 phiên (flows\_get\_stock\_flow) 5. Xu hướng + hỗ trợ/kháng cự + RSI/MACD (signals\_market\_structure, signals\_indicator\_values) 6. So ngành + đồng thuận CTCK (fundamental\_compare\_peers, research\_get\_analyst\_consensus) Cuối cùng: bảng tổng hợp tích cực/tiêu cực mỗi góc, chỉ ra mâu thuẫn, kết luận cho NĐT dài hạn + disclaimer. Dùng SỐ THẬT từ công cụ, không ước lượng.** → Mẹo: vẫn nên hỏi tiếp để đào sâu phần bạn quan tâm nhất FinLens MCP có sẵn các quy trình đóng gói: `/phan_tich_co_phieu` (cơ bản + CTCK + ngành + vĩ mô), `/danh_gia_co_phieu` (thẩm định theo contract), `/toi_uu_danh_muc`, `/loc_tin_hieu`, `/backtest_chien_luoc`, `/phan_tich_co_tuc`. Trên Claude gõ "/" để chọn — mỗi lệnh là một chuỗi đa bước đã tối ưu sẵn. ## Kỹ thuật nâng cao [#kỹ-thuật-nâng-cao] ### So sánh đa mã thay vì soi từng mã [#so-sánh-đa-mã-thay-vì-soi-từng-mã] **Trong HPG, HSG, NKG: mã nào có ROE cao nhất, định giá rẻ nhất và đang được khối ngoại mua ròng? Lập bảng so sánh từng tiêu chí rồi xếp hạng tổng hợp.** → Buộc AI gọi cùng bộ tool cho từng mã rồi lập bảng — đa góc nhìn theo chiều ngang ### Đào sâu khi gặp bất thường [#đào-sâu-khi-gặp-bất-thường] **ROE của mã này giảm mạnh năm ngoái — phân rã DuPont xem do biên lợi nhuận, vòng quay tài sản hay đòn bẩy? Và dòng tiền hoạt động có theo kịp lợi nhuận không?** → fundamental_dupont + fundamental_get_statement (cashflow) — không dừng ở "ROE giảm", phải biết VÌ SAO ### Bắc cầu vĩ mô → cổ phiếu [#bắc-cầu-vĩ-mô--cổ-phiếu] **Xuất khẩu thủy sản đang tăng hay giảm? Những mã nào hưởng lợi? Rồi lấy mã mạnh nhất trong số đó phân tích cơ bản + định giá.** → gso_trade_stocks → chọn mã → fundamental_get_key_metrics — chuỗi vĩ mô → vi mô Luôn yêu cầu AI: (1) **nêu kỳ dữ liệu** mỗi con số; (2) **nói rõ khi thiếu dữ liệu** thay vì suy đoán; (3) **phân biệt dữ kiện với nhận định**; (4) kèm **disclaimer**. Tín hiệu/điểm số chỉ là tham khảo — quyết định đầu tư là của bạn. ## Checklist đa góc nhìn [#checklist-đa-góc-nhìn] * Đã xác định **mục tiêu** (dài hạn / lướt sóng / cổ tức) và chọn lăng kính phù hợp? * Đã soi **định giá & sinh lời** (ưu tiên TTM, so với lịch sử)? * Đã **thẩm định chất lượng** lợi nhuận & dòng tiền (fundamental\_quality\_scan), đào sâu red flags? * Đã xem **dòng tiền** smart money / khối ngoại, nêu rõ kỳ dữ liệu? * Đã kiểm **kỹ thuật & thời điểm** (xu hướng, S/R, chỉ báo bằng số thật)? * Đã đặt vào **bối cảnh ngành / vĩ mô** và đối chiếu **quan điểm CTCK**? * (NĐT cổ tức) Đã đánh giá **lợi suất, payout, độ bền cổ tức** & sự kiện sắp tới? * Đã **đối chiếu chéo** các góc nhìn và chỉ ra mâu thuẫn? * Kết luận có nêu rõ **giả định, giới hạn dữ liệu** và **disclaimer**? ## Bài liên quan [#bài-liên-quan] Key metrics, DuPont, fundamental\_quality\_scan — bộ công cụ cốt lõi của phân tích cơ bản. Smart money vs khối ngoại vs dòng tiền chủ động — đọc đúng tín hiệu. Chuỗi đầy đủ FinLens MCP từ kết nối đến khai thác nâng cao. ### Câu hỏi thường gặp **Làm sao để AI phân tích cổ phiếu sâu, không trả lời hời hợt?** Hãy chia một câu hỏi lớn thành chuỗi bước nhỏ, mỗi bước chỉ nhắm một mục tiêu và chỉ cần 1–2 công cụ, gửi lần lượt và đọc kết quả trước khi đi tiếp. FinLens MCP nêu 5 nguyên tắc điều phối: một bước một mục tiêu; bắc cầu kết quả bước trước sang bước sau; luôn hỏi kỳ dữ liệu (as_of, giá EOD, báo cáo tài chính quý nào); ép AI dùng số thật từ công cụ thay vì ước lượng; và đào sâu, đối chiếu chéo khi gặp con số bất thường. Cách làm này tạo ngữ cảnh tích lũy và cho phép kiểm chứng từng mảnh số liệu. **Phân tích một cổ phiếu đa góc nhìn gồm những góc nào?** FinLens MCP chia thành 6 lăng kính: định giá & cơ bản (fundamental_get_key_metrics, fundamental_dupont, fundamental_get_statement); chất lượng & rủi ro (fundamental_quality_scan, fundamental_get_metric_history); dòng tiền & cung-cầu (flows_get_stock_flow, flows_top_net); kỹ thuật & thời điểm (signals_market_structure, signals_indicator_values, signals_detect_patterns); cổ tức & sự kiện (dividends_analyze_policy, dividends_upcoming); và ngành · vĩ mô · CTCK (fundamental_compare_peers, research_get_analyst_consensus, gso_trade_stocks). Không phải lúc nào cũng cần đủ 6: đầu tư dài hạn nghiêng về định giá, chất lượng, cổ tức và ngành; lướt sóng nghiêng về dòng tiền và kỹ thuật; điều quan trọng là biết mình đang bỏ qua góc nào. **Prompt mẫu để nhờ AI phân tích một mã cổ phiếu là gì?** Một prompt điều phối mẫu yêu cầu AI làm TUẦN TỰ sáu phần và nêu rõ kỳ dữ liệu mỗi phần: hồ sơ + ngành (stocks_get_profile), định giá & sinh lời TTM (fundamental_get_key_metrics), chất lượng & red flag (fundamental_quality_scan), dòng tiền smart money và khối ngoại 20 phiên (flows_get_stock_flow), xu hướng + hỗ trợ/kháng cự + RSI/MACD (signals_market_structure, signals_indicator_values), so ngành + đồng thuận CTCK (fundamental_compare_peers, research_get_analyst_consensus). Kết thúc bằng bảng tổng hợp tích cực/tiêu cực từng góc, chỉ ra mâu thuẫn giữa các góc và kèm disclaimer, đồng thời yêu cầu dùng số thật từ công cụ, không ước lượng. Quy trình nâng cao này yêu cầu gói FinLens Pro. **FinLens MCP có lệnh tắt (slash command) nào để phân tích nhanh?** FinLens MCP có sẵn các quy trình đóng gói dạng lệnh tắt: /phan_tich_co_phieu (cơ bản + CTCK + ngành + vĩ mô), /danh_gia_co_phieu (thẩm định theo contract), /toi_uu_danh_muc, /loc_tin_hieu, /backtest_chien_luoc và /phan_tich_co_tuc. Trên Claude, gõ dấu "/" để chọn; mỗi lệnh là một chuỗi đa bước đã được tối ưu sẵn. Sau khi chạy lệnh tắt, nhà đầu tư vẫn nên hỏi tiếp để đào sâu phần mình quan tâm nhất. --- # Phân tích cổ phiếu ngân hàng bằng AI: NPL, CASA, NII, CIR URL: https://docs.finlens.vn/mcp/ngan-hang Mô tả: Hướng dẫn dùng AI phân tích cổ phiếu ngân hàng Việt Nam qua ba công cụ FinLens MCP: chất lượng tài sản (NPL, bao phủ dự phòng), CASA và NII/CIR/PPOP. Tóm tắt: FinLens MCP phân tích cổ phiếu ngân hàng Việt Nam bằng ba công cụ chuyên ngành thay cho bộ chỉ tiêu doanh nghiệp thông thường: `fundamental_bank_asset_quality` (NPL theo 5 nhóm nợ, nợ nhóm 2 SML, bao phủ dự phòng LLR), `fundamental_bank_funding` (CASA, tỷ trọng tiền gửi có kỳ hạn) và `fundamental_bank_income` (NII, TOI, CIR, PPOP). Tài liệu hướng dẫn cách ghép ba lăng kính này với `fundamental_get_notes` để bóc dư nợ theo ngành kinh tế, kỳ hạn, loại tiền tệ, và với `fundamental_compare_peers` nhóm Banking để xếp hạng toàn ngành theo P/B và ROE. Đối tượng là nhà đầu tư dùng Claude, ChatGPT hoặc Gemini để soi cổ phiếu ngân hàng như VCB, TCB, ACB, CTG; yêu cầu gói FinLens Pro. Sản phẩm: mcp ⏱ Đọc 12 phút · 🟡 Trung cấp – Nâng cao · 🔧 Yêu cầu: FinLens Pro ## Vì sao phân tích ngân hàng khác hẳn? [#vì-sao-phân-tích-ngân-hàng-khác-hẳn] Áp các chỉ tiêu doanh nghiệp thông thường (biên LN gộp, vòng quay hàng tồn kho, EV/EBITDA) lên ngân hàng là sai về bản chất. AI của FinLens **tự nhận diện** mã ngân hàng và chuyển sang bộ công cụ chuyên ngành. Ba câu hỏi cốt lõi khi soi một cổ phiếu ngân hàng: Nợ xấu (NPL) đang ở đâu, dự phòng có đủ dày để hấp thụ? Vốn rẻ (CASA) chiếm bao nhiêu — lợi thế chi phí vốn? Phụ thuộc thu nhập lãi hay đa dạng hóa? Chi phí có gọn? ## Chất lượng tài sản — NPL & bao phủ dự phòng [#chất-lượng-tài-sản--npl--bao-phủ-dự-phòng] `fundamental_bank_asset_quality` là chỉ tiêu rủi ro tín dụng quan trọng NHẤT. Nó bóc dư nợ theo **5 nhóm nợ** và tính: * **NPL** = nợ nhóm 3 + 4 + 5 (dưới tiêu chuẩn / nghi ngờ / có khả năng mất vốn) ÷ tổng dư nợ. Ngưỡng quy định \~3%. * **Nợ nhóm 2 (SML)** — nợ cần chú ý, là cảnh báo SỚM cho nợ xấu hình thành. * **Bao phủ nợ xấu (LLR coverage)** = tổng dự phòng ÷ NPL. >100% = đệm dày, hấp thụ rủi ro tốt; \<70% = đệm mỏng, có thể phải trích lập thêm (ăn vào lợi nhuận). Ví dụ tương phản: một ngân hàng quốc doanh lớn có thể có NPL \~0.6% với bao phủ >250% (đệm cực dày, "của để dành"), trong khi một ngân hàng bán lẻ/tiêu dùng có NPL >3% với bao phủ \~55% (rủi ro cao hơn, đổi lại NIM cao hơn). Cùng là "ngân hàng" nhưng khẩu vị rủi ro khác hẳn. **Chất lượng tài sản của VCB: NPL bao nhiêu, nợ nhóm 2 có đáng lo không, và bao phủ dự phòng có đủ dày? Xu hướng nợ xấu đang cải thiện hay xấu đi?** → bank_asset_quality(VCB) — npl_ratio, sml_ratio, llr_coverage + signal & xu hướng ## Cơ cấu huy động — CASA (vốn rẻ) [#cơ-cấu-huy-động--casa-vốn-rẻ] `fundamental_bank_funding` tính **CASA** = tiền gửi không kỳ hạn ÷ tổng tiền gửi. CASA càng cao → chi phí vốn càng thấp → đệm NIM (biên lãi ròng) càng bền. Đây là một trong những lợi thế cạnh tranh khó sao chép nhất của ngân hàng. **CASA của TCB là bao nhiêu và đang tăng hay giảm? Lợi thế chi phí vốn này có bền không so với mặt bằng ngành?** → bank_funding(TCB) — casa_ratio, term_ratio + xu hướng; so với peers qua fundamental_compare_peers ## Cơ cấu thu nhập & hiệu quả — NII, CIR, PPOP [#cơ-cấu-thu-nhập--hiệu-quả--nii-cir-ppop] `fundamental_bank_income` dựng lại bức tranh lợi nhuận ngân hàng: * **NII** (thu nhập lãi thuần) = thu nhập lãi − chi phí lãi — xương sống lợi nhuận. * **TOI** (tổng thu nhập hoạt động) = NII + thu ngoài lãi (dịch vụ / ngoại hối / chứng khoán / khác). * **Cơ cấu thu nhập**: tỷ trọng NII vs thu ngoài lãi → mức đa dạng hóa (phụ thuộc tín dụng hay không). * **CIR** (cost-income ratio) = chi phí hoạt động ÷ TOI — thấp = hiệu quả chi phí tốt. * **PPOP** = lợi nhuận thuần TRƯỚC dự phòng = TOI − chi phí hoạt động — "công suất" lợi nhuận trước khi trừ chi phí rủi ro tín dụng. Ghép `bank_income` (PPOP — khả năng tạo lợi nhuận) với `bank_asset_quality` (NPL & dự phòng — chi phí rủi ro). Một ngân hàng PPOP mạnh + đệm dự phòng dày = có "của để dành" để vượt chu kỳ tín dụng xấu. **Cơ cấu thu nhập của ACB: NII chiếm bao nhiêu % TOI, thu ngoài lãi có đáng kể không, CIR có đang được tối ưu? Đọc cả PPOP để đánh giá công suất lợi nhuận** → bank_income(ACB) — nii_ratio, non_nii_ratio, cir, ppop + signal ## Bóc tách dư nợ & tiền gửi chi tiết [#bóc-tách-dư-nợ--tiền-gửi-chi-tiết] Ngoài 3 lăng kính chuyên ngành, dùng `fundamental_get_notes` để bóc các mục thuyết minh khác của ngân hàng: dư nợ theo **ngành kinh tế** (tập trung tín dụng), theo **kỳ hạn**, theo **loại tiền tệ**, hoặc tiền gửi theo nhóm khách hàng. Dùng `fundamental_list_notes` để xem mục nào có data. **Dư nợ của CTG phân theo ngành kinh tế — tập trung vào ngành nào nhất? Có rủi ro tập trung tín dụng vào bất động sản không?** → list_notes(CTG) → get_notes(CTG, loans_by_industry) ## So sánh giữa các ngân hàng [#so-sánh-giữa-các-ngân-hàng] Ghép các lăng kính chuyên ngành với `fundamental_compare_peers` (lọc nhóm Banking) để xếp hạng toàn ngành theo P/B, ROE, và đối chiếu NPL/CASA/CIR thủ công giữa các mã. **Trong nhóm ngân hàng, mã nào có chất lượng tài sản tốt (NPL thấp, bao phủ cao) và CASA cao nhưng P/B lại thấp? Tìm giá trị bị bỏ qua** → fundamental_compare_peers(Banking, theo P/B) + bank_asset_quality + bank_funding cho top mã ## Prompt phân tích ngân hàng toàn diện [#prompt-phân-tích-ngân-hàng-toàn-diện] **Phân tích chuyên sâu cổ phiếu ngân hàng VCB: 1. Chất lượng tài sản — NPL, nợ nhóm 2, bao phủ dự phòng & xu hướng 2. Cơ cấu huy động — CASA & lợi thế chi phí vốn 3. Cơ cấu thu nhập — NII vs thu ngoài lãi, CIR, PPOP 4. Định giá P/B vs lịch sử & vs ngành ngân hàng 5. Kết luận: điểm mạnh/yếu & khẩu vị rủi ro** → AI gọi bank_asset_quality + bank_funding + bank_income + valuation_history(pb) + fundamental_compare_peers, tổng hợp Xem thêm [Bài 12 — Công ty phi tài chính](/mcp/cong-ty-thuong) (thuyết minh + DCF) và [Bài 14 — Chứng khoán](/mcp/chung-khoan) (tự doanh, margin, tâm lý thị trường). Lưu ý: P/E·P/B áp dụng mọi loại hình, nhưng **P/S và DCF/EV-EBITDA không dùng cho ngân hàng** — AI sẽ tự chặn và chuyển sang định giá P/B·ROE. ## Bài liên quan [#bài-liên-quan] Cơ cấu chi phí, nợ vay, vốn lưu động và định giá nội tại cho DN phi tài chính. Danh mục tự doanh, cơ cấu doanh thu CTCK và chỉ báo tâm lý toàn ngành. Nền tảng — AI tự chọn bộ chỉ tiêu NIM/NPL/CAR cho ngân hàng. ### Câu hỏi thường gặp **Phân tích cổ phiếu ngân hàng bằng AI như thế nào?** Ngân hàng không có mô hình doanh thu – giá vốn – tồn kho, nên phải soi theo ba trụ cột riêng. FinLens MCP cung cấp `fundamental_bank_asset_quality` cho chất lượng tài sản (NPL, nợ nhóm 2, bao phủ dự phòng), `fundamental_bank_funding` cho cơ cấu huy động (CASA) và `fundamental_bank_income` cho cơ cấu thu nhập & hiệu quả (NII, TOI, CIR, PPOP). Nhà đầu tư chỉ cần hỏi AI bằng ngôn ngữ tự nhiên, ví dụ "Chất lượng tài sản của VCB: NPL bao nhiêu, bao phủ dự phòng có đủ dày?", AI sẽ tự nhận diện mã ngân hàng và gọi đúng bộ công cụ chuyên ngành. **NPL và bao phủ nợ xấu bao nhiêu thì an toàn?** NPL (nợ xấu) là tổng nợ nhóm 3, 4, 5 — dưới tiêu chuẩn, nghi ngờ, có khả năng mất vốn — chia cho tổng dư nợ, với ngưỡng quy định khoảng 3%. Bao phủ nợ xấu (LLR coverage) bằng tổng dự phòng chia NPL: trên 100% là đệm dày hấp thụ rủi ro tốt, dưới 70% là đệm mỏng và ngân hàng có thể phải trích lập thêm, ăn vào lợi nhuận. Cần theo dõi thêm nợ nhóm 2 (SML — nợ cần chú ý) vì đây là cảnh báo sớm cho nợ xấu hình thành. Công cụ `fundamental_bank_asset_quality` trả về npl_ratio, sml_ratio, llr_coverage kèm tín hiệu và xu hướng. **CASA là gì và vì sao quan trọng với cổ phiếu ngân hàng?** CASA là tỷ lệ tiền gửi không kỳ hạn trên tổng tiền gửi. CASA càng cao thì chi phí vốn càng thấp, đệm NIM (biên lãi ròng) càng bền, và đây là một trong những lợi thế cạnh tranh khó sao chép nhất của ngân hàng. Công cụ `fundamental_bank_funding` của FinLens MCP tính casa_ratio và term_ratio kèm xu hướng, có thể đối chiếu với mặt bằng ngành qua `fundamental_compare_peers`. **Có dùng DCF hay EV/EBITDA để định giá cổ phiếu ngân hàng được không?** Không. P/S và DCF/EV-EBITDA không áp dụng cho ngân hàng do đặc thù bảng cân đối; FinLens MCP sẽ tự chặn và chuyển sang định giá theo P/B kết hợp ROE. P/E và P/B thì áp dụng được cho mọi loại hình doanh nghiệp. Có thể dùng `fundamental_valuation_history` với chỉ tiêu P/B để so với lịch sử, và `fundamental_compare_peers` lọc nhóm Banking để so với toàn ngành. --- # Phân tích cơ bản cổ phiếu bằng AI: P/E, ROE, BCTC, DuPont URL: https://docs.finlens.vn/mcp/phan-tich-co-ban Mô tả: Hỏi AI để tra 7 nhóm KPI kèm TTM, đọc BCTC đầy đủ, phân rã DuPont và quét 8 mục chất lượng kế toán, so sánh toàn ngành ICB qua FinLens MCP. Tóm tắt: Hướng dẫn dùng FinLens MCP để phân tích cơ bản cổ phiếu Việt Nam ngay trong Claude, ChatGPT hoặc Gemini: tra 7 nhóm KPI (định giá, sinh lợi, hiệu quả, thanh khoản, dòng tiền, tăng trưởng, đòn bẩy) kèm phiên bản TTM lũy kế 4 quý bằng fundamental_get_key_metrics, và đọc báo cáo tài chính đầy đủ gồm CĐKT, KQKD, LCTT bằng fundamental_get_statement. Hướng dẫn cũng bao gồm phân rã DuPont 3 nhân tố bằng fundamental_dupont, thẩm định 8 mục chất lượng kế toán bằng fundamental_quality_scan, theo dõi xu hướng chỉ tiêu bằng fundamental_get_metric_history và xếp hạng percentile với toàn bộ doanh nghiệp cùng ngành ICB bằng fundamental_compare_peers. Nội dung dành cho nhà đầu tư Việt Nam phân tích cả doanh nghiệp phi tài chính, ngân hàng, chứng khoán và bảo hiểm, với các câu hỏi mẫu cho HPG, VCB, FPT, MWG, VHM, NVL, VNM. Sản phẩm: mcp ⏱ Đọc 12 phút · 🟢 Mọi cấp độ · 🔧 Yêu cầu: FinLens Pro ## 7 nhóm KPI mà AI có thể tra cứu [#7-nhóm-kpi-mà-ai-có-thể-tra-cứu] Công cụ `fundamental_get_key_metrics` trả về 7 nhóm chỉ tiêu, hỗ trợ cả **4 loại doanh nghiệp**: phi tài chính (CT thông thường), ngân hàng (NH), chứng khoán (CK) và bảo hiểm (BH). Mỗi nhóm đều có phiên bản **TTM** (Trailing Twelve Months) tự động. P/E, P/B, EV/EBITDA, P/S, dividend yield ROE, ROA, ROIC, biên lợi nhuận gộp/ròng Vòng quay tài sản, vòng quay hàng tồn kho, kỳ thu tiền Current ratio, quick ratio, cash ratio FCF, CFO/EBITDA, Capex/CFO, FCF yield Revenue/EBITDA/Net income growth YoY, CAGR D/E, Net debt/EBITDA, Interest coverage NH có CAR, NIM, NPL, LDR, CASA thay thế một số chỉ tiêu CT thông thường. BH có Combined Ratio, Loss Ratio, Solvency. AI tự nhận diện loại doanh nghiệp và chọn nhóm phù hợp. ## TTM (Trailing Twelve Months) là gì? [#ttm-trailing-twelve-months-là-gì] **TTM** = lũy kế 4 quý gần nhất, giúp loại bỏ hiệu ứng mùa vụ và phản ánh hiệu quả kinh doanh 12 tháng gần nhất — quan trọng hơn số cả năm tài chính khi đã qua giữa năm. Ví dụ: nếu đang là Q2/2025, TTM = Q3/2024 + Q4/2024 + Q1/2025 + Q2/2025 (nếu đã công bố). * **Số dòng chảy** (doanh thu, lợi nhuận, dòng tiền): cộng 4 quý * **Số tức thời** (tài sản, nợ vay): lấy giá trị cuối kỳ mới nhất Khi hỏi "P/E của HPG là bao nhiêu?" — AI tự dùng EPS TTM thay vì EPS năm tài chính cũ. Bạn không cần nói rõ TTM. ## Lấy chỉ tiêu tổng hợp [#lấy-chỉ-tiêu-tổng-hợp] **Cho tôi xem các chỉ tiêu tài chính cơ bản của HPG: định giá, sinh lợi và sức khỏe tài chính** → fundamental_get_key_metrics, HPG — trả 7 nhóm KPI kèm TTM và so ngành **P/E, P/B và EV/EBITDA của VCB theo TTM là bao nhiêu? Định giá hiện tại đắt hay rẻ so với lịch sử?** → Nhóm valuation TTM + fundamental_get_metric_history để so với lịch sử **Cho tôi ROE và ROIC của FPT theo từng quý trong 2 năm gần nhất — xu hướng đang tăng hay giảm?** → fundamental_get_key_metrics theo quý + fundamental_get_metric_history để vẽ xu hướng ## Đọc Báo cáo Tài chính đầy đủ [#đọc-báo-cáo-tài-chính-đầy-đủ] Công cụ `fundamental_get_statement` trả về BCTC dạng cây line-item đầy đủ — CĐKT (Bảng cân đối kế toán), KQKD (Kết quả kinh doanh) và LCTT (Lưu chuyển tiền tệ): **Cho tôi xem bảng kết quả kinh doanh của MWG 4 quý gần nhất — doanh thu, lợi nhuận gộp và lợi nhuận ròng** → fundamental_get_statement, type="income", ticker="MWG", period="quarterly", limit=4 **Dòng tiền tự do (FCF) của VHM trong 5 năm gần nhất thế nào? CFO có đang bao phủ đủ capex không?** → fundamental_get_statement LCTT + tính FCF = CFO - Capex qua các năm **Cơ cấu nợ của NVL: tổng nợ, nợ ngắn hạn vs dài hạn, D/E và khả năng trả lãi?** → fundamental_get_statement CĐKT + tính leverage ratios, interest coverage từ KQKD ## Phân rã DuPont 3 nhân tố [#phân-rã-dupont-3-nhân-tố] Công cụ `fundamental_dupont` phân rã ROE thành 3 nhân tố: **Biên lợi nhuận ròng × Vòng quay tài sản × Đòn bẩy tài chính**. Biết nhân tố nào đang kéo ROE lên/xuống là chìa khóa phân tích chất lượng lợi nhuận: **Phân rã DuPont ROE của HPG trong 3 năm gần nhất — nhân tố nào đang đóng góp nhiều nhất? Có đang tăng đòn bẩy để duy trì ROE không?** → fundamental_dupont — biên LN × vòng quay × đòn bẩy, trend qua 3 năm **So sánh cấu trúc ROE giữa HPG và HSG — ai có ROE cao hơn vì lý do gì? Mô hình kinh doanh nào bền vững hơn?** → fundamental_dupont cho cả 2 mã, so biên LN (chất lượng sản phẩm) vs vòng quay (hiệu suất) vs đòn bẩy (rủi ro) ## Thẩm định Chất lượng Kế toán [#thẩm-định-chất-lượng-kế-toán] Công cụ `fundamental_quality_scan` kiểm tra **8 mục chất lượng tài chính** và phát hiện các dấu hiệu cảnh báo (red flags): * Chênh lệch CFO vs lợi nhuận kế toán (accrual quality) * Tăng trưởng doanh thu vs phải thu — phát hiện doanh thu ảo * Biến động hàng tồn kho bất thường * Chất lượng dòng tiền tự do (FCF conversion) * Phụ thuộc chi phí lãi vay (leverage stress) * Tính nhất quán biên lợi nhuận qua các quý * Cấu trúc vốn và rủi ro refinancing * Điểm tổng hợp Equity Score và Credit Score **Thẩm định chất lượng tài chính của VHM — có red flag nào về chất lượng lợi nhuận hay dòng tiền không?** → fundamental_quality_scan — 8 mục kiểm tra, điểm Equity/Credit, danh sách red flags cụ thể **Kiểm tra xem NVL có dấu hiệu gian lận kế toán hoặc che giấu nợ không — accrual quality, dòng tiền và phải thu tăng bất thường** → fundamental_quality_scan — phân tích accruals, kiểm tra Beneish M-Score pattern Ngân hàng, chứng khoán và bảo hiểm có bộ chỉ tiêu riêng (NIM/NPL cho NH, margin loan ratio cho CK, combined ratio cho BH). AI tự chọn đúng bộ chỉ tiêu theo loại doanh nghiệp. ## So sánh với doanh nghiệp cùng ngành [#so-sánh-với-doanh-nghiệp-cùng-ngành] Công cụ `fundamental_compare_peers` so sánh với **toàn bộ doanh nghiệp cùng ngành ICB** — không chỉ một vài đối thủ chọn sẵn: **So sánh HPG với các công ty cùng ngành thép về P/E, ROE và tăng trưởng doanh thu — HPG đang ở vị trí nào trong ngành?** → fundamental_compare_peers — xếp hạng + percentile toàn ngành, không chỉ vài đối thủ **Trong ngành ngân hàng, mã nào đang có P/B thấp nhất nhưng ROE cao nhất? Tìm giá trị bị bỏ qua** → fundamental_compare_peers lọc ngành Banking, sort theo P/B tăng dần và ROE giảm dần ## Lịch sử chỉ tiêu — vẽ xu hướng dài hạn [#lịch-sử-chỉ-tiêu--vẽ-xu-hướng-dài-hạn] **Vẽ xu hướng ROE của VNM từ 2016 đến nay theo từng năm — đỉnh cao nhất là khi nào? Đang phục hồi hay tiếp tục suy giảm?** → fundamental_get_metric_history, metric="roe", ticker="VNM", period="annual", limit=9 **Biên lợi nhuận ròng của MWG theo từng quý trong 3 năm gần nhất — xu hướng phục hồi có bền vững không?** → fundamental_get_metric_history, metric="net_margin", period="quarterly", limit=12 ## Prompt phân tích toàn diện (nên thử ngay) [#prompt-phân-tích-toàn-diện-nên-thử-ngay] **Phân tích toàn diện cổ phiếu HPG: 1. Chỉ tiêu tài chính cơ bản 5 năm (ROE, biên LN, FCF, đòn bẩy) 2. Phân rã DuPont — nhân tố nào đang thay đổi? 3. Thẩm định chất lượng kế toán — có red flag nào? 4. So sánh với ngành thép — HPG đang đắt hay rẻ? 5. Kết luận sơ bộ về điểm mạnh/yếu tài chính** → AI lần lượt gọi fundamental_get_key_metrics + fundamental_dupont + fundamental_quality_scan + fundamental_compare_peers, tổng hợp thành bài phân tích ## Đi sâu hơn theo loại doanh nghiệp [#đi-sâu-hơn-theo-loại-doanh-nghiệp] Bài này là nền tảng chung. Mỗi loại doanh nghiệp còn có bộ công cụ **chuyên ngành** riêng để bóc tách thuyết minh BCTC và định giá đúng bản chất — đây là phần khai thác nâng cao: * **[Bài 12 — Công ty phi tài chính](/mcp/cong-ty-thuong):** cơ cấu chi phí (đòn bẩy hoạt động), nợ vay & tái cấp vốn, vốn lưu động, doanh thu theo dòng; định giá re-rating lịch sử (P/E·P/B·P/S) và DCF với WACC tự tính theo CAPM + kịch bản. * **[Bài 13 — Ngân hàng](/mcp/ngan-hang):** chất lượng tài sản (NPL & bao phủ dự phòng), cơ cấu huy động CASA, cơ cấu thu nhập NII/CIR/PPOP. * **[Bài 14 — Chứng khoán](/mcp/chung-khoan):** danh mục tự doanh, cơ cấu doanh thu (tự doanh/margin/môi giới), tài sản khách hàng giữ hộ, và chỉ báo tâm lý thị trường toàn ngành. Bạn không cần nhớ tên công cụ — AI tự nhận diện loại doanh nghiệp (phi tài chính / ngân hàng / chứng khoán / bảo hiểm) và chọn đúng bộ chỉ tiêu. Chỉ cần hỏi tự nhiên: *"Phân tích chuyên sâu cổ phiếu VCB"*. ## Bài liên quan [#bài-liên-quan] Kết hợp phân tích tài chính với theo dõi dòng tiền thực tế của cá mập. Bóc tách chi phí, nợ vay, vốn lưu động và định giá nội tại chuyên sâu. Chuỗi đầy đủ từ kỹ thuật, danh mục đến phân tích chuyên sâu theo ngành. ### Câu hỏi thường gặp **TTM là gì trong phân tích cổ phiếu?** TTM (Trailing Twelve Months) là số liệu lũy kế 4 quý gần nhất, giúp loại bỏ hiệu ứng mùa vụ và phản ánh hiệu quả kinh doanh 12 tháng gần nhất — quan trọng hơn số cả năm tài chính khi đã qua giữa năm. Ví dụ ở Q2/2025, TTM gồm Q3/2024 + Q4/2024 + Q1/2025 + Q2/2025. Với số dòng chảy như doanh thu, lợi nhuận và dòng tiền thì cộng 4 quý; với số tức thời như tài sản và nợ vay thì lấy giá trị cuối kỳ mới nhất. FinLens MCP tự dùng EPS TTM khi được hỏi P/E nên nhà đầu tư không cần nói rõ TTM. **Làm sao để AI đọc báo cáo tài chính của một cổ phiếu Việt Nam?** Công cụ fundamental_get_statement của FinLens MCP trả về báo cáo tài chính dạng cây line-item đầy đủ, gồm bảng cân đối kế toán (CĐKT), kết quả kinh doanh (KQKD) và lưu chuyển tiền tệ (LCTT). Nhà đầu tư chỉ cần hỏi tự nhiên, ví dụ "Cho tôi xem bảng kết quả kinh doanh của MWG 4 quý gần nhất", AI sẽ gọi get_statement với type="income", period="quarterly", limit=4. Từ LCTT có thể tính dòng tiền tự do FCF = CFO − Capex qua các năm, hoặc từ CĐKT tính cơ cấu nợ ngắn hạn/dài hạn, D/E và khả năng trả lãi. **Phân rã DuPont ROE gồm những nhân tố nào?** Công cụ fundamental_dupont của FinLens MCP phân rã ROE thành 3 nhân tố: biên lợi nhuận ròng × vòng quay tài sản × đòn bẩy tài chính. Biết nhân tố nào đang kéo ROE lên hoặc xuống là chìa khóa để đánh giá chất lượng lợi nhuận, chẳng hạn phân biệt doanh nghiệp có ROE cao nhờ biên lợi nhuận với doanh nghiệp phải tăng đòn bẩy để duy trì ROE. Có thể chạy DuPont cho nhiều mã cùng lúc để so sánh cấu trúc ROE, ví dụ giữa HPG và HSG. **Làm sao kiểm tra chất lượng báo cáo tài chính và red flag của doanh nghiệp?** Công cụ fundamental_quality_scan của FinLens MCP kiểm tra 8 mục chất lượng tài chính và liệt kê các dấu hiệu cảnh báo: chênh lệch CFO với lợi nhuận kế toán, tăng trưởng doanh thu so với phải thu, biến động hàng tồn kho bất thường, chất lượng dòng tiền tự do, phụ thuộc chi phí lãi vay, tính nhất quán biên lợi nhuận qua các quý, cấu trúc vốn và rủi ro tái cấp vốn, cùng điểm tổng hợp Equity Score và Credit Score. Ngân hàng, chứng khoán và bảo hiểm được chấm bằng bộ chỉ tiêu riêng như NIM/NPL, margin loan ratio và combined ratio, do AI tự nhận diện loại doanh nghiệp. --- # Thị trường hôm nay & dòng tiền chủ động: đọc phiên bằng AI URL: https://docs.finlens.vn/mcp/phien-truc-tiep Mô tả: Cách dùng FinLens MCP để hỏi AI về thị trường hôm nay: chỉ số, độ rộng, dòng tiền chủ động, VWAP từng mã và cung-cầu đặt lệnh trong phiên. Tóm tắt: FinLens MCP có ba công cụ đọc diễn biến phiên chứng khoán Việt Nam: market_today cho toàn thị trường (chỉ số VNINDEX/VN30/HNX/UPCOM, phái sinh VN30F1M và basis, độ rộng tăng/giảm/kịch trần/kịch sàn, dòng tiền chủ động, khối ngoại, top mã kéo và đè chỉ số), stocks_session_recap dựng lại nhịp phiên một mã từ nến 1 phút (VWAP, hình dạng phiên, RSI/ATR intraday, khối lượng đã pro-rate theo thời gian phiên đã trôi), và stocks_supply_demand đọc sổ lệnh ĐẶT với hai thước đo imbalance_pct và size_diff_pct cùng các nhãn phân kỳ như hidden_supply hay hidden_absorption. Nhà đầu tư Việt Nam hỏi Claude, ChatGPT hoặc Gemini bằng tiếng Việt tự nhiên — ví dụ "thị trường hôm nay thế nào" hay "HPG đang trên hay dưới VWAP" — và AI gọi công cụ tương ứng để trả lời kèm mốc thời gian chốt dữ liệu. Bộ công cụ diễn biến phiên yêu cầu gói FinLens Premium và chỉ mô tả trạng thái phiên, không phải khuyến nghị mua bán. Sản phẩm: mcp ⏱ Đọc 14 phút · 🟠 Trung cấp · 🔧 Yêu cầu: FinLens Premium ## Ba công cụ đọc diễn biến phiên [#ba-công-cụ-đọc-diễn-biến-phiên] Khác với dữ liệu EOD (cuối phiên), hai công cụ đầu đọc **dữ liệu nến 1 phút ĐANG diễn ra** — trả lời hai câu hỏi thường gặp nhất mỗi ngày: *"Thị trường hôm nay thế nào?"* và *"Mã X phiên nay ra sao?"*. Công cụ thứ ba soi **sổ lệnh ĐẶT** của từng phiên (dữ liệu về sau \~17h) để biết lệnh to hay nhỏ đứng sau cung-cầu. Nếu thị trường đang nghỉ, công cụ tự lùi về **phiên gần nhất** và ghi rõ trạng thái. Toàn thị trường hôm nay → `market_today`. Một mã trong phiên → `stocks_session_recap`. Ai ĐẶT lệnh, lệnh to hay nhỏ, cung/cầu có bị che → `stocks_supply_demand`. Dòng tiền LŨY KẾ nhiều phiên → `flows_*` (xem [Bài 3](/mcp/dong-tien)). Xu hướng ngành trung hạn → `market_sector_strength` ([Bài 15](/mcp/suc-manh-nganh)). ## Đánh giá thị trường hôm nay [#đánh-giá-thị-trường-hôm-nay] `market_today` gộp nhiều lát cắt vào một câu trả lời, mỗi phần ghi rõ đơn vị và mốc thời gian chốt dữ liệu (`as_of`): | Khối dữ liệu | Nội dung | | ------------------------ | --------------------------------------------------------------------------------------- | | **Chỉ số** | VNINDEX/VN30/HNX/UPCOM: giá, %thay đổi, biến động sáng/chiều, vị trí trong biên độ ngày | | **Phái sinh** | VN30F1M & `basis` = F − VN30 (dương = premium, âm = discount — tâm lý phái sinh) | | **Độ rộng toàn TT** | Số mã tăng/giảm/đứng giá + **kịch trần/kịch sàn** theo từng sàn (\~1.900 mã) | | **Độ rộng kỹ thuật** | % mã trên MA20/50/200, % quá mua/quá bán (RSI) — *chỉ sàn HOSE, làm mới mỗi giờ* | | **Dòng tiền chủ động** | Ròng mua−bán chủ động của thị trường + theo ngành (xem mục dưới) | | **Khối ngoại** | Mua/bán ròng + top mã NN gom/xả | | **Biến động & đóng góp** | Top tăng/giảm mạnh + top mã KÉO/ĐÈ chỉ số (theo điểm) | **Thị trường hôm nay thế nào? VNINDEX đang tăng hay giảm, độ rộng ra sao, dòng tiền chủ động và khối ngoại đang nghiêng về đâu?** → market_today — chỉ số + breadth + active_flow + foreign trong một câu trả lời **Hôm nay mã nào kéo VNINDEX lên nhiều nhất và mã nào đè mạnh nhất? Có bao nhiêu mã kịch trần, bao nhiêu kịch sàn?** → market_today — top_contributors/top_detractors + breadth_full (ceiling/floor) **Độ rộng toàn thị trường** (tăng/giảm/trần/sàn) là số liệu LIVE trên \~1.900 mã, theo đúng phiên đang mô tả. **Độ rộng kỹ thuật** (%trên-MA, RSI quá mua/bán) chỉ tính cho *sàn HOSE* và được *làm mới mỗi giờ* — nên trong phiên nó vẫn là số của phiên hôm nay nhưng có thể trễ tới \~1 giờ so với giá hiện tại (đầu ngày, khi phiên mới chưa có dữ liệu, sẽ là phiên trước). Mỗi khối đều kèm ngày riêng, đừng gộp hai loại lại với nhau. ## Dòng tiền ròng chủ động là gì? [#dòng-tiền-ròng-chủ-động-là-gì] Đây là điểm mạnh nhất của bộ công cụ. **Mua chủ động** = lệnh khớp thẳng vào giá chào bán (bên mua sốt sắng, "quét" giá lên) = phía CẦU. **Bán chủ động** = khớp thẳng vào giá chào mua = phía CUNG. Chênh lệch `net = mua − bán` cho biết bên nào đang *chủ động* kiểm soát phiên. * **net dương** = cầu chủ động áp đảo (tiền vào quyết liệt). * **net âm** = cung chủ động áp đảo (áp lực bán quyết liệt). * Phần **"không xác định"** (vd lệnh thỏa thuận) được TÁCH RIÊNG, không tính vào net; nếu tỷ trọng > 20% thì diễn giải net thận trọng. Dòng tiền CHỦ ĐỘNG (mua-bán chủ động, 1 phiên) KHÁC dòng tiền **khối ngoại** và KHÁC **smart money lũy kế nhiều phiên** (tự doanh/tổ chức — xem [Bài 3](/mcp/dong-tien)). Đừng trả lời câu hỏi dòng tiền này bằng số của dòng tiền kia. ## Cách đọc dòng tiền — 4 lớp [#cách-đọc-dòng-tiền--4-lớp] Với mỗi cấp (thị trường / ngành / cổ phiếu), đọc theo bốn lớp: ### 1. Cường độ (intensity) [#1-cường-độ-intensity] `|net| / tổng giá trị` → **Mạnh (>10%) / Vừa (4-10%) / Yếu (\<4%)**. Cường độ Yếu nghĩa là phiên lình xình — đừng đọc quá nhiều vào một con số net nhỏ. ### 2. Hình dạng đường cong (trajectory) [#2-hình-dạng-đường-cong-trajectory] Công cụ trả `curve` = dòng tiền ròng LŨY KẾ theo mốc giờ, kèm nhãn hình dạng: | Hình dạng | Ý nghĩa | | -------------------- | --------------------------------------------------------- | | `front_loaded` | Dồn đầu phiên — quyết liệt sớm rồi chững lại | | `back_loaded` | Dồn cuối phiên / ATC — áp lực (mua hoặc bán) mạnh về cuối | | `reversal_up / down` | Đảo chiều giữa phiên (âm→dương hoặc ngược lại) | | `steady` | Đều đặn — gom/xả âm thầm suốt phiên | ### 3. Phân kỳ giá × dòng tiền (divergence) [#3-phân-kỳ-giá--dòng-tiền-divergence] So sánh dấu của net với chiều giá — lớp quan trọng nhất để phát hiện tín hiệu ẩn: * **xác nhận tăng**: net>0 & giá↑ — cầu chủ động đẩy giá, xu hướng khỏe. * **xác nhận giảm**: net\<0 & giá↓ — cung chủ động dìm giá. * **mua trên yếu**: net>0 & giá↓ — có người GOM khi giá giảm (hấp thụ, tín hiệu tích cực ẩn). * **bán trên mạnh**: net\<0 & giá↑ — có người PHÂN PHỐI khi giá tăng (cảnh báo). ### 4. Đọc từ trên xuống (top-down) [#4-đọc-từ-trên-xuống-top-down] Thị trường (ai kiểm soát phiên) → ngành (`sector_flow`: tiền vào/ra nhóm nào) → cổ phiếu (lực mua/bán cụ thể, so với ngành & VNINDEX). **Dòng tiền chủ động toàn thị trường hôm nay đang mua ròng hay bán ròng? Đường cong dồn về đầu hay cuối phiên, và có phân kỳ với chỉ số không?** → market_today active_flow — net, curve, trajectory, divergence **Hôm nay dòng tiền chủ động chảy vào những ngành nào mạnh nhất, rút khỏi ngành nào? Cường độ ra sao?** → market_today sector_flow — top ngành theo |net| kèm intensity ## Diễn biến một cổ phiếu trong phiên [#diễn-biến-một-cổ-phiếu-trong-phiên] `stocks_session_recap(ticker)` dựng lại nhịp phiên của một mã từ nến 1 phút: * **Giá & VWAP**: mở/cao/thấp/hiện tại, gap mở cửa, vị trí trong biên độ ngày, **VWAP** (giá bình quân theo khối lượng) và mã đang trên/dưới VWAP — trần/sàn kèm cờ kịch trần/sàn. * **Hình dạng phiên**: biến động 30' đầu / sáng / chiều / 15' cuối + các phút khối lượng đột biến. * **Chỉ báo intraday**: RSI/ATR trên nến 1', mức sụt sâu & bật cao nhất trong phiên. * **Dòng tiền chủ động của mã**: net/mua/bán + đường cong lũy kế + phân kỳ giá (như trên). * **Cung-cầu đặt lệnh**: tóm tắt phiên gần nhất có dữ liệu (imbalance/size\_diff + nhãn phân kỳ — xem mục dưới); trong phiên thường là số của phiên TRƯỚC vì dữ liệu về sau \~17h. * **Khối lượng**: KL lũy kế so trung bình 5 phiên — *đã PRO-RATE theo % thời gian phiên trôi qua* để so công bằng khi phiên chưa kết thúc. * **Khối ngoại & bối cảnh**: mua/bán ròng NN, RS của mã, chuỗi tăng/giảm, vị trí so MA, so với ngành & VNINDEX. Nếu mới 10h30, KL lũy kế đương nhiên thấp hơn cả ngày. Công cụ chia theo % thời gian đã trôi (`vol_vs_ma5_prorated_pct`) để trả lời đúng câu "hôm nay giao dịch có sôi động bất thường không?" ngay giữa phiên. **HPG phiên nay diễn biến thế nào? Đang trên hay dưới VWAP, dòng tiền chủ động mua hay bán ròng, khối lượng có bất thường so với trung bình không?** → stocks_session_recap HPG — price_action + active_flow + volume (pro-rated) **Cổ phiếu FPT hôm nay giá giảm nhưng có ai đang gom không? Dòng tiền chủ động và diễn biến 15 phút cuối cho thấy điều gì?** → session_recap — divergence 'mua_tren_yeu' + shape last_15m ## Cung-cầu đặt lệnh — lệnh to hay nhỏ đứng sau? [#cung-cầu-đặt-lệnh--lệnh-to-hay-nhỏ-đứng-sau] `stocks_supply_demand(ticker, days)` đọc một lớp dữ liệu KHÁC hẳn mọi thứ ở trên: **lệnh ĐẶT vào sổ** — tức Ý ĐỊNH mua/bán của thị trường — chứ không phải lệnh đã khớp. Dòng tiền chủ động cho biết ai *hành động* quyết liệt; cung-cầu đặt lệnh cho biết ai đang *xếp hàng* và xếp bằng lệnh cỡ nào. Mỗi phiên có hai thước đo, đều chạy trong khung ±100: | Thước đo | Trả lời câu hỏi | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `imbalance_pct` | **Bên nào nhiều hàng hơn?** (KL mua − KL bán) / tổng KL đặt. Dương = cầu áp đảo về LƯỢNG; âm = cung áp đảo. Trong khoảng ±10 coi là cân bằng. | | `size_diff_pct` | **Ai đứng sau?** So KL trung bình MỖI LỆNH mua vs bán. Dương = lệnh mua to hơn ("tay to" phía cầu); âm = lệnh bán to hơn. Kèm `avg_buy_size`/`avg_sell_size` (CP/lệnh) để thấy con số tuyệt đối. | Cách nhớ nhanh: **lượng đặt = "bao nhiêu hàng", quy mô lệnh = "ai đứng sau"**. Tín hiệu đắt giá nhất là khi hai lớp này *nói ngược nhau* — công cụ tự gắn nhãn phân kỳ cho từng phiên và flag các phiên đáng chú ý: | Nhãn phân kỳ | Ý nghĩa | | ---------------------- | ------------------------------------------------------------------------------------------------ | | `hidden_supply` | KL đặt gần cân bằng nhưng lệnh BÁN to hơn hẳn — áp lực cung thật bị che sau các lệnh mua nhỏ lẻ. | | `hidden_demand` | KL đặt gần cân bằng nhưng lệnh MUA to hơn hẳn — cầu tay to đứng sau các lệnh nhỏ lẻ bán. | | `hidden_absorption` | Cung áp đảo về LƯỢNG nhưng lệnh MUA to hơn — dấu hiệu tay to hấp thụ hàng. | | `hidden_distribution` | Cầu áp đảo về LƯỢNG nhưng lệnh BÁN to hơn — dấu hiệu tay to phân phối cho nhỏ lẻ. | | `aligned_accumulation` | Cầu áp đảo cả lượng lẫn quy mô lệnh — hai lớp đồng thuận gom. | | `aligned_distribution` | Cung áp đảo cả lượng lẫn quy mô lệnh — hai lớp đồng thuận xả. | Một phiên HPG có `imbalance_pct = +0.8` (lượng đặt mua/bán gần như cân bằng) nhưng `size_diff_pct = −44`: lệnh mua trung bình \~1.900 CP trong khi lệnh bán trung bình \~4.900 CP — tức mua là nhỏ lẻ rải rác, còn bán là các lệnh to gấp 2,5 lần. Bề mặt "cân bằng" nhưng **cung thật sự đang bị che** (`hidden_supply`). Ngoài chuỗi theo phiên (`days` tối đa 250), công cụ trả phần **tóm tắt**: imbalance/size\_diff trung bình, chuỗi phiên liên tiếp nghiêng một bên (streak), số phiên phân kỳ — và **flags** tự động khi một nhãn phân kỳ lặp lại nhiều phiên gần nhất. **(1)** Lệnh ĐẶT ≠ lệnh KHỚP — lệnh đặt có thể bị hủy, nên đây là thước đo ý định, hãy đối chiếu với dòng tiền chủ động (lệnh đã khớp) trước khi kết luận. **(2)** Dữ liệu về SAU phiên (\~17h) — trong giờ giao dịch, số mới nhất là của phiên TRƯỚC; phiên đang nạp dở được tự động loại. **(3)** `size_diff_pct = null` nghĩa là nguồn mất dữ liệu SỐ LỆNH phiên đó, KHÔNG phải "cân bằng". Không có dữ liệu cho phái sinh/chứng quyền. **Cung-cầu đặt lệnh của HPG 20 phiên gần đây thế nào? Bên nào áp đảo, lệnh to hay nhỏ, có phiên nào cung/cầu bị che không?** → stocks_supply_demand HPG — imbalance/size_diff + nhãn phân kỳ + flags **FPT hôm nay giá tăng nhưng tôi nghi có phân phối. Kiểm tra giúp tôi: dòng tiền chủ động trong phiên và cung-cầu đặt lệnh các phiên gần nhất có xác nhận nghi ngờ đó không?** → stocks_session_recap (lệnh khớp) + stocks_supply_demand (lệnh đặt) — hai lớp bằng chứng độc lập ## Trạng thái phiên & độ tươi dữ liệu [#trạng-thái-phiên--độ-tươi-dữ-liệu] Cả hai công cụ luôn kèm `session_status` và `as_of` (mốc nến 1' cuối) để bạn biết số liệu tính đến khi nào: * **đang giao dịch** — dữ liệu cập nhật theo phút. * **nghỉ trưa** — dữ liệu chốt đến 11:30 (nhận diện theo đồng hồ, không phải "thị trường đứng im"). * **đã đóng cửa** — sau ATC, hoặc đang mô tả phiên gần nhất nếu hôm nay nghỉ. Với mã không có dữ liệu nến trong phiên (\~929/1.700 mã được phủ nến 1 phút), công cụ tự động dùng số liệu EOD và ghi rõ `data_source`. ## Lưu ý quan trọng [#lưu-ý-quan-trọng] * **Đơn vị**: giá cổ phiếu = nghìn VND; chỉ số = điểm; dòng tiền/giá trị = tỷ VND. Công cụ ghi rõ trong từng trường. * **Nhóm nội** (tự doanh/tổ chức/cá nhân) cập nhật sau \~18h nên trong phiên thường chưa có (`investor_groups.available=false`). * **Không phải khuyến nghị**: đây là số liệu mô tả trạng thái phiên. Bạn tự tổng hợp và ra quyết định. Diễn biến trong phiên là quan sát định lượng theo thời gian thực. FinLens không khuyến nghị mua/bán. ## Bài liên quan [#bài-liên-quan] Dòng tiền LŨY KẾ nhiều phiên — bổ sung cho dòng tiền chủ động 1 phiên. Xu hướng ngành trung hạn — ghép với dòng tiền phiên để chọn thời điểm. Chuỗi đầy đủ từ cơ bản đến nâng cao. ### Câu hỏi thường gặp **Dòng tiền chủ động là gì?** Mua chủ động là lệnh khớp thẳng vào giá chào bán, tức bên mua sốt sắng quét giá lên, thuộc phía cầu; bán chủ động là lệnh khớp thẳng vào giá chào mua, thuộc phía cung. Chênh lệch net = mua − bán cho biết bên nào đang chủ động kiểm soát phiên: net dương là cầu chủ động áp đảo, net âm là cung chủ động áp đảo. Phần "không xác định" như lệnh thỏa thuận được tách riêng và không tính vào net; nếu tỷ trọng vượt 20% thì cần diễn giải net thận trọng. Trong FinLens MCP, công cụ market_today trả dòng tiền chủ động cấp thị trường và ngành, còn stocks_session_recap trả dòng tiền chủ động của từng mã. **Làm sao biết cổ phiếu đang bị phân phối hay được gom trong phiên?** So dấu của dòng tiền ròng chủ động với chiều giá trong phiên. Net dương nhưng giá giảm là "mua trên yếu" — có người gom khi giá xuống, tín hiệu tích cực ẩn; net âm nhưng giá tăng là "bán trên mạnh" — dấu hiệu phân phối khi giá lên. Công cụ stocks_session_recap của FinLens MCP gắn sẵn nhãn phân kỳ này cho từng mã kèm diễn biến 15 phút cuối phiên. Có thể đối chiếu thêm stocks_supply_demand để xem lệnh đặt bên nào to hơn trước khi kết luận. **imbalance_pct và size_diff_pct khác nhau thế nào?** Cả hai đều thuộc công cụ stocks_supply_demand của FinLens MCP và đều chạy trong khung ±100. imbalance_pct = (khối lượng đặt mua − khối lượng đặt bán) chia tổng khối lượng đặt, trả lời câu hỏi bên nào nhiều hàng hơn, trong khoảng ±10 coi là cân bằng; size_diff_pct so khối lượng trung bình mỗi lệnh mua với mỗi lệnh bán, trả lời câu hỏi ai đứng sau, dương nghĩa là lệnh mua to hơn. Khi hai lớp nói ngược nhau, công cụ gắn nhãn phân kỳ như hidden_supply, hidden_demand, hidden_absorption hay hidden_distribution. Lưu ý size_diff_pct = null nghĩa là nguồn mất dữ liệu số lệnh của phiên đó, không phải là cân bằng. **Dữ liệu trong phiên của FinLens MCP cập nhật lúc nào?** market_today và stocks_session_recap đọc nến 1 phút đang diễn ra và luôn kèm session_status cùng as_of để biết số liệu tính đến thời điểm nào: đang giao dịch thì cập nhật theo phút, nghỉ trưa thì chốt đến 11:30, sau ATC là đã đóng cửa. Riêng độ rộng kỹ thuật (% mã trên MA20/50/200, RSI quá mua quá bán) chỉ tính cho sàn HOSE và làm mới mỗi giờ nên có thể trễ tới khoảng 1 giờ so với giá hiện tại. Dữ liệu cung-cầu đặt lệnh của stocks_supply_demand về sau phiên khoảng 17h, nên trong giờ giao dịch số mới nhất là của phiên trước. Nhóm nhà đầu tư nội gồm tự doanh, tổ chức và cá nhân cập nhật sau khoảng 18h. --- # Quỹ đầu tư Việt Nam: tra cứu danh mục & smart money bằng AI URL: https://docs.finlens.vn/mcp/quy-dau-tu Mô tả: Dùng FinLens MCP hỏi AI về 185 quỹ đầu tư Việt Nam: danh mục nắm giữ, NAV, hiệu suất và cổ phiếu nào đang được khối quỹ gom hay xả. Tóm tắt: FinLens MCP là MCP server cho phép Claude, ChatGPT và Gemini truy vấn dữ liệu 185 quỹ đầu tư Việt Nam (quỹ mở, quỹ ETF, quỹ đóng) bằng câu hỏi tiếng Việt. Nhóm công cụ fund_* cung cấp danh mục nắm giữ theo tháng từ năm 2014, NAV theo ngày, hiệu suất 1M/3M/6M/1Y/YTD, dòng tiền vào-ra và xếp hạng quỹ. Riêng công cụ fund_stock_ownership đảo chiều dữ liệu danh mục để trả lời: một cổ phiếu đang được những quỹ nào nắm, tỷ trọng cao nhất ở quỹ nào, và khối quỹ đang gom hay xả so với tháng trước. Sản phẩm: mcp ⏱ Đọc 10 phút · 🟡 Trung cấp · 🔧 Yêu cầu: FinLens Pro ## Dữ liệu quỹ đầu tư có gì? [#dữ-liệu-quỹ-đầu-tư-có-gì] FinLens MCP theo dõi **185 quỹ đầu tư** Việt Nam qua nhóm công cụ `fund_*`, gồm cả lịch sử rất dài (danh mục theo tháng từ 2014, NAV theo ngày). Vì danh mục của các quỹ phản ánh quyết định của nhà đầu tư tổ chức, đây chính là góc nhìn **"smart money"**. * 🏦 Quỹ mở * 📊 Quỹ ETF * 🔒 Quỹ đóng * 📦 Danh mục nắm giữ * 📈 NAV & hiệu suất * 💸 Dòng tiền vào/ra * 🏷 Phân bổ ngành * ⭐ Cổ phiếu → quỹ **1)** Một cổ phiếu đang được quỹ nào nắm, khối quỹ gom hay xả? **2)** Một quỹ cụ thể đang nắm gì, phân bổ ngành ra sao? **3)** Quỹ nào hiệu suất tốt nhất / đang hút tiền mạnh nhất? ## Khám phá & hồ sơ quỹ [#khám-phá--hồ-sơ-quỹ] **Liệt kê các quỹ mở cổ phiếu lớn nhất Việt Nam theo quy mô (AUM). Quỹ nào do Dragon Capital quản lý?** → fund_search(fund_type='Quỹ mở', structure='cổ phiếu', sort='aum') — kèm AUM, công ty QLQ, rating **Hồ sơ quỹ VESAF: loại quỹ, công ty quản lý, ngân hàng giám sát, chiến lược đầu tư, NAV & quy mô hiện tại, đầu tư tối thiểu là bao nhiêu?** → fund_profile('VESAF') — loại/cấu trúc/QLQ/giám sát/rating/min-invest/chiến lược + NAV & AUM mới nhất Một mã quỹ (vd `VVDIF`) có thể thuộc 2 tổ chức khác nhau. Khi mơ hồ, AI sẽ trả danh sách `organization_id` để bạn chọn đúng quỹ. ## X-quang danh mục — quỹ đang nắm gì [#x-quang-danh-mục--quỹ-đang-nắm-gì] Xem top cổ phiếu trong danh mục, tỷ trọng, **phân bổ theo ngành**, và đặc biệt là **thay đổi so với tháng trước** (mua mới / bán hết / tăng-giảm tỷ trọng) — để hiểu quỹ đang xoay chuyển thế nào. **Quỹ VFMVSF đang nắm những cổ phiếu nào nhiều nhất? Phân bổ theo ngành ra sao, tổng tỷ trọng cổ phiếu là bao nhiêu?** → fund_holdings('VFMVSF') — top mã + tỷ trọng + phân bổ ngành ICB + % cổ phiếu/danh mục **Tháng gần nhất quỹ VFMVSF đã mua mới hoặc bán hết cổ phiếu nào, tăng/giảm tỷ trọng mã nào mạnh nhất?** → fund_holdings — phần "thay đổi vs kỳ trước": new / exit / up / down theo điểm % ## Hiệu suất & dòng tiền [#hiệu-suất--dòng-tiền] **Quỹ VESAF có hiệu suất NAV thế nào 1 tháng / 3 tháng / 1 năm / từ đầu năm? Dòng tiền gần đây đang vào hay ra?** → fund_performance('VESAF') — return 1M/3M/6M/1Y/YTD + dòng tiền ròng (+ vào, − ra) **Top quỹ cổ phiếu có hiệu suất tốt nhất 1 năm qua? Và quỹ nào đang hút tiền mạnh nhất 3 tháng gần đây?** → fund_rank(metric='return'/'flow', period, fund_type) — xếp theo hiệu suất, dòng tiền hoặc quy mô Dòng tiền vào/ra các quỹ cổ phiếu là chỉ báo tâm lý sớm: tiền vào ròng mạnh thường đi kèm giai đoạn lạc quan, rút ròng mạnh báo hiệu thận trọng. ## Cổ phiếu → Quỹ nắm giữ (Smart Money) [#cổ-phiếu--quỹ-nắm-giữ-smart-money] Đây là công cụ đắt giá nhất: đảo chiều dữ liệu danh mục để hỏi **một cổ phiếu đang được quỹ nào nắm**, tỷ trọng bao nhiêu, và khối quỹ đang **GOM hay XẢ** so với tháng trước — thước đo niềm tin của nhà đầu tư tổ chức. **Cổ phiếu HPG đang được những quỹ nào nắm giữ, tỷ trọng cao nhất ở quỹ nào? Khối quỹ đang gom thêm hay bán ra so với tháng trước?** → fund_stock_ownership('HPG') — số quỹ nắm, top quỹ + tỷ trọng, xu hướng GOM/XẢ (số quỹ tăng vs giảm) **So sánh mức độ được quỹ ưa thích giữa VHM và NVL — mã nào được nhiều quỹ nắm hơn và khối quỹ đang nghiêng về mã nào?** → fund_stock_ownership('VHM') vs ('NVL') — số quỹ, tổng tỷ trọng, xu hướng gom/xả ## Kết hợp với phân tích cổ phiếu [#kết-hợp-với-phân-tích-cổ-phiếu] Sức mạnh thật sự là khi ghép tín hiệu quỹ với cơ bản, dòng tiền và vĩ mô: **Đánh giá HPG đa chiều: 1. Khối quỹ đang gom hay xả HPG (smart money)? 2. Dòng tiền khối ngoại & tự doanh gần đây 3. Cơ bản: ROE, biên lợi nhuận, định giá 4. Yếu tố vĩ mô chi phối ngành thép** → fund_stock_ownership + flows_get_stock_flow + fundamental_get_key_metrics + fin_macro_context NAV / AUM / dòng tiền / đầu tư tối thiểu = **VND**; tỷ trọng & hiệu suất = **%**. Danh mục nắm giữ là ảnh chụp **cuối tháng** (có độ trễ), NAV theo ngày. Tín hiệu quỹ là tham khảo, không phải khuyến nghị đầu tư. ## Bài liên quan [#bài-liên-quan] Ghép tín hiệu quỹ với dòng tiền khối ngoại & tự doanh. Khung vĩ mô top-down trước khi soi từng cổ phiếu/quỹ. Kết hợp niềm tin tổ chức với cơ bản từng cổ phiếu. ### Câu hỏi thường gặp **Làm sao biết cổ phiếu HPG đang được quỹ nào nắm giữ?** Công cụ fund_stock_ownership của FinLens MCP trả lời trực tiếp câu hỏi này: đưa mã cổ phiếu như HPG, AI sẽ cho biết có bao nhiêu quỹ đang nắm, những quỹ có tỷ trọng cao nhất, và xu hướng GOM hay XẢ dựa trên số quỹ tăng so với số quỹ giảm tỷ trọng. Dữ liệu danh mục quỹ là ảnh chụp cuối tháng nên có độ trễ. Tín hiệu quỹ chỉ mang tính tham khảo, không phải khuyến nghị đầu tư. **FinLens MCP theo dõi bao nhiêu quỹ đầu tư Việt Nam?** FinLens MCP theo dõi 185 quỹ đầu tư Việt Nam gồm quỹ mở, quỹ ETF và quỹ đóng thông qua nhóm công cụ fund_*. Dữ liệu gồm danh mục nắm giữ theo tháng từ năm 2014 và NAV theo ngày. Có thể lọc quỹ theo loại, cấu trúc và quy mô AUM bằng fund_search. Tính năng quỹ đầu tư yêu cầu gói FinLens Pro. **Quỹ mở nào có hiệu suất tốt nhất và đang hút tiền mạnh nhất?** Công cụ fund_rank của FinLens MCP xếp hạng quỹ theo hiệu suất, dòng tiền hoặc quy mô, có thể lọc theo loại quỹ và khoảng thời gian. Với từng quỹ cụ thể, fund_performance trả về hiệu suất NAV các kỳ 1M, 3M, 6M, 1Y, YTD kèm dòng tiền ròng, trong đó dấu cộng là tiền vào và dấu trừ là tiền ra. Dòng tiền vào ròng mạnh ở nhóm quỹ cổ phiếu thường đi kèm giai đoạn lạc quan của thị trường. **Xem danh mục và phân bổ ngành của một quỹ đầu tư như thế nào?** Công cụ fund_holdings của FinLens MCP trả về top cổ phiếu trong danh mục kèm tỷ trọng, phân bổ theo ngành ICB, tỷ lệ cổ phiếu trên tổng danh mục, và phần thay đổi so với kỳ trước gồm mã mua mới, mã bán hết, mã tăng hoặc giảm tỷ trọng mạnh nhất. Thông tin hồ sơ quỹ như loại quỹ, công ty quản lý, ngân hàng giám sát, chiến lược đầu tư và mức đầu tư tối thiểu lấy qua fund_profile. NAV, AUM, dòng tiền và mức đầu tư tối thiểu tính bằng VND. --- # Sức mạnh ngành và RS: tìm cổ phiếu dẫn dắt bằng AI URL: https://docs.finlens.vn/mcp/suc-manh-nganh Mô tả: Xếp hạng sức mạnh RS của 19 ngành cấp 2 và ~78 ngành cấp 4, phát hiện dẫn dắt hẹp qua độ phân kỳ breadth và lọc cổ phiếu leader bằng câu hỏi tiếng Việt. Tóm tắt: FinLens MCP xếp hạng sức mạnh tương đối (RS) của 19 ngành cấp 2 và khoảng 78 ngành cấp 4 trên thị trường chứng khoán Việt Nam qua công cụ `market_sector_strength`, trả về sector_rs (momentum chỉ số) và breadth_rs (trung bình RS các mã thành viên) trên thang percentile 1–100. Độ chênh giữa hai con số cho biết ngành có đang "dẫn dắt hẹp" hay không, tức vài mã vốn hóa lớn kéo chỉ số lên trong khi đa số cổ phiếu trong ngành vẫn yếu. Bốn bộ lọc RS của `signals_screen` (min_rs_rating, min_industry_rs, min_rs_vs_industry, min_sector_rs) giúp nhà đầu tư Việt Nam tìm cổ phiếu leader trong ngành đang trend theo phương pháp O'Neil bằng câu hỏi tiếng Việt gửi cho Claude, ChatGPT hoặc Gemini. Sản phẩm: mcp ⏱ Đọc 11 phút · 🟠 Trung cấp · 🔧 Yêu cầu: FinLens Premium ## RS là gì và vì sao quan trọng? [#rs-là-gì-và-vì-sao-quan-trọng] **RS (Relative Strength — sức mạnh tương đối)** đo động lượng giá của một cổ phiếu hay một ngành *so với toàn bộ thị trường*, rồi quy về thang **percentile 1–100**: RS 90 nghĩa là mạnh hơn 90% số mã (hoặc ngành) trong cùng ngày. Đây là xương sống của phương pháp O'Neil / CANSLIM — *"chỉ mua leader trong nhóm dẫn dắt"*. FinLens tính RS theo động lượng đa khung **12 / 6 / 3 / 1 tháng** (giá đã điều chỉnh), rank-then-blend rồi percentile hóa trong rổ thanh khoản mỗi phiên. Bạn không cần tự tính — chỉ cần hỏi, AI gọi 2 công cụ: `market_sector_strength` (cấp ngành) và bộ lọc RS trong `signals_screen` (cấp cổ phiếu). ## Mô hình 3 lớp RS — mỗi lớp trả lời một câu hỏi [#mô-hình-3-lớp-rs--mỗi-lớp-trả-lời-một-câu-hỏi] Với một cổ phiếu, có ba câu hỏi khác nhau và FinLens tách bạch từng lớp: | Chỉ số | Trả lời câu hỏi | Cách đọc | | ----------------------------------- | --------------------------------------------------------------------------- | ---------------------------------- | | `rs_rating` | Bản thân MÃ này có mạnh không? (động lượng giá của mã) | 1–100, càng cao càng mạnh | | `industry_rs` *(breadth)* | Các mã TRONG ngành có mạnh đồng đều không? (trung bình RS thành viên) | 1–100, sức khỏe "rộng" của ngành | | `sector_rs` *(momentum)* | CHỈ SỐ ngành (cap-weight) có đang trend không? (bị mã vốn hóa lớn chi phối) | 1–100, động lượng "đỉnh" của ngành | | `rs_vs_industry` | Mã có phải LEADER trong nội bộ ngành không? | 1–100, xếp hạng nội bộ ngành | Tìm **mã leader (rs\_vs\_industry cao)** nằm trong **ngành đang trend (sector\_rs cao)** mà **breadth cũng khỏe (industry\_rs cao)** — hội tụ cả ba là tín hiệu mạnh nhất. ## Xếp hạng sức mạnh ngành [#xếp-hạng-sức-mạnh-ngành] `market_sector_strength(level=2)` xếp hạng **19 ngành lớn**; `level=4` xếp hạng **\~78 ngành chi tiết**. Hai cấp là **hai bảng xếp hạng riêng biệt** — không so RS cấp 2 với cấp 4. **Xếp hạng các ngành cấp 2 theo sức mạnh RS hiện tại — top 5 ngành đang dẫn dắt thị trường là gì, kèm hiệu suất 12 tháng?** → market_sector_strength level=2 — trả sector_rs 1-100 + r12 (return 12 tháng) **Trong nhóm Bất động sản, các phân ngành cấp 4 nào đang mạnh nhất theo RS? Ngành nào momentum yếu đi?** → market_sector_strength level=4 — lọc quanh nhóm BĐS, đọc sector_rs + breadth_rs ## "Dẫn dắt hẹp" — đọc độ phân kỳ để tránh bẫy [#dẫn-dắt-hẹp--đọc-độ-phân-kỳ-để-tránh-bẫy] Đây là giá trị lớn nhất của công cụ. Ở cấp 4, mỗi ngành có **hai con số**: `sector_rs` (momentum của chỉ số, bị mã vốn hóa lớn chi phối) và `breadth_rs` (trung bình RS các mã thành viên). Độ chênh `divergence = sector_rs − breadth_rs`: * **Divergence dương lớn** = **dẫn dắt hẹp**: vài mega-cap kéo chỉ số ngành lên trong khi đa số mã trong ngành yếu. Ví dụ Bất động sản: momentum \~95 nhưng breadth \~30 — chủ yếu do VIC/VHM. Trend "trên giấy" nhưng dễ gãy, đừng mua đại trà cả ngành. * **Divergence gần 0 hoặc âm** = ngành khỏe đồng đều, sóng lan rộng — an toàn hơn để chọn mã. Một ngành `sector_rs=95` nhưng `breadth_rs=30` (divergence +65) chỉ có nghĩa *chỉ số* ngành mạnh — phần lớn cổ phiếu trong ngành vẫn yếu. Luôn đọc cả hai con số trước khi kết luận "ngành X đang khỏe". **Ngành nào có momentum chỉ số cao nhưng breadth yếu (dẫn dắt hẹp)? Đây là những ngành cần thận trọng khi chọn mã đại trà đúng không?** → market_sector_strength level=4 — so sánh sector_rs vs breadth_rs, đọc divergence ## Lọc leader trong ngành mạnh [#lọc-leader-trong-ngành-mạnh] Sau khi biết ngành nào trend, dùng **4 bộ lọc RS mới của `signals_screen`** để tìm cổ phiếu — kết quả trả kèm cả 4 giá trị RS của từng mã: | Tham số | Ý nghĩa | | -------------------- | -------------------------------------------------------------------- | | `min_rs_rating` | RS tối thiểu của mã (vd 80 = chỉ giữ mã mạnh hơn 80% rổ thanh khoản) | | `min_industry_rs` | Chỉ giữ mã thuộc ngành có breadth mạnh (ngành khỏe đồng đều) | | `min_rs_vs_industry` | Lọc LEADER — mã xếp hạng cao trong nội bộ ngành của nó | | `min_sector_rs` | Chỉ giữ mã thuộc ngành có momentum chỉ số mạnh (ngành đang trend) | **Tìm cổ phiếu vừa là leader trong ngành (RS nội bộ ngành ≥ 80) vừa thuộc ngành có momentum mạnh (sector RS ≥ 70), thanh khoản trên 10 tỷ/ngày — xếp theo sức mạnh** → signals_screen: min_rs_vs_industry=80, min_sector_rs=70, min_avg_value_bil=10 **Trong các mã có RS ≥ 85 và thuộc ngành breadth khỏe (industry RS ≥ 70), mã nào vừa có giá cắt lên MA20 trong 3 phiên gần nhất?** → signals_screen: min_rs_rating=85 + min_industry_rs=70 + rule kỹ thuật price cross MA20 Cần ≥ 252 phiên lịch sử (\~1 năm) mới đủ dữ liệu tính RS. Mã IPO dưới 1 năm sẽ không có RS và bị loại khi bạn bật bất kỳ bộ lọc RS nào — đúng thiết kế, tránh so sánh khập khiễng. ## Quy trình luân chuyển hoàn chỉnh (top-down) [#quy-trình-luân-chuyển-hoàn-chỉnh-top-down] Ghép các bước lại thành một luồng O'Neil từ ngành xuống cổ phiếu — bạn chỉ cần mô tả, AI sẽ tự nối chuỗi công cụ: 1. **Chọn ngành**: `market_sector_strength(level=4)` → ngành momentum mạnh + breadth khỏe (divergence thấp). 2. **Tìm leader**: `signals_screen(icb_code=, min_rs_vs_industry=80)` → cổ phiếu dẫn dắt trong ngành đó. 3. **Kiểm chứng cơ bản**: `fundamental_compare_peers` / `fundamental_quality_scan` → nền tảng có tương xứng với giá không. 4. **Xác nhận dòng tiền**: `flows_sector_flow` → tiền lớn có thực sự chảy vào ngành không. 5. **Góc nhìn phân tích**: `research_list_reports(scope=industry)` → báo cáo ngành từ CTCK. **Ngành cấp 4 nào đang mạnh nhất mà breadth cũng khỏe? Trong ngành đó, tìm 3 mã leader RS cao nhất, kiểm tra ROE và định giá so với ngành, rồi cho biết dòng tiền có đang vào ngành không.** → market_sector_strength → signals_screen → fundamental_compare_peers → flows_sector_flow ## Lưu ý khi đọc số RS [#lưu-ý-khi-đọc-số-rs] * **Thang 1–100**: mọi RS đều là percentile, 100 = mạnh nhất. So sánh trong *cùng ngày* và *cùng pool*. * **Cấp 2 ≠ cấp 4**: hai pool xếp hạng riêng (19 ngành vs \~78 ngành). Không nói "ngành cấp 4 RS 90 mạnh hơn ngành cấp 2 RS 85". * **Thô ở cấp 2**: chỉ 19 ngành nên RS cấp 2 nhảy bậc; công cụ trả kèm `sector_rs_score` (0–1) để sắp xếp mịn hơn khi cần. * **RS là động lượng quá khứ**, không phải dự đoán. Cao có thể nghĩa "đã chạy xa" — luôn ghép với cơ bản, dòng tiền và vùng giá. Sức mạnh tương đối là quan sát định lượng về động lượng. FinLens không khuyến nghị mua/bán — bạn tự tổng hợp và ra quyết định. ## Bài liên quan [#bài-liên-quan] Ghép bộ lọc RS với rule kỹ thuật rồi backtest chiến lược trên mã leader. Xác nhận ngành mạnh bằng dòng tiền thực sự đang chảy vào. Chuỗi đầy đủ từ cơ bản đến nâng cao. ### Câu hỏi thường gặp **RS rating trong chứng khoán là gì?** RS (Relative Strength — sức mạnh tương đối) đo động lượng giá của một cổ phiếu hoặc một ngành so với toàn bộ thị trường, rồi quy về thang percentile 1–100: RS 90 nghĩa là mạnh hơn 90% số mã hoặc ngành trong cùng ngày. FinLens MCP tính RS theo động lượng đa khung 12/6/3/1 tháng trên giá đã điều chỉnh, rank-then-blend rồi percentile hóa trong rổ thanh khoản mỗi phiên. Cổ phiếu cần ít nhất 252 phiên lịch sử (khoảng 1 năm) mới đủ dữ liệu tính RS, nên mã IPO dưới 1 năm sẽ không có RS. Đây là xương sống của phương pháp O'Neil / CANSLIM. **Làm sao biết ngành nào đang mạnh nhất trên thị trường chứng khoán Việt Nam?** Công cụ `market_sector_strength` của FinLens MCP xếp hạng sức mạnh RS theo hai cấp: level=2 cho 19 ngành lớn và level=4 cho khoảng 78 ngành chi tiết. Kết quả trả về sector_rs thang 1–100 kèm hiệu suất 12 tháng (r12), nên chỉ cần hỏi AI "xếp hạng các ngành cấp 2 theo sức mạnh RS hiện tại, top 5 ngành đang dẫn dắt là gì" là có ngay bảng xếp hạng. Lưu ý hai cấp là hai bảng xếp hạng riêng biệt, không so RS cấp 2 với RS cấp 4. Ở cấp 2 chỉ có 19 ngành nên RS nhảy bậc, có thể dùng thêm sector_rs_score (0–1) để sắp xếp mịn hơn. **Dẫn dắt hẹp là gì, vì sao ngành momentum cao vẫn rủi ro?** Dẫn dắt hẹp xảy ra khi một ngành có sector_rs (momentum của chỉ số ngành, bị mã vốn hóa lớn chi phối) cao hơn nhiều so với breadth_rs (trung bình RS các mã thành viên), tức divergence = sector_rs − breadth_rs dương lớn. Ví dụ ngành Bất động sản có momentum khoảng 95 nhưng breadth khoảng 30, chủ yếu do VIC/VHM kéo chỉ số lên trong khi đa số cổ phiếu trong ngành vẫn yếu — trend "trên giấy" nhưng dễ gãy, không nên mua đại trà cả ngành. Ngược lại, divergence gần 0 hoặc âm cho thấy ngành khỏe đồng đều và sóng lan rộng. Công cụ `market_sector_strength` với level=4 trả cả hai con số để so sánh. **Cách lọc cổ phiếu leader trong ngành đang mạnh bằng AI?** Công cụ `signals_screen` của FinLens MCP có bốn bộ lọc RS: min_rs_rating (RS của bản thân mã), min_industry_rs (breadth của ngành), min_rs_vs_industry (xếp hạng nội bộ ngành) và min_sector_rs (momentum chỉ số ngành). Theo phương pháp O'Neil, đặt min_rs_vs_industry=80 kết hợp min_sector_rs=70 và min_avg_value_bil=10 sẽ ra danh sách cổ phiếu leader trong ngành đang trend với thanh khoản trên 10 tỷ đồng mỗi phiên. Quy trình top-down đầy đủ là `market_sector_strength` chọn ngành, `signals_screen` tìm leader, `fundamental_compare_peers` kiểm chứng cơ bản, `flows_sector_flow` xác nhận dòng tiền. RS là động lượng quá khứ, không phải dự đoán, và FinLens MCP không đưa ra khuyến nghị mua/bán. --- # Tin tức chứng khoán AI: điểm tin sáng, sentiment theo mã URL: https://docs.finlens.vn/mcp/tin-tuc-ai Mô tả: Tin tức chứng khoán Việt Nam được FinLens MCP phân tích bằng AI mỗi ~10 phút: tóm tắt, sentiment theo tác động giá, độ quan trọng và trọng số mã liên quan. Tóm tắt: FinLens MCP chạy pipeline AI đọc tin thị trường chứng khoán Việt Nam khoảng 10 phút một lần và gắn sẵn cho mỗi bài: tóm tắt 2-4 câu tiếng Việt, sentiment theo tác động giá dự kiến (positive/negative/neutral kèm điểm −1..1), độ quan trọng từ 1 đến 5, ngành ICB cấp 2, loại tin và loại sự kiện, tầm ảnh hưởng ngắn/trung/dài hạn cùng bảng số liệu trọng yếu trích từ bài. Nhà đầu tư dùng news_market_brief để lấy điểm tin theo cửa sổ morning, today hoặc last24h; news_get_for_stock để xem tin và sentiment tổng hợp của một mã; news_get_for_sector cho tin toàn ngành; news_get_article để đọc chi tiết một bài. Mỗi mã trong một bài có trọng số liên quan từ 0 đến 1 — từ 0.5 trở lên mới được đánh dấu là mã chính, còn mức 0.2 trở xuống chỉ là tên xuất hiện trong bảng thống kê phiên. Sản phẩm: mcp ⏱ Đọc 10 phút · 🟢 Dễ · 🔧 Yêu cầu: FinLens Premium ## Khác gì so với đọc tin thường? [#khác-gì-so-với-đọc-tin-thường] Mỗi phiên có hàng trăm bài tin. Vấn đề không phải thiếu tin — mà là **lọc ra tin nào thật sự tác động giá**. FinLens chạy một pipeline AI **\~10 phút/lần**, mỗi bài được đọc và gắn sẵn: | Thuộc tính | Ý nghĩa | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------ | | **Tóm tắt** | 2–4 câu tiếng Việt — nắm nội dung không cần mở bài | | **Sentiment** | `positive` / `negative` / `neutral` + điểm −1..1 — **theo TÁC ĐỘNG GIÁ dự kiến**, không phải giọng văn bài báo | | **Độ quan trọng** | 1 (nhiễu) → 5 (ảnh hưởng toàn thị trường) | | **Mã liên quan** | Danh sách mã **kèm trọng số 0–1** và lý do liên quan | | **Ngành ICB** | Ngành cấp 2, phân biệt nguồn: hồ sơ DN (chính xác) vs suy từ ngữ cảnh | | **Loại tin / sự kiện** | DN / ngành / điểm tin / vĩ mô / quốc tế · KQKD, M\&A, cổ tức, nhân sự, pháp lý, tăng vốn, kế hoạch, dự án, số liệu vĩ mô | | **Tầm ảnh hưởng** | ngắn (\<1 tháng) · trung (1–6 tháng) · dài (>6 tháng) | | **Bảng số liệu** | Số liệu trọng yếu trích từ bài (doanh thu, lợi nhuận, %tăng trưởng, giá mục tiêu…) | Một bài viết giọng trung tính "Công ty X bị phạt thuế 5 tỷ" vẫn được gắn `negative` vì tác động giá tiêu cực. Ngược lại bài giật tít hoành tráng nhưng không có gì mới có thể là `neutral` + độ quan trọng thấp. ## Điểm tin mỗi sáng [#điểm-tin-mỗi-sáng] Công cụ được dùng nhiều nhất. Ba cửa sổ thời gian: * **morning** — từ **16:00 phiên làm việc trước đến 09:00** (trước giờ giao dịch). Thứ Hai tự động gộp trọn cuối tuần từ 16:00 thứ Sáu, không sót tin cuối tuần. * **today** — tin trong ngày tính đến hiện tại. * **last24h** — 24 giờ gần nhất. Kết quả chia sẵn các mục: **tin trọng yếu** (sắp theo độ quan trọng), **vĩ mô & chính sách**, **quốc tế**, **điểm tin phiên**, **mã được nhắc nhiều nhất** và **độ nóng theo ngành** (kèm sentiment trung bình mỗi ngành). **Điểm tin sáng nay có gì đáng chú ý? Mã nào đang được nhắc nhiều nhất và ngành nào đang nóng?** → news_market_brief(window="morning") — hoặc dùng lệnh tắt /diem_tin_thi_truong **Hôm nay có tin gì ảnh hưởng mạnh tới thị trường không? Chỉ lấy tin quan trọng từ mức 4 trở lên.** → news_market_brief(window="today", min_importance=4) Gõ `/diem_tin_thi_truong` trên Claude — bản tin được dựng thành bài đọc hoàn chỉnh tiếng Việt, tự kèm khung thời gian và miễn trừ. ## Tin theo mã & sentiment tổng hợp [#tin-theo-mã--sentiment-tổng-hợp] Khi phân tích một cổ phiếu, tin tức trả lời câu "có catalyst hay red flag gì gần đây?". Công cụ trả về danh sách bài **và** phần tổng hợp sentiment trên **toàn bộ** bài trong cửa sổ (không chỉ số bài hiển thị): số bài tích cực / tiêu cực / trung tính, điểm trung bình, và **điểm trung bình có trọng số** theo mức liên quan của mã. Điểm trung bình thường coi mọi bài như nhau. Điểm có trọng số ưu tiên bài thật sự VỀ mã đó — phản ánh đúng hơn khi mã bị lẫn trong nhiều bài chỉ nhắc thoáng qua. **HPG tháng qua có tin gì? Tin tức đang nghiêng tích cực hay tiêu cực, có sự kiện nào đáng chú ý không?** → news_get_for_stock(ticker="HPG", days=30) → drill bài quan trọng bằng news_get_article **Ngành ngân hàng tuần này có tin gì, sentiment đang nghiêng về đâu?** → news_get_for_sector — nhận cả mã ngành cấp 4 từ hồ sơ DN, tự quy về cấp 2 ## Trọng số liên quan — chìa khoá để không bị nhiễu [#trọng-số-liên-quan--chìa-khoá-để-không-bị-nhiễu] Đây là phần **quan trọng nhất** của bài. Mỗi mã trong một bài đều có **trọng số liên quan 0–1**: | Trọng số | Nghĩa là | Nên hiểu thế nào | | ----------- | --------------------------------------- | ------------------------------------------------------------------ | | `≥ 0.9` | Bài viết VỀ doanh nghiệp này | Đây là **tin của mã** — đọc kỹ | | `0.6 – 0.8` | Mã là chủ thể chính của bài | | | `0.3 – 0.5` | Được nhắc kèm thông tin | Có nội dung, nhưng bài không xoay quanh mã | | `≤ 0.2` | Chỉ xuất hiện trong thống kê / điểm tin | ⚠️ **KHÔNG phải tin của mã** — chỉ là tên trong bảng số liệu phiên | Mã có trọng số **≥ 0.5** mới được đánh dấu là "mã chính" của bài. Nhờ vậy, hỏi "HPG có tin gì?" sẽ không bị trả về hàng chục bài tổng kết phiên chỉ vô tình liệt kê HPG trong bảng thống kê. Bài tổng kết phiên nhắc hàng chục mã, mỗi mã chỉ ở mức thống kê (≤0.2) — nên theo thiết kế, loại bài này **không gán mã chính cho ai cả**. Muốn biết "mã của tôi có xuất hiện trong điểm tin phiên không?", phải hỏi rõ — AI sẽ bật chế độ quét mọi lượt nhắc. **SSI có được nhắc trong các bài điểm tin phiên tuần này không? Quét cả những bài chỉ nhắc thoáng qua.** → news_get_for_stock(ticker="SSI", days=7, include_mentions=true) ## 4 cạm bẫy khi đọc tin bằng AI [#4-cạm-bẫy-khi-đọc-tin-bằng-ai] 1. **Tin đăng lại bị đếm nhiều lần.** Mọi thống kê đếm **theo BÀI**. Một thông cáo báo chí được 8 báo đăng lại = 8 bài. Mã "được nhắc 12 lần" có thể chỉ là **2 sự kiện** thật. Luôn nhìn tiêu đề trước khi kết luận "tin dày đặc". 2. **Trọng số thấp ≠ tin xấu/tốt của mã.** Xem lại bảng trọng số ở trên — ≤0.2 chỉ là tên trong thống kê. 3. **Sentiment là đánh giá của AI** về tác động giá dự kiến, không phải sự thật đã xảy ra và không phải khuyến nghị. Dùng làm bộ lọc chú ý, không dùng làm lệnh mua/bán. 4. **Luôn nhìn mốc thời gian.** Mỗi kết quả đều kèm khung thời gian và thời điểm tin mới nhất (giờ Việt Nam). Pipeline chạy \~10 phút/lần nên tin vừa đăng vài phút có thể chưa kịp phân tích. ## Kết hợp tin tức với phân tích [#kết-hợp-tin-tức-với-phân-tích] Tin tức mạnh nhất khi làm **chất xúc tác** nối vào các nhóm công cụ khác: 1. **Từ tin → cổ phiếu**: điểm tin sáng → thấy tin quan trọng → xem chi tiết (kèm bảng số liệu) → lấy mã chính → [phân tích cơ bản](/mcp/phan-tich-co-ban) / [dòng tiền](/mcp/dong-tien) / [diễn biến phiên](/mcp/phien-truc-tiep). 2. **Từ tin → ngành**: lấy ngành của bài → tin toàn ngành + [sức mạnh ngành (RS)](/mcp/suc-manh-nganh) để xem tin có đi cùng dòng tiền không. 3. **Chiều ngược lại**: đang phân tích một mã → hỏi tin của mã để tìm catalyst / red flag giải thích biến động giá. **Điểm tin sáng nay có tin nào quan trọng về doanh nghiệp không? Lấy mã của tin đó rồi kiểm tra cơ bản, dòng tiền và sức mạnh ngành xem tin có được thị trường hưởng ứng không.** → news_market_brief → news_get_article → fundamental_* + flows_* + market_sector_strength Bản tin và sentiment là tổng hợp từ tin tức công khai bằng AI. FinLens không khuyến nghị mua/bán — bạn tự kiểm chứng và ra quyết định. ## Bài liên quan [#bài-liên-quan] Tin ra rồi — thị trường phản ứng thế nào? Đọc nhịp phiên ngay sau tin. Kiểm chứng tin bằng số liệu tài chính thật của doanh nghiệp. Chuỗi đầy đủ từ cơ bản đến nâng cao. ### Câu hỏi thường gặp **Làm sao để AI điểm tin chứng khoán mỗi sáng?** Trong FinLens MCP, công cụ news_market_brief(window="morning") gom tin từ 16:00 phiên làm việc trước đến 09:00, tức trước giờ giao dịch; riêng thứ Hai tự động gộp trọn cuối tuần từ 16:00 thứ Sáu nên không sót tin. Hai cửa sổ còn lại là today (tin trong ngày tính đến hiện tại) và last24h (24 giờ gần nhất). Kết quả chia sẵn thành tin trọng yếu sắp theo độ quan trọng, vĩ mô và chính sách, quốc tế, điểm tin phiên, mã được nhắc nhiều nhất và độ nóng theo ngành kèm sentiment trung bình mỗi ngành. Trên Claude có thể gõ lệnh tắt /diem_tin_thi_truong để nhận bản tin dựng thành bài đọc hoàn chỉnh tiếng Việt. **Sentiment tin tức của FinLens MCP nghĩa là gì?** Sentiment trong FinLens MCP được gắn theo TÁC ĐỘNG GIÁ dự kiến của thông tin, không phải theo giọng văn bài báo, với ba nhãn positive/negative/neutral kèm điểm số từ −1 đến 1. Ví dụ một bài viết giọng trung tính đưa tin doanh nghiệp bị phạt thuế vẫn được gắn negative vì tác động giá tiêu cực, ngược lại bài giật tít nhưng không có thông tin mới có thể là neutral kèm độ quan trọng thấp. Đây là đánh giá của AI về tác động dự kiến, không phải sự thật đã xảy ra và không phải khuyến nghị mua/bán — nên dùng làm bộ lọc chú ý. **Cách xem tin tức và sentiment của một mã cổ phiếu như HPG?** Gọi news_get_for_stock(ticker="HPG", days=30) trong FinLens MCP để nhận danh sách bài viết kèm phần tổng hợp sentiment tính trên toàn bộ bài trong cửa sổ thời gian, gồm số bài tích cực/tiêu cực/trung tính, điểm trung bình và điểm trung bình có trọng số theo mức liên quan của mã. Nên ưu tiên đọc điểm CÓ TRỌNG SỐ vì nó đề cao bài thật sự viết về mã đó thay vì coi mọi bài như nhau. Muốn quét cả những bài chỉ nhắc thoáng qua, thêm tham số include_mentions=true; muốn đọc chi tiết một bài quan trọng thì drill xuống bằng news_get_article. **Trọng số liên quan 0-1 của mã trong bài tin nghĩa là gì?** FinLens MCP gắn cho mỗi mã xuất hiện trong một bài tin một trọng số liên quan từ 0 đến 1: từ 0.9 trở lên nghĩa là bài viết VỀ doanh nghiệp đó, 0.6–0.8 là mã đóng vai chủ thể chính, 0.3–0.5 là được nhắc kèm thông tin, còn từ 0.2 trở xuống chỉ là tên xuất hiện trong thống kê hoặc điểm tin phiên chứ không phải tin của mã. Mã đạt trọng số từ 0.5 trở lên mới được đánh dấu là mã chính của bài, nhờ vậy câu hỏi kiểu "HPG có tin gì?" không bị trả về hàng chục bài tổng kết phiên vô tình liệt kê HPG. Theo thiết kế, bài điểm tin phiên không gán mã chính cho bất kỳ mã nào vì mọi mã trong đó đều ở mức thống kê. --- # Dữ liệu trái phiếu doanh nghiệp Việt Nam hỏi bằng AI URL: https://docs.finlens.vn/mcp/trai-phieu Mô tả: Tra cứu trái phiếu doanh nghiệp Việt Nam trên HNX bằng Claude hoặc ChatGPT: lịch đáo hạn, dư nợ theo ngành, hồ sơ tổ chức phát hành và trái phiếu chuyển đổi. Tóm tắt: FinLens MCP có 11 công cụ đọc thị trường trái phiếu doanh nghiệp Việt Nam niêm yết trên HNX, cho phép hỏi Claude, ChatGPT hoặc Gemini bằng tiếng Việt tự nhiên. Nhóm công cụ gồm bond_search tìm trái phiếu theo tổ chức phát hành, ngành, lãi suất và kỳ đáo hạn; bond_maturity_wall dựng lịch đáo hạn để đo áp lực trả nợ theo thời gian và theo ngành; bond_sector_debt đo mức tập trung dư nợ từng ngành; bond_issuer_profile mở hồ sơ một tổ chức phát hành kèm cầu nối sang cổ phiếu niêm yết của chính doanh nghiệp đó; và bond_convertible đọc điều khoản trái phiếu chuyển đổi cùng mức pha loãng tiềm năng. Đây là mảng dữ liệu ít nguồn công khai nhất trên thị trường tài chính Việt Nam. Sản phẩm: mcp Trái phiếu doanh nghiệp là mảng dữ liệu **ít nguồn công khai nhất** trên thị trường tài chính Việt Nam. FinLens MCP có 11 công cụ đọc dữ liệu trái phiếu doanh nghiệp niêm yết trên HNX — bạn hỏi bằng tiếng Việt, AI tự gọi công cụ và trả về số liệu thật. ## Vì sao nhà đầu tư cổ phiếu cũng cần đọc trái phiếu [#vì-sao-nhà-đầu-tư-cổ-phiếu-cũng-cần-đọc-trái-phiếu] Áp lực đáo hạn trái phiếu đè thẳng lên dòng tiền và bảng cân đối của doanh nghiệp — thứ quyết định giá cổ phiếu. Công cụ `bond_issuer_profile` có sẵn cầu nối từ tổ chức phát hành sang **cổ phiếu niêm yết** của chính doanh nghiệp đó, nên bạn soi được cả hai phía trong một câu hỏi. ## Tra cứu trái phiếu [#tra-cứu-trái-phiếu] **Tìm trái phiếu doanh nghiệp ngành bất động sản có lãi suất trên 10% và đáo hạn trong năm nay** → `bond_search` : lọc theo ngành, lãi suất coupon, kỳ đáo hạn **Cho tôi chi tiết trái phiếu này: kỳ hạn, lãi suất, tài sản đảm bảo và lịch trả nợ** → `bond_get` : kỳ hạn, lãi suất, tài sản đảm bảo, lịch trả ## Áp lực đáo hạn [#áp-lực-đáo-hạn] **Những doanh nghiệp nào có trái phiếu đáo hạn trong 6 tháng tới? Áp lực dồn vào ngành nào?** → `bond_maturity_wall` : lịch đáo hạn theo thời gian và theo ngành **Ngành nào đang gánh nhiều dư nợ trái phiếu nhất hiện nay?** → `bond_sector_debt` : dư nợ theo ngành, mức tập trung rủi ro ## Tổ chức phát hành [#tổ-chức-phát-hành] **Doanh nghiệp này đã phát hành những lô trái phiếu nào, tổng dư nợ bao nhiêu, và cổ phiếu niêm yết tương ứng là mã nào?** → `bond_issuer_profile` : hồ sơ phát hành + cầu nối sang cổ phiếu niêm yết **Liệt kê các tổ chức phát hành trái phiếu kèm dư nợ, sắp xếp từ lớn xuống nhỏ** → `bond_list_issuers` : danh sách tổ chức phát hành + dư nợ ## Toàn cảnh thị trường [#toàn-cảnh-thị-trường] **Thị trường trái phiếu doanh nghiệp hiện nay quy mô bao nhiêu, phát hành và đáo hạn thế nào?** → `bond_market_overview` : quy mô, phát hành, đáo hạn **Xu hướng phát hành trái phiếu thay đổi ra sao, mặt bằng lãi suất coupon đang ở đâu?** → `bond_issuance_trend` \+ `bond_coupon_landscape` ## Trái phiếu chuyển đổi [#trái-phiếu-chuyển-đổi] **Trái phiếu chuyển đổi của doanh nghiệp này có điều khoản gì, pha loãng tiềm năng bao nhiêu phần trăm?** → `bond_convertible` : điều khoản chuyển đổi và mức pha loãng tiềm năng Các công cụ trái phiếu chỉ trả về dữ liệu và mô tả trạng thái thị trường. Chúng không đưa ra khuyến nghị mua bán, và không thay thế việc đọc bản cáo bạch cùng điều khoản phát hành gốc. ## Bảng công cụ trái phiếu [#bảng-công-cụ-trái-phiếu] | Công cụ | Chức năng | | ----------------------- | -------------------------------------------------------------------- | | `bond_search` | Tìm trái phiếu theo tổ chức phát hành, ngành, lãi suất, đáo hạn | | `bond_get` | Chi tiết một trái phiếu: kỳ hạn, lãi suất, tài sản đảm bảo, lịch trả | | `bond_list_issuers` | Danh sách tổ chức phát hành kèm dư nợ | | `bond_issuer_profile` | Hồ sơ phát hành một tổ chức + cầu nối sang cổ phiếu niêm yết | | `bond_market_overview` | Tổng quan thị trường: quy mô, phát hành, đáo hạn | | `bond_maturity_wall` | Lịch đáo hạn — áp lực trả nợ theo thời gian và ngành | | `bond_sector_debt` | Dư nợ theo ngành — mức tập trung rủi ro | | `bond_issuance_trend` | Xu hướng phát hành theo thời gian | | `bond_coupon_landscape` | Phân bố lãi suất coupon trên thị trường | | `bond_convertible` | Trái phiếu chuyển đổi — điều khoản và pha loãng tiềm năng | | `bond_lookup_column` | Tra cứu các trường dữ liệu trái phiếu khả dụng | ## Bài liên quan [#bài-liên-quan] Cơ cấu nợ vay và áp lực tái cấp vốn nhìn từ báo cáo tài chính. Lãi suất, tín dụng và điều hành thị trường mở — bối cảnh chi phí vốn. Tra cứu toàn bộ công cụ FinLens MCP theo 12 nhóm. ### Câu hỏi thường gặp **Tra cứu trái phiếu doanh nghiệp Việt Nam ở đâu?** Dữ liệu trái phiếu doanh nghiệp niêm yết trên HNX có thể tra bằng FinLens MCP qua Claude, ChatGPT hoặc Gemini. Công cụ bond_search tìm theo tổ chức phát hành, ngành, lãi suất coupon và kỳ đáo hạn; bond_get mở chi tiết một mã trái phiếu gồm kỳ hạn, lãi suất, tài sản đảm bảo và lịch trả nợ; bond_list_issuers liệt kê tổ chức phát hành kèm dư nợ. Đây là mảng dữ liệu có ít nguồn công khai ở Việt Nam. **Làm sao biết doanh nghiệp nào sắp đáo hạn trái phiếu?** Công cụ bond_maturity_wall của FinLens MCP dựng lịch đáo hạn toàn thị trường — thường gọi là maturity wall — cho thấy áp lực trả nợ dồn vào những khoảng thời gian nào và tập trung ở ngành nào. Kết hợp bond_issuer_profile để xem hồ sơ phát hành của từng tổ chức. Chỉ cần hỏi trợ lý AI bằng tiếng Việt, ví dụ những doanh nghiệp nào có trái phiếu đáo hạn trong sáu tháng tới. **Trái phiếu doanh nghiệp có liên quan gì tới cổ phiếu của chính doanh nghiệp đó?** Công cụ bond_issuer_profile có cầu nối từ tổ chức phát hành trái phiếu sang cổ phiếu niêm yết của cùng doanh nghiệp. Nhờ vậy nhà đầu tư cổ phiếu đánh giá được áp lực trả nợ trái phiếu đang đè lên bảng cân đối của doanh nghiệp mình đang nắm. Với trái phiếu chuyển đổi, bond_convertible cho biết điều khoản và mức pha loãng tiềm năng lên số cổ phiếu lưu hành. **Ngành nào đang tập trung nhiều dư nợ trái phiếu nhất?** Công cụ bond_sector_debt của FinLens MCP đo mức tập trung dư nợ trái phiếu theo từng ngành, còn bond_issuance_trend cho thấy xu hướng phát hành thay đổi theo thời gian và bond_coupon_landscape cho biết mặt bằng lãi suất coupon trên thị trường. Ba công cụ này ghép lại trả lời được câu hỏi rủi ro đang dồn ở đâu và chi phí vốn của thị trường đang ở mức nào. --- # Phân tích kinh tế vĩ mô và xuất nhập khẩu Việt Nam bằng AI URL: https://docs.finlens.vn/mcp/vi-mo Mô tả: Tra cứu CPI, IIP, FDI, GDP từ Tổng cục Thống kê và số liệu xuất nhập khẩu Hải quan theo mặt hàng bằng AI, rồi ánh xạ thẳng sang cổ phiếu ngành liên quan. Tóm tắt: FinLens MCP cho phép hỏi Claude, ChatGPT hoặc Gemini về kinh tế vĩ mô và dữ liệu tài chính Việt Nam bằng tiếng Việt, dựa trên hai nguồn chính thức: số liệu kinh tế - xã hội hàng tháng của Tổng cục Thống kê (CPI, IIP, bán lẻ, FDI, GDP, đăng ký doanh nghiệp, vận tải, du lịch quốc tế, lao động việc làm) và dữ liệu xuất nhập khẩu chi tiết theo mặt hàng, nước đối tác, tỉnh thành của Tổng cục Hải quan. Các công cụ fin_dashboard, fin_get_series, fin_search, fin_compare, gso_trade và gso_trade_series trả về snapshot toàn cảnh theo tháng, chuỗi thời gian và so sánh giữa hai kỳ. Riêng gso_trade_stocks ánh xạ mặt hàng xuất nhập khẩu sang danh sách cổ phiếu Việt Nam tiêu biểu của ngành đó, phục vụ nhà đầu tư phân tích top-down từ vĩ mô xuống từng mã. Sản phẩm: mcp ⏱ Đọc 10 phút · 🟡 Trung cấp · 🔧 Yêu cầu: FinLens Pro ## Dữ liệu từ hai nguồn chính thức [#dữ-liệu-từ-hai-nguồn-chính-thức] FinLens MCP tổng hợp dữ liệu vĩ mô từ 2 nguồn chính thức: * **Tổng cục Thống kê (GSO)** — số liệu KT-XH công bố hàng tháng: CPI, IIP, bán lẻ, FDI, GDP, đăng ký doanh nghiệp, vận tải, du lịch… * **Tổng cục Hải quan** — dữ liệu xuất nhập khẩu chi tiết theo mặt hàng, nước đối tác và tỉnh thành — cập nhật hàng tháng Các nhóm chỉ tiêu GSO sẵn có: * 📈 CPI & Lạm phát * 🏭 IIP Công nghiệp * 🛍 Bán lẻ & Tiêu dùng * 💰 FDI Đầu tư ngoại * 📊 GDP Tăng trưởng * 🏢 Doanh nghiệp mới * 🚢 Xuất nhập khẩu * ✈️ Du lịch quốc tế * 🚛 Vận tải hàng hóa * 👷 Lao động & Việc làm ## Toàn cảnh KT-XH tháng — snapshot nhanh [#toàn-cảnh-kt-xh-tháng--snapshot-nhanh] **Tình hình kinh tế Việt Nam tháng 5/2025 thế nào? Tóm tắt tất cả chỉ tiêu chính: CPI, IIP, xuất khẩu, FDI và tiêu dùng** → fin_dashboard: tháng 5/2025 — snapshot toàn bộ chỉ tiêu chính + XNK cùng kỳ **Kinh tế Việt Nam quý 1/2025 tổng thể thế nào? Ngành nào tăng trưởng tốt, ngành nào đang khó khăn?** → fin_dashboard 3 tháng đầu năm — so sánh IIP, bán lẻ, xuất khẩu giữa các ngành ## Tra cứu chỉ tiêu cụ thể [#tra-cứu-chỉ-tiêu-cụ-thể] **CPI tháng 5/2025 tăng bao nhiêu % so với cùng kỳ? Nhóm hàng nào đóng góp nhiều nhất vào lạm phát? Lương thực thực phẩm và nhà ở tăng bao nhiêu?** → fin_get_series hoặc fin_dashboard: CPI tổng + phân nhóm — thực phẩm, nhà ở, giáo dục, y tế **Tìm dữ liệu về sản lượng thép và kim loại màu trong thống kê công nghiệp — mã chỉ tiêu và số liệu mới nhất** → fin_search: "thép kim loại" — tìm trong dữ liệu thô chưa chuẩn hoá, gợi ý mã chỉ tiêu **FDI vào tỉnh Bình Dương và Long An trong 5 tháng đầu 2025 là bao nhiêu? So sánh với cùng kỳ 2024** → gso_province_profile / gso_rank_regions: FDI theo tỉnh — Bình Dương, Long An, xếp hạng địa phương ## Xu hướng theo thời gian & So sánh kỳ [#xu-hướng-theo-thời-gian--so-sánh-kỳ] **Vẽ xu hướng CPI theo tháng trong 12 tháng gần nhất — lạm phát đang tăng hay giảm? So với mục tiêu 4.5% của Chính phủ?** → fin_get_series: CPI, 12 tháng gần nhất — trend + so với target **So sánh IIP tháng 5/2025 với tháng 5/2024 — sản xuất công nghiệp đang phục hồi hay tiếp tục yếu?** → fin_compare: IIP, kỳ 1 = T5/2025, kỳ 2 = T5/2024 — chênh lệch tuyệt đối và % ## Xuất Nhập Khẩu Hải Quan — dữ liệu chi tiết [#xuất-nhập-khẩu-hải-quan--dữ-liệu-chi-tiết] XNK cập nhật theo tháng — nhanh hơn GDP quý. Xuất khẩu tăng/giảm mạnh là chỉ báo sớm cho lợi nhuận quý của các doanh nghiệp xuất khẩu. FDI vào một ngành thường dẫn trước đầu tư vào cổ phiếu ngành đó. **Top 10 mặt hàng xuất khẩu của Việt Nam tháng 5/2025 và tăng trưởng YoY — mặt hàng nào đang bùng nổ nhất?** → gso_trade: type=export, period=T5/2025, view=commodity, top=10 **Việt Nam nhập khẩu nhiều nhất từ nước nào trong 2025? Trung Quốc chiếm bao nhiêu % nhập khẩu? Có xu hướng giảm phụ thuộc không?** → gso_trade: type=import, view=country — cơ cấu đối tác nhập khẩu + trend **Xuất khẩu điện tử và linh kiện điện tử Việt Nam 5 tháng đầu 2025 thế nào? Tốc độ tăng trưởng và thị trường xuất khẩu chính là đâu?** → gso_trade + gso_trade_series: "điện tử linh kiện" — trị giá, %YoY, top thị trường **Vẽ chuỗi xuất khẩu dệt may 12 tháng gần nhất — có đang phục hồi sau giai đoạn giảm không? Thị trường Mỹ và EU chiếm tỷ trọng thế nào?** → gso_trade_series: "dệt may", 12 tháng — trend theo tháng + cơ cấu thị trường ## XNK → Cổ phiếu ngành — cầu nối độc đáo [#xnk--cổ-phiếu-ngành--cầu-nối-độc-đáo] Công cụ `gso_trade_stocks` ánh xạ trực tiếp từ mặt hàng XNK sang danh sách cổ phiếu VN tiêu biểu của ngành đó: **Xuất khẩu thủy sản tháng 5/2025 tăng mạnh — cổ phiếu ngành thủy sản nào hưởng lợi trực tiếp? Trị giá XNK lũy kế và %YoY của ngành là bao nhiêu?** → gso_trade_stocks: "thủy sản" — ánh xạ sang ANV, CMX, HVG, IDI, VHC... kèm XNK mới nhất **Dựa trên số liệu xuất khẩu gỗ và sản phẩm gỗ 2025, triển vọng nhóm cổ phiếu gỗ như thế nào? Thị trường Mỹ đang chiếm tỷ trọng bao nhiêu?** → gso_trade "gỗ" → gso_trade_stocks (cổ phiếu tiêu biểu) → so với XNK trend ## Tích hợp phân tích vĩ mô vào quyết định đầu tư [#tích-hợp-phân-tích-vĩ-mô-vào-quyết-định-đầu-tư] **Phân tích top-down cho ngành thép Việt Nam: 1. CPI và IIP sản xuất thép 4 tháng gần nhất 2. Xuất khẩu thép và nhập khẩu nguyên liệu (quặng sắt, thép phế) 3. FDI vào ngành kim loại 4. Cổ phiếu thép nào đang hưởng lợi từ xu hướng vĩ mô? 5. So sánh với fundamental của HPG và HSG** → Kết hợp GSO + trade data + trade_stocks + fundamental_compare_peers cho bức tranh từ vĩ mô đến vi mô Số liệu GSO thường công bố 15–25 ngày sau khi tháng kết thúc. Dữ liệu đầy đủ nhất là tháng trước tháng hiện tại. FinLens tự động trả kỳ mới nhất có sẵn. ## Bài liên quan [#bài-liên-quan] Quỹ nào đang gom/xả cổ phiếu, hiệu suất & dòng tiền các quỹ. Kết hợp tín hiệu vĩ mô với dòng tiền giao dịch thực tế. Sau khi có bức tranh vĩ mô, đi sâu vào cơ bản từng cổ phiếu trong ngành. Đọc báo cáo ngành từ các CTCK để bổ sung góc nhìn chuyên nghiệp. Chuỗi đầy đủ FinLens MCP từ cơ bản đến nâng cao. ### Câu hỏi thường gặp **Tra CPI và lạm phát Việt Nam bằng AI như thế nào?** FinLens MCP cung cấp công cụ fin_get_series và fin_dashboard để lấy CPI tổng cùng CPI phân nhóm như lương thực thực phẩm, nhà ở, giáo dục, y tế theo từng tháng. Người dùng chỉ cần hỏi bằng tiếng Việt, ví dụ CPI tháng 5/2025 tăng bao nhiêu phần trăm so với cùng kỳ và nhóm hàng nào đóng góp nhiều nhất vào lạm phát. Công cụ fin_get_series còn dựng được chuỗi CPI 12 tháng gần nhất để xem lạm phát đang tăng hay giảm. **Dữ liệu xuất nhập khẩu liên quan gì đến cổ phiếu ngành?** Công cụ gso_trade_stocks của FinLens MCP ánh xạ trực tiếp từ mặt hàng xuất nhập khẩu sang danh sách cổ phiếu Việt Nam tiêu biểu của ngành đó, ví dụ mặt hàng thủy sản ánh xạ sang ANV, CMX, HVG, IDI, VHC kèm trị giá xuất nhập khẩu mới nhất và %YoY. Số liệu xuất nhập khẩu cập nhật theo tháng, nhanh hơn GDP công bố theo quý, nên thường được dùng làm chỉ báo sớm cho lợi nhuận quý của doanh nghiệp xuất khẩu. Đây là dữ liệu tham chiếu, không phải khuyến nghị đầu tư. **Số liệu Tổng cục Thống kê trên FinLens MCP trễ bao lâu?** Số liệu Tổng cục Thống kê (GSO) thường công bố 15–25 ngày sau khi tháng kết thúc, nên dữ liệu đầy đủ nhất luôn là tháng liền trước tháng hiện tại, tức độ trễ khoảng 1–2 tháng. FinLens MCP tự động trả về kỳ mới nhất có sẵn khi được hỏi. Dữ liệu xuất nhập khẩu từ Tổng cục Hải quan cũng được cập nhật theo tháng. **Có tra được FDI theo từng tỉnh không?** Có. Công cụ gso_province_profile của FinLens MCP mở hồ sơ kinh tế một tỉnh, còn gso_rank_regions xếp hạng các địa phương theo một chỉ tiêu, nhờ đó lấy được vốn FDI vào từng nơi như Bình Dương hay Long An và so sánh với cùng kỳ năm trước. Ngoài FDI, nhóm chỉ tiêu vĩ mô trên FinLens MCP còn có CPI, IIP công nghiệp, bán lẻ và tiêu dùng, GDP, đăng ký doanh nghiệp mới, vận tải hàng hóa, du lịch quốc tế và lao động việc làm. --- # Quy ước dữ liệu FinLens URL: https://docs.finlens.vn/platform Mô tả: Đơn vị giá, mã ngành ICB, quy ước thời gian và khóa API — những điều cần nắm trước khi dùng bất kỳ sản phẩm nào của FinLens. Sản phẩm: platform Các quy ước dưới đây áp dụng cho **mọi** sản phẩm FinLens: [web](/webapp), [Python SDK](/python-sdk), [MCP](/mcp) và mobile. Nắm trước sẽ tránh được phần lớn lỗi khi ghép dữ liệu từ nhiều nguồn. ## Đơn vị giá [#đơn-vị-giá] | Loại tài sản | Đơn vị | Ví dụ | | ----------------- | ---------- | ------------------------- | | Cổ phiếu, chỉ số | Nghìn đồng | `23.4` = 23.400 VND | | Chứng quyền | Đồng | `1250` = 1.250 VND | | Giá trị giao dịch | Tỷ đồng | `1234.5` = 1.234,5 tỷ VND | Khi so sánh giá chứng quyền với giá cổ phiếu cơ sở, phải quy đổi trước. Nhân giá cổ phiếu với 1.000 để đưa về đơn vị đồng. ## Giá điều chỉnh [#giá-điều-chỉnh] Toàn bộ dữ liệu giá lịch sử đã được **điều chỉnh** theo cổ tức và chia tách. Nghĩa là chuỗi giá dùng trực tiếp để tính lợi suất mà không cần xử lý thêm. ## Phân ngành [#phân-ngành] FinLens dùng chuẩn **ICB** (Industry Classification Benchmark). Các hàm thống kê theo ngành mặc định lấy ICB cấp 2. ## Chọn cách truy cập dữ liệu [#chọn-cách-truy-cập-dữ-liệu] | Bạn muốn | Dùng | | ------------------------------------------------ | ------------------------- | | Xem biểu đồ, bảng giá, bộ lọc trên trình duyệt | [FinLens Web](/webapp) | | Hỏi Claude, ChatGPT hoặc Gemini bằng tiếng Việt | [FinLens MCP](/mcp) | | Lấy dữ liệu thô về `pandas.DataFrame` để tự tính | [Python SDK](/python-sdk) | Trang này là khung nội dung khởi tạo. Các mục chi tiết (khóa API, hạn mức, mã lỗi) sẽ được bổ sung khi migrate nội dung từ các repo sản phẩm. --- # Báo cáo tài chính Python: lấy BCTC cổ phiếu Việt Nam URL: https://docs.finlens.vn/python-sdk/bao-cao-tai-chinh Mô tả: Dùng finlens lấy báo cáo tài chính doanh nghiệp niêm yết Việt Nam theo năm hoặc quý về pandas DataFrame: cân đối kế toán, kết quả kinh doanh, lưu chuyển tiền tệ. Tóm tắt: Trang mô tả nhóm `client.financials` của thư viện Python finlens — báo cáo tài chính của doanh nghiệp niêm yết Việt Nam, trả về `pandas.DataFrame`. Ba phương thức: `statement()` cho số liệu từng khoản mục, `periods()` cho biết mã nào có số liệu ở kỳ nào, và `line_items()` cho cây khoản mục của một loại hình doanh nghiệp. Chữ ký là `statement(symbols, *, kind="balance_sheet", period="annual", start_year=None, end_year=None, quarters=None, refresh=False, on_error="warn")`; `kind` nhận `balance_sheet`, `income_statement`, `cash_flow_direct`, `cash_flow_indirect`, còn `period` nhận `annual` hoặc `quarterly`. Frame luôn ở dạng long với mười hai cột `symbol`, `company_type`, `kind`, `year`, `quarter`, `period_label`, `item_id`, `line_item`, `parent_id`, `level`, `order_index`, `value`; mỗi dòng mang `company_type` của chính nó (`CT` phi tài chính, `NH` ngân hàng, `CK` chứng khoán, `BH` bảo hiểm) nên gọi nhiều mã khác loại hình trong một lời gọi là chuyện bình thường. `item_id` là mã hiển thị do máy chủ cấp: nó ổn định theo thời gian và chỉ có nghĩa trong phạm vi một `(company_type, kind)`, còn `parent_id` mang `item_id` của khoản mục cha. Cột `quarter` bằng `0` nghĩa là cả năm chứ không phải thiếu quý, và `value` tính bằng VND thô. Namespace `client.reporting` của bản 0.1.x không còn tồn tại. In English: Vietnamese listed-company financial statements — balance sheet, income statement and cash flow, annual or quarterly — as long-format pandas DataFrames. Sản phẩm: python-sdk Cân đối kế toán, kết quả kinh doanh và lưu chuyển tiền tệ của doanh nghiệp niêm yết — theo năm hoặc theo quý, trả về `pandas.DataFrame`. Ba phương thức, và chúng trả lời ba câu hỏi khác nhau: | Gọi | Trả lời câu hỏi | | -------------------------------- | ----------------------------------------- | | `client.financials.statement()` | Khoản mục này của kỳ này bằng bao nhiêu? | | `client.financials.periods()` | Mã này có số liệu ở những kỳ nào? | | `client.financials.line_items()` | Loại báo cáo này gồm những khoản mục nào? | Namespace nay tên là **`financials`**. `client.reporting` không còn tồn tại và sẽ ném `AttributeError`. Tham số cũng đổi theo, không chỉ đổi tên namespace: | 0.1.x | 1.x | | ---------------------------------- | ------------------------------------------------------------------ | | `symbol=` | `symbols` — **tham số vị trí**, mọi tham số sau nó là keyword-only | | `statement="balance"` | `kind="balance_sheet"` | | `period="year"` / `"quarter"` | `period="annual"` / `"quarterly"` | | `values_format="long"` / `"cross"` | không còn — frame **luôn** ở dạng long | | `start_year` bắt buộc | `start_year=None` là để máy chủ chọn dải thực có | ## Bốn loại hình doanh nghiệp, bốn cây khoản mục [#bốn-loại-hình-doanh-nghiệp-bốn-cây-khoản-mục] Đây là điều chi phối cả trang: **không tồn tại một "bảng cân đối kế toán" duy nhất.** Có bốn cây khác nhau, một cho mỗi loại hình doanh nghiệp, không cùng số khoản mục và không cùng tên khoản mục. | `company_type` | Loại hình | | -------------- | -------------------------- | | `CT` | Doanh nghiệp phi tài chính | | `NH` | Ngân hàng | | `CK` | Công ty chứng khoán | | `BH` | Bảo hiểm | Loại hình của từng mã do **máy chủ tra**, và nó đi kèm ngay ở cột `company_type` của mỗi dòng — bạn không phải gọi thêm gì trước, cũng không phải tự giữ một bảng tra riêng. Frame ở dạng **long** và mỗi dòng mang `company_type` của chính nó, nên ba cây khác nhau nằm chung một bảng được: ```python df = client.financials.statement("HPG,VCB,SSI") sorted(df["company_type"].unique()) # ['CK', 'CT', 'NH'] ``` Đây là mặc định chứ không phải một trường hợp đặc biệt. Bản 0.1.x bắt bạn kiểm loại hình trước mỗi lần lấy báo cáo và tự loại bỏ mã "sai loại"; ràng buộc đó là do client tự áp, không phải do dữ liệu. Loại hình thứ **năm** là `QU` (quỹ), và nó **không có báo cáo tài chính dạng cây** — đó là trạng thái vĩnh viễn của dữ liệu chứ không phải một khoảng trống tạm thời. Mã thuộc `QU` đi vào phần lỗi **theo từng mã** và không làm hỏng phần còn lại của lời gọi; xem `on_error` ở [Xử lý lỗi](/python-sdk/xu-ly-loi). ## `statement()` — số liệu từng khoản mục [#statement--số-liệu-từng-khoản-mục] ```python client.financials.statement( symbols, *, kind="balance_sheet", period="annual", start_year=None, end_year=None, quarters=None, refresh=False, on_error="warn", ) -> DataFrame ``` Chỉ `symbols` là tham số vị trí; mọi tham số còn lại là **keyword-only**. | Tham số | Kiểu | Mặc định | Nội dung | | ------------ | ---------------------------------- | ----------------- | ---------------------------------------------------------------------------------------- | | `symbols` | `SymbolsArg` | — | `"HPG"`, `"HPG,VCB"` hoặc `["HPG", "VCB"]`. Được phép trộn nhiều loại hình doanh nghiệp. | | `kind` | `StatementKind` | `"balance_sheet"` | Đúng **một** loại báo cáo. Bốn giá trị ở bảng bên dưới. | | `period` | `StatementPeriod` | `"annual"` | `"annual"` (số liệu cả năm) hoặc `"quarterly"` (số liệu quý). | | `start_year` | `int` hoặc `None` | `None` | Năm đầu của khoảng. `None` là lấy từ đầu dải thực có của từng mã. | | `end_year` | `int` hoặc `None` | `None` | Năm cuối, **tính cả chính nó**. `None` là lấy tới hết dải thực có. | | `quarters` | `str`, `Sequence[int]` hoặc `None` | `None` | Lọc theo quý: `"1,3"` hoặc `[1, 3]`. `None` nghĩa là **tất cả các quý**. | | `refresh` | `bool` | `False` | Bỏ qua bản trong cache và lấy lại từ máy chủ. | | `on_error` | `OnError` | `"warn"` | `warn` · `raise` · `ignore` — số phận của các mã lỗi trong lời gọi nhiều mã. | ### Bốn giá trị của `kind` [#bốn-giá-trị-của-kind] | Giá trị | Báo cáo | | -------------------- | ---------------------------- | | `balance_sheet` | Cân đối kế toán | | `income_statement` | Kết quả kinh doanh | | `cash_flow_direct` | Lưu chuyển tiền tệ trực tiếp | | `cash_flow_indirect` | Lưu chuyển tiền tệ gián tiếp | Tên chứ không phải số thứ tự: một con số như `3` không tự nói nó là lưu chuyển tiền tệ trực tiếp hay gián tiếp, nên mỗi người đọc phải giữ một bảng tra nằm ngoài dữ liệu — và nếu nguồn đánh số lại thì mọi truy vấn vẫn chạy, chỉ trả sai báo cáo. Công ty chứng khoán (`CK`) không lập lưu chuyển tiền tệ trực tiếp. Yêu cầu tổ hợp đó nhận một lỗi **400** — một `finlens.ValidationError` nói rõ loại hình, `kind` bạn đã hỏi, và những `kind` còn dùng được — chứ **không** phải một bảng rỗng. Phân biệt này quan trọng vì "rỗng" đã mang một nghĩa khác hẳn: *khoảng bạn hỏi hợp lệ nhưng không có dòng nào*. Dùng lại nó cho *tổ hợp này không tồn tại* là xoá mất đúng thông tin bạn cần để biết phải làm gì tiếp. ### Cột trả về [#cột-trả-về] | Cột | dtype | Nội dung | | -------------- | --------- | --------------------------------------------------------------------------------------- | | `symbol` | `string` | Mã chứng khoán, viết hoa. | | `company_type` | `string` | `CT` · `NH` · `CK` · `BH` — quyết định cây khoản mục nào áp cho dòng này. | | `kind` | `string` | Loại báo cáo của dòng. | | `year` | `int16` | Năm của kỳ. | | `quarter` | `int8` | **`0` là cả năm**, `1..4` là quý. Không bao giờ `null`. | | `period_label` | `string` | Nhãn kỳ đọc được: `"2025"` hoặc `"Q1 2025"`. | | `item_id` | `int32` | Mã hiển thị của khoản mục, chỉ có nghĩa trong phạm vi `(company_type, kind)`. | | `line_item` | `string` | Tên khoản mục theo nguồn, ví dụ `"TỔNG CỘNG TÀI SẢN"`. | | `parent_id` | `Int32` | `item_id` **của khoản mục cha**, `null` ở node gốc. | | `level` | `int8` | Độ sâu trong cây. | | `order_index` | `int32` | Thứ tự trình bày của bản báo cáo. | | `value` | `float64` | Giá trị của khoản mục, **VND thô**. `null` là *kỳ đó không có số*, không phải *bằng 0*. | Mười hai cột luôn có mặt đúng dtype **kể cả khi không có dòng nào**, nên bạn không cần bọc `if not df.empty` quanh mỗi lời gọi. `item_id` là một **mã hiển thị** do máy chủ cấp, không phải id nội bộ của nguồn: nó được cấp một lần và **không đổi theo thời gian**, nên con số bạn ghi vào notebook hôm nay vẫn trỏ đúng khoản mục ấy về sau. Đổi lại, nó chỉ có nghĩa **trong phạm vi một `(company_type, kind)`** — cùng một con số ở hai loại hình doanh nghiệp là hai khoản mục khác hẳn nhau. Frame giữ nguyên thứ tự máy chủ gửi, tức **kỳ mới nhất đứng trước** — đó là thứ người mở một báo cáo tài chính muốn thấy đầu tiên. Muốn khác thì `df.sort_values(...)`. ```python import finlens client = finlens.client() df = client.financials.statement("HPG") df.attrs["finlens"]["units"]["value"] # 'VND' # Kết quả kinh doanh theo quý, từ 2023 df = client.financials.statement( "HPG", kind="income_statement", period="quarterly", start_year=2023, ) # Chỉ quý 1 và quý 3 df = client.financials.statement("HPG", period="quarterly", quarters=[1, 3]) ``` ### `quarter = 0` nghĩa là cả năm [#quarter--0-nghĩa-là-cả-năm] Cột `quarter` **không bao giờ `null`**: một kỳ không thuộc quý nào thì mang `0` chứ không mang giá trị thiếu. `0` nghĩa là *cả năm*, không phải *thiếu quý*. ```python ca_nam = df[df["quarter"] == 0] # số liệu năm theo_quy = df[df["quarter"] > 0] # số liệu quý ``` Lọc nhầm không ném lỗi nào — bạn chỉ nhận một bảng ngắn hơn. Có hai thứ tên gần giống nhau và **cố ý** không trùng tên: * Tham số **`period=`** nhận `"annual"` / `"quarterly"` — nó nói *bạn muốn kỳ loại nào*. * Cột **`period_label`** mang `"2025"` / `"Q1 2025"` — nó nói *dòng này thuộc kỳ nào*. Hai tập giá trị rời hẳn nhau. Nếu cột đó cũng tên `period` thì `df[df["period"] == "annual"]` sẽ trả bảng rỗng mà **không** ném lỗi nào — người viết tin mình đang lọc, thực ra đang xoá sạch. Muốn lọc thì lọc theo `quarter`. ### Dựng lại cây báo cáo từ chính frame này [#dựng-lại-cây-báo-cáo-từ-chính-frame-này] Mỗi dòng đã mang sẵn `parent_id`, `level` và `order_index`, nên bạn dựng được cây ngay trên bảng số liệu — **không cần** gọi `line_items()` trước: ```python ky = df[(df["symbol"] == "HPG") & (df["quarter"] == 0) & (df["year"] == 2025)] goc = ky[ky["parent_id"].isna()] # các node gốc con = ky.groupby("parent_id")["item_id"].apply(list) # con của từng node # Đọc theo đúng thứ tự của bản báo cáo giấy ky.sort_values("order_index")[["level", "line_item", "value"]] ``` `Int32` (viết hoa) là kiểu số nguyên **nullable** của pandas, và ở đây đó là điều kiện để phép dựng cây phía trên đúng: node gốc có `parent_id` là `null`. `int32` thường của numpy không mang được giá trị thiếu — nó biến `null` thành `0`, tức biến **mọi node gốc thành con của một node số 0 không tồn tại**. Cây bạn dựng lại sẽ có thêm một tầng bịa ra, và không có lỗi nào được ném. ```python goc = ky[ky["parent_id"].isna()] # đúng goc = ky[ky["parent_id"] == 0] # sai ``` ### Join hai mã khác loại hình [#join-hai-mã-khác-loại-hình] `item_id` chỉ có nghĩa **trong phạm vi `(company_type, kind)`**. Cùng một số ở hai loại hình là hai khoản mục khác hẳn nhau, nên khoá join phải mang theo cả hai cột đó: ```python # Đúng a.merge(b, on=["company_type", "kind", "item_id"]) # Sai — ghép nhầm hai khoản mục không liên quan a.merge(b, on="item_id") ``` ### Vài giá trị vượt ngưỡng chính xác của số thực [#vài-giá-trị-vượt-ngưỡng-chính-xác-của-số-thực] Một số ít bản ghi trong nguồn có giá trị vượt trần số nguyên an toàn (2⁵³ ≈ 9,007 × 10¹⁵). Máy chủ **phát nguyên giá trị** thay vì cắt hay clamp: chính con số vô lý đó là tín hiệu duy nhất cho biết bản ghi nguồn đã hỏng, còn sửa nó trong im lặng là sửa dữ liệu của người khác. Đây **không** phải chuyện thang đo. Một ngân hàng lớn có những dòng cỡ 10¹⁵ VND hoàn toàn thật và vẫn nằm dưới trần; chia mọi thứ cho 10⁶ "cho an toàn" là làm lệch hàng triệu dòng đúng đắn để né vài dòng sai. Hệ quả bạn phải biết: cột `value` là `float64` với đúng 53 bit phần định trị, nên **những dòng vượt trần đã bị làm tròn ngay trong bảng**. Gặp một giá trị vô lý so với quy mô doanh nghiệp thì đọc lại từ báo cáo gốc, đừng tin con số trong bảng. Và đừng chuyển tiếp frame này sang JavaScript mà không xử lý — `Number` mất độ chính xác từ sớm hơn nhiều so với `int` của Python. ## `periods()` — kỳ nào thực sự có số liệu [#periods--kỳ-nào-thực-sự-có-số-liệu] ```python client.financials.periods( symbols, *, refresh=False, on_error="warn", ) -> DataFrame ``` Một dòng cho mỗi bộ (`symbol`, `year`, `quarter`). Dùng nó để chọn `start_year` / `end_year` cho đúng, thay vì hỏi một khoảng rồi nhận về bảng rỗng và không biết vì sao. Rẻ hơn `statement()` rất nhiều: nó chỉ trả lịch kỳ, không trả khoản mục nào. | Cột | dtype | Nội dung | | -------------- | -------- | ------------------------------ | | `symbol` | `string` | Mã chứng khoán. | | `company_type` | `string` | Loại hình doanh nghiệp của mã. | | `year` | `int16` | Năm của kỳ. | | `quarter` | `int8` | `0` là cả năm, `1..4` là quý. | | `period_label` | `string` | `"2025"` hoặc `"Q1 2025"`. | Không cột nào ở đây mang đơn vị — đây là lịch kỳ, không phải số liệu. Kết quả sắp **tăng dần** theo `symbol`, `year`, `quarter`. Đây là chỗ khác `statement()` một cách có chủ đích: bảng này là một trục thời gian để chọn khoảng, mà một trục thời gian thì đọc xuôi. ```python ky = client.financials.periods("HPG") nam_co_du_lieu = sorted(ky.loc[ky["quarter"] == 0, "year"].unique()) df = client.financials.statement("HPG", start_year=int(min(nam_co_du_lieu))) ``` Một dòng ở đây nghĩa là *mã này có ít nhất một báo cáo trong kỳ đó*. Nó **không** hứa rằng cả bốn loại báo cáo đều có mặt trong kỳ ấy — muốn chính xác tới từng loại thì hỏi thẳng `statement()`. Một mã thường có cả dòng năm lẫn dòng quý cho cùng một `year`, và đó không phải trùng lặp. Yêu cầu một khoảng rộng hơn dải thực có **không phải lỗi**: máy chủ cắt về phần có thật thay vì từ chối cả lời gọi. `periods()` là cách biết trước dải đó. ## `line_items()` — cây khoản mục, không cần mã nào [#line_items--cây-khoản-mục-không-cần-mã-nào] ```python client.financials.line_items( *, com_type, kind, refresh=False, on_error="warn", ) -> DataFrame ``` Phương thức duy nhất trong nhóm **không nhận mã chứng khoán**, và cũng không có tham số vị trí nào. Khoá của cây là cặp `(com_type, kind)` — cấu trúc báo cáo không thuộc về một doanh nghiệp cụ thể nào. | Tham số | Kiểu | Mặc định | Nội dung | | ---------- | --------------- | ------------ | ----------------------------------- | | `com_type` | `CompanyType` | **bắt buộc** | `"CT"` · `"NH"` · `"CK"` · `"BH"`. | | `kind` | `StatementKind` | **bắt buộc** | Cùng bốn giá trị với `statement()`. | | `refresh` | `bool` | `False` | Bỏ qua bản trong cache. | | `on_error` | `OnError` | `"warn"` | Xử lý lỗi. | Cả hai đều **không có giá trị mặc định**, và đó là chủ đích: bốn loại hình có bốn cây khác nhau nên không giá trị nào là trung lập, còn `kind` thì đoán hộ sẽ trả về một cây bạn không hỏi. `statement()` mặc định được `balance_sheet` vì hỏi báo cáo mà không nói loại nào thì cân đối kế toán là câu trả lời ít bất ngờ nhất; ở đây thì không. `"QU"` (quỹ) **không nằm trong kiểu `CompanyType`**, nên gõ nó vào là một gạch đỏ ngay trong IDE chứ không phải một lỗi sau một vòng gọi mạng. ### Cột trả về [#cột-trả-về-1] | Cột | dtype | Nội dung | | -------------- | -------- | ----------------------------------------------- | | `company_type` | `string` | Loại hình doanh nghiệp của cây. | | `kind` | `string` | Loại báo cáo của cây. | | `item_id` | `int32` | Mã hiển thị của khoản mục. | | `line_item` | `string` | Tên khoản mục. | | `parent_id` | `Int32` | `item_id` của khoản mục cha, `null` ở node gốc. | | `level` | `int8` | Độ sâu trong cây. | | `order_index` | `int32` | Thứ tự trình bày. | Không cột nào mang đơn vị — đây là cấu trúc, không phải số liệu. Năm cột cây trùng đúng tên và đúng dtype với `statement()`, nên hai frame join được với nhau theo `(company_type, kind, item_id)` mà không phải đổi hình. `statement()` đã trả kèm `parent_id` / `level` / `order_index` ở **mỗi dòng**, nên bạn dựng được cây ngay trên frame số liệu. Phương thức này dùng khi muốn biết cấu trúc **trước** lúc hỏi số, hoặc muốn so cây của hai loại hình doanh nghiệp. Bản 0.1.x làm ngược: nó gọi một bước kiểm tra trước mỗi lần lấy báo cáo, chỉ để lấy thứ mà máy chủ vốn đã trả kèm. ```python cay_nh = client.financials.line_items(com_type="NH", kind="balance_sheet") cay_ct = client.financials.line_items(com_type="CT", kind="balance_sheet") len(cay_nh) != len(cay_ct) # True — hai cây, hai kích thước # Đọc cây theo đúng thứ tự trình bày cay_nh.sort_values("order_index")[["level", "line_item"]] ``` ## Đơn vị là VND thô [#đơn-vị-là-vnd-thô] Mọi giá trị trong `statement()` tính bằng **VND thô** — không phải nghìn VND như cột giá cổ phiếu, cũng không phải triệu hay tỷ đồng. ```python df.attrs["finlens"]["units"]["value"] # 'VND' ``` Nghĩa là tổng tài sản của một doanh nghiệp lớn sẽ là một con số mười lăm chữ số. Muốn hiển thị cho người đọc thì chia ở tầng trình bày, đừng chia trong dữ liệu — `df["value"] / 1e9` để ra tỷ đồng. ⚠️ `DataFrame.attrs` **không sống sót** qua `pd.concat` hay `merge` của pandas. Đọc đơn vị ra biến **trước khi** ghép bảng. Chi tiết ở [Kiểu dữ liệu](/python-sdk/kieu-du-lieu). ## Bản async [#bản-async] Cả ba phương thức đều có bản bất đồng bộ với **cùng chữ ký**: ```python import asyncio import finlens async def main(): async with finlens.AsyncClient() as client: df = await client.financials.statement("HPG,VCB", kind="income_statement") asyncio.run(main()) ``` ## Xem thêm [#xem-thêm] Giá theo phiên và dòng tiền theo nhóm nhà đầu tư. `StatementKind`, `CompanyType` và cách đọc `df.attrs["finlens"]`. `on_error`, `ValidationError` và cây ngoại lệ `FL_*`. Hỏi báo cáo tài chính bằng ngôn ngữ tự nhiên qua trợ lý AI. ### Câu hỏi thường gặp **Làm sao lấy báo cáo tài chính cổ phiếu Việt Nam bằng Python?** Dùng `client.financials.statement()` của thư viện Python finlens: `client = finlens.client()` rồi `client.financials.statement("HPG", kind="income_statement", period="quarterly", start_year=2023)`. Chỉ `symbols` là tham số vị trí, mọi tham số còn lại keyword-only. Kết quả là `pandas.DataFrame` ở dạng long — một dòng là một khoản mục của một kỳ — với các cột `symbol`, `company_type`, `kind`, `year`, `quarter`, `period_label`, `line_item`, `value` cùng ba cột dựng cây `parent_id`, `level`, `order_index`. Giá trị tính bằng VND thô. **finlens hỗ trợ những loại báo cáo tài chính nào?** Tham số `kind` của `client.financials.statement()` nhận bốn giá trị: `"balance_sheet"` (cân đối kế toán), `"income_statement"` (kết quả kinh doanh), `"cash_flow_direct"` (lưu chuyển tiền tệ trực tiếp) và `"cash_flow_indirect"` (lưu chuyển tiền tệ gián tiếp). Chu kỳ chọn qua `period` với `"annual"` hoặc `"quarterly"`, khoảng thời gian qua `start_year` và `end_year` — bỏ trống là lấy trọn dải thực có — và lọc quý qua `quarters=[1, 3]`. Công ty chứng khoán không lập lưu chuyển tiền tệ trực tiếp, nên tổ hợp đó nhận một lỗi 400 rõ ràng chứ không phải một bảng rỗng. **Lấy báo cáo tài chính của nhiều mã khác loại hình cùng lúc được không?** Được, và đó là mặc định chứ không phải trường hợp đặc biệt. `client.financials.statement("HPG,VCB,SSI")` của thư viện Python finlens chạy bình thường dù HPG là doanh nghiệp phi tài chính, VCB là ngân hàng và SSI là công ty chứng khoán: frame ở dạng long và mỗi dòng mang `company_type` của chính nó. Bốn loại hình `CT`, `NH`, `CK`, `BH` có bốn cây khoản mục khác nhau nên `item_id` chỉ có nghĩa trong phạm vi `(company_type, kind)` — khoá join phải mang theo cả hai cột đó. Quỹ (`QU`) không có báo cáo dạng cây và đi vào phần lỗi theo từng mã. **Cột quarter bằng 0 trong bảng báo cáo tài chính nghĩa là gì?** Nghĩa là dòng đó là số liệu cả năm, không phải thiếu quý. Trong thư viện Python finlens, cột `quarter` không bao giờ `null`: `0` là cả năm, `1` đến `4` là quý. Vì vậy `df[df["quarter"] > 0]` lọc ra số liệu quý và loại sạch số liệu năm, còn `df[df["quarter"] == 0]` mới cho số liệu năm — lọc nhầm không ném lỗi nào, bạn chỉ nhận một bảng ngắn hơn. Nhãn kỳ đọc được nằm ở cột `period_label` với giá trị dạng `"2025"` hoặc `"Q1 2025"`. **client.reporting của bản 0.1.x còn dùng được không?** Không. Ở bản 1.x namespace tên là `client.financials`, và `client.reporting` ném `AttributeError`. Tham số cũng đổi chứ không chỉ đổi tên namespace: `symbol=` thành `symbols` ở vị trí đầu (mọi tham số sau nó là keyword-only), `statement="balance"` thành `kind="balance_sheet"`, `period="year"` và `"quarter"` thành `period="annual"` và `"quarterly"`, còn `values_format` không còn vì frame luôn ở dạng long. `start_year` nay bỏ trống được để máy chủ chọn trọn dải thực có. --- # Cài đặt thư viện Python finlens và lấy khoá API URL: https://docs.finlens.vn/python-sdk/cai-dat Mô tả: 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(). Tóm tắt: Trang hướng dẫn cài thư viện Python `finlens` để lấy dữ liệu chứng khoán Việt Nam về `pandas.DataFrame`: chạy `pip install finlens` trên Python từ 3.11 trở lên — ràng buộc kéo theo từ pandas 3.0 — và lệnh cài chỉ thêm ba phụ thuộc `pandas`, `httpx`, `packaging`. Khoá API của bản 1.x có dạng `flk_...`, tạo trong mục API Key của tài khoản finlens.vn và chỉ hiển thị đúng một lần; về sau máy chủ chỉ trả lại 12 ký tự đầu qua `client.whoami()["key"]["prefix"]`. Cấu hình xếp theo thứ tự ưu tiên: tham số truyền vào `finlens.client(api_key=...)`, biến môi trường `FINLENS_API_KEY`, rồi file `finlens.toml` chọn bằng `profile=` — thư viện cố ý không tự đọc file `.env`. `finlens.client()` không chạm mạng nên đặt ở cell đầu notebook luôn an toàn; muốn kiểm khoá ngay thì gọi `client.connect()`, `client.status()` hoặc `client.whoami()`, và kiểm `finlens.__version__` phải bắt đầu bằng `1.`. Trang cũng nêu context manager `with finlens.client() as client`, các tham số `timeout`, `deadline`, `max_concurrency`, `max_retries`, `ca_bundle`, và `finlens.build_info()` để gửi kèm khi báo lỗi. In English: how to install the finlens Python library (pip install finlens, Python 3.11+), create an flk_ API key and run the first query for Vietnamese stock market data. Sản phẩm: python-sdk 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 [#cài-đặt] ### Kiểm tra phiên bản Python [#kiểm-tra-phiên-bản-python] Thư viện yêu cầu **Python 3.11 trở lên**. ```bash 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 [#cài-từ-pypi] ```bash pip install finlens ``` Lệ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 [#lấy-khoá-api] Đăng nhập [finlens.vn](https://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 [#đặt-khoá-vào-biến-môi-trường] ```bash # Linux / macOS export FINLENS_API_KEY="flk_..." ``` ```powershell # 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 [#chạy-truy-vấn-đầu-tiên] ```python 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) ``` ```text symbol date open high low close volume 0 HPG 2026-01-05 23.57 23.70 22.94 23.17 59427911.0 ``` Giá tính bằng **nghìn đồng**: `23.17` nghĩa là 23.170 VND. 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 [#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. ```python 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): ```toml [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`. 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 [#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: ```python 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 [#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". ```python 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ông ``` `client.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: ```python client.whoami()["account"]["tier"] # 'pro' client.limits()["requests_remaining"] # 4783 client.limits()["max_symbols_per_request"] ``` 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 [#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: ```python client = finlens.client() client.connect() # ném lỗi ngay tại đây nếu khoá hỏng ``` ## Đóng client đúng cách [#đó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: ```python 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: ```python import finlens async def main(): async with finlens.AsyncClient() as client: df = await client.eod.stock.ohlcv("HPG") ``` ## Tuỳ chỉnh client [#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 [#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](/python-sdk/xu-ly-loi). ## Tiếp theo [#tiếp-theo] 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ư. Thanh giá theo phút, từng lệnh khớp và giá trị mua bán chủ động. Giá trị hợp lệ của từng tham số và hình dạng của `client.whoami()`. 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. ```python >>> 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`. --- # Changelog finlens Python: nhật ký thay đổi thư viện URL: https://docs.finlens.vn/python-sdk/changelog Mô tả: Nhật ký thay đổi thư viện Python finlens: bản 1.1.1 thêm supply_demand, active_volume và basis; kèm mọi thay đổi phá vỡ tương thích khi nâng từ 0.1.x lên 1.x. Tóm tắt: Bản mới nhất của thư viện Python finlens trên PyPI là **1.1.1**, phát hành ngày 06/08/2026 và cài bằng `pip install finlens` (yêu cầu Python 3.11 trở lên). Trang này là nhật ký thay đổi của thư viện — thư viện lấy dữ liệu chứng khoán Việt Nam trả về `pandas.DataFrame` — và là nơi tra những thay đổi phá vỡ tương thích khi nâng từ dòng 0.1.x lên dòng 1.x. Đổi tên: `client.eod.market` thành `client.eod.index`, `client.reporting` thành `client.financials`, module `finlens.types` thành `finlens.typing`. Đổi hình dạng dữ liệu: tên cột nay viết thường theo snake_case (`Date` thành `date`, `Close` thành `close`), frame kết quả luôn đủ cột đúng dtype kể cả khi 0 dòng, và bảng dòng tiền luôn có cột `group`. Đổi từ vựng: `interval="1M"` bị từ chối, dữ liệu cuối ngày dùng `1mo` còn dữ liệu trong phiên dùng `1min`. Đổi chữ ký: tham số `symbol` thành `symbols` (cấp ngành là `icb`), và chỉ tham số đầu tiên là positional. Đổi môi trường: Python 3.11 trở lên, pandas 3.0 trở lên, `httpx` thay cho `requests` và `pydantic` đã bị gỡ; khoá API có tiền tố `flk_`. Dòng 1.x cũng thêm hẳn bốn bề mặt mới: `client.intraday` (`ohlcv()`, `ticks()`, `net_active_value()`), `client.financials`, `client.meta` và hai namespace giá cuối ngày `client.eod.derivative`, `client.eod.warrant` — cùng `client.eod.sector.ohlcv()`, tham số `refresh`, `on_error`, `adjusted` và siêu dữ liệu `df.attrs["finlens"]`. Bản 1.1.1 chỉ thêm, không đổi chữ ký hay tên cột nào: `client.eod.stock.supply_demand()` cho khối lượng và số lệnh ĐẶT vào sổ (trung vị tỷ lệ trên khối lượng khớp là 2,756 lần, ba cột `_count` dùng `Int64` nullable); `client.eod.stock.active_volume()` cùng `client.eod.derivative.active_volume()` cho khối lượng khớp chủ động hai rổ, không cộng được với `client.intraday.*.net_active_value()` vốn có ba rổ và tính bằng VND — cùng một phiên VN30F1M hai bên lệch 57,5%, 520% và 30,1%; `client.eod.derivative.basis()` cùng `client.intraday.derivative.basis()` cho chênh lệch hợp đồng tương lai với chỉ số cơ sở, `basis_pct = basis / spot_close * 100` trên thang 0–100 và không phương thức nào có tham số `interval`; và `client.eod.derivative.investor.flow()` cùng `breakdown()` cho dòng tiền cấp hợp đồng phái sinh, chỉ hai nhóm `foreign` và `proprietary`, khối lượng tính bằng hợp đồng. Bản này cũng thêm mã lỗi `FL_DATA_NO_UNDERLYING` (ánh xạ về `finlens.NoDataError`) và hai kiểu công khai `DerivativeInvestorGroup`, `DerivativeInvestorGroupsArg`. In English: changelog of the finlens Python library, including every breaking change from the 0.1.x line to 1.x. Sản phẩm: python-sdk Nhật ký thay đổi của thư viện Python `finlens`. Bản mới nhất là **`1.1.1`** — kiểm bằng `finlens.__version__`. Các mục `1.0.0a1` đến `1.0.0a7` bên dưới là bản thử nghiệm, **chỉ phát hành trên TestPyPI** và chưa bao giờ có trên PyPI. Nếu bạn cài bằng `pip install finlens` thì bản đầu tiên bạn nhận được là `1.1.1`; các mục alpha giữ lại để tra cứu lịch sử chứ không phải để nâng cấp theo. Dòng 1.x là một bản **viết lại**, không phải một bản nâng cấp tiệm tiến. Code viết cho 0.1.x sẽ không chạy nguyên trạng; bảng ngay dưới đây là danh sách đầy đủ những chỗ gãy. ## Nâng cấp từ 0.1.x — mọi chỗ gãy [#nâng-cấp-từ-01x--mọi-chỗ-gãy] Năm nhóm. Gần như tất cả đều ném lỗi ngay nên bạn thấy liền — trừ **một dòng duy nhất**: đơn vị của `net_active_value` đổi mà không có exception nào. Đó là dòng đáng đọc kỹ nhất trong cả trang. ### 1. Đổi tên [#1-đổi-tên] | Bản 0.1.x | Bản 1.x | | ---------------------- | ----------------------- | | `client.eod.market` | **`client.eod.index`** | | `client.reporting` | **`client.financials`** | | Module `finlens.types` | **`finlens.typing`** | Cả ba đều ném `AttributeError` hoặc `ModuleNotFoundError`, nên không có kịch bản nào chạy tiếp với dữ liệu sai. ### 2. Đổi chữ ký [#2-đổi-chữ-ký] | Bản 0.1.x | Bản 1.x | | ----------------------------------------------- | ----------------------------------------------------------------- | | Tham số `symbol` (số ít) | **`symbols`**; ở cấp ngành là **`icb`** | | `ohlcv("HPG", start, end, "1W")` | Chỉ tham số **đầu tiên** là positional, phần còn lại keyword-only | | Ngành nhận tên tiếng Việt `"Ngân hàng"` | Ngành nhận **mã ICB dạng chuỗi**: `"8600"` | | `statement(statement="balance", period="year")` | `statement(kind="balance_sheet", period="annual")` | Luật keyword-only là hàng rào cho một lớp bug đã xảy ra thật: ở 0.1.x một chuỗi interval truyền theo vị trí có thể rơi vào một tham số boolean, không lỗi và dữ liệu vẫn về. ### 3. Đổi từ vựng `interval` [#3-đổi-từ-vựng-interval] `interval="1M"` và `interval="1m"` đều **bị từ chối** bằng `finlens.InvalidIntervalError` với mã `FL_VALIDATION_INTERVAL_AMBIGUOUS`. Trong từ vựng cũ hai giá trị này chỉ khác nhau ở chữ hoa nhưng lệch nhau 43.200 lần. * Dữ liệu cuối ngày: `1d` · `1w` · `1mo` · `3mo` · `6mo` · `1y` * Dữ liệu trong phiên: `1min` · `5min` · `15min` · `30min` · `1h` · `4h` ### 4. Đổi hình dạng dữ liệu — nhóm im lặng nhất [#4-đổi-hình-dạng-dữ-liệu--nhóm-im-lặng-nhất] | Bản 0.1.x | Bản 1.x | | ------------------------------------- | -------------------------------------------------------------- | | Cột `Date`, `Open`, `Close`, `Volume` | **snake\_case viết thường**: `date`, `open`, `close`, `volume` | | Bảng dòng tiền không có cột `group` | **luôn có `group`**, kể cả khi chỉ hỏi một nhóm | | Kết quả rỗng có thể thiếu cột | Frame **luôn đủ cột đúng dtype**, kể cả 0 dòng | | `net_active_value` gọi là "tỷ đồng" | **VND thô** — xem mục `1.0.0` | `df["Date"]` ném `KeyError` chắc chắn chứ không thỉnh thoảng: vì frame rỗng cũng đủ cột đúng dtype, không có đường nào để một tên cột viết hoa lọt qua. Đơn vị của `net_active_value` là chỗ duy nhất **không** ném lỗi khi bạn đọc sai. Đọc `df.attrs["finlens"]["units"]` thay vì giả định. ### 5. Đổi môi trường [#5-đổi-môi-trường] | Bản 0.1.x | Bản 1.x | | -------------------------------- | ------------------------------------------------------- | | Python ≥ 3.10 | **Python ≥ 3.11** | | pandas ≥ 2.1.2 | **pandas ≥ 3.0** | | `requests` | **`httpx`** | | `pydantic` là phụ thuộc bắt buộc | **đã gỡ** — còn đúng ba: `pandas`, `httpx`, `packaging` | | Khoá API không tiền tố | Khoá mới có tiền tố **`flk_`** | 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. Chi tiết ở [Cài đặt](/python-sdk/cai-dat). *** ## `1.1.1` — 06/08/2026 [#111--06082026] Bản này **chỉ thêm**. Không phương thức nào đổi chữ ký, không cột nào đổi tên, không đơn vị nào đổi nghĩa — code đang chạy trên `1.1.0` chạy nguyên trạng. Bốn nhóm dữ liệu mới, và cả bốn đều nằm ở những chỗ dễ đọc nhầm thành một bảng đã có. Ba cảnh báo dưới đây đáng đọc trước khi gõ dòng đầu tiên. ### Thêm — `supply_demand()`: khối lượng và số lệnh ĐẶT vào sổ [#thêm--supply_demand-khối-lượng-và-số-lệnh-đặt-vào-sổ] ```python client.eod.stock.supply_demand("HPG", start="2026-08-01") ``` Sáu cột số: `buy_order_volume` · `sell_order_volume` · `net_order_volume` · `buy_order_count` · `sell_order_count` · `net_order_count`. ⚠️ **Đây là lệnh ĐẶT, không phải lệnh đã khớp.** Trung vị của tỷ lệ `buy_order_volume / volume` — cùng mã, cùng phiên, `volume` lấy từ `ohlcv()` — là **2,756 lần**; 99,77% số dòng có khối lượng đặt lớn hơn hoặc bằng khối lượng khớp. Đó là lý do mọi tên cột mang chữ `_order_`: trừ một cột ở đây cho `volume` của `ohlcv()` là so hai đại lượng chênh nhau khoảng ba lần, và **không có exception nào chặn**. Ba cột `_count` dùng `Int64` **viết hoa** và mang được giá trị thiếu — máy chủ phát giá trị thiếu ở khoảng **11%** số dòng. Kiểm bằng `.isna()`, đừng so với `0`. Khi gộp kỳ, một phiên thiếu số lệnh làm cả ba cột `_count` của kỳ đó thiếu theo. **Chỉ có ở `client.eod.stock`.** Chỉ số, ngành, chứng quyền và phái sinh không có dữ liệu sổ lệnh nào, nên `client.eod.warrant.supply_demand` là `AttributeError` chứ không phải một bảng rỗng. ### Thêm — `active_volume()`: khối lượng khớp lệnh chủ động cuối ngày [#thêm--active_volume-khối-lượng-khớp-lệnh-chủ-động-cuối-ngày] ```python client.eod.stock.active_volume("HPG") client.eod.derivative.active_volume("VN30F1M") ``` Ba cột: `active_buy_volume` · `active_sell_volume` · `net_active_volume`. ⚠️ **Không phải `client.intraday.*.net_active_value()`, và hai frame không cộng được với nhau.** Cùng một phiên VN30F1M, ba cột tương ứng lệch nhau **57,5% · 520% · 30,1%**. Chúng khác ở cả ba chiều: **số rổ** (hai ở đây, ba ở kia vì kia tách riêng phần khớp lệnh định kỳ), **đơn vị** (khối lượng ở đây và **không có cột tiền nào**; VND ở kia), và **nguồn**. Phép cộng hai frame không ném exception nào, chỉ cho ra một con số sai. Phần khớp lệnh định kỳ **không biến mất — nó bị trộn vào**: `active_buy_volume + active_sell_volume` bằng đúng khối lượng khớp cả phiên. Đơn vị khối lượng đổi theo namespace — **cổ phiếu** ở `client.eod.stock`, **hợp đồng** ở `client.eod.derivative` — trong khi bộ tên cột giống hệt nhau. Đọc `df.attrs["finlens"]["units"]`. ### Thêm — `basis()`: chênh lệch phái sinh và chỉ số cơ sở [#thêm--basis-chênh-lệch-phái-sinh-và-chỉ-số-cơ-sở] ```python client.eod.derivative.basis("VN30F1M") # theo phiên client.intraday.derivative.basis("VN30F1M") # bước 1 phút ``` Bảy cột: `symbol` · `index_symbol` · `date` (hoặc `time`) · `future_close` · `spot_close` · `basis` · `basis_pct`. ```text basis = future_close - spot_close # điểm chỉ số basis_pct = basis / spot_close * 100 # phần trăm, thang 0–100 ``` ⚠️ `basis_pct` là cột `_pct` **đầu tiên** của thư viện. Mẫu số là **`spot_close`** chứ không phải giá hợp đồng, và thang là **0–100** chứ không phải 0–1. Hai mẫu số chỉ lệch nhau khoảng **0,3%** nên chọn nhầm gần như không nhìn ra được trên một biểu đồ — đó là lý do công thức được viết thẳng vào tài liệu thay vì để bạn suy. **Không phương thức nào trong cặp này có `interval`**, kể cả bản theo phiên: gộp một chênh lệch qua nhiều bước không có nghĩa hiển nhiên nào — trung bình, giá trị cuối kỳ và biên độ là ba câu trả lời khác nhau. Dùng `df.resample(...)` nếu bạn cần, ở đó bạn tự chọn. `index_symbol` là một **cột thật**, không phải một chi tiết trong `df.attrs`: `attrs` biến mất ngay khi bạn `pd.concat` hai frame. Bản trong phiên bắt đầu từ **09:15**, không phải 09:00 — trước 09:15 chỉ số chưa được tính theo từng phút, còn bar 09:00 là kết quả khớp lệnh định kỳ ATO, một cơ chế hình thành giá khác hẳn các bar liên tục phía sau. ### Thêm — dòng tiền nhà đầu tư ở cấp hợp đồng phái sinh [#thêm--dòng-tiền-nhà-đầu-tư-ở-cấp-hợp-đồng-phái-sinh] ```python client.eod.derivative.investor.flow("VN30F1M") client.eod.derivative.investor.breakdown("VN30F1M") ``` **Cùng bộ chín cột** với `client.eod.stock.investor.*`, nên hai bảng ghép được với nhau. Khác đúng hai chỗ, và cả hai nằm trong kiểu của tham số: * **Chỉ `foreign` và `proprietary`.** Bốn nhóm chi tiết nhận **400** — nguồn của chúng khoá theo danh mục doanh nghiệp niêm yết, nơi không hợp đồng phái sinh nào có mặt. `DerivativeInvestorGroup` thu hẹp `Literal` để lỗi đó thành một gạch đỏ lúc gõ code, và `breakdown()` bỏ trống `groups` hỏi **hai** nhóm chứ không phải sáu như ở cấp mã. * **Khối lượng tính bằng hợp đồng**, không phải cổ phiếu. ⚠️ **Đây là hợp đồng KHỚP ròng và giá trị DANH NGHĨA.** `net_volume` là chênh lệch hợp đồng đã khớp trong kỳ, **không phải vị thế mở** — cộng dồn nó qua nhiều phiên không cho ra vị thế tích luỹ. Các cột `*_value` là giá trị danh nghĩa của số hợp đồng đó, đã quy đổi ra VND thô bằng hệ số hợp đồng ở máy chủ, không phải số tiền thực bỏ ra. Tự nhân `net_volume` với giá đóng cửa mà quên hệ số hợp đồng là lệch **100.000 lần**, và phép nhân đó vẫn chạy. ### Thêm — mã lỗi `FL_DATA_NO_UNDERLYING` [#thêm--mã-lỗi-fl_data_no_underlying] Ánh xạ về `finlens.NoDataError`. Nó đi trong phần lỗi **theo từng mã**, nên một hợp đồng không có chuỗi chỉ số cơ sở không làm hỏng cả lời gọi `basis()`. Mã riêng chứ không dùng lại `FL_DATA_EMPTY` vì hai bệnh khác nhau: `FL_DATA_EMPTY` là *khoảng bạn hỏi không có dòng nào*, còn mã này là *hợp đồng này không có chỉ số cơ sở trong dữ liệu*, tức không đổi `start`/`end` nào cứu được. Nó cũng cố ý **không** phải `InvalidSymbolError` — mã bạn gõ hoàn toàn đúng, và bảo người dùng đi kiểm tra một mã đã đúng là một chẩn đoán sai. ### Thêm — hai kiểu công khai [#thêm--hai-kiểu-công-khai] `finlens.DerivativeInvestorGroup` và `finlens.DerivativeInvestorGroupsArg`. Alias riêng chứ không dùng lại `SectorInvestorGroup` dù trùng tập giá trị: hai chỗ hẹp lại vì hai lý do khác nhau — ở cấp ngành là một nguồn thực chất chỉ có sàn HOSE, còn ở đây là một danh mục không chứa hợp đồng phái sinh — và hai lý do đó có thể đổi độc lập. *** ## `1.1.0` — 05/08/2026 [#110--05082026] ### Đã đổi — báo cáo tài chính dùng `item_id`, và cột `field` bị bỏ [#đã-đổi--báo-cáo-tài-chính-dùng-item_id-và-cột-field-bị-bỏ] `client.financials.statement()` và `client.financials.line_items()` nay trả `item_id` thay cho `line_item_id`, và **không còn cột `field`**. Cột `parent_id` mang `item_id` của khoản mục cha; `level` và `order_index` không đổi. ```python df = client.financials.statement("HPG", kind="balance_sheet") df["item_id"] # trước là df["line_item_id"] — tên cũ ném KeyError df["field"] # KeyError: cột này không còn ``` `item_id` là **mã hiển thị** do máy chủ cấp, ổn định theo thời gian, và chỉ có nghĩa trong phạm vi một `(company_type, kind)` — cùng một con số ở hai loại hình doanh nghiệp là hai khoản mục khác hẳn nhau. Nó không phải định danh của hệ thống nguồn, nên đừng dùng nó để tra ngược sang nơi khác. Máy chủ đã chuyển sang bộ cột mới. Nếu bạn đang chạy `1.0.0` hoặc `1.0.1`, `client.financials.statement()` ném `TypeError` — không phải lỗi của finlens nên thông báo không nhắc gì tới phiên bản. Chữa bằng `pip install -U finlens`. Các nhóm dữ liệu khác (`eod`, `intraday`, `meta`) vẫn chạy bình thường ở bản cũ. ### Đã đổi — cột `date` của một kỳ đã gộp nhóm là **phiên cuối**, không phải đầu kỳ [#đã-đổi--cột-date-của-một-kỳ-đã-gộp-nhóm-là-phiên-cuối-không-phải-đầu-kỳ] Với `interval` có gộp nhóm (`1w` · `1mo` · `3mo` · `6mo` · `1y`), cột `date` nay mang **phiên giao dịch cuối cùng thực sự có dữ liệu** trong kỳ. Trước bản này nó mang mốc **đầu** kỳ. `interval="1d"` không đổi — nó vốn đã là ngày phiên. ```python client.eod.stock.ohlcv("HPG", start="2023-01-01", end="2023-12-31", interval="1mo") # trước: 2023-01-01, 2023-02-01, 2023-03-01, 2023-04-01, ... # nay : 2023-01-31, 2023-02-28, 2023-03-31, 2023-04-28, ... ``` Số dòng **không đổi** — bề rộng kỳ giữ nguyên, chỉ cái nhãn đổi. Ba lý do, theo thứ tự quan trọng: * **`close` của dòng đó là giá đóng cửa của phiên mang ngày đó.** Trước đây ngày và giá kể hai chuyện khác nhau: dòng `1mo` dán nhãn `2023-01-01` nhưng `close` lấy từ phiên cuối tháng. * **Kỳ đang dở không mang mốc tương lai.** Nếu dùng ngày cuối **theo lịch** thì `1y` của năm nay sẽ là `2026-12-31`, một mốc tương lai nằm giữa chuỗi dữ liệu, và `df[df["date"] <= hôm_nay]` sẽ âm thầm đánh rơi kỳ hiện tại. * **Ngày trả về luôn là một phiên có thật**, không phải một mốc tính ra. Lấy ngày cuối theo lịch thì 39% số kỳ `1mo` sẽ mang một ngày thị trường đóng cửa — đo trên dữ liệu thật 2020–2026. Tháng 1/2025 nghỉ Tết là ví dụ rõ nhất: phiên cuối là **24/01** trong khi lịch nói 31/01. Áp dụng cho `client.eod.*.ohlcv()`, `client.eod.sector.ohlcv()` và `client.eod.*.investor.flow()`. Với dòng tiền, mọi nhóm nhà đầu tư trong cùng một kỳ nhận **cùng một** `date`, kể cả khi các nguồn cập nhật lệch nhau một phiên. Nếu bạn đang lưu kết quả đã resample: ngày cũ và ngày mới không khớp nhau, nên mọi phép join theo `date` với dữ liệu đã lưu sẽ trượt. Lấy lại dữ liệu thay vì ghép hai bên. *** ## `1.0.1` — 05/08/2026 [#101--05082026] **Mã của thư viện không đổi một dòng nào so với `1.0.0`.** Nếu bạn đang dùng `1.0.0` thì không có lý do gì phải nâng cấp — bản này chỉ sửa trang giới thiệu trên PyPI. Điều đó kiểm chứng được, không phải lời hứa: so từng byte hai wheel `cp312-manylinux` của `1.0.0` và `1.0.1` thì **cả 15 module đã biên dịch đều giống hệt nhau**; chỉ bốn file đổi, và cả bốn đều là siêu dữ liệu (`METADATA`, `RECORD`, `_version.py`, `_build_info.py`). ### Đã sửa — bốn liên kết trên trang PyPI trả về 404 [#đã-sửa--bốn-liên-kết-trên-trang-pypi-trả-về-404] `README.md` là phần mô tả của gói, và PyPI hiển thị nó **một mình**, không có cây thư mục nào bên cạnh để một đường dẫn tương đối trỏ tới. Bốn liên kết vì vậy hỏng ngay trên trang của `1.0.0`: huy hiệu giấy phép, hai liên kết `CHANGELOG.md`, và liên kết `LICENSE`. Nay chúng trỏ về chính trang bạn đang đọc và về [toàn văn giấy phép MIT](https://opensource.org/license/mit). PyPI **không cho tải lại** một phiên bản đã phát hành. Trang của `1.0.0` vì thế giữ nguyên bốn liên kết hỏng vĩnh viễn — đó là toàn bộ lý do `1.0.1` tồn tại. *** ## `1.0.0` — 05/08/2026 [#100--05082026] Bản chính thức đầu tiên trên PyPI. Cài bằng `pip install finlens`. ```bash pip install finlens ``` Gom toàn bộ bề mặt đã thử nghiệm ở các bản alpha, cộng một thay đổi về cache mô tả ngay dưới đây. ### Đã sửa — dữ liệu cuối ngày của phiên vừa đóng không còn bị đóng băng [#đã-sửa--dữ-liệu-cuối-ngày-của-phiên-vừa-đóng-không-còn-bị-đóng-băng] Bảng cuối ngày được cập nhật **liên tục trong phiên, 08:45–15:00**, và nguồn còn chạm vào dòng của ngày đó một lát sau khi đóng cửa: chốt giá ATC, tính lại hệ số điều chỉnh, bổ sung số khối ngoại. Trước bản này, từ đúng 15:00 kết quả bị giữ trong bộ nhớ đệm **bảy ngày** — một bản chụp giữa chừng bị ghim suốt cả tuần, không ngoại lệ, không cảnh báo. | Bạn gọi lúc | `end` bỏ trống | `end` là hôm nay | `end` là năm cũ | | ------------- | -------------- | ---------------- | --------------- | | 08:45 – 14:59 | 60 giây | 60 giây | 7 ngày | | từ 15:00 | 60 giây | **30 phút** | 7 ngày | Điều kiện hẹp ở "khoảng chạm phiên vừa đóng", không phải "mọi khoảng đã chốt": một truy vấn năm 2024 đã bất biến thật, cho nó hết hạn sau 30 phút chỉ bắt bạn gọi lại cùng một thứ mà không đổi lấy gì. Không cần làm gì để nhận thay đổi này — nó nằm trong logic chọn thời gian sống của bộ nhớ đệm. Muốn bỏ qua đệm ở một lời gọi bất kỳ thì thêm `refresh=True`. ### Bề mặt đầy đủ của 1.0.0 [#bề-mặt-đầy-đủ-của-100] ```python client.eod.stock.ohlcv("HPG", start="2026-01-01", adjusted=False) client.eod.sector.ohlcv("8355") client.eod.stock.investor.breakdown("HPG") client.intraday.stock.ticks("HPG", date="2026-08-03") client.intraday.stock.net_active_value("HPG", interval="1h") client.financials.statement("HPG", kind="balance_sheet", period="quarterly") client.meta.symbols(exchange="HOSE", icb="8300") ``` Chi tiết từng nhóm nằm ở các mục alpha bên dưới, hoặc ở trang tham chiếu tương ứng trong mục lục bên trái. *** ## `1.0.0a7` — 04/08/2026 [#100a7--04082026] Bốn bề mặt mới. ### Thêm — dữ liệu trong phiên [#thêm--dữ-liệu-trong-phiên] ```python client.intraday.stock.ohlcv("HPG", interval="5min") client.intraday.stock.ticks("HPG", date="2026-08-03") client.intraday.stock.net_active_value("HPG") ``` * Cột thời gian tên **`time`** và **mang múi giờ** `Asia/Ho_Chi_Minh`, khác cột `date` naive của EOD. Bỏ múi giờ thì pandas đoán UTC và 09:15 giờ Việt Nam bị đọc lệch bảy tiếng — ra ngoài cả phiên giao dịch. * **Giá trong phiên là giá thô, không điều chỉnh quyền** — ngược với `client.eod.stock`. Nối hai chuỗi mà không đọc `df.attrs["finlens"]["price_basis"]` sẽ cho một bậc thang giả ở mỗi lần chia tách quyền. * `ticks()` nhận **một mã, một phiên** mỗi lời gọi, và giới hạn đó nằm trong **chữ ký** — tham số đầu tên `symbol` số ít, không phải `symbols`. * `client.intraday.index` **không có** `net_active_value()`: dữ liệu tick của chỉ số không ghi chiều lệnh chủ động. Một sự vắng mặt trong dữ liệu là một sự vắng mặt trong API. * Cột `side` có **ba** giá trị chứ không phải hai: `buy` · `sell` · `auction`. Chi tiết ở [Dữ liệu trong phiên](/python-sdk/intraday). ### Đã sửa — `net_active_value` từng có ba đơn vị cho một tên cột [#đã-sửa--net_active_value-từng-có-ba-đơn-vị-cho-một-tên-cột] Đây là thay đổi phá vỡ tương thích nặng nhất của bản này, và nó nằm trong chính con số chứ không chỉ ở tên hàm: | | Bản 0.1.x | Bản 1.x | | --------- | ---------------------------- | ----------------------------------------------- | | Cổ phiếu | chia cho 10⁶ | **VND thô** | | Phái sinh | không quy đổi hệ số hợp đồng | **VND thô**, đã nhân hệ số hợp đồng | | Tài liệu | gọi là "tỷ đồng" | `df.attrs["finlens"]["units"]` khai rõ từng cột | Với cổ phiếu, con số mới lớn hơn con số cũ **10⁶ lần**. Với phái sinh, con số cũ vốn không thuộc đơn vị nào nên **không quy đổi được** — đọc lại từ đầu. Mã phái sinh chưa có hệ số hợp đồng xác nhận thì các cột `*_value` trả `null` kèm cảnh báo, chứ không phải một con số đoán; các cột `*_volume` vẫn trả bình thường. ### Thêm — báo cáo tài chính [#thêm--báo-cáo-tài-chính] ```python client.financials.statement("HPG,VCB,SSI", kind="income_statement", period="quarterly", start_year=2023) client.financials.line_items(com_type="NH", kind="balance_sheet") client.financials.periods("HPG") ``` Frame ở dạng **long** và mỗi dòng mang `company_type` của chính nó, nên một lời gọi được phép **trộn nhiều loại hình doanh nghiệp**. Ràng buộc "mỗi lần một loại" của 0.1.x là do client tự áp. Chi tiết ở [Báo cáo tài chính](/python-sdk/bao-cao-tai-chinh). ### Thêm — tra cứu danh mục [#thêm--tra-cứu-danh-mục] ```python client.meta.symbols(exchange="HOSE", icb="8300") client.meta.sectors(level=2) client.meta.warrants(underlying="HPG") ``` Câu hỏi mở đầu một phiên làm việc không phải "giá HPG hôm qua" mà là **"có những mã nào"**. Trước bản này thư viện không trả lời được. * Một tham số `icb=` nhận **cả mã cấp 2 lẫn mã cấp 4** — bạn không phải biết trước mã mình cầm thuộc cấp nào. * Chứng chỉ quỹ nằm **cùng bảng** với cổ phiếu, phân biệt bằng cột `kind`. * `exchange` nhận `"HOSE"` · `"HNX"` · `"UPCOM"`. Chi tiết ở [Tra cứu danh mục](/python-sdk/tra-cuu-danh-muc). ### Thêm — chỉ số ngành ICB [#thêm--chỉ-số-ngành-icb] `client.eod.sector.ohlcv("8600")` trả chuỗi giá của chỉ số ngành, đơn vị **điểm chỉ số**. Namespace `client.eod.sector` trước đó chỉ có `investor.flow()`. ⚠️ Hai phương thức của namespace này **khác thứ nguyên nhau**: `ohlcv()` là điểm chỉ số, `investor.flow()` là VND thô. ### Thêm — `adjusted` cho `eod.*.ohlcv()` [#thêm--adjusted-cho-eodohlcv] ```python client.eod.stock.ohlcv("VCB", adjusted=False) # giá khớp lệnh thật ``` Mặc định vẫn là `True`, nên không lời gọi nào đang chạy bị đổi kết quả. Cơ sở giá đọc ở `df.attrs["finlens"]["price_basis"]`. ⚠️ `client.intraday.*.ohlcv()` **không** có tham số này — giá trong phiên vốn đã là giá thô. Bất đối xứng có chủ đích, không phải một chỗ quên. *** ## `1.0.0a6` — 04/08/2026 [#100a6--04082026] ### Đã sửa — lỗi chứng chỉ TLS không còn bị báo cáo thành lỗi máy chủ [#đã-sửa--lỗi-chứng-chỉ-tls-không-còn-bị-báo-cáo-thành-lỗi-máy-chủ] Trên máy nằm sau proxy kiểm tra TLS, bản trước báo "backend đang không phản hồi" trong khi máy chủ hoàn toàn khoẻ — thông báo ấy gửi người đọc đi kiểm đúng chỗ không có vấn đề gì. Lỗi chứng chỉ còn bị thử lại ba lần, dù một chứng chỉ không tin được sẽ không trở nên đáng tin sau hai giây. Nay lỗi chứng chỉ được nhận là **vĩnh viễn**: không thử lại, và có lớp riêng `finlens.TlsVerificationError` — **kế thừa `ConnectionFailedError`** nên code đang bắt lớp cha vẫn chạy y nguyên. Thông báo chỉ thẳng đường sửa: `finlens.client(ca_bundle=...)` hoặc biến môi trường `FINLENS_CA_BUNDLE`. ### Đã sửa — `finlens.build_info()["built_at"]` trả cùng một mốc cho mọi bản [#đã-sửa--finlensbuild_infobuilt_at-trả-cùng-một-mốc-cho-mọi-bản] Trường này trả một dấu thời gian cố định cho **mọi** bản build. Với một gói mà bạn không đọc được mã nguồn, câu hỏi đầu tiên khi báo lỗi là *"đang chạy binary nào, build lúc nào"* — và trường đó đang trả lời sai cho tất cả mọi người. Nay nó là mốc thật của bản build. *** ## `1.0.0a5` — 04/08/2026 [#100a5--04082026] ### Thêm — `investor.flow()` và `investor.breakdown()` [#thêm--investorflow-và-investorbreakdown] ```python client.eod.stock.investor.flow("HPG", group="foreign") client.eod.stock.investor.breakdown(["HPG", "VCB"]) client.eod.sector.investor.flow("8600") client.eod.index.investor.flow("VNINDEX") ``` `flow()` hỏi một nhóm, `breakdown()` hỏi nhiều nhóm — **cùng một schema**, nên hai bảng ghép được với nhau mà không phải đổi hình. ### Đã sửa — sáu nhóm nhà đầu tư không cùng một định nghĩa [#đã-sửa--sáu-nhóm-nhà-đầu-tư-không-cùng-một-định-nghĩa] Đây là chỗ sửa lỗi ngữ nghĩa nặng nhất so với 0.1.x. Tài liệu cũ liệt kê sáu nhóm phẳng như sáu thứ ngang hàng. Thực tế: * Bốn nhóm chi tiết (cá nhân / tổ chức × trong nước / nước ngoài) là một **phân hoạch đầy đủ** — tổng `net_value` của chúng bằng 0. * `foreign` lấy **cả giao dịch thoả thuận**, nên nó **không** bằng `foreign_individual + foreign_institutional`. * `proprietary` (tự doanh) đến từ một vũ trụ dữ liệu khác và **không phải** nhóm con của `local_institutional`, dù trực giác nói ngược lại. Cộng cả sáu nhóm cho ra một con số vô nghĩa, và 0.1.x không có gì ngăn điều đó. **Cột `group` nay luôn có mặt**, kể cả khi lời gọi chỉ hỏi một nhóm — đó là chỗ duy nhất mang được "con số này tính trên cơ sở nào" ở mức từng dòng. Ở cấp ngành, kiểu `SectorInvestorGroup` chỉ nhận `"foreign"` và `"proprietary"`, nên xin bốn nhóm chi tiết ở đó bị chặn ngay lúc gõ code. ### Đã sửa — response sai hình dạng ném lỗi thay vì trả bảng rỗng [#đã-sửa--response-sai-hình-dạng-ném-lỗi-thay-vì-trả-bảng-rỗng] Tới bản trước, một response mà client không hiểu được có thể trở thành một bảng **rỗng** hoặc vài dòng bịa, im lặng cả hai trường hợp. Bảng rỗng là kịch bản xấu nhất của cả dự án: người dùng đọc "khối ngoại mua ròng 0 đồng" trong khi thật ra client không đọc được dữ liệu. Nay nó ném `finlens.SchemaMismatchError` với mã `FL_DATA_SCHEMA`. *** ## `1.0.0a4` — 03/08/2026 [#100a4--03082026] ### Thay đổi phá vỡ tương thích — Python và pandas [#thay-đổi-phá-vỡ-tương-thích--python-và-pandas] Yêu cầu **`pandas >= 3.0`** và **`Python >= 3.11`** (trước đó là `pandas >= 2.1.2` và `Python >= 3.10`). Hai dòng pandas khác nhau ở những chỗ **im lặng**: cùng một chuỗi ngày cho ra `datetime64[us]` trên pandas 3.0 nhưng `datetime64[ns]` trên 2.x — nên một frame rỗng và một frame có dữ liệu mang dtype khác nhau tuỳ phiên bản pandas của người dùng. Python 3.11 là hệ quả kéo theo: pandas 3.0 chỉ có wheel cho CPython 3.11 đến 3.14. Wheel Linux đòi **glibc ≥ 2.28** (Debian 10 / RHEL 8 / Ubuntu 18.10 trở lên) — chính ràng buộc mà pandas đặt ra, không phải một lựa chọn riêng. *** ## `1.0.0a1` — 03/08/2026 [#100a1--03082026] Bản alpha đầu tiên, chỉ phát hành trên TestPyPI. Có `client.eod.stock`, `client.eod.index`, `client.eod.derivative`, `client.eod.warrant`. Toàn bộ nền tảng của dòng 1.x xuất hiện ở bản này: * `finlens.client()` và `finlens.AsyncClient` — bản async có **cùng chữ ký** với bản đồng bộ. * **Tạo client không gọi mạng.** Đặt `finlens.client()` ở cell đầu notebook luôn an toàn; muốn kiểm khoá ngay thì gọi `client.connect()`. * Cấu hình bốn tầng: tham số truyền vào > biến môi trường `FINLENS_*` > `finlens.toml` > mặc định. * Cây ngoại lệ hoàn chỉnh gốc ở `finlens.FinLensError`, kèm mã lỗi `FL_*` ổn định và bảy lớp cảnh báo tắt được chọn lọc. * `finlens.PartialFetchError` **mang theo dữ liệu đã lấy được** ở `.data` — không bao giờ mất 49 mã thành công vì 1 mã hỏng. * `finlens.ValidationError` **kế thừa đôi** từ `ValueError`, nên code cũ viết `except ValueError:` vẫn chạy sau khi nâng cấp. * `ca_bundle` cho môi trường có proxy kiểm tra TLS. Cố ý **không** có tuỳ chọn tắt kiểm chứng chỉ. ### Đã sửa so với 0.1.11 [#đã-sửa-so-với-0111] * **`CompanyTypeMismatchError` nằm ngoài cây `FinLensError`.** Nay nó là `finlens.CompanyTypeMismatchError(ValidationError)`, tức vừa trong cây vừa vẫn là `ValueError`. Hệ quả: `except finlens.FinLensError` giờ **là** đủ — nếu code của bạn còn một nhánh `except RuntimeError` viết theo hướng dẫn cũ, nhánh đó nay là code chết. * **Cây ngoại lệ đảo chiều phụ thuộc**, nguyên nhân khiến `except FinLensError:` ở 0.1.x gần như không bắt được gì. * **So sánh phiên bản bằng chuỗi**: `"0.1.9" < "0.1.11"` là `False`, nên cổng kiểm tra hỗ trợ đã chết đúng ở vùng phiên bản đang dùng. * **`finlens.__version__` báo sai.** 0.1.x fallback về `"0.0.0"` ở mọi bản chưa cài đầy đủ. *** ## Dòng 0.1.x — đã đóng băng [#dòng-01x--đã-đóng-băng] Bản phát hành cuối là **0.1.11** (09/01/2026). Dòng này không còn được cập nhật và **không được tài liệu này mô tả** — mọi trang tham chiếu ở đây nói về 1.x. Nếu bạn đang đọc một tài liệu, một bài viết hay một câu trả lời của trợ lý AI mà nó dùng `clients.` (số nhiều), `client.eod.market`, `client.reporting`, cột `Date` viết hoa hay `interval="1D"`, thì đó là nội dung của dòng 0.1.x — không lời gọi nào trong số đó chạy được trên bản 1.x. Từng chỗ gãy nằm ở bảng **Nâng cấp từ 0.1.x** đầu trang. ### Câu hỏi thường gặp **Phiên bản mới nhất của thư viện Python finlens là bản nào?** Bản mới nhất là **1.1.1**, phát hành ngày 06/08/2026 trên PyPI. Cài bằng `pip install finlens` và kiểm bằng `finlens.__version__` — chuỗi trả về phải bắt đầu bằng `1.`. Nếu nó vẫn là `0.1.x` thì máy đang chạy Python 3.10 hoặc cũ hơn: bản 1.x khai `requires-python >= 3.11` nên pip lặng lẽ lùi về dòng cũ thay vì báo lỗi. Các bản `1.0.0a1` đến `1.0.0a7` chỉ tồn tại trên TestPyPI và chưa bao giờ có trên PyPI. **Nâng finlens từ 0.1.x lên 1.x thì đoạn code nào bị gãy?** Bốn nhóm. Một, đổi tên: `client.eod.market` thành `client.eod.index`, `client.reporting` thành `client.financials`, `finlens.types` thành `finlens.typing`. Hai, tên cột nay viết thường theo snake_case nên `df["Date"]` ném `KeyError`, phải đổi thành `df["date"]`. Ba, `interval="1M"` bị từ chối — dùng `"1mo"` cho dữ liệu cuối ngày và `"1min"` cho dữ liệu trong phiên. Bốn, chữ ký: tham số tên `symbols` (cấp ngành là `icb`) và chỉ tham số đầu tiên là positional, nên `ohlcv("HPG", "2026-01-01", "1w")` ném `TypeError`. **Vì sao client.eod.market báo AttributeError?** Vì ở bản 1.x của thư viện Python finlens, namespace chỉ số đã đổi tên thành `client.eod.index`. Gọi `client.eod.index.ohlcv("VNINDEX")` thay cho `client.eod.market.ohlcv("VNINDEX")`. Cùng đợt đổi tên đó, `client.reporting` thành `client.financials`, và bản 1.x thêm hai namespace giá cuối ngày chưa từng có: `client.eod.derivative` cho hợp đồng phái sinh và `client.eod.warrant` cho chứng quyền có bảo đảm. Namespace `client.eod.sector` nay có thêm `ohlcv()` trả chỉ số ngành ICB, tính bằng điểm chỉ số. **Vì sao df['Date'] báo KeyError khi đọc dữ liệu chứng khoán bằng Python?** Vì tên cột đã đổi sang snake_case viết thường, không có ngoại lệ nào. Trong thư viện Python finlens bản 1.x, bảy cột của `ohlcv()` là `symbol`, `date`, `open`, `high`, `low`, `close`, `volume`; cấp ngành dùng `icb`, `icb_name`, `icb_level` thay cho cột mã cũ. Đây là `KeyError` chắc chắn chứ không phải thỉnh thoảng, vì bản 1.x bảo đảm frame luôn đủ cột đúng dtype kể cả khi không có dòng nào — không có đường nào để một tên cột viết hoa lọt qua. **interval='1M' báo lỗi ở bản mới, phải thay bằng gì?** Thay bằng `"1mo"` nếu bạn muốn một tháng, hoặc `"1min"` nếu bạn muốn một phút. Trong từ vựng cũ `1M` là một tháng còn `1m` là một phút, chỉ khác nhau ở chữ hoa nhưng lệch nhau 43.200 lần, nên thư viện Python finlens từ chối thẳng cả hai bằng `finlens.InvalidIntervalError` với mã `FL_VALIDATION_INTERVAL_AMBIGUOUS` kèm gợi ý thay vì đoán ý. Dữ liệu cuối ngày nhận `1d`, `1w`, `1mo`, `3mo`, `6mo`, `1y`; dữ liệu trong phiên nhận `1min`, `5min`, `15min`, `30min`, `1h`, `4h`. **Bản 1.x của finlens thêm những nhóm dữ liệu nào so với 0.1.x?** Bốn bề mặt mới. Dữ liệu trong phiên: `client.intraday.stock` và `client.intraday.derivative` với `ohlcv()`, `ticks()` (từng lệnh đã khớp) và `net_active_value()`, còn `client.intraday.index` có `ohlcv()` và `ticks()`. Báo cáo tài chính: `client.financials.statement()`, `periods()`, `line_items()`. Tra cứu danh mục: `client.meta.symbols()`, `sectors()`, `warrants()`. Ở giá cuối ngày có thêm hai namespace `client.eod.derivative` và `client.eod.warrant`, còn `client.eod.sector` được bổ sung `ohlcv()` trả chỉ số ngành ICB. Kèm theo là tham số `adjusted`, `refresh`, `on_error` và siêu dữ liệu `df.attrs["finlens"]` mang đơn vị từng cột. **Bản 1.1.1 của thư viện Python finlens thêm những gì?** Bản 1.1.1 chỉ thêm, không phương thức nào đổi chữ ký và không cột nào đổi tên. Bốn nhóm dữ liệu mới: `client.eod.stock.supply_demand()` trả khối lượng và số lệnh ĐẶT vào sổ — là lệnh đặt chứ không phải lệnh đã khớp, trung vị tỷ lệ trên khối lượng khớp là 2,756 lần; `client.eod.stock.active_volume()` cùng `client.eod.derivative.active_volume()` trả khối lượng khớp chủ động hai rổ và không có cột tiền, nên không cộng được với `client.intraday.*.net_active_value()` vốn có ba rổ tính bằng VND; `client.eod.derivative.basis()` cùng `client.intraday.derivative.basis()` trả chênh lệch hợp đồng tương lai với chỉ số cơ sở, cả hai đều không có tham số `interval`; và `client.eod.derivative.investor.flow()` cùng `breakdown()` trả dòng tiền cấp hợp đồng phái sinh với đúng hai nhóm `foreign` và `proprietary`. Kèm mã lỗi `FL_DATA_NO_UNDERLYING` và hai kiểu `DerivativeInvestorGroup`, `DerivativeInvestorGroupsArg`. --- # Giá lịch sử cổ phiếu Việt Nam bằng Python (EOD) URL: https://docs.finlens.vn/python-sdk/eod Mô tả: Dùng finlens lấy OHLCV cuối ngày, sổ lệnh đặt, khối lượng chủ động, chênh lệch phái sinh và dòng tiền nhóm nhà đầu tư của chứng khoán Việt Nam về pandas DataFrame. Tóm tắt: Trang mô tả nhóm `client.eod` của thư viện Python finlens — giá theo phiên và dòng tiền theo nhóm nhà đầu tư của thị trường chứng khoán Việt Nam, trả về `pandas.DataFrame`. Năm namespace con chia theo loại tài sản vì mỗi loại một đơn vị: `client.eod.stock.ohlcv()` tính bằng nghìn VND, `client.eod.index.ohlcv()` và `client.eod.derivative.ohlcv()` tính bằng điểm chỉ số, `client.eod.warrant.ohlcv()` tính bằng VND thô, còn `client.eod.sector.ohlcv()` trả chỉ số ngành ICB. Chữ ký là `ohlcv(symbols, *, start=None, end=None, interval="1d", adjusted=True, refresh=False, on_error="warn")` — chỉ tham số đầu là positional, mọi tham số còn lại keyword-only; ở cấp ngành tham số đầu tên `icb`, nhận mã ICB dạng chuỗi kèm `icb_level` bằng 4 hoặc 2. Cột trả về viết thường: `symbol`, `date`, `open`, `high`, `low`, `close`, `volume`; `interval` nhận `1d`, `1w`, `1mo`, `3mo`, `6mo`, `1y` và việc gộp kỳ chạy ở máy chủ. Với năm giá trị có gộp kỳ, cột `date` là phiên giao dịch cuối cùng thực sự có dữ liệu trong kỳ — không phải ngày đầu kỳ và cũng không phải ngày cuối theo lịch, nên `interval="1mo"` cho tháng 1/2025 trả về `2025-01-24`. Dòng tiền lấy bằng `client.eod.stock.investor.flow()` và `breakdown()`, cấp chỉ số chỉ có `flow()` và hiện chỉ `VNINDEX` có dữ liệu, cấp ngành chỉ phục vụ `foreign` và `proprietary`; frame luôn đủ chín cột kể cả khi 0 dòng: `symbol`, `date`, `group`, `buy_value`, `sell_value`, `net_value`, `buy_volume`, `sell_volume`, `net_volume`, đơn vị VND thô. Bản 1.1.1 thêm bốn bề mặt cuối ngày. `client.eod.stock.supply_demand()` trả khối lượng và số lệnh ĐẶT vào sổ với các cột `buy_order_volume`, `sell_order_volume`, `net_order_volume`, `buy_order_count`, `sell_order_count`, `net_order_count` — đây là lệnh đặt chứ không phải lệnh đã khớp, trung vị tỷ lệ `buy_order_volume / volume` là 2,756 lần, ba cột `_count` dùng kiểu `Int64` nullable nên kiểm bằng `.isna()` chứ đừng so với 0, và phương thức này chỉ tồn tại ở `client.eod.stock`. `client.eod.stock.active_volume()` cùng `client.eod.derivative.active_volume()` trả `active_buy_volume`, `active_sell_volume`, `net_active_volume` — hai rổ và không có cột tiền nào, nên không cộng được với `client.intraday.*.net_active_value()` vốn có ba rổ tính bằng VND: cùng một phiên VN30F1M hai bên lệch nhau 57,5%, 520% và 30,1%. `client.eod.derivative.basis()` trả `symbol`, `index_symbol`, `date`, `future_close`, `spot_close`, `basis`, `basis_pct`, với `basis = future_close - spot_close` tính bằng điểm chỉ số và `basis_pct = basis / spot_close * 100` trên thang 0–100 — mẫu số là giá chỉ số chứ không phải giá hợp đồng — và đây là phương thức duy nhất của nhóm EOD không có tham số `interval`. `client.eod.derivative.investor.flow()` cùng `breakdown()` dùng chung schema chín cột với cấp mã nhưng chỉ phục vụ `foreign` và `proprietary`, khối lượng tính bằng hợp đồng, và giá trị là giá trị danh nghĩa của số hợp đồng đã khớp chứ không phải vị thế mở. In English: end-of-day OHLCV for Vietnamese stocks, indices, futures, covered warrants and ICB sector indices, plus order-book supply and demand, active traded volume, futures basis and investor money flows, as pandas DataFrames. Sản phẩm: python-sdk Nhóm `client.eod` trả về **giá theo phiên**, **sổ lệnh đặt**, **khối lượng khớp chủ động**, **chênh lệch phái sinh với chỉ số cơ sở** và **dòng tiền theo nhóm nhà đầu tư** dưới dạng `pandas.DataFrame`. Năm namespace con chia theo loại tài sản, và đó không phải cách đặt tên cho gọn: mỗi loại tài sản một đơn vị, nên một lời gọi không bao giờ trả về bảng trộn nghìn VND với điểm chỉ số. ```python import finlens client = finlens.client() # đọc khoá từ biến FINLENS_API_KEY df = client.eod.stock.ohlcv("HPG,VCB", start="2026-01-01") df.attrs["finlens"]["units"]["close"] # 'kVND' ``` | Bản 0.1.x | Bản 1.x | | --------------------------------------- | ---------------------------------------------------------------- | | `client.eod.market` | **`client.eod.index`** | | Cột `Date`, `Open`, `Close`, `Volume` | **`date`, `open`, `close`, `volume`** — snake\_case, viết thường | | `interval="1M"` | **`interval="1mo"`** — cả `1M` lẫn `1m` đều bị từ chối | | Tham số `symbol` (số ít) | **`symbols`**; ở cấp ngành là **`icb`** | | Ngành nhận tên tiếng Việt `"Ngân hàng"` | Ngành nhận **mã ICB dạng chuỗi**: `"8600"` | | `ohlcv("HPG", start, end, "1W")` | Mọi tham số sau mã là **keyword-only** | Danh sách đầy đủ ở [Changelog](/python-sdk/changelog). ## Năm namespace, năm đơn vị [#năm-namespace-năm-đơn-vị] | Namespace | Dữ liệu | Cột giá | Khối lượng | Phương thức | | ----------------------- | ---------------------- | ------------- | ------------ | ---------------------------------------------------------------------------------------------- | | `client.eod.stock` | Cổ phiếu và ETF | **nghìn VND** | cổ phiếu | `ohlcv()` · `supply_demand()` · `active_volume()` · `investor.flow()` · `investor.breakdown()` | | `client.eod.index` | Chỉ số | điểm chỉ số | cổ phiếu | `ohlcv()` · `investor.flow()` | | `client.eod.derivative` | Hợp đồng phái sinh | điểm chỉ số | **hợp đồng** | `ohlcv()` · `active_volume()` · `basis()` · `investor.flow()` · `investor.breakdown()` | | `client.eod.warrant` | Chứng quyền có bảo đảm | **VND thô** | chứng quyền | `ohlcv()` | | `client.eod.sector` | Ngành ICB | điểm chỉ số | cổ phiếu | `ohlcv()` · `investor.flow()` · `investor.breakdown()` | Việc tách namespace chính là thứ bảo đảm đơn vị: `client.eod.stock` và `client.eod.index` không bao giờ trả về cùng một bảng, nên `pd.concat` hai kết quả của **cùng một** namespace luôn an toàn về đơn vị. Bảng chỉ liệt kê những phương thức **thực sự tồn tại**, và chỗ nào không liệt kê thì gọi vào sẽ ném `AttributeError` ngay tại chỗ: ```python client.eod.warrant.supply_demand("CHPG2628") # AttributeError client.eod.derivative.supply_demand("VN30F1M") # AttributeError client.eod.index.active_volume("VNINDEX") # AttributeError client.eod.stock.basis("HPG") # AttributeError ``` Sổ lệnh đặt chỉ tồn tại cho **cổ phiếu** trong dữ liệu; hỏi nó cho chỉ số, ngành, chứng quyền hay phái sinh cho ra **0 dòng**. Còn `basis()` cần một chỉ số cơ sở để trừ, và chỉ hợp đồng tương lai mới có thứ đó. Một sự vắng mặt trong dữ liệu phải là một sự vắng mặt trong API — cùng lý do `client.intraday.index` không có `net_active_value()`. Phát ra một phương thức luôn trả bảng rỗng là bắt bạn tự đoán xem đó là "không có giao dịch" hay "không có dữ liệu". `client.eod.sector.ohlcv()` trả về **chỉ số ngành**, tính bằng **điểm chỉ số**. `client.eod.sector.investor.flow()` trả về **dòng tiền**, tính bằng **VND thô**. Hai bảng cùng khoá theo `icb`, cùng nằm trong một namespace, nên cám dỗ chia bảng này cho bảng kia là có thật — và làm vậy là chia hai đại lượng không cùng thứ nguyên. Không có exception nào được ném. ## Luật chung cho mọi hàm trong `client.eod` [#luật-chung-cho-mọi-hàm-trong-clienteod] Bảy điều dưới đây đúng cho **mọi** phương thức của nhóm EOD, nên phần tham chiếu bên dưới không nhắc lại chúng. **1. Chỉ tham số đầu tiên là positional.** Đó là `symbols` (hoặc `icb` ở cấp ngành). Mọi tham số còn lại là keyword-only: ```python client.eod.stock.ohlcv("HPG", start="2026-01-01", interval="1w") # đúng client.eod.stock.ohlcv("HPG", "2026-01-01", "1w") # TypeError ``` Đây là hàng rào cho một lớp bug đã xảy ra thật ở 0.1.x, nơi thứ tự tham số khiến một chuỗi interval bị gán nhầm vào một cờ boolean — không lỗi, và dữ liệu vẫn về. **2. Một mã, nhiều mã, hay một danh sách đều được.** Ba cách viết sau tương đương, và nhiều mã đi trong **một** lời gọi mạng chứ không phải nhiều lời gọi tuần tự: ```python client.eod.stock.ohlcv("HPG") client.eod.stock.ohlcv("HPG,VCB") client.eod.stock.ohlcv(["HPG", "VCB"]) ``` **3. `interval` viết thường, và việc gộp kỳ chạy ở máy chủ.** Sáu giá trị: `1d` · `1w` · `1mo` · `3mo` · `6mo` · `1y`. `interval="1w"` trả về thanh tuần đã gộp sẵn, không phải thanh ngày để bạn tự gộp. Một ngoại lệ duy nhất trong cả nhóm EOD: **`basis()` không có tham số `interval`** — lý do nằm ở mục của chính nó bên dưới. Trong từ vựng cũ `1M` là một **tháng** còn `1m` là một **phút** — phân biệt duy nhất bằng chữ hoa, trong khi hai giá trị đó lệch nhau 43.200 lần. Cả hai đều nhận một lỗi rõ ràng thay vì bị đoán ý: ```text Interval '1M' nhập nhằng: có thể là một phút hoặc một tháng. Dùng '1min' cho một phút, hoặc '1mo' cho một tháng. ``` Với dữ liệu cuối ngày, giá trị bạn cần là **`1mo`**. Lỗi là `finlens.InvalidIntervalError`, mã `FL_VALIDATION_INTERVAL_AMBIGUOUS`. **4. Một kỳ đã gộp được dán nhãn bằng phiên giao dịch CUỐI trong kỳ.** Với `interval="1d"`, `date` là ngày của chính phiên đó. Với năm giá trị còn lại — `1w`, `1mo`, `3mo`, `6mo`, `1y` — `date` là **phiên giao dịch cuối cùng thực sự có dữ liệu** trong kỳ. Không phải ngày đầu kỳ, và cũng **không phải ngày cuối theo lịch**. ```python df = client.eod.stock.ohlcv("HPG", start="2025-01-01", end="2025-03-31", interval="1mo") df["date"].dt.strftime("%Y-%m-%d").tolist() # ['2025-01-24', '2025-02-28', '2025-03-31'] ``` Tháng 1/2025 ra `2025-01-24` chứ không phải `2025-01-01`, và cũng không phải `2025-01-31`: thị trường nghỉ Tết từ ngày 25, nên phiên cuối cùng có dữ liệu là ngày 24. Đó đúng là phiên mà `close` của dòng ấy lấy giá — ngày và giá kể cùng một chuyện. Lấy ngày cuối theo lịch thì chúng kể hai chuyện khác nhau, và độ lệch lớn nhất rơi đúng vào những kỳ có kỳ nghỉ dài. `date` là phiên **cuối** kỳ, nhưng `open` là giá mở cửa của phiên **đầu** kỳ. Hai cột trên cùng một dòng trỏ tới hai phiên khác nhau, và điều đó là đúng: dòng ấy mô tả cả kỳ, chỉ được dán nhãn bằng phiên cuối. Nên đừng đọc một dòng `1mo` như thể nó là phiên ngày 24/01. `open` của nó không phải giá mở cửa hôm 24/01, và `volume` của nó không phải khối lượng riêng phiên ấy — đó là tổng cả tháng. Hai hệ quả đáng dùng: * **Kỳ đang dở không bao giờ mang một mốc ở tương lai.** Kỳ `1mo` của tháng này, hay kỳ `1y` của năm nay, được dán nhãn bằng phiên gần nhất đã có dữ liệu chứ không phải ngày cuối tháng hay 31/12. Nhờ vậy `df[df["date"] <= hom_nay]` không âm thầm đánh rơi kỳ hiện tại — một cái bẫy mà nhãn theo lịch chắc chắn giăng ra. * **Muốn nhãn theo kỳ thì tự đổi, đừng suy ra bằng phép trừ.** Khoảng cách giữa `date` và mốc đầu kỳ không cố định, nên `df["date"] - pd.offsets.MonthBegin()` là sai. Dùng `df["date"].dt.to_period("M")` — nó lấy kỳ chứa ngày đó. **5. `refresh=False` — bỏ qua bản đã lưu trong cache.** Dùng khi bạn biết dữ liệu vừa đổi. Đừng đặt mặc định là `True`: nó vô hiệu hoá chính thứ giữ cho một lời gọi 50 mã rẻ như một lời gọi. **6. `on_error="warn"` — một mã hỏng không làm mất các mã còn lại.** | Giá trị | Hành vi | | ------------------------------- | ----------------------------------------------------------------------------------------------------- | | `"warn"` *(mặc định)* | Giữ phần lấy được, phát `finlens.PartialDataWarning`, ghi mã hỏng vào `df.attrs["finlens"]["failed"]` | | `"raise"` | Ném `finlens.PartialFetchError` — ngoại lệ này **mang theo** phần đã lấy được ở `.data` | | `"ignore"` | Giữ phần lấy được, không cảnh báo | ```python df = client.eod.stock.ohlcv("HPG,KHONGTONTAI") df.attrs["finlens"]["partial"] # True df.attrs["finlens"]["failed"] # {'KHONGTONTAI': {'code': ..., 'message': ...}} ``` Chi tiết ở [Xử lý lỗi](/python-sdk/xu-ly-loi). **7. Kết quả rỗng vẫn đủ cột và đúng kiểu.** Ngày thị trường nghỉ, hay khoảng thời gian không có dữ liệu, bạn nhận về một DataFrame **0 dòng nhưng đủ cột** — nên `df["close"]` không ném `KeyError` và bạn không cần viết `if not df.empty` quanh mọi lời gọi. ## `ohlcv()` — giá theo phiên [#ohlcv--giá-theo-phiên] Có mặt ở bốn namespace: `stock`, `index`, `derivative`, `warrant`. Bản cấp ngành nhận mã ICB nên có chữ ký riêng — xem mục **Chỉ số ngành ICB** bên dưới. ```python ohlcv(symbols, *, start=None, end=None, interval="1d", adjusted=True, refresh=False, on_error="warn") ``` | Tham số | Kiểu | Mặc định | Mô tả | | ---------- | ------------- | -------- | ----------------------------------------------------------------------------------------------------------------------- | | `symbols` | `SymbolsArg` | — | `"HPG"`, `"HPG,VCB"`, hoặc `["HPG", "VCB"]`. Mọi mã phải cùng loại tài sản với namespace đang gọi. **Positional.** | | `start` | `DateArg` | `None` | Ngày bắt đầu. Mặc định **1 năm trước** `end`. | | `end` | `DateArg` | `None` | Ngày kết thúc. Mặc định hôm nay. | | `interval` | `EodInterval` | `"1d"` | `1d` · `1w` · `1mo` · `3mo` · `6mo` · `1y`. | | `adjusted` | `bool` | `True` | Giá đã điều chỉnh quyền hay giá khớp lệnh thật. Xem mục dưới. | | `refresh` | `bool` | `False` | Bỏ qua cache. | | `on_error` | `OnError` | `"warn"` | `warn` · `raise` · `ignore`. | ### Cột trả về [#cột-trả-về] | Cột | Kiểu | Có thể `NaN` | Đơn vị | Mô tả | | -------- | ---------------- | ------------ | ------------------- | ----------------------------------------------------------------------------------------------- | | `symbol` | `string` | không | — | Mã chứng khoán, viết hoa. | | `date` | `datetime64[ns]` | không | — | Ngày giao dịch, **không mang múi giờ**. Với interval có gộp kỳ, đây là **phiên cuối** trong kỳ. | | `open` | `float64` | có | theo namespace | Giá mở cửa kỳ — giá mở cửa của phiên **đầu** kỳ, không phải phiên mà `date` trỏ tới. | | `high` | `float64` | có | theo namespace | Giá cao nhất trong kỳ. | | `low` | `float64` | có | theo namespace | Giá thấp nhất trong kỳ. | | `close` | `float64` | có | theo namespace | Giá đóng cửa kỳ — giá đóng cửa của đúng phiên mà `date` trỏ tới. | | `volume` | `float64` | có | cổ phiếu / hợp đồng | Khối lượng khớp, **cộng dồn** trong kỳ. | Bảng được sắp theo `symbol` rồi `date`, chỉ mục là `RangeIndex` mặc định. Hai chi tiết hay làm người đọc vấp: * **`date` cố ý không mang múi giờ.** Một ngày giao dịch không phải một thời điểm; gắn múi giờ vào nó tạo ra một thời điểm giả lúc 00:00 mà không ai muốn nói tới. Cột `time` của dữ liệu [trong phiên](/python-sdk/intraday) thì ngược lại — nó *là* một thời điểm nên có mang múi giờ. * **`volume` là `float64` chứ không phải `int64`,** vì cột này nullable và `int64` của pandas không mang được `NaN`. Một kỳ không có dữ liệu phải ra `NaN` chứ không phải `0` — "không có dữ liệu" khác "khối lượng bằng 0". Kiểm bằng `.isna()`, đừng so với `0`. ### `adjusted` — giá điều chỉnh hay giá khớp lệnh thật [#adjusted--giá-điều-chỉnh-hay-giá-khớp-lệnh-thật] ```python # Mặc định: giá đã điều chỉnh quyền — chuỗi liên tục, dùng để tính lợi suất df = client.eod.stock.ohlcv("VCB", start="2020-01-01") df.attrs["finlens"]["price_basis"] # 'adjusted' # Giá khớp lệnh thật của phiên đó — dùng khi đối chiếu sao kê hay tính thuế raw = client.eod.stock.ohlcv("VCB", start="2020-01-01", adjusted=False) raw.attrs["finlens"]["price_basis"] # 'raw' ``` Giá điều chỉnh được scale lại sau mỗi lần chia tách hay trả cổ tức, nên chúng **không khớp** với giá bảng điện của ngày đó. Ba hệ quả đáng nhớ: * **Giá điều chỉnh thay đổi theo thời gian.** Sau mỗi sự kiện quyền, toàn bộ lịch sử được tính lại — cùng một lời gọi chạy hôm nay và tháng sau có thể ra số khác. Nếu bạn lưu kết quả ra parquet để dùng lâu dài, hãy lưu kèm bản `adjusted=False`; chỉ giá khớp lệnh mới là bất biến. * **Cột `volume` không đổi theo cờ này.** Nó luôn là số cổ phiếu thật, nên với `adjusted=True` thì `close * volume` **không** bằng giá trị giao dịch thật của phiên. * **Chỉ số, phái sinh và chứng quyền không có giá điều chỉnh.** Với chúng `price_basis` luôn là `raw`, bất kể bạn truyền gì vào `adjusted`. Giá luôn được làm tròn **2 chữ số thập phân**: HOSE có bước giá 10 đồng, nên chữ số thứ ba trở đi chỉ là phần dư của phép chia khi tính giá điều chỉnh. ### Bốn namespace trong thực tế [#bốn-namespace-trong-thực-tế] ```python # Cổ phiếu và ETF — nghìn VND. 23.17 nghĩa là 23.170 đồng. client.eod.stock.ohlcv("HPG,VCB,FPT", start="2026-01-01") # Chỉ số — điểm chỉ số, không phải nghìn VND. client.eod.index.ohlcv("VNINDEX", interval="1mo") # Phái sinh — điểm chỉ số, khối lượng tính bằng HỢP ĐỒNG. client.eod.derivative.ohlcv("VN30F1M") # Chứng quyền — VND THÔ. Cộng thẳng với giá cổ phiếu là sai 1000 lần. client.eod.warrant.ohlcv("CHPG2628") ``` `client.eod.stock` trả giá bằng **nghìn VND**, `client.eod.warrant` trả giá bằng **VND thô**. Đây đúng là kịch bản sai âm thầm: hai bảng cùng tên cột, cùng kiểu, và phép trừ giữa chúng vẫn chạy. Đọc `df.attrs["finlens"]["units"]["close"]` trước khi tính bất cứ thứ gì bắc cầu giữa hai namespace. ## `client.eod.sector.ohlcv()` — chỉ số ngành ICB [#clienteodsectorohlcv--chỉ-số-ngành-icb] Chuỗi giá của **chỉ số ngành ICB**, một lời gọi cho nhiều ngành. Khoá là **mã ngành**, không phải mã chứng khoán — nên tham số đầu tiên tên là `icb`, và chữ ký khác bốn namespace kia. ```python ohlcv(icb, *, icb_level=4, start=None, end=None, interval="1d", refresh=False, on_error="warn") ``` | Tham số | Kiểu | Mặc định | Mô tả | | ----------- | ------------- | -------- | ----------------------------------------------------------------------------------------------- | | `icb` | `IcbArg` | — | `"8600"`, `"8600,3570"`, hoặc `["8600", "3570"]`. Chuỗi chứ không phải số. **Positional.** | | `icb_level` | `IcbLevel` | `4` | Cấp ICB: `4` hoặc `2`. Cấp khác nhận lỗi 400. | | `start` | `DateArg` | `None` | Ngày bắt đầu. Mặc định 1 năm trước `end`. | | `end` | `DateArg` | `None` | Ngày kết thúc. Mặc định hôm nay. | | `interval` | `EodInterval` | `"1d"` | `1d` · `1w` · `1mo` · `3mo` · `6mo` · `1y`. | | `refresh` | `bool` | `False` | Bỏ qua cache. | | `on_error` | `OnError` | `"warn"` | `warn` · `raise` · `ignore`. | Không có tham số `adjusted` ở đây: chỉ số ngành không phải giá của một mã nào nên không có sự kiện quyền nào để điều chỉnh. `price_basis` luôn là `raw`. **Mã ngành phải là chuỗi**, vì `8600` viết dạng số sẽ làm mất số `0` đứng đầu ở các mã ngành khác. Mọi mã trong một lời gọi phải thuộc đúng cấp khai ở `icb_level`; mã lệch cấp đi vào phần lỗi **theo từng mã** chứ không làm hỏng cả lời gọi. Không nhớ mã ngành thì tra bằng `client.meta.sectors(level=4)` — xem [Tra cứu danh mục](/python-sdk/tra-cuu-danh-muc). ### Cột trả về [#cột-trả-về-1] | Cột | Kiểu | Có thể `NaN` | Đơn vị | Mô tả | | ----------- | ---------------- | ------------ | --------------- | ------------------------------------------------------------------------------------------- | | `icb` | `string` | không | — | Mã ngành ICB. | | `icb_name` | `string` | **có** | — | Tên ngành. `null` khi mã ngành có trong bảng chỉ số nhưng chưa có trong danh mục ngành. | | `icb_level` | `int8` | không | — | Cấp của mã ngành: `2` hoặc `4`. | | `date` | `datetime64[ns]` | không | — | Ngày giao dịch, không mang múi giờ. Với interval có gộp kỳ, đây là **phiên cuối** trong kỳ. | | `open` | `float64` | có | **điểm chỉ số** | Giá trị chỉ số của phiên **đầu** kỳ. | | `high` | `float64` | có | **điểm chỉ số** | Giá trị chỉ số cao nhất trong kỳ. | | `low` | `float64` | có | **điểm chỉ số** | Giá trị chỉ số thấp nhất trong kỳ. | | `close` | `float64` | có | **điểm chỉ số** | Giá trị chỉ số của phiên **cuối** kỳ — đúng phiên mà `date` trỏ tới. | | `volume` | `float64` | có | cổ phiếu | Tổng khối lượng khớp của các mã cấu thành, cộng dồn trong kỳ. | | `n_stocks` | `Int32` | **có** | — | Số mã cấu thành chỉ số trong kỳ. | ```python df = client.eod.sector.ohlcv("8600", start="2026-01-01") df.attrs["finlens"]["units"]["close"] # 'index_point' # Cấp 2 — cũng là số gốc chứ không phải số cộng lên df = client.eod.sector.ohlcv("8000", icb_level=2) ``` `Int32` viết hoa là kiểu số nguyên **nullable** của pandas, không phải `int32` của numpy. Phiên nào nguồn không có số mã cấu thành thì đó là **thiếu**, và `int32` thường sẽ biến cái thiếu ấy thành `0` — tức thành "ngành này không có mã nào", một câu khác hẳn, mà không có lỗi nào được ném. ```python df[df["n_stocks"].isna()] # đúng df[df["n_stocks"] == 0] # sai — trộn "thiếu dữ liệu" với "không có mã nào" ``` Cột này được phát ra chứ không bị giấu vì nó **giải thích** những bước nhảy của chuỗi chỉ số: một ngành từ 3 mã lên 5 mã thì chuỗi đứt đoạn ở đúng chỗ ấy, và không cột nào khác nói ra được. Khi resample, `n_stocks` lấy giá trị của **phiên cuối kỳ** — đúng phiên mà `date` trỏ tới — chứ không phải tổng. Nó là một trạng thái, không phải một lượng cộng dồn được. **Cả hai cấp ICB đều là số gốc ở phương thức này.** Chỉ số ngành được tính sẵn ở cả cấp 2 lẫn cấp 4, nên ở đây không có phép cộng nào. Đó là chỗ nó khác `investor.flow()` cùng namespace, nơi con số cấp 2 là tổng do máy chủ cộng từ các ngành con cấp 4 — đừng chuyển kết luận từ phương thức này sang phương thức kia. ## `supply_demand()` — khối lượng và số lệnh ĐẶT vào sổ [#supply_demand--khối-lượng-và-số-lệnh-đặt-vào-sổ] Chỉ có ở **`client.eod.stock`**. Chỉ số, ngành, chứng quyền và phái sinh không có dữ liệu sổ lệnh nào, nên chúng không phát phương thức này. ```python supply_demand(symbols, *, start=None, end=None, interval="1d", refresh=False, on_error="warn") ``` | Tham số | Kiểu | Mặc định | Mô tả | | ---------------------------------- | ------------- | -------- | ---------------------------------------------------------------------------------- | | `symbols` | `SymbolsArg` | — | `"HPG"`, `"HPG,VCB"`, hoặc `["HPG", "VCB"]`. **Positional.** | | `interval` | `EodInterval` | `"1d"` | `1d` · `1w` · `1mo` · `3mo` · `6mo` · `1y`. Khi gộp kỳ, **mọi cột đều được CỘNG**. | | `start` `end` `refresh` `on_error` | | | Như mọi hàm EOD khác. | Trung vị của tỷ lệ `buy_order_volume / volume` — cùng mã, cùng phiên, với `volume` là khối lượng **khớp** của `ohlcv()` — là **2,756 lần**. 99,77% số dòng có khối lượng đặt lớn hơn hoặc bằng khối lượng khớp, và có rất nhiều phiên khối lượng khớp bằng **0** mà sổ lệnh vẫn có lệnh đặt. Đó là lý do **mọi tên cột ở đây mang chữ `_order_`**. Trừ một cột của bảng này cho `volume` của `ohlcv()`, hay đặt nó cạnh `buy_volume` của `investor.flow()`, là so hai đại lượng chênh nhau khoảng ba lần — và **không có exception nào chặn phép tính đó**. ```python dat = client.eod.stock.supply_demand("HPG", start="2026-08-01") khop = client.eod.stock.ohlcv("HPG", start="2026-08-01") # dat["buy_order_volume"] - khop["volume"] <- vô nghĩa, và vẫn chạy ``` Đại lượng này trả lời "áp lực đặt lệnh bên nào lớn hơn", không trả lời "ai đã mua bao nhiêu". ### Cột trả về [#cột-trả-về-2] Tám cột, **luôn đủ** kể cả khi không có dòng nào. Sáu cột số chia làm **hai họ, hai kiểu dữ liệu**. | Cột | Kiểu | Có thể thiếu | Đơn vị | Mô tả | | ------------------- | ---------------- | ------------ | -------- | ------------------------------------------------------------------------------------------- | | `symbol` | `string` | không | — | Mã chứng khoán, viết hoa. | | `date` | `datetime64[ns]` | không | — | Ngày giao dịch, không mang múi giờ. Với interval có gộp kỳ, đây là **phiên cuối** trong kỳ. | | `buy_order_volume` | `float64` | có | cổ phiếu | Khối lượng **đặt mua** trong kỳ. | | `sell_order_volume` | `float64` | có | cổ phiếu | Khối lượng **đặt bán** trong kỳ. | | `net_order_volume` | `float64` | có | cổ phiếu | `buy_order_volume - sell_order_volume`. Dương là áp lực đặt mua lớn hơn. | | `buy_order_count` | `Int64` | **có** | — | Số **lệnh** đặt mua trong kỳ. | | `sell_order_count` | `Int64` | **có** | — | Số **lệnh** đặt bán trong kỳ. | | `net_order_count` | `Int64` | **có** | — | `buy_order_count - sell_order_count`. | Ba cột `_count` **không mang đơn vị**: một cái đếm không có thứ nguyên nào, nên `units["buy_order_count"]` là `None` chứ không phải bỏ sót. ```python df = client.eod.stock.supply_demand("HPG", start="2026-08-01") df.attrs["finlens"]["units"]["buy_order_volume"] # 'share' ``` `Int64` viết hoa là kiểu số nguyên **nullable** của pandas, không phải `int64` của numpy. Máy chủ phát giá trị thiếu khi nguồn không ghi số lệnh trong khi vẫn ghi khối lượng, và điều đó xảy ra ở khoảng **11%** số dòng. `int64` thường không mang được giá trị thiếu nên nó sẽ biến cái thiếu ấy thành `0` — tức thành "phiên này không ai đặt lệnh mua", một câu khác hẳn, mà không có lỗi nào được ném. ```python df[df["buy_order_count"].isna()] # đúng df[df["buy_order_count"] == 0] # sai — trộn "chưa biết" với "không có lệnh" ``` Và khi gộp kỳ: **một kỳ chứa dù chỉ một phiên thiếu số lệnh thì cả ba cột `_count` của kỳ đó đều thiếu.** Một tổng thiếu trông hợp lý còn nguy hiểm hơn một ô trống. Ba cột `_volume` không chịu ràng buộc này. Ba cột khối lượng là `float64` chứ không phải một kiểu nguyên, và đó là một lời hứa được giữ: nguồn lưu chúng ở độ chính xác đơn, nên những con số hàng chục triệu **đã** được làm tròn trước khi tới bạn. Khai kiểu nguyên sẽ nói rằng đây là số đếm chính xác từng cổ phiếu; nó không phải. **Khi gộp kỳ, mọi cột đều cộng dồn** — khác quy tắc của OHLCV, nơi `open` và `close` lấy hai đầu kỳ. `interval="1w"` cho một dòng mỗi tuần, giá trị là **tổng** của các phiên trong tuần. ## `active_volume()` — khối lượng khớp lệnh CHỦ ĐỘNG [#active_volume--khối-lượng-khớp-lệnh-chủ-động] Có ở **`client.eod.stock`** và **`client.eod.derivative`**. Cùng bộ tên cột, khác đơn vị khối lượng. ```python active_volume(symbols, *, start=None, end=None, interval="1d", refresh=False, on_error="warn") ``` ```python cp = client.eod.stock.active_volume("HPG", start="2026-08-01") cp.attrs["finlens"]["units"]["net_active_volume"] # 'share' ps = client.eod.derivative.active_volume("VN30F1M") ps.attrs["finlens"]["units"]["net_active_volume"] # 'contract' ``` Hai đại lượng nghe giống nhau và **không cộng được với nhau**. Cùng một phiên VN30F1M, ba cột tương ứng của hai bảng lệch nhau **57,5% · 520% · 30,1%**. | | `eod.*.active_volume()` | `intraday.*.net_active_value()` | | -------- | ------------------------------------ | -------------------------------------------------------------------- | | Số rổ | **hai** — mua chủ động, bán chủ động | **ba** — thêm `auction` tách riêng | | Cột tiền | **không có cột nào** | `buy_value`, `sell_value`, `net_value`, `auction_value` bằng **VND** | | Nguồn | một bảng tổng hợp cuối ngày | dựng từ bảng lệnh đã khớp | Phép cộng hay phép trừ giữa hai frame **không ném exception nào**, chỉ cho ra một con số sai. Đó là lý do hai phương thức mang hai cái tên khác hẳn nhau, chứ không phải cùng tên ở hai namespace. ### Cột trả về [#cột-trả-về-3] Năm cột, luôn đủ kể cả khi không có dòng nào. **Không có cột nào mang giá trị tiền.** | Cột | Kiểu | Có thể `NaN` | Đơn vị | Mô tả | | -------------------- | ---------------- | ------------ | ----------------------- | ------------------------------------------------------------------------------------------- | | `symbol` | `string` | không | — | Mã chứng khoán hoặc mã hợp đồng, viết hoa. | | `date` | `datetime64[ns]` | không | — | Ngày giao dịch, không mang múi giờ. Với interval có gộp kỳ, đây là **phiên cuối** trong kỳ. | | `active_buy_volume` | `float64` | có | cổ phiếu / **hợp đồng** | Khối lượng **mua chủ động**: bên mua nâng giá chạm bên bán. | | `active_sell_volume` | `float64` | có | cổ phiếu / **hợp đồng** | Khối lượng **bán chủ động**: bên bán hạ giá chạm bên mua. | | `net_active_volume` | `float64` | có | cổ phiếu / **hợp đồng** | `active_buy_volume - active_sell_volume`. Dương là mua chủ động ròng. | **Đơn vị khối lượng đổi theo namespace** trong khi bộ tên cột giữ nguyên: cổ phiếu ở `client.eod.stock`, **hợp đồng** ở `client.eod.derivative`. Đọc `df.attrs["finlens"]["units"]["net_active_volume"]` thay vì giả định — đây đúng là kịch bản `pd.concat` hai frame rồi có một cột mang hai đơn vị. `active_buy_volume + active_sell_volume` bằng **đúng** khối lượng khớp cả phiên. Nguồn chia trọn 100% khối lượng thành đúng hai phía, nên phiên định kỳ ATO/ATC — vốn không có bên chủ động nào — đã nằm sẵn trong một trong hai cột. Hệ quả: `active_buy_volume` ở đây **rộng hơn** `buy_volume` của `client.intraday.*.net_active_value()`, nơi ATO/ATC có cột `auction_volume` riêng. Hai cái tên khác nhau chính vì hai định nghĩa khác nhau. Muốn tách bạch phần khớp lệnh định kỳ thì dùng bảng trong phiên, không dùng bảng này — xem [Dữ liệu trong phiên](/python-sdk/intraday). **Không có cột `*_value` nào, và đó không phải một thiếu sót.** Nguồn của bảng này không có cột tiền; quy đổi ra VND phải nhân giá và — với phái sinh — nhân hệ số hợp đồng. Chỉ `net_active_value()` trong phiên mới có đủ dữ liệu làm hai phép tính đó. **Khi gộp kỳ, mọi cột đều cộng dồn.** ## `basis()` — chênh lệch phái sinh và chỉ số cơ sở [#basis--chênh-lệch-phái-sinh-và-chỉ-số-cơ-sở] Chỉ có ở **`client.eod.derivative`**, và chỉ phục vụ các mã `VN30F*`. ```python basis(symbols, *, start=None, end=None, refresh=False, on_error="warn") ``` Đây là phương thức duy nhất của nhóm EOD không nhận `interval`, và `client.intraday.derivative.basis()` cũng vậy. Gộp một **chênh lệch** qua nhiều bước không có nghĩa hiển nhiên nào: trung bình của kỳ, giá trị cuối kỳ và biên độ trong kỳ là ba câu trả lời khác nhau cho cùng một câu hỏi. Chọn hộ một trong ba là chôn một quyết định phân tích vào thư viện. Cần thì `df.resample(...)` trên chính frame này, nơi bạn tự chọn. ### Cột trả về [#cột-trả-về-4] Bảy cột, luôn đủ kể cả khi không có dòng nào. | Cột | Kiểu | Có thể `NaN` | Đơn vị | Mô tả | | -------------- | ---------------- | ------------ | --------------- | ----------------------------------------------------------------------------------------- | | `symbol` | `string` | không | — | Mã hợp đồng phái sinh, ví dụ `VN30F1M`. | | `index_symbol` | `string` | không | — | Mã chỉ số cơ sở đã dùng để tính, ví dụ `VN30`. | | `date` | `datetime64[ns]` | không | — | Ngày giao dịch, không mang múi giờ. Không có gộp kỳ ở đây nên đây luôn là một phiên thật. | | `future_close` | `float64` | có | **điểm chỉ số** | Giá đóng cửa của hợp đồng tương lai. | | `spot_close` | `float64` | có | **điểm chỉ số** | Giá đóng cửa của chỉ số cơ sở. Đây là **mẫu số** của `basis_pct`. | | `basis` | `float64` | có | **điểm chỉ số** | `future_close - spot_close`. | | `basis_pct` | `float64` | có | **phần trăm** | `basis / spot_close * 100`. | ```text basis = future_close - spot_close # điểm chỉ số basis_pct = basis / spot_close * 100 # phần trăm, thang 0–100 ``` Hai chi tiết không suy ra được từ cái tên, nên cả hai được viết ra: * **Mẫu số là `spot_close`, không phải `future_close`.** Hai mẫu số chỉ lệch nhau khoảng **0,3%** nên chọn nhầm gần như không nhìn ra được trên một biểu đồ. * **Thang là 0–100, không phải 0–1.** Nhân thêm 100 lần nữa là sai 100 lần, cũng không có gì báo. `basis` thì là **hiệu tuyệt đối** — không chia cho gì, không nhân 100 — nên nó vẫn mang đơn vị của hai vế: **điểm chỉ số**. Dương là hợp đồng giao dịch cao hơn chỉ số (*contango*), âm là thấp hơn (*backwardation*). ```python df = client.eod.derivative.basis("VN30F1M", start="2026-08-01") df.attrs["finlens"]["units"]["basis"] # 'index_point' df.attrs["finlens"]["units"]["basis_pct"] # 'pct' sorted(df["index_symbol"].unique()) # ['VN30'] ``` Lý do rất cụ thể: `df.attrs` **biến mất** ngay khi bạn `pd.concat` hai frame. Khi đó hai dòng của hai hợp đồng trên hai chỉ số khác nhau trông y hệt nhau, trong khi `basis` của chúng đo hai thứ khác nhau — và không cột nào còn nói ra được điều đó. Mã không phải phái sinh nhận lỗi **400** ngay. Nhưng một mã phái sinh **có tồn tại** mà không có chuỗi chỉ số cơ sở trong dữ liệu thì đi vào phần lỗi theo từng mã với mã lỗi `FL_DATA_NO_UNDERLYING`, ánh xạ về `finlens.NoDataError`: ```python df = client.eod.derivative.basis(["VN30F1M", "VN100F1M"]) # PartialDataWarning — df chỉ chứa VN30F1M df.attrs["finlens"]["failed"] # {'VN100F1M': {'code': 'FL_DATA_NO_UNDERLYING', 'message': ...}} ``` Mã lỗi này khác `FL_DATA_EMPTY` vì hai bệnh khác nhau: `FL_DATA_EMPTY` là *khoảng bạn hỏi không có dòng nào*, còn mã này là *hợp đồng này không có chỉ số cơ sở*, tức không đổi `start`/`end` nào cứu được. Nó cũng **không** phải `InvalidSymbolError` — mã bạn gõ hoàn toàn đúng. Đây là hành vi mặc định `on_error="warn"`; đặt `on_error="raise"` nếu bạn muốn một mã hỏng làm hỏng cả lời gọi. Bản bước 1 phút của cùng công thức nằm ở [`client.intraday.derivative.basis()`](/python-sdk/intraday). ## Dòng tiền theo nhóm nhà đầu tư [#dòng-tiền-theo-nhóm-nhà-đầu-tư] Hai phương thức, có mặt ở bốn cấp: | Đường dẫn | `flow()` | `breakdown()` | Nhóm phục vụ | Khối lượng | | -------------------------------- | -------- | ------------- | ------------------------------------------- | ------------ | | `client.eod.stock.investor` | ✔ | ✔ | cả sáu nhóm | cổ phiếu | | `client.eod.index.investor` | ✔ | — | cả sáu nhóm, nhưng chỉ `VNINDEX` có dữ liệu | cổ phiếu | | `client.eod.sector.investor` | ✔ | ✔ | chỉ `foreign` và `proprietary` | cổ phiếu | | `client.eod.derivative.investor` | ✔ | ✔ | chỉ `foreign` và `proprietary` | **hợp đồng** | `flow()` hỏi **một** nhóm, `breakdown()` hỏi **nhiều** nhóm. Cả hai trả về **cùng một schema**, nên hai bảng ghép được với nhau mà không phải đổi hình. `client.eod.stock.ohlcv()` trả giá bằng **nghìn VND**, còn `client.eod.stock.investor.flow()` trả giá trị bằng **VND thô**. Khối lượng tính bằng **cổ phiếu**, không phải lô. Đó chính là lý do dòng tiền sống trong một namespace riêng chứ không phải vài phương thức thêm vào `client.eod.stock`: hai bộ cột không cùng đơn vị. ### Sáu nhóm — và chỉ bốn nhóm cộng được với nhau [#sáu-nhóm--và-chỉ-bốn-nhóm-cộng-được-với-nhau] Đây là chỗ dễ tính sai nhất của cả trang. Sáu giá trị của tham số `group` **không thuộc cùng một vũ trụ dữ liệu**, và cộng cả sáu lại cho ra một con số vô nghĩa. | Giá trị `group` | Nghĩa | Có dữ liệu từ | Độ phủ sàn | | ----------------------- | ------------------------------------------------------ | ------------- | ------------ | | `foreign` | Nhà đầu tư nước ngoài, **gồm cả giao dịch thoả thuận** | 2010 | cả ba sàn | | `foreign_individual` | Cá nhân nước ngoài | 2024 | **chỉ HOSE** | | `foreign_institutional` | Tổ chức nước ngoài | 2024 | **chỉ HOSE** | | `local_individual` | Cá nhân trong nước | 2024 | **chỉ HOSE** | | `local_institutional` | Tổ chức trong nước | 2024 | **chỉ HOSE** | | `proprietary` | Tự doanh công ty chứng khoán | 2022 | cả ba sàn | **Bốn nhóm chi tiết là một phân hoạch đầy đủ của khớp lệnh.** Tổng `net_value` của chúng bằng 0 — mua ròng của nhóm này đúng bằng bán ròng của nhóm kia. Kiểm được bằng một dòng: ```python bon_nhom = ["foreign_individual", "foreign_institutional", "local_individual", "local_institutional"] df = client.eod.stock.investor.breakdown("HPG", groups=bon_nhom) df.groupby("date")["net_value"].sum().abs().max() # xấp xỉ 0 ``` **`foreign` và `proprietary` nằm ngoài phân hoạch đó.** Cộng chúng vào bốn nhóm trên là cộng hai lần, hoặc cộng hai vũ trụ dữ liệu khác nhau: * `foreign` lấy **cả giao dịch thoả thuận** chứ không riêng khớp lệnh, nên nó **không** bằng `foreign_individual + foreign_institutional`. * `proprietary` (tự doanh) đến từ một nguồn khác hẳn và **không phải** nhóm con của `local_institutional`, dù trực giác nói ngược lại. Có những phiên tự doanh mua ròng lớn hơn cả tổ chức trong nước. 1. **Muốn cộng thì chỉ cộng bốn nhóm chi tiết.** Chúng là phân hoạch duy nhất. 2. **Bốn nhóm chi tiết trên thực tế chỉ có dữ liệu cho mã sàn HOSE.** Với mã HNX hay UPCOM, chúng trả về bảng rỗng — hãy dùng `foreign`, nhóm phủ đủ ba sàn. 3. **Tự doanh về trễ khoảng ba phiên.** Những phiên gần nhất của nhóm `proprietary` có thể chưa có dòng nào, và đó không phải lỗi. Cuối cùng, **không có giá trị `"all"`.** Muốn mọi nhóm thì gọi `breakdown()` và để `groups=None`. ### `flow()` — một nhóm [#flow--một-nhóm] ```python flow(symbols, *, group="foreign", start=None, end=None, interval="1d", refresh=False, on_error="warn") ``` | Tham số | Kiểu | Mặc định | Mô tả | | --------------------------------------------- | --------------- | ----------- | ----------------------------------------------------------------- | | `symbols` | `SymbolsArg` | — | `"HPG"`, `"HPG,VCB"`, hoặc `["HPG", "VCB"]`. **Positional.** | | `group` | `InvestorGroup` | `"foreign"` | Đúng **một** nhóm trong sáu giá trị ở bảng trên. | | `start` `end` `interval` `refresh` `on_error` | | | Như mọi hàm EOD khác. | ```python df = client.eod.stock.investor.flow("HPG,VCB", start="2026-01-01") df.attrs["finlens"]["units"]["net_value"] # 'VND' # Tự doanh, và chỉ tự doanh df = client.eod.stock.investor.flow("HPG", group="proprietary") ``` ### `breakdown()` — nhiều nhóm trong một lời gọi [#breakdown--nhiều-nhóm-trong-một-lời-gọi] ```python breakdown(symbols, *, groups=None, start=None, end=None, interval="1d", refresh=False, on_error="warn") ``` | Tham số | Kiểu | Mặc định | Mô tả | | --------------------------------------------- | ------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | `symbols` | `SymbolsArg` | — | Như trên. **Positional.** | | `groups` | `InvestorGroupsArg` | `None` | `"foreign,proprietary"` hoặc `["foreign", "proprietary"]`. `None` nghĩa là **đầy đủ các nhóm** mà cấp này phục vụ, không phải "không nhóm nào". | | `start` `end` `interval` `refresh` `on_error` | | | Như mọi hàm EOD khác. | Kết quả ở dạng **long format**: một dòng cho mỗi bộ ba `symbol` × `date` × `group`. Muốn bảng rộng thì tự `pivot` — thư viện cố ý không làm sẵn bước đó, vì pivot là quyết định trình bày của bạn còn long format mới là thứ ghép và lọc được. ```python df = client.eod.stock.investor.breakdown("HPG", groups=bon_nhom) rong = df.pivot(index="date", columns="group", values="net_value") ``` ### Cột trả về — cấp mã và cấp chỉ số [#cột-trả-về--cấp-mã-và-cấp-chỉ-số] Chín cột, **luôn đủ** kể cả khi không có dòng nào. | Cột | Kiểu | Có thể `NaN` | Đơn vị | Mô tả | | ------------- | ---------------- | ------------ | ----------- | ------------------------------------------------------------------------------------------- | | `symbol` | `string` | không | — | Mã chứng khoán, viết hoa. | | `date` | `datetime64[ns]` | không | — | Ngày giao dịch, không mang múi giờ. Với interval có gộp kỳ, đây là **phiên cuối** trong kỳ. | | `group` | `string` | không | — | Nhóm nhà đầu tư của dòng này. | | `buy_value` | `float64` | có | **VND thô** | Giá trị mua trong kỳ. | | `sell_value` | `float64` | có | **VND thô** | Giá trị bán trong kỳ. | | `net_value` | `float64` | có | **VND thô** | `buy_value - sell_value`. Dương là mua ròng. | | `buy_volume` | `float64` | có | cổ phiếu | Khối lượng mua trong kỳ. | | `sell_volume` | `float64` | có | cổ phiếu | Khối lượng bán trong kỳ. | | `net_volume` | `float64` | có | cổ phiếu | `buy_volume - sell_volume`. | **Cột `group` luôn có mặt**, kể cả khi lời gọi chỉ hỏi một nhóm. Đó là chỗ duy nhất mang được "con số này tính trên cơ sở nào" ở mức **từng dòng** — bỏ nó đi thì thông tin ấy biến mất ngay khi bạn `concat` hai bảng. **Không có cột tỷ trọng nào.** Tỷ trọng là một phép chia bạn tự làm được, và 0.1.x từng đặt tên cột `*_ratio` nhưng tính trên thang 0–100 — sai 100 lần, rất khó thấy. **Khi resample, mọi cột số đều cộng dồn** — khác quy tắc của OHLCV. `interval="1w"` cho một dòng mỗi tuần mỗi nhóm, giá trị là **tổng** của các phiên trong tuần chứ không phải giá trị cuối kỳ. Riêng cột `date` theo đúng luật chung của nhóm EOD: nó mang **phiên giao dịch cuối** trong kỳ. Và **mọi nhóm của cùng một kỳ mang cùng một ngày** — nhãn được tính trên cả kỳ chứ không tính riêng từng nhóm, nên bảng vẫn `pivot` được theo `date` kể cả khi các nhóm có phiên cuối khác nhau. ### Cấp chỉ số — chỉ `VNINDEX`, và chỉ có `flow()` [#cấp-chỉ-số--chỉ-vnindex-và-chỉ-có-flow] ```python df = client.eod.index.investor.flow("VNINDEX", start="2026-01-01") ``` Ở cấp chỉ số chỉ có `flow()`. Và trong thực tế **chỉ `VNINDEX` có dữ liệu** — tài liệu 0.1.x hứa cả `VN30`, `HNXINDEX` và `UPINDEX`, không mã nào trong số đó có số liệu dòng tiền. Điều đó nguy hiểm hơn một lỗi, vì mặc định `on_error="warn"` nghĩa là lời gọi **không** thất bại: ```python df = client.eod.index.investor.flow(["VNINDEX", "VN30"]) # PartialDataWarning — df chỉ chứa VNINDEX df.attrs["finlens"]["failed"] ``` Đặt `on_error="raise"` nếu bạn muốn biết ngay thay vì phát hiện muộn. Cột trả về giống hệt bảng cấp mã ở trên, kể cả tên cột `symbol`. ### Cấp ngành — hai nhóm, hai cấp ICB [#cấp-ngành--hai-nhóm-hai-cấp-icb] ```python flow(icb, *, icb_level=4, group="foreign", start=None, end=None, interval="1d", refresh=False, on_error="warn") breakdown(icb, *, icb_level=4, groups=None, start=None, end=None, interval="1d", refresh=False, on_error="warn") ``` | Tham số | Kiểu | Mặc định | Mô tả | | --------------------------------------------- | ------------------------- | ----------- | ---------------------------------------------------------------------- | | `icb` | `IcbArg` | — | `"8600"`, `"8600,3570"`, hoặc `["8600", "3570"]`. **Positional.** | | `icb_level` | `IcbLevel` | `4` | Cấp ICB: `4` hoặc `2`. | | `group` | `SectorInvestorGroup` | `"foreign"` | Chỉ `"foreign"` hoặc `"proprietary"` — chỉ ở `flow()`. | | `groups` | `SectorInvestorGroupsArg` | `None` | `None` nghĩa là **cả hai** nhóm — chỉ ở `breakdown()`. | | `start` `end` `interval` `refresh` `on_error` | | | Như mọi hàm EOD khác. | ```python df = client.eod.sector.investor.flow("8600", start="2026-01-01") df.attrs["finlens"]["units"]["net_value"] # 'VND' df = client.eod.sector.investor.breakdown("8600") sorted(df["group"].unique()) # ['foreign', 'proprietary'] ``` Bốn nhóm chi tiết (`foreign_individual`, `foreign_institutional`, `local_individual`, `local_institutional`) **không tồn tại ở cấp ngành — ở bất kỳ cấp ICB nào**. Cái bị chặn là một *nguồn*, không phải một *cấp*: nguồn của bốn nhóm đó thực chất chỉ có sàn HOSE, trong khi ngay ở cấp 4 một ngành đã trải cả ba sàn — con số tổng hợp sẽ thiếu hẳn phần HNX và UPCOM mà không có gì trong bảng nói ra. Yêu cầu chúng nhận một lỗi 400 rõ ràng chứ không phải một bảng rỗng im lặng, và kiểu `SectorInvestorGroup` đã chặn ngay lúc bạn gõ code. Muốn bốn nhóm đó thì hỏi ở cấp mã. Hai nhóm còn lại nằm trên **hai trục rời nhau** nên cũng không cộng được với nhau: `foreign` lấy cả thoả thuận, còn `proprietary` đến từ một nguồn khác hẳn. Cấp 4 đọc thẳng số gốc của nguồn. Cấp 2 là **tổng của các ngành con cấp 4** do máy chủ cộng lại. Phép cộng đó đầy đủ với nhóm `foreign`. Với `proprietary` thì có một khoảng trống đã biết: vài ngành cấp 4 có dữ liệu khối ngoại nhưng không có dữ liệu tự doanh, nên phần của chúng vắng khỏi tổng cấp 2 — máy chủ phát một cảnh báo nêu đích danh những ngành đó. Và đừng chuyển kết luận này sang `client.eod.sector.ohlcv()`: ở đó **cả hai cấp đều là số gốc**, vì chỉ số ngành được tính sẵn ở cả hai cấp. Ở cấp ngành, hai nhóm cũng không cùng độ dài lịch sử: `foreign` có lịch sử dài hơn hẳn `proprietary`. ### Cột trả về — cấp ngành [#cột-trả-về--cấp-ngành] Mười một cột, luôn đủ kể cả khi không có dòng nào. Khác bảng cấp mã ở chỗ ba cột `symbol` được thay bằng bộ `icb` / `icb_name` / `icb_level`. | Cột | Kiểu | Có thể `NaN` | Đơn vị | Mô tả | | ------------- | ---------------- | ------------ | ----------- | ------------------------------------------------------------------------------------------- | | `icb` | `string` | không | — | Mã ngành ICB, cấp 2 hoặc cấp 4 theo `icb_level`. | | `icb_name` | `string` | có | — | Tên ngành. | | `icb_level` | `int64` | không | — | Cấp của mã ngành: `2` hoặc `4`. | | `date` | `datetime64[ns]` | không | — | Ngày giao dịch, không mang múi giờ. Với interval có gộp kỳ, đây là **phiên cuối** trong kỳ. | | `group` | `string` | không | — | `foreign` hoặc `proprietary`. | | `buy_value` | `float64` | có | **VND thô** | Giá trị mua của cả ngành trong kỳ. | | `sell_value` | `float64` | có | **VND thô** | Giá trị bán của cả ngành trong kỳ. | | `net_value` | `float64` | có | **VND thô** | `buy_value - sell_value`. | | `buy_volume` | `float64` | có | cổ phiếu | Khối lượng mua của cả ngành. | | `sell_volume` | `float64` | có | cổ phiếu | Khối lượng bán của cả ngành. | | `net_volume` | `float64` | có | cổ phiếu | `buy_volume - sell_volume`. | ### Cấp hợp đồng phái sinh — hai nhóm, khối lượng bằng hợp đồng [#cấp-hợp-đồng-phái-sinh--hai-nhóm-khối-lượng-bằng-hợp-đồng] ```python flow(symbols, *, group="foreign", start=None, end=None, interval="1d", refresh=False, on_error="warn") breakdown(symbols, *, groups=None, start=None, end=None, interval="1d", refresh=False, on_error="warn") ``` | Tham số | Kiểu | Mặc định | Mô tả | | --------------------------------------------- | ----------------------------- | ----------- | --------------------------------------------------------------------------------------------------- | | `symbols` | `SymbolsArg` | — | `"VN30F1M"`, `"VN30F1M,VN30F2M"`, hoặc danh sách. Tất cả phải là mã phái sinh. **Positional.** | | `group` | `DerivativeInvestorGroup` | `"foreign"` | Chỉ `"foreign"` hoặc `"proprietary"` — chỉ ở `flow()`. | | `groups` | `DerivativeInvestorGroupsArg` | `None` | `None` nghĩa là **cả hai** nhóm — chỉ ở `breakdown()`. | | `start` `end` `interval` `refresh` `on_error` | | | Như mọi hàm EOD khác. | **Cùng bộ chín cột** với bảng cấp mã ở trên, nên hai bảng ghép được với nhau mà không phải đổi hình. Khác đúng hai chỗ, và cả hai nằm trong kiểu của tham số. ```python df = client.eod.derivative.investor.flow("VN30F1M", start="2026-01-01") df.attrs["finlens"]["units"]["net_volume"] # 'contract' df = client.eod.derivative.investor.breakdown("VN30F1M") sorted(df["group"].unique()) # ['foreign', 'proprietary'] ``` Bốn nhóm chi tiết (`foreign_individual`, `foreign_institutional`, `local_individual`, `local_institutional`) **không tồn tại ở cấp hợp đồng phái sinh** và nhận lỗi **400**, không phải một bảng rỗng: nguồn của chúng khoá theo danh mục **doanh nghiệp niêm yết**, nơi không hợp đồng phái sinh nào có mặt. Kiểu `DerivativeInvestorGroup` chỉ khai hai giá trị nên IDE gạch đỏ ngay lúc bạn gõ, trước cả một vòng gọi mạng. Đây cũng là chỗ `breakdown()` ở đây khác `client.eod.stock.investor.breakdown()`: bỏ trống `groups` ở cấp mã cho **sáu** nhóm, bỏ trống ở đây cho **hai**. Hai nhóm này nằm trên **hai trục rời nhau** và không cộng được với nhau — cùng lý do với cấp mã và cấp ngành. Hai chỗ dễ đọc nhầm nhất của bảng này, và cả hai đều không có gì báo: **1. `net_volume` là chênh lệch hợp đồng ĐÃ KHỚP trong kỳ, không phải vị thế mở.** Một nhóm mở rồi đóng hết trong cùng phiên có `net_volume` bằng 0 dù đã khớp hàng nghìn hợp đồng; ngược lại, `net_volume` dương không nói vị thế mở cuối phiên là bao nhiêu. Cộng dồn `net_volume` qua nhiều phiên **không** cho ra vị thế tích luỹ — bảng này không mang thông tin đó. **2. Các cột `*_value` là giá trị DANH NGHĨA của số hợp đồng đó**, đã quy đổi ra **VND thô** bằng hệ số hợp đồng ở máy chủ — không phải số tiền nhà đầu tư thực bỏ ra, vốn chỉ là phần ký quỹ. Cũng vì vậy đừng tự nhân `net_volume` với giá đóng cửa của `ohlcv()` rồi so với `net_value`: bỏ quên hệ số hợp đồng là lệch **100.000 lần**, và phép nhân đó vẫn chạy. ```python df.attrs["finlens"]["units"]["net_value"] # 'VND' df.attrs["finlens"]["units"]["net_volume"] # 'contract' ``` Bộ tên cột giống hệt bản cổ phiếu, nên `pd.concat` một frame phái sinh với một frame cổ phiếu cho ra một cột `net_volume` mang **hai** đơn vị — và `df.attrs` không sống sót qua `concat` để nói ra điều đó. ## Đơn vị — kiểm bằng một dòng, đừng giả định [#đơn-vị--kiểm-bằng-một-dòng-đừng-giả-định] Trong riêng nhóm EOD, cột tên `close` mang **ba** đơn vị khác nhau ở ba chỗ: | Gọi gì | `units["close"]` | | --------------------------------------------------------------------------------------------------- | ----------------------------- | | `client.eod.stock.ohlcv(...)` | `'kVND'` — nghìn VND | | `client.eod.index.ohlcv(...)` · `client.eod.derivative.ohlcv(...)` · `client.eod.sector.ohlcv(...)` | `'index_point'` — điểm chỉ số | | `client.eod.warrant.ohlcv(...)` | `'VND'` — VND thô | Và các bảng dòng tiền dùng `'VND'` cho mọi cột `*_value`, bất kể namespace cha tính bằng gì. Bốn giá trị `units` còn lại bạn sẽ gặp trong nhóm EOD: | Cột | `units[...]` | Xuất hiện ở | | --------------------------------------------------------- | --------------------------- | ----------------------------------------------------------------------- | | `volume`, `*_order_volume`, `*_active_volume`, `*_volume` | `'share'` hoặc `'contract'` | mọi bảng có khối lượng — **đổi theo namespace**, không đổi theo tên cột | | `basis`, `future_close`, `spot_close` | `'index_point'` | `basis()` | | `basis_pct` | `'pct'` | `basis()` — thang **0–100** | | `buy_order_count`, `sell_order_count`, `net_order_count` | `None` | `supply_demand()` — một cái đếm không có thứ nguyên | ```python df.attrs["finlens"]["units"] # cột -> đơn vị df.attrs["finlens"]["price_basis"] # 'adjusted' hoặc 'raw' df.attrs["finlens"]["as_of"] # mốc nước của dữ liệu ``` `DataFrame.attrs` là thông tin đi kèm, **không phải cơ chế bảo vệ** — pandas bỏ nó khi bạn `pd.concat` hay `df.merge`. Đọc đơn vị **trước** khi ghép bảng. Bảo vệ thật nằm ở chỗ tách namespace: một lời gọi không bao giờ trộn được hai đơn vị, vì `client.eod.stock` và `client.eod.index` không trả về cùng một bảng. Chi tiết từng khoá của `df.attrs["finlens"]` ở [Kiểu dữ liệu](/python-sdk/kieu-du-lieu). ## Xem tiếp [#xem-tiếp] Thanh giá theo phút, từng lệnh khớp và dòng tiền chủ động. Giá trong phiên là giá thô — không nối thẳng được với chuỗi EOD. `EodInterval`, `InvestorGroup`, `IcbLevel` và toàn bộ nội dung của `df.attrs["finlens"]`. Cây ngoại lệ, mã `FL_*`, và `on_error` trong lời gọi nhiều mã. Những gì đổi tên hoặc đổi hành vi khi nâng từ 0.1.x lên 1.x. ### Câu hỏi thường gặp **Làm sao lấy dữ liệu OHLCV của một mã cổ phiếu Việt Nam bằng Python?** Dùng `client.eod.stock.ohlcv()` của thư viện Python finlens: `client = finlens.client()` rồi `client.eod.stock.ohlcv("HPG", start="2026-01-01", end="2026-01-31")`. Hàm trả về `pandas.DataFrame` với bảy cột viết thường `symbol`, `date`, `open`, `high`, `low`, `close`, `volume`. Chỉ `symbols` là tham số vị trí, mọi tham số còn lại keyword-only; `symbols` nhận `"HPG"`, `"HPG,VCB"` hoặc `["HPG", "VCB"]` trong một lời gọi. Tham số `interval` nhận `"1d"`, `"1w"`, `"1mo"`, `"3mo"`, `"6mo"`, `"1y"` — viết thường, không có `"1M"`; ở giá trị có gộp kỳ, `date` là phiên giao dịch cuối trong kỳ. **Lấy dữ liệu chỉ số VNINDEX bằng Python như thế nào?** Namespace chỉ số của thư viện Python finlens tên là `client.eod.index`: gọi `client.eod.index.ohlcv("VNINDEX", start="2026-01-01", interval="1mo")`. Tên `client.eod.market` là của bản 0.1.x và nay ném `AttributeError`. Giá chỉ số tính bằng điểm chỉ số chứ không phải nghìn VND — nhân VNINDEX với 1000 là sai mà không có exception nào báo; kiểm bằng `df.attrs["finlens"]["units"]["close"]`, nó trả `'index_point'`. Dòng tiền cấp chỉ số nằm ở `client.eod.index.investor.flow("VNINDEX")` và hiện chỉ `VNINDEX` có dữ liệu. **Lấy được mua bán ròng của khối ngoại và tự doanh bằng Python không?** Được, bằng `flow()` và `breakdown()` trong namespace `investor` của thư viện Python finlens: `client.eod.stock.investor.flow("HPG", group="foreign")` cho một nhóm, `client.eod.stock.investor.breakdown("HPG")` cho nhiều nhóm trong một frame. Cấp chỉ số là `client.eod.index.investor.flow()`, cấp ngành là `client.eod.sector.investor.flow("8600")`. Kết quả luôn đủ chín cột kể cả khi 0 dòng: `symbol`, `date`, `group`, `buy_value`, `sell_value`, `net_value`, `buy_volume`, `sell_volume`, `net_volume`. Giá trị tính bằng VND thô, khối lượng tính bằng cổ phiếu. **Cộng được những nhóm nhà đầu tư nào lại với nhau?** Chỉ bốn nhóm chi tiết: `foreign_individual`, `foreign_institutional`, `local_individual` và `local_institutional`. Chúng là một phân hoạch đầy đủ của khớp lệnh nên tổng `net_value` bằng 0, và trên thực tế chỉ có dữ liệu cho mã sàn HOSE. Hai nhóm còn lại nằm ngoài phân hoạch đó: `foreign` gồm cả giao dịch thoả thuận nên không bằng tổng hai nhóm ngoại chi tiết, còn `proprietary` (tự doanh) đến từ nguồn khác hẳn và không phải nhóm con của `local_institutional`. Với mã HNX hay UPCOM thì dùng `foreign`, nhóm phủ đủ ba sàn. Không có giá trị `"all"` — muốn mọi nhóm thì gọi `breakdown()` và để `groups=None`. **Lấy dữ liệu giá theo ngành ICB bằng Python thế nào?** Gọi `client.eod.sector.ohlcv("8600", icb_level=4)` của thư viện Python finlens. Tham số đầu tên là `icb`, positional, và nhận mã ngành ICB dạng chuỗi: `"8600"`, `"8600,3570"` hoặc `["8600", "3570"]` — chuỗi chứ không phải số, vì ép sang số làm mất số 0 đứng đầu ở những mã như `"0533"`. `icb_level` nhận `4` hoặc `2`. Frame trả về gồm `icb`, `icb_name`, `icb_level`, `date`, `open`, `high`, `low`, `close`, `volume` và `n_stocks`, đơn vị là điểm chỉ số. Không nhớ mã ngành thì tra bằng `client.meta.sectors(level=4)`. **Giá cổ phiếu trả về đã điều chỉnh quyền chưa?** Mặc định là đã điều chỉnh. Với thư viện Python finlens, `client.eod.stock.ohlcv("VCB")` trả chuỗi giá đã điều chỉnh quyền, còn `client.eod.stock.ohlcv("VCB", adjusted=False)` trả giá khớp lệnh thật của phiên — dùng khi đối chiếu sao kê hoặc dựng lại một lệnh cũ. Cơ sở giá đọc được ở `df.attrs["finlens"]["price_basis"]` với giá trị `'adjusted'` hoặc `'raw'`. Cột `volume` không đổi theo cờ này, nó luôn là số cổ phiếu thật. Chỉ số, phái sinh và chứng quyền không có giá điều chỉnh nên `price_basis` của chúng luôn là `'raw'`. **Lấy khối lượng đặt mua và đặt bán (sổ lệnh) của cổ phiếu Việt Nam bằng Python thế nào?** Gọi `client.eod.stock.supply_demand("HPG", start="2026-08-01")` của thư viện Python finlens. Frame trả về tám cột: `symbol`, `date`, `buy_order_volume`, `sell_order_volume`, `net_order_volume`, `buy_order_count`, `sell_order_count`, `net_order_count`. Đây là lệnh ĐẶT vào sổ chứ không phải lệnh đã khớp — trung vị tỷ lệ `buy_order_volume` trên `volume` của `ohlcv()` là 2,756 lần, nên trừ hai cột đó cho nhau là so hai đại lượng chênh nhau khoảng ba lần, và không có exception nào chặn. Ba cột `_count` dùng `Int64` viết hoa và mang được giá trị thiếu, nên kiểm bằng `.isna()` chứ đừng so với 0. Phương thức chỉ tồn tại ở `client.eod.stock`; gọi nó ở chỉ số, ngành, chứng quyền hay phái sinh ném `AttributeError`. **active_volume cuối ngày khác net_active_value trong phiên ở chỗ nào?** Khác ở cả ba chiều, và hai frame không cộng được với nhau. `client.eod.stock.active_volume()` cùng `client.eod.derivative.active_volume()` của thư viện Python finlens có hai rổ là `active_buy_volume` và `active_sell_volume`, không có cột tiền nào; còn `client.intraday.*.net_active_value()` có ba rổ vì tách riêng khớp lệnh định kỳ ATO/ATC thành `auction_value` và `auction_volume`, đồng thời phát giá trị bằng VND. Cùng một phiên VN30F1M, ba cột tương ứng của hai bảng lệch nhau 57,5%, 520% và 30,1%. Ở bản cuối ngày phần khớp lệnh định kỳ không biến mất mà bị trộn vào hai rổ, nên `active_buy_volume` rộng hơn `buy_volume` của bản trong phiên. Phép cộng giữa hai frame không ném exception nào, chỉ cho ra một con số sai. **Tính chênh lệch giữa hợp đồng VN30F1M và chỉ số cơ sở bằng Python thế nào?** Gọi `client.eod.derivative.basis("VN30F1M")` cho bản theo phiên, hoặc `client.intraday.derivative.basis("VN30F1M")` cho bản bước 1 phút — cả hai đều của thư viện Python finlens. Frame gồm `symbol`, `index_symbol`, `date` (bản trong phiên dùng `time`), `future_close`, `spot_close`, `basis` và `basis_pct`. Công thức là `basis = future_close - spot_close` tính bằng điểm chỉ số, còn `basis_pct = basis / spot_close * 100` trên thang 0–100: mẫu số là giá chỉ số chứ không phải giá hợp đồng, và hai mẫu số chỉ lệch nhau khoảng 0,3% nên chọn nhầm rất khó thấy. Không phương thức nào trong cặp này có tham số `interval`. Mã phái sinh không có chỉ số cơ sở đi vào phần lỗi theo từng mã với mã `FL_DATA_NO_UNDERLYING`, ánh xạ về `finlens.NoDataError`. **Lấy dòng tiền khối ngoại và tự doanh của hợp đồng phái sinh bằng Python thế nào?** Gọi `client.eod.derivative.investor.flow("VN30F1M")` hoặc `client.eod.derivative.investor.breakdown("VN30F1M")` của thư viện Python finlens. Chúng dùng chung schema chín cột với cấp mã — `symbol`, `date`, `group`, `buy_value`, `sell_value`, `net_value`, `buy_volume`, `sell_volume`, `net_volume` — nên hai bảng ghép được với nhau. Nhưng cấp phái sinh chỉ phục vụ hai nhóm `foreign` và `proprietary`: bốn nhóm chi tiết nhận lỗi 400 và đã bị kiểu `DerivativeInvestorGroup` chặn từ lúc gõ code, nên `breakdown()` bỏ trống `groups` hỏi hai nhóm chứ không phải sáu. Khối lượng tính bằng hợp đồng, không phải cổ phiếu. `net_volume` là chênh lệch hợp đồng đã khớp trong kỳ chứ không phải vị thế mở, và các cột `*_value` là giá trị danh nghĩa quy đổi bằng hệ số hợp đồng, không phải số tiền thực bỏ ra. --- # Thư viện Python lấy dữ liệu chứng khoán Việt Nam URL: https://docs.finlens.vn/python-sdk Mô tả: Thư viện Python finlens trả dữ liệu chứng khoán Việt Nam về pandas DataFrame: giá cuối ngày, dữ liệu trong phiên, dòng tiền nhà đầu tư và báo cáo tài chính. Tóm tắt: finlens là thư viện Python cài bằng `pip install finlens`, đưa dữ liệu chứng khoán Việt Nam về dạng `pandas.DataFrame` để dùng thẳng trong notebook, mô hình định lượng hay pipeline dữ liệu. Ba dòng mở đầu là `import finlens`, `client = finlens.client()` (khoá đọc từ biến môi trường `FINLENS_API_KEY`) và `client.eod.stock.ohlcv("HPG,VCB", start="2026-01-01")`. Trang liệt kê toàn bộ namespace của đối tượng client: `client.eod.stock`, `client.eod.index`, `client.eod.derivative`, `client.eod.warrant` và `client.eod.sector` cho giá cuối ngày; `client.eod.stock.investor.flow()` cùng `breakdown()` cho dòng tiền theo nhóm nhà đầu tư; `client.intraday.stock` với `ohlcv()`, `ticks()`, `net_active_value()` cho dữ liệu trong phiên; `client.financials` cho báo cáo tài chính; `client.meta` cho danh mục mã, cây ngành ICB và chứng quyền. Tên cột viết thường theo snake_case (`symbol`, `date`, `open`, `close`, `volume`); với interval có gộp kỳ (`1w`, `1mo`, `3mo`, `6mo`, `1y`) thì cột `date` mang phiên giao dịch cuối cùng thực sự có dữ liệu trong kỳ chứ không phải ngày đầu kỳ. Giá cổ phiếu tính bằng nghìn VND còn chỉ số tính bằng điểm chỉ số — đơn vị từng cột đọc được ở `df.attrs["finlens"]["units"]`. Yêu cầu Python 3.11 trở lên và pandas 3.0 trở lên, giấy phép MIT. In English: finlens is a Python library for Vietnamese stock market data — end-of-day and intraday OHLCV, tick-by-tick trades, investor money flows, financial statements and instrument metadata, all returned as pandas DataFrames (pip install finlens). Sản phẩm: python-sdk `finlens` là thư viện Python lấy dữ liệu thị trường chứng khoán Việt Nam — giá cuối ngày, giá trong phiên, từng lệnh khớp, dòng tiền theo nhóm nhà đầu tư, báo cáo tài chính và danh mục mã. Mọi truy vấn trả về `pandas.DataFrame` trần: ghi được `to_parquet`, nối được `pd.concat`, dùng được mọi tutorial pandas bạn từng đọc. ```bash pip install finlens ``` ## Bắt đầu trong ba dòng [#bắt-đầu-trong-ba-dòng] ```python import finlens client = finlens.client() # đọc biến môi trường FINLENS_API_KEY df = client.eod.stock.ohlcv("HPG,VCB,FPT", start="2026-01-01", end="2026-01-05") ``` ```text symbol date open high low close volume 0 FPT 2026-01-05 94.40 94.40 91.93 93.71 7129300.0 1 HPG 2026-01-05 23.57 23.70 22.94 23.17 59427911.0 2 VCB 2026-01-05 ... ... ... ... ... ``` Giá cổ phiếu tính bằng **nghìn đồng** — `23.17` nghĩa là 23.170 VND. Tên cột viết thường toàn bộ theo `snake_case`, kể cả `date`. Chưa có khoá API thì bắt đầu ở [Cài đặt và khoá API](/python-sdk/cai-dat). Yêu cầu môi trường, lấy khoá `flk_...`, truy vấn đầu tiên và cách kiểm tra đã cài đúng bản. `ohlcv()` cho cổ phiếu, chỉ số, phái sinh, chứng quyền và chỉ số ngành ICB; dòng tiền theo nhóm nhà đầu tư. Thanh giá theo phút, từng lệnh khớp với `ticks()`, và giá trị mua bán chủ động. Cân đối kế toán, kết quả kinh doanh và lưu chuyển tiền tệ theo năm hoặc theo quý, ở dạng long. Có những mã nào, ngành ICB nào, chứng quyền nào — ba lời gọi mở đầu mọi phiên làm việc. Giá trị hợp lệ của từng tham số, hình dạng `df.attrs["finlens"]`, và các `TypedDict` của `whoami()` / `limits()`. Cây ngoại lệ gốc `FinLensError`, mã `FL_*`, và các lớp cảnh báo tắt được chọn lọc. ## Lấy được những dữ liệu gì [#lấy-được-những-dữ-liệu-gì] Một đối tượng `client` duy nhất, chia thành các namespace theo loại dữ liệu và loại tài sản. | Đường dẫn | Dữ liệu | Ví dụ | | ---------------------------- | ------------------------------------------------ | --------------------------------------------------------- | | `client.eod.stock` | Giá cuối ngày của cổ phiếu, ETF và chứng chỉ quỹ | `client.eod.stock.ohlcv("HPG")` | | `client.eod.index` | Giá cuối ngày của chỉ số | `client.eod.index.ohlcv("VNINDEX")` | | `client.eod.derivative` | Giá cuối ngày của hợp đồng phái sinh | `client.eod.derivative.ohlcv("VN30F1M")` | | `client.eod.warrant` | Giá cuối ngày của chứng quyền có bảo đảm | `client.eod.warrant.ohlcv("CHPG2628")` | | `client.eod.sector` | Chỉ số ngành ICB | `client.eod.sector.ohlcv("8355")` | | `client.eod.stock.investor` | Dòng tiền theo nhóm nhà đầu tư, cấp mã | `client.eod.stock.investor.flow("HPG")` | | `client.eod.sector.investor` | Dòng tiền theo nhóm nhà đầu tư, cấp ngành | `client.eod.sector.investor.flow("8355")` | | `client.eod.index.investor` | Dòng tiền theo nhóm nhà đầu tư, cấp chỉ số | `client.eod.index.investor.flow("VNINDEX")` | | `client.intraday.stock` | Trong phiên: thanh giá, tick, mua bán chủ động | `client.intraday.stock.ticks("HPG", date="2026-08-03")` | | `client.intraday.index` | Trong phiên, chỉ số | `client.intraday.index.ohlcv("VNINDEX", interval="5min")` | | `client.intraday.derivative` | Trong phiên, phái sinh | `client.intraday.derivative.net_active_value("VN30F1M")` | | `client.financials` | Báo cáo tài chính | `client.financials.statement("HPG")` | | `client.meta` | Danh mục mã, cây ngành, chứng quyền | `client.meta.symbols(exchange="HOSE")` | Ngoài dữ liệu, `client` còn trả lời về chính nó: `client.whoami()` cho gói dịch vụ và tình trạng khoá, `client.limits()` cho hạn mức hiệu lực, `client.status()` cho trạng thái service, `client.cache.stats()` cho số liệu cache. ### Giá cuối ngày [#giá-cuối-ngày] ```python client.eod.stock.ohlcv("HPG", start="2020-01-01", interval="1w") client.eod.stock.ohlcv("HPG", adjusted=False) # giá khớp lệnh thật của phiên client.eod.index.ohlcv("VNINDEX", interval="1mo") client.eod.sector.ohlcv("8355") # chỉ số ngành, mã ICB cấp 4 ``` Cổ phiếu có dữ liệu từ **2007**, chỉ số ngành từ **2000**. Giá cổ phiếu mặc định **đã điều chỉnh quyền**; `adjusted=False` cho chuỗi giá đúng như phiên hôm đó, dùng khi đối chiếu sao kê hoặc dựng lại một lệnh cũ. Cột `volume` không đổi theo cờ này — nó luôn là số cổ phiếu thật. Gộp nhóm chạy ở **server**: `interval="1w"` trả về thanh tuần đã gộp, không phải thanh ngày để bạn tự gộp lại. Một kỳ đã gộp được dán nhãn bằng **phiên giao dịch cuối** trong kỳ, nên `interval="1mo"` cho tháng 1/2025 ra `2025-01-24` — phiên cuối trước kỳ nghỉ Tết — chứ không phải `2025-01-01` hay `2025-01-31`. ### Trong phiên và tick-by-tick [#trong-phiên-và-tick-by-tick] ```python client.intraday.stock.ohlcv("HPG", interval="5min") client.intraday.stock.ticks("HPG", date="2026-08-03") # từng lệnh khớp client.intraday.stock.net_active_value("HPG", interval="1h") # mua/bán chủ động ``` Tick có từ **2022**. Cột thời gian ở đây tên `time` và **mang múi giờ** `+07:00`, khác cột `date` naive của dữ liệu cuối ngày — một thanh trong phiên là một thời điểm, không phải một ngày giao dịch. `ticks()` lấy **một mã, một phiên** mỗi lời gọi, và giới hạn đó nằm trong chính chữ ký hàm: tham số đầu là `symbol` số ít. Một phiên phái sinh sôi động là hàng chục nghìn dòng. Ngược với `client.eod.stock`, giá trong phiên **chưa điều chỉnh quyền**. Nối một chuỗi trong phiên vào một chuỗi cuối ngày mà không đọc `df.attrs["finlens"]["price_basis"]` sẽ cho một bậc thang giả ở đúng ngày chia tách, và không có lỗi nào báo. `client.intraday.index` **không có** `net_active_value()`, và đó không phải một thiếu sót: bảng tick của chỉ số không ghi chiều lệnh chủ động, nên không có dữ liệu nào để tính. Một sự vắng mặt trong dữ liệu là một sự vắng mặt trong API. ### Dòng tiền theo nhóm nhà đầu tư [#dòng-tiền-theo-nhóm-nhà-đầu-tư] ```python client.eod.stock.investor.flow("HPG", group="foreign") client.eod.stock.investor.breakdown("HPG") # nhiều nhóm trong một frame client.eod.sector.investor.flow("8355") # theo ngành ICB ``` `flow()` hỏi một nhóm, `breakdown()` hỏi nhiều nhóm — cùng một dataset, cùng một bộ cột. Cột `group` **luôn có mặt**, kể cả khi bạn chỉ hỏi một nhóm, vì đó là chỗ duy nhất nói được "con số này tính trên cơ sở nào" ở mức từng dòng. | Nhóm | Có từ | Phạm vi | | --------------------------------------------- | ----- | --------- | | `foreign` | 2010 | cả ba sàn | | `foreign_individual`, `foreign_institutional` | 2024 | HOSE | | `local_individual`, `local_institutional` | 2024 | HOSE | | `proprietary` (tự doanh) | 2022 | cả ba sàn | **Bốn nhóm chi tiết** (cá nhân/tổ chức × trong nước/nước ngoài) là một phân hoạch đầy đủ của khớp lệnh: tổng mua ròng của chúng bằng 0, vì mua ròng của nhóm này là bán ròng của nhóm kia. `foreign` gồm cả giao dịch thoả thuận nên **chồng lấn** lên hai nhóm ngoại chi tiết, còn `proprietary` (tự doanh) đến từ một nguồn khác hẳn và **không phải** nhóm con của `local_institutional`. Cộng cả sáu nhóm lại cho ra một con số vô nghĩa. Ở cấp **ngành** chỉ có `foreign` và `proprietary`; bốn nhóm chi tiết không tồn tại ở đó. Ở cấp **chỉ số**, hiện chỉ `VNINDEX` có dữ liệu. ### Báo cáo tài chính [#báo-cáo-tài-chính] ```python client.financials.statement("HPG", kind="balance_sheet", period="quarterly") client.financials.periods("HPG") # kỳ nào có số liệu client.financials.line_items(com_type="NH", kind="balance_sheet") ``` Có từ **2004**. Frame ở dạng **long** — một dòng là một khoản mục của một kỳ — và mỗi dòng mang `company_type` của chính nó, nên `statement(["HPG", "VCB"])` chạy được dù HPG là doanh nghiệp phi tài chính còn VCB là ngân hàng. Bốn loại hình (`CT` phi tài chính, `NH` ngân hàng, `CK` chứng khoán, `BH` bảo hiểm) có bốn cây khoản mục khác nhau. ### Tra cứu danh mục [#tra-cứu-danh-mục] ```python client.meta.symbols() # toàn bộ danh mục client.meta.symbols(exchange="HOSE") client.meta.symbols(icb="8300") # toàn ngành ngân hàng client.meta.symbols(kind="fund") # chứng chỉ quỹ niêm yết client.meta.sectors(level=2) # cây ngành ICB client.meta.warrants(underlying="HPG") ``` Đây thường là lời gọi **đầu tiên** của một phiên làm việc: trước khi hỏi giá của một mã, người ta hỏi *có những mã nào*. Tham số `icb=` nhận cả mã cấp 2 lẫn mã cấp 4, nên bạn không cần biết mã mình đang cầm thuộc cấp nào. ```python tickers = client.meta.symbols(exchange="HOSE")["symbol"].tolist() ``` Chi tiết ba phương thức, bộ lọc và cột trả về ở [Tra cứu danh mục](/python-sdk/tra-cuu-danh-muc). ## Đơn vị — đọc trước khi tính toán [#đơn-vị--đọc-trước-khi-tính-toán] Đây là nguồn lỗi số một khi làm việc với dữ liệu chứng khoán Việt Nam, và nó **sai âm thầm**: không exception nào, chỉ là một con số sai. | Loại dữ liệu | Cột giá | Khối lượng | Giá trị tiền | | ---------------------------- | --------------------------------- | ------------ | ------------ | | Cổ phiếu, ETF, chứng chỉ quỹ | **nghìn VND** (`22.3` = 22.300 đ) | cổ phiếu | VND | | Chỉ số | điểm chỉ số | cổ phiếu | — | | Chỉ số ngành ICB | điểm chỉ số | cổ phiếu | — | | Phái sinh | điểm chỉ số | **hợp đồng** | VND | | Chứng quyền | **VND thô** | chứng quyền | VND | | Dòng tiền nhà đầu tư | — | cổ phiếu | **VND thô** | | Báo cáo tài chính | — | — | **VND thô** | Đơn vị được khai báo chứ không phải đoán — mỗi frame mang theo đơn vị của chính nó: ```python df.attrs["finlens"]["units"] # {'close': 'kVND', 'volume': 'share', ...} df.attrs["finlens"]["price_basis"] # 'adjusted' hoặc 'raw' df.attrs["finlens"]["as_of"] # mốc nước của dữ liệu ``` `attrs` mang tính thông tin, không phải cơ chế bảo vệ — pandas bỏ nó khi ghép frame. Đọc đơn vị **trước** khi ghép. Bảo vệ thật nằm ở chỗ tách namespace: `client.eod.stock` và `client.eod.index` không bao giờ trả về cùng một bảng, nên một lời gọi không thể trộn nghìn VND với điểm chỉ số. ## Từ vựng interval [#từ-vựng-interval] | Nhóm | Giá trị hợp lệ | | ----------- | ------------------------------------------------- | | Cuối ngày | `1d` · `1w` · `1mo` · `3mo` · `6mo` · `1y` | | Trong phiên | `1min` · `5min` · `15min` · `30min` · `1h` · `4h` | Trong từ vựng cũ `1M` là một **tháng** còn `1m` là một **phút** — phân biệt duy nhất bằng chữ hoa, và hai giá trị đó lệch nhau 43.200 lần. Ở đây tháng là `1mo`, phút là `1min`, và `"1M"` bị **từ chối** kèm gợi ý thay vì âm thầm trả về một biểu đồ sai. Hai nhóm dán nhãn ngược nhau, và chỗ này dễ suy sai từ nhóm này sang nhóm kia: | Nhóm | Cột thời gian | Mốc của một kỳ đã gộp | | ----------- | --------------------- | --------------------------------- | | Cuối ngày | `date`, naive | **Phiên giao dịch cuối** trong kỳ | | Trong phiên | `time`, mang `+07:00` | **Đầu** bước thời gian | Cuối ngày lấy phiên cuối vì `close` của dòng ấy là giá của đúng phiên đó — nhãn theo lịch sẽ trỏ tới một ngày mà thị trường không mở, và với kỳ đang dở thì trỏ cả tới một ngày ở tương lai. Chi tiết ở [Giá cuối ngày](/python-sdk/eod). ## Một mã lỗi không làm mất các mã còn lại [#một-mã-lỗi-không-làm-mất-các-mã-còn-lại] Mặc định `on_error="warn"`: bạn nhận về những mã lấy được kèm một `PartialDataWarning`, và chi tiết từng mã hỏng nằm ở `df.attrs["finlens"]["failed"]`. Đặt `on_error="raise"` nếu muốn một mã hỏng làm cả lời gọi thất bại — ngoại lệ `PartialFetchError` vẫn **mang theo** phần đã lấy được ở `.data`. Mọi phương thức cũng nhận `refresh=True` để bỏ qua cache và lấy lại từ server. Kết quả rỗng vẫn **đúng cột, đúng kiểu**: ngày thị trường nghỉ, `df["close"]` vẫn chạy và không `KeyError`. Bạn không cần bọc `if not df.empty` quanh mọi lời gọi. Chi tiết ở [Xử lý lỗi](/python-sdk/xu-ly-loi). ## Yêu cầu môi trường [#yêu-cầu-môi-trường] * **Python 3.11+** * **pandas 3.0+** * Chạy được trên Windows, Linux và macOS * Có gợi ý kiểu theo chuẩn [PEP 561](https://peps.python.org/pep-0561/), nên autocomplete và `mypy` hoạt động đầy đủ Giấy phép **MIT**. Gói phát hành trên [PyPI](https://pypi.org/project/finlens/). ## Bản bất đồng bộ [#bản-bất-đồng-bộ] Mọi thứ có bản async với **cùng chữ ký**, dùng chung một lõi với bản đồng bộ — không có chuyện một bên được sửa bug còn bên kia thì không. ```python import asyncio import finlens async def main(): async with finlens.AsyncClient() as client: df = await client.eod.stock.ohlcv("HPG,VCB") asyncio.run(main()) ``` ## Không viết code thì dùng gì? [#không-viết-code-thì-dùng-gì] Nếu bạn muốn hỏi thẳng bằng tiếng Việt thay vì viết truy vấn, hãy dùng [FinLens MCP](/mcp) — máy chủ Model Context Protocol nối Claude, ChatGPT và Gemini vào cùng nguồn dữ liệu chứng khoán Việt Nam, có thêm các nhóm dữ liệu SDK chưa phủ như báo cáo phân tích của công ty chứng khoán, quỹ đầu tư và trái phiếu doanh nghiệp. Muốn xem dạng giao diện đồ thị thì vào [FinLens Web](/webapp). ## Hỗ trợ [#hỗ-trợ] Gặp lỗi hoặc cần tư vấn cách dùng, liên hệ trực tiếp: Khi báo lỗi, kèm theo `finlens.build_info()` và `request_id` trong thông báo lỗi — hai thứ đó cho biết chính xác bản build nào và request nào. Xem thêm [nhật ký thay đổi](/python-sdk/changelog). ### Câu hỏi thường gặp **Làm sao lấy dữ liệu giá cổ phiếu Việt Nam bằng Python?** Cài thư viện bằng `pip install finlens`, tạo client bằng `finlens.client()` (khoá đọc từ biến môi trường `FINLENS_API_KEY`), rồi gọi `client.eod.stock.ohlcv("HPG", start="2026-01-01", end="2026-01-31")`. Hàm trả về `pandas.DataFrame` với bảy cột viết thường `symbol`, `date`, `open`, `high`, `low`, `close`, `volume`, dùng được ngay trong notebook hay pipeline dữ liệu. Giá cổ phiếu tính bằng nghìn đồng: `23.17` nghĩa là 23.170 VND. Mặc định `interval="1d"` cho một dòng mỗi phiên; với `"1w"` hay `"1mo"` thì mỗi dòng là một kỳ đã gộp và cột `date` mang phiên giao dịch cuối trong kỳ. **Thư viện finlens cung cấp những loại dữ liệu chứng khoán nào?** Đối tượng client của finlens chia theo namespace. Giá cuối ngày nằm ở `client.eod.stock`, `client.eod.index`, `client.eod.derivative`, `client.eod.warrant` và `client.eod.sector` — mỗi loại tài sản một namespace vì mỗi loại một đơn vị. Dòng tiền theo nhóm nhà đầu tư ở `client.eod.stock.investor.flow()` và `breakdown()`. Dữ liệu trong phiên ở `client.intraday.stock` với `ohlcv()`, `ticks()` và `net_active_value()`. Báo cáo tài chính ở `client.financials.statement()`, còn danh mục mã, cây ngành ICB và chứng quyền ở `client.meta.symbols()`, `client.meta.sectors()`, `client.meta.warrants()`. **Tham số group của finlens nhận giá trị nào, và cộng được nhóm nào lại?** Ở cấp mã, `group` nhận sáu giá trị: `"foreign"`, `"foreign_individual"`, `"foreign_institutional"`, `"local_individual"`, `"local_institutional"` và `"proprietary"` (tự doanh). Nhưng chỉ bốn nhóm chi tiết — cá nhân và tổ chức, trong nước và nước ngoài — là một phân hoạch đầy đủ, tổng `net_value` của chúng bằng 0. `foreign` gồm cả giao dịch thoả thuận nên chồng lấn lên hai nhóm ngoại chi tiết, còn `proprietary` đến từ nguồn khác hẳn và không phải nhóm con của `local_institutional`; cộng cả sáu lại cho ra một con số vô nghĩa. Ở cấp ngành chỉ có `"foreign"` và `"proprietary"`. **Thư viện finlens yêu cầu môi trường gì và dùng giấy phép nào?** finlens yêu cầu Python từ 3.11 trở lên và pandas từ 3.0 trở lên, chạy được trên Windows, Linux và macOS. Lệnh `pip install finlens` chỉ kéo theo ba phụ thuộc: `pandas`, `httpx` và `packaging` — `pydantic` và `requests` không còn ở bản 1.x. Gói có gợi ý kiểu theo chuẩn PEP 561 nên autocomplete và `mypy` hoạt động đầy đủ. Thư viện phát hành trên PyPI dưới giấy phép MIT. **Đơn vị giá trong dữ liệu chứng khoán Việt Nam trả về là gì?** Với thư viện Python finlens, cổ phiếu và ETF trả giá bằng nghìn VND (`22.3` là 22.300 đồng), chỉ số và phái sinh trả bằng điểm chỉ số, còn chứng quyền trả bằng VND thô. Giá trị dòng tiền nhà đầu tư và số liệu báo cáo tài chính luôn là VND thô. Đừng đoán theo tên cột: mỗi DataFrame mang theo đơn vị của chính nó ở `df.attrs["finlens"]["units"]`, ví dụ `df.attrs["finlens"]["units"]["close"]` trả `'kVND'` với cổ phiếu và `'index_point'` với chỉ số. Lưu ý `df.attrs` không sống sót qua `pd.concat` hay `merge` của pandas. --- # Dữ liệu trong phiên (intraday) cổ phiếu Việt Nam URL: https://docs.finlens.vn/python-sdk/intraday Mô tả: Lấy dữ liệu trong phiên cổ phiếu, chỉ số, phái sinh Việt Nam về pandas DataFrame: thanh giá 1min đến 4h, từng lệnh khớp, dòng tiền chủ động và basis bước 1 phút. Tóm tắt: Trang mô tả nhóm `client.intraday` của thư viện Python finlens — dữ liệu trong phiên của thị trường chứng khoán Việt Nam, trả về `pandas.DataFrame`. Bốn phương thức: `ohlcv()` cho thanh giá theo bước thời gian, `ticks()` cho từng lệnh đã khớp, `net_active_value()` cho giá trị mua bán chủ động và `basis()` cho chênh lệch giữa hợp đồng tương lai với chỉ số cơ sở; ba phương thức đầu có ở `client.intraday.stock` và `client.intraday.derivative`, `client.intraday.index` có `ohlcv()` và `ticks()` nhưng không có `net_active_value()` vì dữ liệu tick của chỉ số không ghi chiều lệnh chủ động, còn `basis()` chỉ có ở `client.intraday.derivative`. Kiểu `IntradayInterval` khai đúng sáu giá trị `1min`, `5min`, `15min`, `30min`, `1h`, `4h` — không có `1m`, và interval cuối ngày không dùng được ở đây. Ba điểm khác hẳn dữ liệu cuối ngày: cột thời gian tên `time`, kiểu `datetime64[ns, Asia/Ho_Chi_Minh]` mang sẵn offset +07:00; mốc của một thanh là đầu bước, trong khi một kỳ cuối ngày đã gộp được dán nhãn bằng phiên giao dịch cuối trong kỳ; và giá trong phiên luôn là giá thô chưa điều chỉnh quyền nên không nối thẳng được vào chuỗi EOD. `ticks()` nhận `symbol` số ít cùng một `date`, trả về `symbol`, `time`, `price`, `volume`, `side`, `value`, trong đó `side` có ba giá trị `buy`, `sell` và `auction`. Bản 1.1.1 thêm `client.intraday.derivative.basis()`: bảy cột `symbol`, `index_symbol`, `time`, `future_close`, `spot_close`, `basis`, `basis_pct` với `basis = future_close - spot_close` tính bằng điểm chỉ số và `basis_pct = basis / spot_close * 100` trên thang 0–100; bước 1 phút cố định và không có tham số `interval`. Chuỗi của một phiên bắt đầu từ 09:15 chứ không phải 09:00, vì trước 09:15 chỉ số chưa được tính theo từng phút nên vế `spot_close` không tồn tại, còn bar 09:00 là kết quả khớp lệnh định kỳ ATO — một cơ chế hình thành giá khác hẳn các bar liên tục phía sau. Đừng cộng `net_active_value()` với `client.eod.*.active_volume()` của nhóm cuối ngày: bản trong phiên có ba rổ và tính bằng VND, bản cuối ngày có hai rổ và không có cột tiền, cùng một phiên VN30F1M hai bên lệch nhau 57,5%, 520% và 30,1%. In English: intraday OHLCV bars, tick-by-tick trades, active buy/sell value and one-minute futures basis for Vietnamese stocks, indices and futures as pandas DataFrames. Sản phẩm: python-sdk Bốn phương thức cho dữ liệu trong phiên: thanh giá theo bước thời gian, từng lệnh đã khớp, dòng tiền mua/bán chủ động, và chênh lệch giữa hợp đồng tương lai với chỉ số cơ sở — của phiên đang chạy hoặc một phiên đã qua. Trước khi viết dòng đầu tiên, có **hai điểm khác hẳn dữ liệu cuối ngày**. Bỏ qua chúng thì code vẫn chạy, không exception nào, chỉ là kết quả sai: cột thời gian ở đây **mang múi giờ**, và giá ở đây là **giá thô**. ## Bốn phương thức có ở những namespace nào [#bốn-phương-thức-có-ở-những-namespace-nào] | Namespace | `ohlcv()` | `ticks()` | `net_active_value()` | `basis()` | | ---------------------------- | --------- | --------- | -------------------- | ------------ | | `client.intraday.stock` | ✓ | ✓ | ✓ | **không có** | | `client.intraday.index` | ✓ | ✓ | **không có** | **không có** | | `client.intraday.derivative` | ✓ | ✓ | ✓ | ✓ | Ô nào ghi "không có" thì gọi vào ném `AttributeError` ngay tại chỗ, không phải trả về một bảng rỗng. `basis()` chỉ có ở phái sinh vì nó cần một chỉ số cơ sở để trừ, và chỉ hợp đồng tương lai mới có thứ đó. Ba namespace tách nhau vì ba loại tài sản **khác đơn vị**: cổ phiếu tính giá bằng nghìn VND và khối lượng bằng cổ phiếu, chỉ số tính bằng điểm chỉ số, phái sinh tính giá bằng điểm chỉ số và khối lượng bằng **hợp đồng**. Một lời gọi vì vậy không bao giờ trả về bảng trộn hai đơn vị. Dữ liệu tick của chỉ số **không ghi chiều lệnh chủ động** — không có gì để tính mua chủ động hay bán chủ động cho một chỉ số. Đây là một sự vắng mặt trong **dữ liệu**, nên nó cũng là một sự vắng mặt trong API: phát ra một phương thức trả về cột toàn `null` chỉ để cho đủ bộ là bắt bạn tự đoán xem đó là "không có giao dịch" hay "không có dữ liệu". `ticks()` thì **vẫn có** ở chỉ số, và khác biệt đó có lý do: bảng tick chỉ số vẫn mang `time`, `price` và `volume` thật — chỉ hai cột `side` và `value` là `null`. Bỏ luôn `ticks()` sẽ giấu mất bốn cột có dữ liệu thật. ```python df = client.intraday.index.ticks("VNINDEX", date="2026-08-03") df["side"].isna().all() # True df["price"].notna().any() # True ``` ## Cột `time` mang múi giờ, cột `date` của EOD thì không [#cột-time-mang-múi-giờ-cột-date-của-eod-thì-không] Mọi bảng trong phiên đều có cột thời gian tên **`time`**, kiểu `datetime64[ns, Asia/Ho_Chi_Minh]`, tức mang sẵn offset `+07:00`. Dữ liệu cuối ngày thì có cột **`date`** naive, không múi giờ. Bất đối xứng này có chủ đích: **một thanh trong phiên là một thời điểm, còn một phiên cuối ngày là một ngày.** Một thời điểm mà không mang múi giờ thì pandas đoán là UTC, và 09:15 giờ Việt Nam bị đọc thành 16:15 — ra ngoài cả phiên giao dịch. Một ngày giao dịch thì ngược lại: gắn múi giờ vào nó là bịa ra một độ chính xác không có thật. ```python import finlens client = finlens.client() trong_phien = client.intraday.stock.ohlcv("HPG", start="2026-08-03") trong_phien["time"].dt.tz # cuoi_ngay = client.eod.stock.ohlcv("HPG", start="2026-08-03") cuoi_ngay["date"].dt.tz # None ``` Múi giờ của bảng cũng nằm ở `df.attrs["finlens"]["tz"]`. Nếu bạn cần so với dữ liệu nước ngoài, đổi múi giờ bằng `.dt.tz_convert("UTC")` — đừng gỡ múi giờ bằng `.dt.tz_localize(None)`, đó là cách âm thầm lệch bảy tiếng. Mốc thời gian là **đầu bước**: dòng `09:15` với `interval="1min"` gói các lệnh khớp từ 09:15:00 đến trước 09:16:00. Đừng chuyển quy ước này sang dữ liệu cuối ngày. Ở đó, một kỳ đã gộp (`interval="1mo"` chẳng hạn) mang **phiên giao dịch cuối cùng thực sự có dữ liệu** trong kỳ, không phải mốc đầu kỳ — `1mo` của tháng 1/2025 ra `2025-01-24`. Xem [Giá cuối ngày](/python-sdk/eod). Hai nhóm khác nhau vì hai thứ khác nhau: một bước trong phiên là một **khoảng thời gian đều đặn**, còn một kỳ cuối ngày là một tập **phiên giao dịch** có thể thưa bất kỳ đâu vì nghỉ lễ. ## Giá trong phiên là giá thô, chưa điều chỉnh quyền [#giá-trong-phiên-là-giá-thô-chưa-điều-chỉnh-quyền] `client.eod.stock.ohlcv()` mặc định trả **giá đã điều chỉnh quyền**. `client.intraday.*.ohlcv()` thì luôn trả **giá thô** — đúng con số đã khớp trên bảng điện hôm đó, và **không có tham số `adjusted`** ở đây. Hai chuỗi này không cùng cơ sở giá. Ghép thẳng chúng lại sẽ cho một chuỗi gãy đúng ở ngày chia tách hay trả cổ tức bằng cổ phiếu — và không có gì báo, vì cả hai bảng đều đúng theo cơ sở của riêng mình. Cơ sở giá nằm ở `df.attrs["finlens"]["price_basis"]`; đọc nó thay vì giả định: ```python trong_phien.attrs["finlens"]["price_basis"] # 'raw' cuoi_ngay.attrs["finlens"]["price_basis"] # 'adjusted' ``` Muốn nối hai chuỗi, lấy phần EOD ở cùng cơ sở: ```python cuoi_ngay_tho = client.eod.stock.ohlcv("HPG", adjusted=False) cuoi_ngay_tho.attrs["finlens"]["price_basis"] # 'raw' ``` Chỉ số, phái sinh và chứng quyền không có khái niệm giá điều chỉnh, nên `price_basis` của chúng luôn là `raw` ở cả hai bên. ## `ohlcv()` — thanh giá theo bước thời gian [#ohlcv--thanh-giá-theo-bước-thời-gian] ```python client.intraday.stock.ohlcv( symbols, *, start=None, end=None, interval="1min", refresh=False, on_error="warn", ) -> DataFrame ``` Chỉ `symbols` là tham số vị trí; mọi tham số còn lại là **keyword-only**. | Tham số | Kiểu | Mặc định | Nội dung | | ---------- | ------------------ | -------- | ------------------------------------------------------------------------------------------------- | | `symbols` | `SymbolsArg` | — | `"HPG"`, `"HPG,VCB"` hoặc `["HPG", "VCB"]`. Tất cả phải cùng loại tài sản với namespace đang gọi. | | `start` | `DateArg` | `None` | Ngày bắt đầu. Bỏ trống thì máy chủ chọn khoảng mặc định. | | `end` | `DateArg` | `None` | Ngày kết thúc. Mặc định là hôm nay. | | `interval` | `IntradayInterval` | `"1min"` | `1min` · `5min` · `15min` · `30min` · `1h` · `4h`. | | `refresh` | `bool` | `False` | Bỏ qua bản trong cache và lấy lại từ máy chủ. | | `on_error` | `OnError` | `"warn"` | `warn` · `raise` · `ignore` — số phận của các mã lỗi trong lời gọi nhiều mã. | Việc gộp nhóm chạy ở **máy chủ**: `interval="5min"` trả về thanh 5 phút đã gộp sẵn, không phải thanh 1 phút để bạn tự gộp. Nhiều mã cũng đi trong **một** lời gọi chứ không phải nhiều lời gọi tuần tự. Độ dài khoảng thời gian được phép lấy một lần do máy chủ quyết định, đọc bằng `client.limits()["max_intraday_days"]`. `IntradayInterval` có đúng sáu giá trị: `1min`, `5min`, `15min`, `30min`, `1h`, `4h`. **Không có `1m`** — trong từ vựng cũ `1m` là một phút còn `1M` là một tháng, chỉ khác nhau ở chữ hoa nhưng lệch nhau 43.200 lần, nên cả hai đều bị từ chối bằng `finlens.InvalidIntervalError` thay vì bị đoán ý. Interval cuối ngày (`1d`, `1w`, `1mo`…) cũng **không dùng được** ở đây — muốn thanh ngày thì gọi `client.eod`. Kiểu `IntradayInterval` được khai hẹp đúng bằng sáu giá trị trên, nên IDE gạch đỏ ngay lúc bạn gõ, trước cả một vòng gọi mạng. ### Cột trả về [#cột-trả-về] | Cột | dtype | Đơn vị | `null`? | | -------- | ---------------------------------- | ----------------- | ------- | | `symbol` | `string` | — | không | | `time` | `datetime64[ns, Asia/Ho_Chi_Minh]` | — | không | | `open` | `float64` | theo loại tài sản | có | | `high` | `float64` | theo loại tài sản | có | | `low` | `float64` | theo loại tài sản | có | | `close` | `float64` | theo loại tài sản | có | | `volume` | `float64` | theo loại tài sản | có | Bảng **luôn có đủ bảy cột đúng dtype kể cả khi không có dòng nào**, nên bạn không cần bọc `if not df.empty` quanh mỗi lời gọi. `volume` là `float64` chứ không phải `int64` vì cột này nullable: một bước không có lệnh nào phải ra `NaN`, không phải `0`. ```python import finlens client = finlens.client() df = client.intraday.stock.ohlcv("HPG", start="2026-08-03") df.attrs["finlens"]["units"]["close"] # 'kVND' # Thanh 5 phút, gộp ở máy chủ df = client.intraday.stock.ohlcv(["HPG", "VCB"], interval="5min") # Chỉ số và phái sinh nằm ở namespace riêng vì chúng khác đơn vị vni = client.intraday.index.ohlcv("VNINDEX") f1m = client.intraday.derivative.ohlcv("VN30F1M") ``` Vũ trụ mã chỉ số: `VNINDEX`, `VN30`, `VNXALL`, `HNXINDEX`, `HNX30`, `UPINDEX`. Cùng một lời gọi lúc 10:00 và lúc 15:30 cho ra hai kết quả khác nhau, và đó là đúng chứ không phải lỗi. Mốc nước của bảng nằm ở `df.attrs["finlens"]["as_of"]`. ## `ticks()` — từng lệnh đã khớp [#ticks--từng-lệnh-đã-khớp] ```python client.intraday.stock.ticks( symbol, *, date=None, refresh=False, on_error="warn", ) -> DataFrame ``` Mỗi dòng là **một lệnh đã khớp**: không gộp, không resample. Muốn thanh giá theo phút thì gọi `ohlcv()`; muốn dòng tiền chủ động đã cộng dồn thì gọi `net_active_value()`. Tham số đầu tên là **`symbol`** (số ít) và `date` là **một** ngày — khác hẳn hai phương thức kia vốn nhận `symbols` số nhiều. Giới hạn này nằm trong **chữ ký** chứ không phải trong một lỗi runtime bạn chỉ gặp sau khi request đã quá lớn. Lý do rất cụ thể: một phiên của một mã đã là hàng chục nghìn dòng, và một phiên phái sinh sôi động là **hơn 90.000 dòng**. Đây là phương thức duy nhất trả dữ liệu chưa gộp; `ohlcv()` và `net_active_value()` nhận nhiều mã được vì chúng đọc bản đã gộp sẵn ở máy chủ. Truyền một danh sách vào đây sẽ nhận `finlens.ValidationError` **trước khi** chạm mạng, chứ không âm thầm lấy mã đầu tiên. Muốn nhiều mã thì gọi nhiều lần: ```python khung = [client.intraday.stock.ticks(ma, date="2026-08-03") for ma in ("HPG", "VCB")] ``` Bỏ trống `date` thì máy chủ chọn phiên mặc định. Nhận cả chuỗi lẫn `datetime.date`: ```python from datetime import date client.intraday.stock.ticks("HPG", date="2026-08-03") client.intraday.stock.ticks("HPG", date=date(2026, 8, 3)) ``` ### Cột trả về [#cột-trả-về-1] | Cột | dtype | Đơn vị | `null`? | | -------- | ---------------------------------- | ----------------------------- | ------- | | `symbol` | `string` | — | không | | `time` | `datetime64[ns, Asia/Ho_Chi_Minh]` | — | không | | `price` | `float64` | giá, theo loại tài sản | có | | `volume` | `float64` | khối lượng, theo loại tài sản | có | | `side` | `string` | — | có | | `value` | `float64` | **VND thô** | có | Một frame chỉ chứa **một** mã. Sáu cột luôn có mặt kể cả khi không có dòng nào. ### Cột `side` có ba giá trị, không phải hai [#cột-side-có-ba-giá-trị-không-phải-hai] | Giá trị | Nghĩa | | --------- | -------------------------------------------------------------- | | `buy` | Bên **mua** chủ động — nâng giá lên chạm bên bán. | | `sell` | Bên **bán** chủ động — hạ giá xuống chạm bên mua. | | `auction` | Khớp lệnh **định kỳ** ATO/ATC — **không có** bên chủ động nào. | Phiên định kỳ khớp toàn bộ lệnh tại một mức giá duy nhất, nên ở đó không tồn tại khái niệm "bên chủ động" — xếp nó vào mua hay bán đều là bịa ra một chiều không có thật. Và nó chiếm **1,4% đến 8,6% khối lượng phiên tuỳ mã**, đủ lớn để làm lệch mọi con số ròng nếu bị gộp nhầm. Muốn riêng phần khớp lệnh liên tục thì lọc ra, đừng gộp: ```python lien_tuc = df[df["side"] != "auction"] ``` Với **chỉ số**, cả `side` và `value` đều `null`: dữ liệu tick chỉ số không ghi chiều lệnh chủ động và cũng không có giá trị tiền. Hai cột vẫn **có mặt** với toàn `null` thay vì biến mất, để một frame chỉ số vẫn `concat` được với một frame cổ phiếu. ### Một dòng tick mang hai họ đơn vị [#một-dòng-tick-mang-hai-họ-đơn-vị] Đây là chỗ dễ sai nhất của cả trang, vì nó nằm ngay **trong cùng một dòng**: * `price` là **giá** — nghìn VND với cổ phiếu, điểm chỉ số với chỉ số và phái sinh. * `value` là **tiền** — luôn **VND thô**, không phụ thuộc loại tài sản. ```python df = client.intraday.stock.ticks("HPG", date="2026-08-03") df.attrs["finlens"]["units"]["price"] # 'kVND' df.attrs["finlens"]["units"]["value"] # 'VND' ``` `value` do **máy chủ tính**, không phải phép nhân `price × volume` bạn tự làm được: nó đã nhân sẵn hệ số quy đổi của loại tài sản. Nhân tay rồi so với `value` mà quên đổi đơn vị sẽ lệch **1.000 lần với cổ phiếu** và **100.000 lần với phái sinh** — hai con số này không có exception nào chặn được, chỉ có `units` chặn được. Với phái sinh, `value` cũng có thể là `null`: quy đổi ra VND cần hệ số hợp đồng, và máy chủ chỉ phát số cho mã đã có hệ số **xác nhận**. `null` ở đây nghĩa là *chưa biết*, không phải *bằng không* — sai một hệ số là sai 100.000 lần, nên `null` tốt hơn một con số đoán. Cột `volume` vẫn trả bình thường. ## `net_active_value()` — dòng tiền mua/bán chủ động [#net_active_value--dòng-tiền-muabán-chủ-động] ```python client.intraday.stock.net_active_value( symbols, *, start=None, end=None, interval="1min", refresh=False, on_error="warn", ) -> DataFrame ``` Cùng bộ tham số với `ohlcv()`, và cùng nhận **nhiều mã** trong một lời gọi. Có ở `client.intraday.stock` và `client.intraday.derivative`; **không có** ở `client.intraday.index`. Giá trị và khối lượng khớp lệnh **chủ động** theo từng bước thời gian, tách làm ba nhóm: mua chủ động, bán chủ động, và khớp lệnh định kỳ. ### Cột trả về [#cột-trả-về-2] | Cột | dtype | Đơn vị | Nội dung | | ---------------- | ---------------------------------- | ---------- | ----------------------------------------------------- | | `symbol` | `string` | — | Mã chứng khoán. | | `time` | `datetime64[ns, Asia/Ho_Chi_Minh]` | — | Đầu bước thời gian. | | `buy_value` | `float64` | **VND** | Giá trị mua chủ động trong bước. | | `sell_value` | `float64` | **VND** | Giá trị bán chủ động trong bước. | | `net_value` | `float64` | **VND** | `buy_value - sell_value`. Dương là mua chủ động ròng. | | `auction_value` | `float64` | **VND** | Giá trị khớp lệnh định kỳ ATO/ATC. | | `buy_volume` | `float64` | khối lượng | Khối lượng mua chủ động. | | `sell_volume` | `float64` | khối lượng | Khối lượng bán chủ động. | | `net_volume` | `float64` | khối lượng | `buy_volume - sell_volume`. | | `auction_volume` | `float64` | khối lượng | Khối lượng khớp lệnh định kỳ. | Mười cột luôn có mặt kể cả khi không có dòng nào. Khối lượng tính bằng **cổ phiếu** với cổ phiếu, bằng **hợp đồng** với phái sinh — đọc `df.attrs["finlens"]["units"]["buy_volume"]`. ### Ba nhóm, hai công thức, một chỗ rất dễ hiểu nhầm [#ba-nhóm-hai-công-thức-một-chỗ-rất-dễ-hiểu-nhầm] * `net_value = buy_value - sell_value` — một **hiệu**. * `buy_value + sell_value + auction_value` — một **tổng**, chính là toàn bộ giá trị khớp của bước đó. Đừng cộng `auction_value` vào `net_value`. Một bên là hiệu, một bên là tổng, và ATO/ATC không có chiều để mà cộng vào. Ba nhóm khối lượng cộng lại **đúng bằng** khối lượng phiên của dữ liệu cuối ngày, nên đây là phép đối chiếu bạn tự chạy được: ```python trong_phien = client.intraday.stock.net_active_value("HPG", start="2026-08-03") tong_kl = trong_phien[["buy_volume", "sell_volume", "auction_volume"]].sum().sum() cuoi_ngay = client.eod.stock.ohlcv("HPG", start="2026-08-03", end="2026-08-03") tong_kl == cuoi_ngay["volume"].iloc[0] ``` Nhóm cuối ngày có một phương thức tên gần giống, [`client.eod.stock.active_volume()`](/python-sdk/eod) và bản phái sinh của nó. Hai đại lượng **không cộng được với nhau**: cùng một phiên VN30F1M, ba cột tương ứng lệch nhau **57,5% · 520% · 30,1%**. | | `intraday.*.net_active_value()` | `eod.*.active_volume()` | | -------- | ------------------------------- | ---------------------------------- | | Số rổ | **ba** — `auction` tách riêng | **hai** — phần định kỳ bị trộn vào | | Cột tiền | có, tính bằng **VND** | **không có cột tiền nào** | | Nguồn | dựng từ bảng lệnh đã khớp | một bảng tổng hợp cuối ngày | Hệ quả trực tiếp của cột thứ nhất: `buy_volume` ở đây **hẹp hơn** `active_buy_volume` ở kia, vì ở kia phiên ATO/ATC đã nằm sẵn trong một trong hai rổ. Hai phương thức mang hai cái tên khác hẳn nhau chính vì hai định nghĩa khác nhau — và phép cộng giữa hai frame **không ném exception nào**, chỉ cho ra một con số sai. Bản 0.1.x có hai bản cài đặt khác nhau cho cùng một tên cột: bản cổ phiếu chia cho 10⁶, bản phái sinh không chia, còn tài liệu thì gọi nó là "tỷ đồng" — ba câu trả lời cho một câu hỏi. Ở 1.x máy chủ tự tính và khai **một** đơn vị duy nhất: **VND thô**. Với cổ phiếu, con số mới lớn hơn con số cũ **10⁶ lần**; với phái sinh, con số cũ vốn không thuộc đơn vị nào nên không quy đổi được — hãy đọc lại từ đầu. ```python df.attrs["finlens"]["units"]["net_value"] # 'VND' ``` Với phái sinh, các cột `*_value` có thể trả `null` khi mã chưa có hệ số hợp đồng xác nhận; các cột `*_volume` vẫn trả bình thường. Kiểm bằng `.isna()`, đừng đọc `null` thành `0`. ```python # Gộp về thanh 15 phút — giá trị được CỘNG trong bước df = client.intraday.stock.net_active_value("HPG", interval="15min") # Nhiều mã trong một lời gọi df = client.intraday.stock.net_active_value(["HPG", "VCB"], interval="1h") # Phái sinh: cùng chữ ký, khác đơn vị khối lượng df = client.intraday.derivative.net_active_value("VN30F1M") df.attrs["finlens"]["units"]["buy_volume"] # hợp đồng, không phải cổ phiếu ``` ## `basis()` — chênh lệch phái sinh và chỉ số cơ sở, bước 1 phút [#basis--chênh-lệch-phái-sinh-và-chỉ-số-cơ-sở-bước-1-phút] ```python client.intraday.derivative.basis( symbols, *, start=None, end=None, refresh=False, on_error="warn", ) -> DataFrame ``` Chỉ có ở `client.intraday.derivative`, và chỉ phục vụ các mã `VN30F*`. Cùng đại lượng và **cùng công thức** với [`client.eod.derivative.basis()`](/python-sdk/eod); chỉ cột thời gian khác — ở đây là `time` mang múi giờ, ở kia là `date` naive. Đây là phương thức duy nhất trong nhóm trong phiên **không** nhận `interval`, và bản cuối ngày của nó cũng vậy. Gộp một **chênh lệch** lên bước lớn hơn không có nghĩa hiển nhiên nào: trung bình của bước, giá trị cuối bước và biên độ trong bước là ba câu trả lời khác nhau cho cùng một câu hỏi. Chọn hộ một trong ba là chôn một quyết định phân tích vào thư viện. Cần thì `df.resample(...)` trên chính frame này. ### Cột trả về [#cột-trả-về-3] | Cột | dtype | Đơn vị | `null`? | | -------------- | ---------------------------------- | --------------- | ------- | | `symbol` | `string` | — | không | | `index_symbol` | `string` | — | không | | `time` | `datetime64[ns, Asia/Ho_Chi_Minh]` | — | không | | `future_close` | `float64` | **điểm chỉ số** | có | | `spot_close` | `float64` | **điểm chỉ số** | có | | `basis` | `float64` | **điểm chỉ số** | có | | `basis_pct` | `float64` | **phần trăm** | có | Bảy cột luôn có mặt kể cả khi không có dòng nào. ```text basis = future_close - spot_close # điểm chỉ số basis_pct = basis / spot_close * 100 # phần trăm, thang 0–100 ``` ⚠️ Mẫu số của `basis_pct` là **`spot_close`**, không phải `future_close`, và kết quả **đã nhân 100**. Hai mẫu số chỉ lệch nhau khoảng **0,3%** nên chọn nhầm gần như không nhìn ra được trên một biểu đồ — đó chính là lý do công thức được viết thẳng ra đây. Giải thích đầy đủ, kể cả vì sao `index_symbol` là một **cột thật** chứ không phải một chi tiết trong `df.attrs`, nằm ở [trang cuối ngày](/python-sdk/eod). ```python df = client.intraday.derivative.basis("VN30F1M", start="2026-08-05") df.attrs["finlens"]["units"]["basis"] # 'index_point' df.attrs["finlens"]["units"]["basis_pct"] # 'pct' ``` ### Chuỗi bắt đầu từ 09:15, và khoảng trước đó vắng mặt có chủ đích [#chuỗi-bắt-đầu-từ-0915-và-khoảng-trước-đó-vắng-mặt-có-chủ-đích] Bar đầu tiên của một phiên là **09:15**, không phải 09:00 và cũng không phải 09:01. Hai lý do rời nhau, cùng dẫn tới một mốc: **1. Trước 09:15, chỉ số chưa được tính theo từng phút.** Hợp đồng phái sinh mở cửa sớm hơn cổ phiếu nên nó **có** bar liên tục suốt khoảng 09:01–09:14, nhưng vế `spot_close` thì không tồn tại ở đó. Đo trên **3/3 phiên** kiểm: chỉ số có đúng **một** bar lúc 09:00 rồi không có bar nào cho tới 09:15. Ghép hai vế ở khoảng đó sẽ cho ra `spot_close` là `null`, tức `basis` cũng `null` — một cột toàn ô trống suốt mười bốn phút đầu phiên. **2. Bar 09:00 có đủ hai vế, nhưng nó là một cơ chế hình thành giá khác hẳn.** 09:00 là kết quả **khớp lệnh định kỳ ATO**: toàn bộ lệnh khớp tại một mức giá duy nhất, không có bên chủ động nào, không có chuỗi giá liên tục dẫn tới nó. Một chênh lệch tính trên hai giá đấu giá định kỳ không so sánh được với chênh lệch tính trên các bar khớp lệnh liên tục phía sau — đặt chung một chuỗi là trộn hai đại lượng. Mốc 09:15 vì vậy loại cả hai: khoảng không có vế spot **lẫn** bar đấu giá định kỳ. Kết quả là một chuỗi không có ô trống nào ngay từ bar đầu. ```python df = client.intraday.derivative.basis("VN30F1M", start="2026-08-05") df["time"].min().strftime("%H:%M") # '09:15' df["basis"].isna().sum() # 0 ``` Bảng này chậm hơn thị trường một quãng có thể lên tới **quãng chục phút**, nên bar cuối cùng bạn nhận được không phải phút vừa xong. Mốc nước thật của bảng nằm ở `df.attrs["finlens"]["as_of"]` — so nó với đồng hồ trước khi kết luận "chênh lệch đang là bao nhiêu ngay lúc này". Ngoài phiên thì không có chuyện đó: một phiên đã đóng là một chuỗi đã đầy đủ. Mã phái sinh không có chuỗi chỉ số cơ sở trong dữ liệu đi vào **phần lỗi theo từng mã** với mã `FL_DATA_NO_UNDERLYING` (`finlens.NoDataError`), chứ không làm hỏng cả lời gọi — hành vi và ví dụ giống hệt bản cuối ngày. ## Đơn vị trong phiên, tra nhanh [#đơn-vị-trong-phiên-tra-nhanh] | Loại tài sản | Cột giá (`open`…`close`, `price`) | Khối lượng | Cột tiền (`value`, `*_value`) | | ---------------------------- | ---------------------------------- | ------------ | ----------------------------- | | Cổ phiếu, ETF, chứng chỉ quỹ | **nghìn VND** — `22.3` là 22.300 đ | cổ phiếu | **VND thô** | | Chỉ số | điểm chỉ số | cổ phiếu | không có | | Phái sinh | điểm chỉ số | **hợp đồng** | **VND thô** | Riêng `basis()` nằm ngoài bảng này vì cả hai vế của nó đều là **điểm chỉ số** theo định nghĩa: `future_close`, `spot_close` và `basis` là `'index_point'`, còn `basis_pct` là `'pct'` trên thang **0–100**. Bảng trên để bạn ước lượng nhanh. Câu trả lời đáng tin duy nhất là `units` của chính bảng bạn vừa nhận, tra theo **tên cột**: ```python df.attrs["finlens"]["units"] # {'symbol': None, 'time': None, 'price': 'kVND', 'volume': 'share', # 'side': None, 'value': 'VND'} ``` ⚠️ `DataFrame.attrs` **không sống sót** qua `pd.concat` hay `merge` của pandas. Đọc đơn vị ra biến **trước khi** ghép bảng. Chi tiết ở [Kiểu dữ liệu](/python-sdk/kieu-du-lieu). ## Bản async [#bản-async] Mọi phương thức trên đều có bản bất đồng bộ với **cùng chữ ký**: ```python import asyncio import finlens async def main(): async with finlens.AsyncClient() as client: df = await client.intraday.stock.ticks("HPG", date="2026-08-03") asyncio.run(main()) ``` ## Xem thêm [#xem-thêm] Giá theo phiên đã điều chỉnh quyền, sổ lệnh đặt, khối lượng chủ động, chênh lệch phái sinh và dòng tiền theo nhóm nhà đầu tư. `IntradayInterval`, `df.attrs["finlens"]` và cách đọc đơn vị từng cột. `on_error`, `PartialFetchError` và cây ngoại lệ `FL_*`. Cùng dữ liệu này qua trợ lý AI, không cần viết code. ### Câu hỏi thường gặp **Làm sao lấy dữ liệu theo phút của một mã cổ phiếu Việt Nam bằng Python?** Gọi `client.intraday.stock.ohlcv("HPG", start="2026-08-03", interval="5min")` của thư viện Python finlens. Chỉ `symbols` là tham số vị trí; `start`, `end`, `interval`, `refresh` và `on_error` đều keyword-only. Frame trả về gồm `symbol`, `time`, `open`, `high`, `low`, `close`, `volume` — luôn đủ bảy cột đúng dtype kể cả khi 0 dòng, nên không cần bọc `if not df.empty`. Cột thời gian tên `time` chứ không phải `date`, và nó mang múi giờ `Asia/Ho_Chi_Minh`. Việc gộp thanh chạy ở máy chủ nên `interval="5min"` trả về thanh 5 phút đã gộp sẵn. **Dữ liệu trong phiên hỗ trợ những khung thời gian nào?** Thư viện Python finlens khai kiểu `IntradayInterval` với đúng sáu giá trị: `"1min"`, `"5min"`, `"15min"`, `"30min"`, `"1h"` và `"4h"`, mặc định là `"1min"`. Không có `"1m"`: trong từ vựng cũ `1m` là một phút còn `1M` là một tháng, chỉ khác nhau ở chữ hoa nhưng lệch nhau 43.200 lần, nên cả hai đều bị từ chối bằng `finlens.InvalidIntervalError` thay vì bị đoán ý. Interval cuối ngày (`1d`, `1w`, `1mo`, `3mo`, `6mo`, `1y`) cũng không dùng được ở đây — muốn thanh ngày thì gọi `client.eod`. **Lấy từng lệnh đã khớp (tick) của một cổ phiếu bằng Python thế nào?** Gọi `client.intraday.stock.ticks("HPG", date="2026-08-03")` của thư viện Python finlens. Đây là phương thức duy nhất trong nhóm nhận `symbol` số ít và đúng một `date` cho mỗi lời gọi — giới hạn nằm trong chữ ký, nên truyền một danh sách vào sẽ nhận `finlens.ValidationError` trước khi chạm mạng. Frame gồm sáu cột `symbol`, `time`, `price`, `volume`, `side`, `value`. Cột `side` có ba giá trị: `buy` là mua chủ động, `sell` là bán chủ động và `auction` là khớp lệnh định kỳ ATO/ATC — phiên định kỳ không có bên chủ động nên đừng gộp nó vào mua hay bán. **finlens có dữ liệu trong phiên của VNINDEX và hợp đồng VN30F1M không?** Có. Chỉ số nằm ở `client.intraday.index.ohlcv("VNINDEX")` và phái sinh ở `client.intraday.derivative.ohlcv("VN30F1M")`; cả hai namespace còn có `ticks()`. Riêng `net_active_value()` chỉ có ở `client.intraday.stock` và `client.intraday.derivative` — `client.intraday.index` không có, vì dữ liệu tick của chỉ số không ghi chiều lệnh chủ động nên không có gì để tính. Ba namespace tách nhau vì khác đơn vị: cổ phiếu tính giá bằng nghìn VND, chỉ số và phái sinh tính bằng điểm chỉ số, và khối lượng phái sinh tính bằng hợp đồng. **Vì sao không nối được chuỗi giá trong phiên vào chuỗi giá cuối ngày?** Vì hai chuỗi không cùng cơ sở giá. Trong thư viện Python finlens, `client.eod.stock.ohlcv()` mặc định trả giá đã điều chỉnh quyền, còn `client.intraday.*.ohlcv()` luôn trả giá thô đúng như đã khớp trên bảng điện — và không có tham số `adjusted` ở nhóm trong phiên. Ghép thẳng hai chuỗi sẽ tạo một bậc thang giả đúng ở ngày chia tách hay trả cổ tức bằng cổ phiếu mà không có lỗi nào báo. Đọc `df.attrs["finlens"]["price_basis"]` để biết cơ sở giá, và lấy phần cuối ngày bằng `adjusted=False` nếu muốn cùng cơ sở. **Vì sao chuỗi basis trong phiên bắt đầu từ 09:15 mà không phải 09:00?** Vì hai lý do rời nhau cùng dẫn tới một mốc. Thứ nhất, trước 09:15 chỉ số chưa được tính theo từng phút: hợp đồng phái sinh mở cửa sớm hơn nên nó có bar liên tục suốt khoảng 09:01–09:14, nhưng vế `spot_close` không tồn tại ở đó, ghép vào chỉ cho ra một cột toàn ô trống. Thứ hai, bar 09:00 tuy có đủ hai vế nhưng là kết quả khớp lệnh định kỳ ATO — toàn bộ lệnh khớp tại một mức giá duy nhất, không có bên chủ động nào — nên một chênh lệch tính trên hai giá đấu giá định kỳ không so sánh được với chênh lệch tính trên các bar khớp lệnh liên tục phía sau. Trong thư viện Python finlens, `client.intraday.derivative.basis("VN30F1M")` vì vậy trả bar đầu tiên lúc 09:15 và không có ô trống nào trong cột `basis`. --- # Kiểu dữ liệu finlens.typing: WhoAmI, Limits, FrameMeta URL: https://docs.finlens.vn/python-sdk/kieu-du-lieu Mô tả: Tham chiếu kiểu dữ liệu finlens.typing của thư viện Python finlens: WhoAmI, Limits, FrameMeta, EodInterval và cách đọc đơn vị từng cột trong df.attrs. Tóm tắt: Trang mô tả module `finlens.typing` của thư viện Python `finlens` — thư viện trả dữ liệu chứng khoán Việt Nam về `pandas.DataFrame`. Nội dung chia hai nhóm: các alias kiểu cho tham số (`SymbolsArg`, `IcbArg`, `DateArg`, `EodInterval` với sáu giá trị `1d`, `1w`, `1mo`, `3mo`, `6mo`, `1y` — năm giá trị sau gộp kỳ ở máy chủ và dán nhãn mỗi dòng bằng phiên giao dịch cuối cùng thực sự có dữ liệu trong kỳ, không phải ngày đầu kỳ — `IntradayInterval` với `1min`, `5min`, `15min`, `30min`, `1h`, `4h`, `OnError` với `warn`/`raise`/`ignore`, `InvestorGroup`, `SectorInvestorGroup`, `DerivativeInvestorGroup` — hai alias sau cùng chỉ nhận `foreign` và `proprietary` — `StatementKind`, `CompanyType`, `Tier`), và các `TypedDict` mô tả những giá trị trả về không phải bảng: `WhoAmI` của `client.whoami()`, `Limits` của `client.limits()`, `CacheStats` của `client.cache.stats()` và `ServiceStatus` của `client.status()`. Phần dài nhất nói về `FrameMeta` — nội dung `df.attrs["finlens"]` đi kèm mỗi DataFrame, gồm `dataset`, `units`, `price_basis`, `tz`, `as_of`, `fetched_at`, `request_id`, `truncated`, `partial`, `failed` — nơi đọc đơn vị của từng cột và biết mã nào không lấy được. Module `finlens.types` của bản 0.1.x đã bị gỡ bỏ; ở 1.x mọi kiểu đều được re-export ở cấp `finlens`. In English: reference for the finlens Python library type surface — whoami(), limits(), and the per-column units carried in df.attrs for Vietnamese stock market DataFrames. Sản phẩm: python-sdk Mọi hàm truy vấn dữ liệu đều trả về `pandas.DataFrame`. Những gì **không phải bảng** — bạn là ai, hạn mức còn bao nhiêu, bảng vừa nhận mang đơn vị gì — nằm ở module `finlens.typing`. Module này chia làm hai nhóm, phục vụ hai nhu cầu khác nhau: * **Alias kiểu** — trả lời "tham số này nhận giá trị nào", và dùng để chú thích kiểu cho chính code của bạn. * **`TypedDict`** — mô tả hình dạng của các dict mà `whoami()`, `limits()` và `df.attrs["finlens"]` trả về. Bản 0.1.x có module `finlens.types` với `ApiKeyValidationResponse`, `ApiKeyMeta`, `BackendMessage`, `MessageType` và `iter_messages()`. Ở 1.x **không tên nào trong số đó còn tồn tại** — `import finlens.types` ném `ModuleNotFoundError`. Thay thế tương ứng: gọi `client.whoami()` để nhận `WhoAmI`, gọi `client.limits()` để nhận `Limits`. Thông báo của máy chủ nay đi qua cơ chế `warnings` chuẩn của Python, xem [Xử lý lỗi](/python-sdk/xu-ly-loi). ## Import ở đâu [#import-ở-đâu] Mọi kiểu đều được re-export ở **cấp `finlens`**, nên bạn không cần nhớ tên module con: ```python import finlens from pandas import DataFrame def lay_gia(ma: finlens.SymbolsArg, interval: finlens.EodInterval = "1d") -> DataFrame: client = finlens.client() return client.eod.stock.ohlcv(ma, interval=interval) def con_du_han_muc(han_muc: finlens.Limits) -> bool: return han_muc["requests_remaining"] > 100 ``` Viết `from finlens.typing import Limits` cũng đúng, chỉ dài hơn. Gói có gợi ý kiểu theo chuẩn [PEP 561](https://peps.python.org/pep-0561/), nên IDE và `mypy` đọc được cả hai cách. ## Alias kiểu [#alias-kiểu] | Alias | Xuất hiện ở | Trả lời câu hỏi | | ----------------------------- | ------------------------------ | ----------------------------------- | | `SymbolsArg` | tham số `symbols` | Truyền một mã hay nhiều mã thế nào? | | `IcbArg` | tham số `icb` | Mã ngành viết ra sao? | | `DateArg` | `start`, `end` | Ngày nhận chuỗi hay `date`? | | `EodInterval` | `interval` | Gộp theo tuần, tháng viết là gì? | | `OnError` | `on_error` | Một mã hỏng thì cả lời gọi ra sao? | | `InvestorGroup` | `group` cấp mã và cấp chỉ số | Có những nhóm nhà đầu tư nào? | | `SectorInvestorGroup` | `group` cấp ngành | Cấp ngành có nhóm nào? | | `DerivativeInvestorGroup` | `group` cấp hợp đồng phái sinh | Phái sinh có nhóm nào? | | `InvestorGroupsArg` | `groups` cấp mã | Hỏi nhiều nhóm một lần thế nào? | | `SectorInvestorGroupsArg` | `groups` cấp ngành | Như trên, ở cấp ngành. | | `DerivativeInvestorGroupsArg` | `groups` cấp phái sinh | Như trên, ở cấp phái sinh. | | `Tier` | `whoami()["account"]["tier"]` | Gói dịch vụ tên là gì? | ### `SymbolsArg` và `IcbArg` [#symbolsarg-và-icbarg] ```python SymbolsArg = str | Sequence[str] IcbArg = str | Sequence[str] ``` Ba cách viết dưới đây tương đương nhau, và hợp lệ ở **mọi** hàm nhận mã: ```python client.eod.stock.ohlcv("HPG") client.eod.stock.ohlcv("HPG,VCB") client.eod.stock.ohlcv(["HPG", "VCB"]) ``` `IcbArg` giống hệt về hình dạng nhưng khác về nội dung: nó nhận **mã ngành ICB cấp 4** dưới dạng chuỗi — `"8600"`, `"8600,3570"`, `["8600", "3570"]`. Phải là chuỗi chứ không phải số, vì `8600` viết dạng số sẽ làm mất số `0` đứng đầu ở các mã khác. ### `DateArg` [#datearg] ```python DateArg = str | date | datetime | None ``` ```python from datetime import date client.eod.stock.ohlcv("HPG", start="2026-01-01") client.eod.stock.ohlcv("HPG", start=date(2026, 1, 1)) ``` Truyền `datetime` cũng được, nhưng **phần giờ bị bỏ**: đây là ngày giao dịch, không phải một thời điểm. `None` nghĩa là dùng mặc định — `start` mặc định là một năm trước `end`, `end` mặc định là hôm nay. ### `EodInterval` [#eodinterval] ```python EodInterval = Literal["1d", "1w", "1mo", "3mo", "6mo", "1y"] ``` Sáu giá trị, **chỉ viết thường**. Không có `1m`, và đó là chủ ý. Trong từ vựng cũ `1M` là một **tháng** còn `1m` là một **phút** — phân biệt duy nhất bằng chữ hoa, trong khi hai giá trị đó lệch nhau 43.200 lần. Ở đây tháng là `1mo`, và cả `1M` lẫn `1m` đều nhận một lỗi rõ ràng thay vì một biểu đồ sai: ```text Interval '1m' nhập nhằng: có thể là một phút hoặc một tháng. Dùng '1min' cho một phút, hoặc '1mo' cho một tháng. ``` Với dữ liệu cuối ngày, giá trị bạn cần là **`1mo`**. Lỗi này là `finlens.InvalidIntervalError`, mã `FL_VALIDATION_INTERVAL_AMBIGUOUS`. ```python # Đúng client.eod.stock.ohlcv("HPG", interval="1mo") # Sai — InvalidIntervalError client.eod.stock.ohlcv("HPG", interval="1M") ``` Cùng một bộ giá trị này dùng cho cả `ohlcv()` lẫn `flow()` và `breakdown()`. Việc gộp kỳ chạy ở phía máy chủ, nên `interval="1w"` trả về thanh tuần đã gộp sẵn chứ không phải thanh ngày để bạn tự gộp. `1d` trả về ngày của chính phiên đó. Năm giá trị còn lại — `1w`, `1mo`, `3mo`, `6mo`, `1y` — dán nhãn mỗi dòng bằng **phiên giao dịch cuối cùng thực sự có dữ liệu** trong kỳ, không phải ngày đầu kỳ và cũng không phải ngày cuối theo lịch: ```python df = client.eod.stock.ohlcv("HPG", start="2025-01-01", end="2025-03-31", interval="1mo") df["date"].dt.strftime("%Y-%m-%d").tolist() # ['2025-01-24', '2025-02-28', '2025-03-31'] ``` Tháng 1/2025 ra `2025-01-24` vì thị trường nghỉ Tết từ ngày 25. Lý do và các hệ quả khi lọc theo ngày ở [Giá cuối ngày](/python-sdk/eod). ### `OnError` [#onerror] ```python OnError = Literal["warn", "raise", "ignore"] ``` | Giá trị | Hành vi | | ------------------------------- | ---------------------------------------------------------------------------------------------- | | `"warn"` *(mặc định)* | Giữ phần lấy được, phát `PartialDataWarning`, ghi mã hỏng vào `df.attrs["finlens"]["failed"]`. | | `"raise"` | Ném `PartialFetchError`, ngoại lệ này **mang theo** phần đã lấy được ở `.data`. | | `"ignore"` | Giữ phần lấy được, không cảnh báo. | Mặc định là `"warn"` chứ không phải `"raise"` vì một mã hỏng không được làm mất 49 mã còn lại. Chi tiết ở [Xử lý lỗi](/python-sdk/xu-ly-loi). ### Nhóm nhà đầu tư [#nhóm-nhà-đầu-tư] ```python InvestorGroup = Literal[ "foreign", "foreign_individual", "foreign_institutional", "local_individual", "local_institutional", "proprietary", ] SectorInvestorGroup = Literal["foreign", "proprietary"] DerivativeInvestorGroup = Literal["foreign", "proprietary"] ``` Hai alias sau hẹp hơn có chủ đích: bốn nhóm chi tiết **không tồn tại** ở cấp ngành, cũng **không tồn tại** ở cấp hợp đồng phái sinh. Thu hẹp `Literal` biến một lỗi mạng thành một lỗi lúc bạn gõ code. Chúng trùng tập giá trị nhưng là **hai alias riêng**, vì hai chỗ hẹp lại vì hai lý do khác nhau và hai lý do đó có thể đổi độc lập: ở cấp ngành, cái bị chặn là một nguồn thực chất chỉ có sàn HOSE; ở cấp phái sinh, nguồn của bốn nhóm chi tiết khoá theo danh mục **doanh nghiệp niêm yết**, nơi không hợp đồng phái sinh nào có mặt. Ba alias dạng số nhiều dùng cho `breakdown()`: ```python InvestorGroupsArg = str | Sequence[InvestorGroup] | None SectorInvestorGroupsArg = str | Sequence[SectorInvestorGroup] | None DerivativeInvestorGroupsArg = str | Sequence[DerivativeInvestorGroup] | None ``` `None` nghĩa là **đầy đủ các nhóm** mà cấp đó phục vụ, không phải "không nhóm nào". Và **không có giá trị `"all"`** ở bất kỳ đâu — muốn tất cả thì để `None`, muốn một tập cụ thể thì liệt kê ra. Chỉ **bốn nhóm chi tiết** (`foreign_individual`, `foreign_institutional`, `local_individual`, `local_institutional`) tạo thành một phân hoạch đầy đủ — tổng `net_value` của chúng bằng 0. `foreign` gồm cả giao dịch thỏa thuận nên **không** bằng tổng hai nhóm nước ngoài chi tiết. `proprietary` (tự doanh) **không** là nhóm con của `local_institutional`. Cộng cả sáu lại cho ra một con số vô nghĩa. ### `Tier` [#tier] ```python Tier = Literal["free", "standard", "pro", "premium"] ``` Đọc bằng `client.whoami()["account"]["tier"]`. ## Các `TypedDict` [#các-typeddict] Đây là `TypedDict`, tức **lúc chạy chúng là `dict` thuần**. Truy cập bằng khóa, không phải bằng thuộc tính, và chúng không có phương thức nào: ```python me = client.whoami() me["account"]["tier"] # đúng me.account.tier # AttributeError ``` Đổi lại, bạn không phải cài thêm thư viện nào để đọc kết quả, và IDE vẫn gợi ý đủ tên khóa. ### `WhoAmI` — `client.whoami()` [#whoami--clientwhoami] ```python import finlens client = finlens.client(api_key="flk_...") me = client.whoami() me["account"]["tier"] # 'pro' me["key"]["prefix"] # 'flk_9f2a41c3' me["limits"]["requests_remaining"] # 4812 me["version"]["latest_client_version"] # '1.1.1' me["server_time"] # '2026-08-04T15:04:21+07:00' ``` | Khóa | Kiểu | Nội dung | | ------------- | ------------- | ------------------------------------------ | | `account` | `AccountInfo` | Gói dịch vụ và tình trạng tài khoản. | | `key` | `KeyInfo` | Khóa API đang dùng. | | `version` | `VersionInfo` | Đối chiếu phiên bản client với máy chủ. | | `limits` | `Limits` | Hạn mức hiệu lực. | | `server_time` | `str` | Giờ máy chủ, RFC 3339 kèm offset `+07:00`. | Tạo client **không** gọi mạng; `whoami()` là một lời gọi thật, nên nó cũng là cách kiểm tra khóa còn dùng được hay không ngay lúc khởi động ứng dụng. ### `AccountInfo` [#accountinfo] | Khóa | Kiểu | Nội dung | | ------------ | ----------------- | ---------------------------------------- | | `tier` | `Tier` | `free` · `standard` · `pro` · `premium`. | | `status` | `str` hoặc `None` | Tình trạng tài khoản. | | `expires_at` | `str` hoặc `None` | Thời điểm gói dịch vụ hết hạn. | `expires_at` ở đây là hạn của **gói dịch vụ**, khác với hạn của **khóa** trong `KeyInfo`. Hai thứ hết hạn độc lập nhau và cần hai hành động khác nhau — gia hạn tài khoản, hay tạo khóa mới — nên chúng cũng ném hai lớp ngoại lệ khác nhau: `AccountExpiredError` và `ApiKeyExpiredError`. ### `KeyInfo` [#keyinfo] | Khóa | Kiểu | Nội dung | | ------------ | ----------------- | ------------------------------------------------ | | `prefix` | `str` | **12 ký tự đầu** của khóa, ví dụ `flk_9f2a41c3`. | | `expires_at` | `str` hoặc `None` | Thời điểm khóa hết hạn. | Máy chủ chỉ trả về 12 ký tự đầu, đủ để bạn nhận ra mình đang dùng khóa nào khi có nhiều môi trường, và không đủ để ai đó đọc log rồi dùng lại. Không có thuộc tính nào trong SDK trả ra khóa đầy đủ — nếu bạn làm mất khóa thì tạo khóa mới, không có đường lấy lại. Bản 0.1.x làm ngược lại: nó công bố cả khóa trong phản hồi xác thực. ### `VersionInfo` [#versioninfo] `VersionInfo` là cái tên duy nhất sống sót từ `finlens.types` cũ sang `finlens.typing`, và đó chính là chỗ dễ nhầm nhất trên trang này: autocomplete gợi ý đúng tên, rồi code chết ở dòng sau. Ba trường cũ `client_version`, `backend_version`, `minimum_supported_version` và hai phương thức `requires_upgrade()`, `is_out_of_support()` **đều không còn**. Nó nay là một `TypedDict` với ba khóa khác hẳn. | Khóa | Kiểu | Nội dung | | ----------------------- | ----- | ----------------------------------------------- | | `contract_version` | `str` | Phiên bản hợp đồng API mà máy chủ đang phục vụ. | | `min_client_version` | `str` | Bản `finlens` thấp nhất còn được chấp nhận. | | `latest_client_version` | `str` | Bản mới nhất trên PyPI. | Bạn không cần tự so sánh ba con số này. Client tự làm: có bản mới hơn thì nó phát `UpgradeAvailableWarning`, còn bản của bạn quá cũ để dùng thì nó ném `UpgradeRequiredError`. ```python import finlens client = finlens.client() print(finlens.__version__) # bản đang chạy print(client.whoami()["version"]["latest_client_version"]) ``` ### `Limits` — `client.limits()` [#limits--clientlimits] ```python han_muc = client.limits() han_muc["requests_remaining"] # 4812 han_muc["max_symbols_per_request"] # 50 han_muc["resets_at"] # '2026-08-05T00:00:00+07:00' ``` | Khóa | Kiểu | Nội dung | | ------------------------- | ----------------- | ------------------------------------------------------------ | | `requests_per_day` | `int` | Hạn mức lượt gọi mỗi ngày. | | `requests_remaining` | `int` | Số lượt còn lại trong chu kỳ hiện tại. | | `resets_at` | `str` | Thời điểm hạn mức được đặt lại. | | `history_days` | `int` hoặc `None` | Độ dài lịch sử được phép truy vấn. `None` là không giới hạn. | | `max_symbols_per_request` | `int` | Số mã tối đa trong một lời gọi. | | `max_concurrency` | `int` | Số request song song tối đa. | | `max_rows` | `int` | Số dòng tối đa của một kết quả. | | `max_intraday_days` | `int` | Số ngày dữ liệu trong phiên được phép lấy một lần. | Những con số này do **máy chủ** quyết định và đọc được lúc chạy, không phải hằng số biên dịch sẵn trong thư viện. Nghĩa là khi hạn mức của bạn được nới, bản `finlens` đang cài sẽ dùng ngay giá trị mới mà không cần nâng cấp. Chạm hạn mức thì bạn nhận `RateLimitError` hoặc `DailyQuotaExceededError`; sắp cạn thì nhận `QuotaLowWarning`. Xem [Xử lý lỗi](/python-sdk/xu-ly-loi). `Limits` cũng chính là giá trị nằm ở `whoami()["limits"]` — `client.limits()` chỉ là lối đi tắt. ## `FrameMeta` — siêu dữ liệu đi kèm mỗi DataFrame [#framemeta--siêu-dữ-liệu-đi-kèm-mỗi-dataframe] Đây là kiểu bạn sẽ đọc nhiều nhất. Mỗi bảng trả về đều mang theo một `FrameMeta` ở `df.attrs["finlens"]`, và nó trả lời ba câu hỏi mà bản thân bảng không trả lời được: **những con số này đơn vị gì**, **dữ liệu tính tới lúc nào**, và **có mã nào không lấy được không**. ```python import finlens client = finlens.client() df = client.eod.stock.ohlcv("HPG,VCB", start="2026-01-01") meta = df.attrs["finlens"] meta["dataset"] # 'eod.ohlcv' meta["units"]["close"] # 'kVND' meta["price_basis"] # 'adjusted' meta["as_of"] # '2026-08-04T15:00:00+07:00' meta["partial"] # False ``` | Khóa | Kiểu | Nội dung | | ------------- | ----------------- | ----------------------------------------------------------------- | | `dataset` | `str` | Tên bộ dữ liệu, ví dụ `eod.ohlcv`. | | `units` | `dict` | Tên cột → đơn vị. `None` nghĩa là cột đó không mang đơn vị. | | `price_basis` | `str` hoặc `None` | `adjusted` (đã điều chỉnh quyền) hoặc `raw`. | | `tz` | `str` hoặc `None` | Múi giờ của các mốc thời điểm trong bảng, luôn là giờ thị trường. | | `as_of` | `str` hoặc `None` | Mốc nước của dữ liệu, RFC 3339 kèm offset `+07:00`. | | `fetched_at` | `str` | Lúc client nhận dữ liệu, theo đồng hồ máy bạn, tính bằng UTC. | | `request_id` | `str` hoặc `None` | Mã định danh lượt gọi. Gửi kèm khi báo lỗi. | | `truncated` | `bool` | `True` khi kết quả đã bị cắt ở giới hạn số dòng của gói. | | `partial` | `bool` | `True` khi có ít nhất một mã thất bại. | | `failed` | `dict` | Mã → lý do thất bại, mỗi giá trị là một `FailedSymbol`. | ### Đọc đơn vị ở đâu [#đọc-đơn-vị-ở-đâu] Đơn vị **không cố định theo tên cột** — nó phụ thuộc loại tài sản. Cùng cột `close`: cổ phiếu là nghìn VND, chỉ số là điểm chỉ số, chứng quyền là VND thô. Cùng cột `volume`: cổ phiếu tính bằng cổ phiếu, phái sinh tính bằng hợp đồng. Vì vậy `units` là câu trả lời duy nhất đáng tin: ```python gia = client.eod.stock.ohlcv("HPG") gia.attrs["finlens"]["units"]["close"] # 'kVND' — 23.4 nghĩa là 23.400 VND dong_tien = client.eod.stock.investor.flow("HPG") dong_tien.attrs["finlens"]["units"]["net_value"] # 'VND' — VND thô ``` Hai bảng trên nằm ở hai namespace khác nhau chính vì hai bộ cột đó không cùng đơn vị. Nhân nhầm 1000 là loại lỗi không ném ngoại lệ nào — chỉ có `units` chặn được nó. ### Phân biệt "chưa có dữ liệu" với "dữ liệu của bạn cũ" [#phân-biệt-chưa-có-dữ-liệu-với-dữ-liệu-của-bạn-cũ] `as_of` là mốc nước do máy chủ công bố, tính theo giờ thị trường. `fetched_at` là lúc máy bạn nhận bảng, tính bằng UTC. Hai trục khác nhau là có chủ đích: ```python meta = df.attrs["finlens"] meta["as_of"] # '2026-08-04T15:00:00+07:00' — dữ liệu tính tới đây meta["fetched_at"] # '2026-08-04T08:31:07+00:00' — bạn lấy về lúc này ``` Bảng thiếu phiên hôm nay mà `as_of` vẫn là hôm qua nghĩa là thị trường chưa chốt, không phải bạn đang dùng bản cũ. ### Biết một mã bị lỗi bằng cách nào [#biết-một-mã-bị-lỗi-bằng-cách-nào] Với `on_error="warn"` (mặc định), lời gọi không ném lỗi — nó trả về phần lấy được và ghi phần hỏng vào `partial` và `failed`: ```python df = client.eod.stock.ohlcv(["HPG", "VCB", "KHONGTONTAI"]) meta = df.attrs["finlens"] meta["partial"] # True list(meta["failed"]) # ['KHONGTONTAI'] meta["failed"]["KHONGTONTAI"]["code"] # 'FL_VALIDATION_SYMBOL' meta["failed"]["KHONGTONTAI"]["message"] ``` Kiểm `partial` là cách rẻ nhất để biết một lô nhiều mã có trọn vẹn hay không. Nếu bạn muốn dừng hẳn thay vì đi tiếp, dùng `on_error="raise"` rồi đọc `.data` và `.failures` của `PartialFetchError`. `truncated` là chuyện khác: nó `True` khi bảng bị cắt ở giới hạn số dòng của gói dịch vụ. Dữ liệu bạn nhận vẫn đúng, chỉ là chưa hết — thu hẹp khoảng thời gian hoặc chia nhỏ danh sách mã rồi gọi lại. Đây là hành vi của pandas, không phải của `finlens`. Ghép hai bảng bằng `pd.concat` hay `df.merge` sẽ cho một bảng **không còn** `attrs["finlens"]` — đơn vị, mốc nước và danh sách mã hỏng biến mất cùng lúc. ```python import pandas as pd a = client.eod.stock.ohlcv("HPG") b = client.eod.stock.ohlcv("VCB") gop = pd.concat([a, b]) gop.attrs.get("finlens") # None ``` Cần giữ lại thì đọc ra biến **trước khi** ghép: ```python don_vi = a.attrs["finlens"]["units"] gop = pd.concat([a, b]) gop.attrs["finlens"] = a.attrs["finlens"] # gán lại nếu bạn chắc hai bảng cùng đơn vị ``` `attrs` mang tính thông tin, **không phải cơ chế bảo vệ**. Thứ bảo vệ thật là việc tách namespace: `client.eod.stock` và `client.eod.index` không bao giờ trả về cùng một bảng, nên một lời gọi không thể trộn nghìn VND với điểm chỉ số. ### `FailedSymbol` [#failedsymbol] Mỗi giá trị trong `failed` là một dict hai khóa: | Khóa | Kiểu | Nội dung | | --------- | ----------------- | --------------------------------------------- | | `code` | `str` hoặc `None` | Mã lỗi ổn định, ví dụ `FL_VALIDATION_SYMBOL`. | | `message` | `str` | Mô tả cho người đọc. | Phân nhánh theo `code`, đừng so khớp `message` — nội dung thông báo được phép đổi, còn `code` thì không. ## Hai kiểu còn lại [#hai-kiểu-còn-lại] `CacheStats` là hình dạng của `client.cache.stats()`, gồm `hits`, `misses`, `entries`, `bytes`, `evictions`. Tỷ lệ `hits` trên `hits + misses` cho biết cache có đang giúp gì không. ```python client.cache.stats()["hits"] ``` `ServiceStatus` là hình dạng của `client.status()` — trạng thái dịch vụ, đọc được **cả khi khóa API sai**, nên nó là chỗ để phân biệt "backend đang có vấn đề" với "khóa của tôi có vấn đề". Nó gồm `contract_version`, `min_client_version`, `latest_client_version`, `status` và `server_time`. ## Xem thêm [#xem-thêm] Các hàm trả về DataFrame, tên cột và ý nghĩa từng cột. Cây ngoại lệ, mã `FL_*` và cách bắt lỗi đúng tầng. ### Câu hỏi thường gặp **Làm sao biết cột close trong DataFrame đang tính bằng đơn vị gì?** Đọc `df.attrs["finlens"]["units"]`. Mỗi DataFrame do thư viện Python finlens trả về đều mang theo một `FrameMeta` ở khoá `finlens` của `df.attrs`, trong đó `units` ánh xạ tên cột sang đơn vị: `df.attrs["finlens"]["units"]["close"]` trả `'kVND'` với cổ phiếu, nghĩa là 23.4 tương ứng 23.400 VND, còn `units["net_value"]` của bảng dòng tiền là `'VND'` thô. Đơn vị không cố định theo tên cột mà phụ thuộc loại tài sản, nên `units` là câu trả lời duy nhất đáng tin. Lưu ý `df.attrs` không sống sót qua `pd.concat` hay `df.merge`. **client.whoami() của finlens trả về những gì?** `client.whoami()` trả về một `WhoAmI` — lúc chạy là `dict` thuần — với năm khoá: `account` (`tier`, `status`, `expires_at`), `key` (`prefix` là 12 ký tự đầu của khoá, và `expires_at`), `version` (`contract_version`, `min_client_version`, `latest_client_version`), `limits`, và `server_time`. Đọc bằng khoá chứ không bằng thuộc tính: `client.whoami()["account"]["tier"]` cho ra `'pro'`. Tạo client không gọi mạng, còn `whoami()` là một lời gọi thật, nên nó cũng là cách kiểm tra khoá API còn dùng được hay không. **Kiểm tra hạn mức còn lại của khóa API bằng Python thế nào?** Gọi `client.limits()` của thư viện Python finlens. Kết quả là một `dict` kiểu `Limits` gồm `requests_per_day`, `requests_remaining`, `resets_at`, `history_days`, `max_symbols_per_request`, `max_concurrency`, `max_rows` và `max_intraday_days`, đọc bằng `client.limits()["requests_remaining"]`. Những con số này do máy chủ quyết định và đọc được lúc chạy chứ không phải hằng số biên dịch sẵn trong thư viện. Cùng giá trị đó cũng nằm ở `client.whoami()["limits"]`. **Tham số interval của finlens nhận những giá trị nào?** Có hai họ riêng biệt. `EodInterval` cho dữ liệu cuối ngày khai đúng sáu giá trị, tất cả viết thường: `1d`, `1w`, `1mo`, `3mo`, `6mo` và `1y`. `IntradayInterval` cho dữ liệu trong phiên khai sáu giá trị khác: `1min`, `5min`, `15min`, `30min`, `1h` và `4h`. Không có `1m`: trong từ vựng cũ `1M` là một tháng còn `1m` là một phút, chỉ khác nhau ở chữ hoa nhưng lệch nhau 43.200 lần, nên thư viện Python finlens từ chối thẳng cả hai bằng `finlens.InvalidIntervalError` với mã `FL_VALIDATION_INTERVAL_AMBIGUOUS` thay vì đoán ý. **Với interval là 1mo thì cột date trả về ngày nào trong tháng?** Trả về **phiên giao dịch cuối cùng thực sự có dữ liệu** trong kỳ — không phải ngày đầu kỳ, và cũng không phải ngày cuối theo lịch. Với thư viện Python finlens, `client.eod.stock.ohlcv("HPG", start="2025-01-01", end="2025-03-31", interval="1mo")` cho `2025-01-24`, `2025-02-28` rồi `2025-03-31`: tháng 1/2025 dừng ở ngày 24 vì thị trường nghỉ Tết từ ngày 25. Luật này đúng cho cả năm giá trị có gộp kỳ (`1w`, `1mo`, `3mo`, `6mo`, `1y`) và cho mọi phương thức cuối ngày; `1d` không đổi vì nó vốn đã là ngày phiên. Nhờ vậy kỳ đang dở không bao giờ mang một mốc ở tương lai. **Module finlens.types có còn trong bản 1.x không?** Không. `finlens.types` cùng `ApiKeyValidationResponse`, `ApiKeyMeta`, `BackendMessage`, `MessageType` và `iter_messages()` chỉ tồn tại ở bản 0.1.x; ở 1.x `import finlens.types` ném `ModuleNotFoundError`. Module thay thế là `finlens.typing`, và mọi kiểu đều được re-export ở cấp `finlens` nên viết `finlens.Limits` là đủ. Thông tin khoá và hạn mức nay lấy bằng `client.whoami()` và `client.limits()`. Riêng `VersionInfo` giữ nguyên tên nhưng nay là `TypedDict` ba khoá `contract_version`, `min_client_version`, `latest_client_version`, không còn phương thức nào. --- # Tra cứu danh mục mã chứng khoán Việt Nam bằng Python URL: https://docs.finlens.vn/python-sdk/tra-cuu-danh-muc Mô tả: Dùng finlens lấy danh sách mã chứng khoán HOSE, HNX, UPCOM, cây ngành ICB và danh mục chứng quyền có bảo đảm về pandas DataFrame, kèm bộ lọc theo sàn và ngành. Tóm tắt: Trang hướng dẫn dùng thư viện Python finlens để tra cứu danh mục thị trường chứng khoán Việt Nam. Ba phương thức nằm trong namespace `client.meta` và đều keyword-only từ đầu: `symbols()` trả danh sách mã cổ phiếu và chứng chỉ quỹ đang niêm yết kèm sàn, loại hình doanh nghiệp và cả hai cấp ngành ICB (`symbol`, `exchange`, `kind`, `company_type`, `icb_level4`, `icb_name4`, `icb_level2`, `icb_name2`, `name`, `short_name`); `sectors()` trả cây ngành ICB với `icb`, `level`, `name_vi`, `parent_icb`; `warrants()` trả danh mục chứng quyền có bảo đảm với `symbol`, `underlying`, `issuer`, `exercise_price`, `maturity_date`. Bộ lọc gồm `exchange` nhận `HOSE`, `HNX` hoặc `UPCOM`, `icb` nhận cả mã cấp 2 lẫn mã cấp 4 trong cùng một tham số, `kind` phân biệt `stock` với `fund`, và `company_type` phân biệt bốn loại hình doanh nghiệp. Lấy danh sách mã để lặp bằng `client.meta.symbols(exchange="HOSE")["symbol"].tolist()` rồi đưa thẳng sang `client.eod`, `client.intraday` hay `client.financials`. In English: look up Vietnamese listed tickers, the ICB sector tree and covered warrants with the finlens Python library, returned as pandas DataFrames. Sản phẩm: python-sdk Trước khi hỏi giá của một mã, người ta hỏi **có những mã nào**. Ba phương thức trong `client.meta` trả lời đúng ba câu hỏi mở đầu đó, và tất cả đều trả về `pandas.DataFrame`. | Gọi | Trả lời câu hỏi | | ------------------------ | --------------------------------------------------- | | `client.meta.symbols()` | Thị trường có những mã nào, mã nào thuộc ngành nào? | | `client.meta.sectors()` | Mã ngành ICB nào tồn tại, tên tiếng Việt là gì? | | `client.meta.warrants()` | Chứng quyền nào đang niêm yết trên mã cơ sở nào? | Đây là danh mục, **không phải số liệu**: không cột nào ở đây mang đơn vị, trừ `exercise_price` của chứng quyền. ```python import finlens client = finlens.client() tickers = client.meta.symbols(exchange="HOSE")["symbol"].tolist() df = client.eod.stock.ohlcv(tickers[:50], start="2026-01-01") ``` `df["symbol"].tolist()` là cầu nối giữa trang này và mọi trang còn lại: lấy danh sách mã ở đây rồi đưa thẳng sang [`client.eod`](/python-sdk/eod), [`client.intraday`](/python-sdk/intraday) hay [`client.financials`](/python-sdk/bao-cao-tai-chinh). Khác `client.eod.*` (nơi `symbols` hoặc `icb` là tham số vị trí), cả ba phương thức của `client.meta` đều **keyword-only từ đầu**. Đầu vào của chúng là bộ lọc, không phải một danh sách mã cần lấy dữ liệu — mà một bộ lọc bỏ trống được thì không có lý do gì để đứng ở vị trí đầu tiên. ```python client.meta.symbols(exchange="HOSE") # đúng client.meta.symbols("HOSE") # TypeError ``` Bỏ trống hết bộ lọc là chuyện bình thường và là lời gọi thường gặp nhất: `client.meta.symbols()` trả về **trọn** danh mục. ## `symbols()` — danh mục mã và chứng chỉ quỹ [#symbols--danh-mục-mã-và-chứng-chỉ-quỹ] ```python client.meta.symbols( *, exchange=None, icb=None, kind=None, company_type=None, refresh=False, on_error="warn", ) -> DataFrame ``` Bốn bộ lọc **cộng dồn** với nhau: khai cả `exchange` lẫn `icb` là hỏi giao của hai điều kiện, không phải hợp. | Tham số | Kiểu | Mặc định | Nội dung | | -------------- | ---------------- | -------- | -------------------------------------------------------------------------------------------------------- | | `exchange` | `ExchangeArg` | `None` | `"HOSE"` · `"HNX"` · `"UPCOM"`. Không phân biệt hoa thường. `None` là cả ba sàn. | | `icb` | `IcbFilterArg` | `None` | `"8300"`, `"8300,8355"` hoặc `["8300", "8355"]`. Nhận **cả mã cấp 2 lẫn mã cấp 4**. `None` là mọi ngành. | | `kind` | `SymbolKindArg` | `None` | `"stock"` cổ phiếu · `"fund"` chứng chỉ quỹ. `None` là cả hai. | | `company_type` | `CompanyTypeArg` | `None` | `"CT"` · `"NH"` · `"CK"` · `"BH"`. `None` là mọi loại hình. | | `refresh` | `bool` | `False` | Bỏ qua bản trong cache và lấy lại từ máy chủ. | | `on_error` | `OnError` | `"warn"` | `warn` · `raise` · `ignore`. | `exchange` là tên **sàn giao dịch**, không phải tên chỉ số. `"VNINDEX"` là mã chỉ số của HOSE và nó nhận một lỗi **400** ở đây chứ không phải một bảng rỗng — kiểu `ExchangeArg` biến lỗi đó thành một gạch đỏ ngay trong IDE. ### Cột trả về [#cột-trả-về] | Cột | dtype | Có thể `null` | Nội dung | | -------------- | -------- | ------------- | ---------------------------------------------------------------------------------- | | `symbol` | `string` | không | Mã chứng khoán, viết hoa. Ví dụ `HPG`. | | `exchange` | `string` | có | Sàn niêm yết: `HOSE` · `HNX` · `UPCOM`. | | `kind` | `string` | không | `stock` cổ phiếu · `fund` chứng chỉ quỹ. | | `company_type` | `string` | có | `CT` phi tài chính · `NH` ngân hàng · `CK` chứng khoán · `BH` bảo hiểm · `QU` quỹ. | | `icb_level4` | `string` | có | **Mã** ngành ICB cấp 4. Ví dụ `8355`. | | `icb_name4` | `string` | có | Tên ngành cấp 4, tiếng Việt. | | `icb_level2` | `string` | có | **Mã** ngành ICB cấp 2. Ví dụ `8300`. | | `icb_name2` | `string` | có | Tên ngành cấp 2, tiếng Việt. | | `name` | `string` | có | Tên đầy đủ của tổ chức phát hành. | | `short_name` | `string` | có | Tên gọi tắt. Ví dụ `Hòa Phát`. | Mười cột luôn có mặt đúng dtype **kể cả khi bộ lọc không khớp dòng nào**, nên bạn không cần bọc `if not df.empty` quanh lời gọi. Frame sắp **tăng dần** theo `symbol`. `icb_level4 == "8355"` nghĩa là *mã ngành cấp 4 của mã này là 8355* — không phải "cấp của nó bằng 8355". Đọc tên cột như `icb_code_level4` thì không bao giờ nhầm. Cùng lý do đó, mã ngành luôn là **chuỗi**. `8355` viết dạng số làm mất số `0` đứng đầu ở những mã như `"0533"`. ### Mỗi dòng mang sẵn cả hai cấp ngành [#mỗi-dòng-mang-sẵn-cả-hai-cấp-ngành] `icb_level4` là cấp được gán trực tiếp trong dữ liệu; `icb_level2` đã được máy chủ suy ra qua chuỗi cha và đặt sẵn trên **mỗi dòng**. Nhờ vậy bạn gộp theo ngành lớn bằng một phép `groupby`, không phải gọi thêm `sectors()` rồi tự nối cây: ```python df = client.meta.symbols() df.groupby("icb_name2")["symbol"].count().sort_values(ascending=False) ``` Và vì bộ lọc `icb` nhận cả hai cấp, bạn hỏi được ngành lớn mà không cần biết nó gồm những ngành con nào: ```python ngan_hang = client.meta.symbols(icb="8300") # mã cấp 2 — cả ngành ngân hàng chi_tiet = client.meta.symbols(icb="8355") # mã cấp 4 ``` Máy chủ tra cấp giúp bạn, nên **không có tham số `icb_level`** ở phương thức này để phải nhớ. Mã thuộc cấp 1 hoặc cấp 3 nhận **400** kèm giải thích, chứ không phải một bảng rỗng. Không nhớ mã thì tra bằng `client.meta.sectors()` ở mục dưới. Hai tham số này trông giống nhau nhưng trả lời hai câu hỏi khác hẳn: * **`kind`** nói *đây là loại tài sản gì* — cổ phiếu hay chứng chỉ quỹ niêm yết. * **`company_type`** nói *cây khoản mục báo cáo tài chính nào áp cho mã này*. Chứng chỉ quỹ xuất hiện ở cột `company_type` với giá trị `QU`, nhưng `"QU"` **cố ý không nằm** trong kiểu `CompanyTypeArg` — quỹ không có báo cáo tài chính dạng cây nào, nên `company_type="QU"` là một gạch đỏ lúc gõ code chứ không phải một lỗi sau một vòng gọi mạng. ```python quy = client.meta.symbols(kind="fund") # đúng quy = client.meta.symbols(company_type="QU") # sai ``` Số chứng chỉ quỹ niêm yết hiện đếm được hai chữ số và **tất cả đều trên HOSE**. ```python # Ngân hàng trên HOSE, kèm tên gọi tắt nh = client.meta.symbols(exchange="HOSE", company_type="NH") nh[["symbol", "short_name", "icb_name4"]] # Mọi mã chứng khoán (không gồm chứng chỉ quỹ) trên UPCOM upcom = client.meta.symbols(exchange="UPCOM", kind="stock") ``` ## `sectors()` — cây ngành ICB [#sectors--cây-ngành-icb] ```python client.meta.sectors( *, level=None, refresh=False, on_error="warn", ) -> DataFrame ``` Nguồn duy nhất của mã ngành cho **mọi** tham số `icb` trong thư viện — kể cả `client.eod.sector.ohlcv()` và `client.eod.sector.investor.flow()`. Một bảng ngành chép tay sẽ đúng lúc bạn chép và sai vào một lúc nào đó bạn không biết; lời gọi này thì không. | Tham số | Kiểu | Mặc định | Nội dung | | ---------- | ------------- | -------- | ----------------------------------------------------------------- | | `level` | `IcbLevelArg` | `None` | `2` ngành lớn hoặc `4` ngành chi tiết. `None` trả **cả hai cấp**. | | `refresh` | `bool` | `False` | Bỏ qua cache. | | `on_error` | `OnError` | `"warn"` | `warn` · `raise` · `ignore`. | | Cột | dtype | Có thể `null` | Nội dung | | ------------ | -------- | ------------- | ----------------------------------------- | | `icb` | `string` | không | Mã ngành ICB, **chuỗi số**. Ví dụ `8355`. | | `level` | `int8` | không | Cấp trong cây: `2` hoặc `4`. | | `name_vi` | `string` | có | Tên ngành, tiếng Việt. | | `parent_icb` | `string` | có | Mã ngành cha, `null` ở gốc cây. | Frame sắp tăng dần theo `level` rồi `icb`, nên một lời gọi mang cả hai cấp đọc ra được là một cái cây chứ không phải một danh sách phẳng trộn lẫn. **Không có cột tên tiếng Anh.** `name_vi` là tên duy nhất, và đó là trạng thái vĩnh viễn chứ không phải một khoảng trống tạm thời — phát một cột toàn `null` để bạn tự đoán thì tệ hơn không phát. ```python nganh = client.meta.sectors(level=2) len(nganh) # 19 # Dựng lại cây bằng chính bảng này ca_cay = client.meta.sectors() con_cua = ca_cay.groupby("parent_icb")["icb"].apply(list) ``` Chỉ **hai** cấp được phục vụ. Cấp 1 và cấp 3 có tồn tại trong chuẩn ICB nhưng không cấp nào trong hai cấp đó có dữ liệu tổng hợp, nên chúng nhận **400** chứ không trả một bảng rỗng — và kiểu `IcbLevelArg` chặn chúng ngay lúc gõ code. Cây ICB có đủ bốn cấp; lời gọi này chỉ trả về hai cấp được phục vụ. Nghĩa là `parent_icb` của một dòng cấp 4 trỏ tới một mã **không có mặt trong chính bảng này**, và phép ghép sau đây sẽ mất gần hết dòng mà không báo lỗi nào: ```python cap4 = ca_cay[ca_cay["level"] == 4] cap2 = ca_cay[ca_cay["level"] == 2] cap4.merge(cap2, left_on="parent_icb", right_on="icb") # sai — ghép hụt ``` Muốn ngành cấp 2 của một mã chứng khoán thì đọc cột `icb_level2` mà `client.meta.symbols()` trả về, nơi chuỗi cha đã được nối sẵn. `level=2` là **cấp** — một số nguyên. `icb="8300"` là **mã ngành** — một chuỗi. Hai thứ đi qua hai tham số khác nhau và không đổi chỗ cho nhau được; kiểu khác nhau chính là thứ giữ cho việc nhầm lẫn không diễn ra trong im lặng. Thêm một chỗ dễ vấp: thông báo lỗi từ máy chủ có thể gọi tham số này là `icb_level`. Trong Python thì tên nó là **`level`** — gõ `icb_level=2` nhận `TypeError` ngay lập tức chứ không âm thầm bỏ qua bộ lọc. ## `warrants()` — danh mục chứng quyền có bảo đảm [#warrants--danh-mục-chứng-quyền-có-bảo-đảm] ```python client.meta.warrants( *, underlying=None, active_only=True, refresh=False, on_error="warn", ) -> DataFrame ``` Chứng quyền nào đang niêm yết trên mã cơ sở nào, kèm điều khoản hợp đồng. | Tham số | Kiểu | Mặc định | Nội dung | | ------------- | --------------- | -------- | ------------------------------------------------------------------------------------ | | `underlying` | `UnderlyingArg` | `None` | Mã **cơ sở**: `"HPG"`, `"HPG,FPT"` hoặc `["HPG", "FPT"]`. `None` là mọi chứng quyền. | | `active_only` | `bool` | `True` | `True` chỉ trả mã **chưa đáo hạn**; `False` trả cả mã đã hết hạn. | | `refresh` | `bool` | `False` | Bỏ qua cache. | | `on_error` | `OnError` | `"warn"` | `warn` · `raise` · `ignore`. | `underlying` là mã của **cổ phiếu cơ sở**, không phải mã của chứng quyền. Mã chứng quyền (`CHPG2525`) nằm ở cột `symbol` của kết quả. | Cột | dtype | Có thể `null` | Đơn vị | Nội dung | | ---------------- | ---------------- | ------------- | ----------- | ----------------------------------------------------- | | `symbol` | `string` | không | — | Mã chứng quyền. Ví dụ `CHPG2525`. | | `underlying` | `string` | có | — | Mã cơ sở. Ví dụ `HPG`. | | `issuer` | `string` | có | — | Mã công ty chứng khoán phát hành. Ví dụ `SSI`, `VND`. | | `exercise_price` | `float64` | có | **VND thô** | Giá thực hiện. | | `maturity_date` | `datetime64[ns]` | có | — | Ngày đáo hạn, **không mang múi giờ**. | Cộng thẳng `exercise_price` với cột `close` của `client.eod.stock.ohlcv()` là sai **1.000 lần** — và không có exception nào được ném. Kiểm bằng một dòng thay vì giả định: ```python cq = client.meta.warrants(underlying="HPG") cq.attrs["finlens"]["units"]["exercise_price"] # 'VND' ``` `price_basis` của bảng này là `null` chứ không phải `raw`: giá thực hiện là một **điều khoản hợp đồng**, không phải một mức giá quan sát được trên thị trường, nên câu hỏi "đã điều chỉnh quyền chưa" không áp cho nó. `active_only=True` giữ lại những mã có ngày đáo hạn **từ hôm nay trở đi** theo giờ Việt Nam — chứng quyền đáo hạn đúng hôm nay vẫn còn trong bảng. `maturity_date` là tín hiệu duy nhất cho biết một chứng quyền còn hạn, nên đừng tìm một cột trạng thái nào khác. ```python # Chứng quyền còn hạn trên HPG cq = client.meta.warrants(underlying="HPG") cq[["symbol", "issuer", "exercise_price", "maturity_date"]] # Tra một mã đã hết hạn gặp trong dữ liệu lịch sử cu = client.meta.warrants(active_only=False) df = client.eod.warrant.ohlcv(cu["symbol"].tolist()[:5]) ``` Lời gọi này chỉ trả **danh mục**. Giá và khối lượng giao dịch của chính chứng quyền nằm ở `client.eod.warrant.ohlcv()` — xem [Dữ liệu cuối ngày](/python-sdk/eod). ## Độ phủ — và cách tự đếm lại [#độ-phủ--và-cách-tự-đếm-lại] Danh mục hiện có hơn **1.600 mã** trên cả ba sàn: UPCOM đông nhất, rồi tới HOSE, rồi HNX. Cây ngành có **19 ngành cấp 2** và khoảng một trăm ngành cấp 4. Những con số này đổi theo từng đợt niêm yết mới, nên đừng chép chúng vào code — đếm lại bằng chính thư viện: ```python df = client.meta.symbols() len(df) # tổng số mã df["exchange"].value_counts() # phân bố theo sàn df["kind"].value_counts() # cổ phiếu và chứng chỉ quỹ len(client.meta.sectors(level=4)) # số ngành chi tiết len(client.meta.warrants()) # chứng quyền còn hạn ``` Một lời gọi `symbols()` là **một** request và trả về cả danh mục trong một frame. Nếu gói dịch vụ của bạn có `max_rows` nhỏ hơn số dòng của danh mục, kết quả bị cắt ngắn kèm cảnh báo và `df.attrs["finlens"]["truncated"]` bằng `True`: ```python df.attrs["finlens"]["truncated"] # True nghĩa là bảng chưa đầy đủ client.limits()["max_rows"] # hạn mức hiệu lực của khoá bạn đang dùng ``` Thu hẹp bằng bộ lọc (`exchange=`, `icb=`) thay vì phân trang thủ công. Ngược lại, danh mục **không** bị kẹp theo độ sâu lịch sử (`history_days`) của gói: ở đây không có một con số giá nào, nên nó không phải thứ mà giới hạn ấy sinh ra để bảo vệ. ## Cache 24 giờ [#cache-24-giờ] Kết quả của cả ba phương thức được cache **24 giờ** — danh mục đổi theo tháng chứ không theo phiên. Dùng `refresh=True` khi bạn biết vừa có mã mới niêm yết: ```python df = client.meta.symbols(refresh=True) ``` Với dữ liệu giá, `df.attrs["finlens"]["as_of"]` cho biết dữ liệu mới tới đâu. Với ba bảng danh mục thì không: không có cách nào biết danh mục vừa đổi lúc nào, nên "lúc bạn hỏi" là câu trả lời trung thực duy nhất. Đừng đọc nó là "danh mục vừa cập nhật lúc đó" — nó chỉ nói rằng ta không biết. ## Bản async [#bản-async] Cả ba phương thức đều có bản bất đồng bộ với **cùng chữ ký**: ```python import asyncio import finlens async def main(): async with finlens.AsyncClient() as client: df = await client.meta.symbols(exchange="HOSE") tickers = df["symbol"].tolist() asyncio.run(main()) ``` ## Xem tiếp [#xem-tiếp] Đưa danh sách mã vừa lấy sang `ohlcv()`, và dùng mã ngành ICB cho chỉ số ngành. `company_type` ở đây quyết định cây khoản mục nào áp cho mã. `ExchangeArg`, `SymbolKindArg`, `IcbLevelArg` và nội dung `df.attrs["finlens"]`. Hỏi thẳng "ngành ngân hàng có những mã nào" bằng tiếng Việt qua trợ lý AI. ### Câu hỏi thường gặp **Làm sao lấy danh sách toàn bộ mã cổ phiếu đang niêm yết trên HOSE bằng Python?** Gọi `client.meta.symbols(exchange="HOSE")` của thư viện Python finlens rồi lấy cột `symbol` ra danh sách Python bằng `df["symbol"].tolist()`. Tham số `exchange` nhận `"HOSE"`, `"HNX"` hoặc `"UPCOM"`; bỏ trống thì trả về cả ba sàn. Đây là tên sàn giao dịch chứ không phải tên chỉ số, nên `exchange="VNINDEX"` nhận một lỗi 400. Cả ba phương thức của `client.meta` đều keyword-only, nên `client.meta.symbols("HOSE")` ném `TypeError`. **Tra mã ngành ICB của cổ phiếu Việt Nam ở đâu?** Gọi `client.meta.sectors()` của thư viện Python finlens để lấy cây ngành ICB — mỗi dòng gồm mã ngành `icb`, cấp `level`, tên tiếng Việt `name_vi` và mã ngành cha `parent_icb`. Truyền `level=2` cho ngành lớn hoặc `level=4` cho ngành chi tiết; bỏ trống thì trả cả hai cấp. Chỉ hai cấp này được phục vụ: cấp 1 và cấp 3 có trong chuẩn ICB nhưng không có dữ liệu tổng hợp nên nhận lỗi 400 chứ không trả bảng rỗng. Đây là nguồn mã ngành cho mọi tham số `icb` trong thư viện. **Lọc cổ phiếu theo ngành trong finlens phải dùng mã ngành cấp mấy?** Tham số `icb` của `client.meta.symbols()` nhận cả mã cấp 2 lẫn mã cấp 4 trong cùng một tham số, nên bạn không cần biết trước mã mình đang cầm thuộc cấp nào — `icb="8300"` (ngành ngân hàng, cấp 2) và `icb="8355"` (cấp 4) đều chạy, và phương thức này không có tham số `icb_level` để phải nhớ. Mã ngành luôn là chuỗi chứ không phải số, vì ép sang số sẽ làm mất số 0 đứng đầu ở những mã như `"0533"`. Mỗi dòng kết quả mang sẵn cả `icb_level4` lẫn `icb_level2` nên gộp theo ngành lớn chỉ cần một phép `groupby`. **Làm sao biết chứng quyền nào còn hạn và gắn với mã cơ sở nào?** Gọi `client.meta.warrants(underlying="HPG")` của thư viện Python finlens để lấy chứng quyền trên một mã cơ sở, hoặc bỏ trống tham số để lấy toàn bộ. Mặc định `active_only=True` chỉ trả những mã có ngày đáo hạn từ hôm nay trở đi theo giờ Việt Nam; đặt `active_only=False` khi cần tra một mã cũ gặp trong dữ liệu lịch sử. Frame gồm `symbol`, `underlying`, `issuer`, `exercise_price` và `maturity_date`. Cột `exercise_price` tính bằng VND thô, không phải nghìn VND như giá cổ phiếu, nên cộng thẳng nó với cột `close` là sai 1.000 lần. **Lọc chứng chỉ quỹ niêm yết bằng tham số nào?** Dùng `client.meta.symbols(kind="fund")` của thư viện Python finlens, không dùng `company_type`. Cột `kind` nhận `"stock"` cho cổ phiếu và `"fund"` cho chứng chỉ quỹ niêm yết; đây là trường duy nhất phân biệt được hai loại tài sản. Tham số `company_type` phục vụ việc khác: nó nói cây khoản mục báo cáo tài chính nào áp cho mã, với bốn giá trị `"CT"`, `"NH"`, `"CK"`, `"BH"` — loại `"QU"` (quỹ) cố ý không nằm trong từ vựng của nó vì quỹ không có báo cáo tài chính dạng cây. --- # Xử lý lỗi finlens: FinLensError và cây ngoại lệ Python URL: https://docs.finlens.vn/python-sdk/xu-ly-loi Mô tả: Cách bắt lỗi khi lấy dữ liệu chứng khoán bằng finlens: except FinLensError bắt trọn cây ngoại lệ, rẽ nhánh theo mã FL_*, dùng on_error cho lời gọi nhiều mã. Tóm tắt: Trang mô tả cách xử lý lỗi của thư viện Python `finlens` — thư viện trả dữ liệu chứng khoán Việt Nam về `pandas.DataFrame`. Mọi ngoại lệ công khai đều là con của `finlens.FinLensError`, nên một khối `except finlens.FinLensError` là bắt trọn; các nhánh gồm `ConfigurationError`, `UnsupportedOperationError`, `AuthError` (`InvalidApiKeyError`, `ApiKeyExpiredError`, `AccountExpiredError`, `AccountInactiveError`), `TierError` (`DatasetNotInTierError`, `SymbolNotInTierError`), `QuotaError` (`RateLimitError`, `DailyQuotaExceededError`), `ValidationError` (`InvalidSymbolError`, `InvalidDateRangeError`, `InvalidIntervalError`, `CompanyTypeMismatchError`, `UnitMismatchError`), `TransportError` (`ConnectionFailedError`, `TlsVerificationError`, `RequestTimeoutError`, `ServerError`), `DataError` (`DecodingError`, `SchemaMismatchError`, `NoDataError`, `PartialFetchError`), `UpgradeRequiredError` và `IncompatibleApiVersionError`. Mỗi ngoại lệ mang `.code` (mã ổn định dạng `FL_*`), `.message`, `.request_id`, `.status_code`, `.detail` và `.doc_url`, kèm bảng tra từ mã như `FL_QUOTA_DAILY`, `FL_VALIDATION_INTERVAL_AMBIGUOUS`, `FL_TRANSPORT_TLS` sang lớp tương ứng. Trang cũng nói về tham số `on_error` (`warn`, `raise`, `ignore`) cho lời gọi nhiều mã và cây cảnh báo `FinLensWarning` gồm `UpgradeAvailableWarning`, `QuotaLowWarning`, `PartialDataWarning`, `DataQualityWarning`, `TierLimitWarning`. In English: how to handle errors from the finlens Python library — catch FinLensError, branch on the stable FL_* code, and use on_error for multi-symbol calls. Sản phẩm: python-sdk Mọi lỗi thư viện `finlens` chủ động sinh ra đều nằm trong một cây thừa kế duy nhất, gốc là `finlens.FinLensError`. Trang này nói bạn nên bắt ở mức nào, đọc gì từ ngoại lệ bắt được, và phân biệt lỗi (dừng chương trình) với cảnh báo (không dừng). ## Một dòng bắt hết [#một-dòng-bắt-hết] ```python import finlens client = finlens.client() # đọc FINLENS_API_KEY try: df = client.eod.stock.ohlcv("HPG", start="2024-01-01", end="2024-06-30") except finlens.FinLensError as exc: print(exc.code, "-", exc.message) ``` Đây là cam kết của bản 1.x và có test khẳng định: **mọi** lớp lỗi công khai của thư viện đều là con của `FinLensError`. Tài liệu của bản 0.1.x nói ngược lại — rằng `except FinLensError` để lọt `CompanyTypeMismatchError` và các lỗi bị tầng dòng tiền ném lại thành `RuntimeError`. Cả hai chỗ đó đã được sửa. Nếu code của bạn còn một nhánh `except RuntimeError` viết theo hướng dẫn cũ, nhánh đó nay là code chết — bỏ đi được. Không cần `except Exception`. Bắt rộng như vậy sẽ nuốt luôn `KeyboardInterrupt` của bạn, lỗi gõ sai tên cột, và mọi thứ khác không liên quan đến FinLens. ## Ngoại lệ mang theo những gì [#ngoại-lệ-mang-theo-những-gì] Mọi lớp trong cây đều có sáu thuộc tính sau: | Thuộc tính | Kiểu | Nội dung | | -------------- | ------------- | ------------------------------------------------------- | | `.code` | `str` | Mã lỗi ổn định, máy đọc được — ví dụ `"FL_QUOTA_DAILY"` | | `.message` | `str` | Mô tả cho người đọc, tiếng Việt | | `.request_id` | `str \| None` | Mã của request thất bại. Gửi kèm khi báo lỗi | | `.status_code` | `int \| None` | Mã trạng thái HTTP, nếu lỗi đến từ một response | | `.detail` | `Any` | Dữ liệu cấu trúc kèm theo, nếu có | | `.doc_url` | `str` | Trang tài liệu của mã lỗi này | `str(exc)` gộp ba thứ quan trọng nhất lại: ```text [FL_QUOTA_DAILY] Đã dùng hết hạn mức 5000 request/ngày. Đặt lại lúc 2026-08-05T00:00:00+07:00. (request_id=req_8f3a1c) -> https://docs.finlens.vn/python-sdk/errors/FL_QUOTA_DAILY ``` `code` là hợp đồng: nó không đổi, không được dịch. `message` thì được phép đổi chữ và được phép dịch bất cứ lúc nào. ```python try: df = client.eod.stock.ohlcv("HPG") except finlens.QuotaError as exc: if exc.code == "FL_QUOTA_DAILY": # đúng ... if "hạn mức" in exc.message: # sai — sẽ hỏng khi câu chữ đổi ... ``` Một số lớp mang thêm thuộc tính riêng: | Lớp | Thuộc tính thêm | | ------------------------- | ----------------------------------------------------------------------- | | `TierError` và các con | `.account_type` (gói hiện tại), `.required_tier` (gói tối thiểu cần có) | | `RateLimitError` | `.retry_after` — số giây nên chờ | | `DailyQuotaExceededError` | `.resets_at` — thời điểm hạn mức đặt lại, chuỗi kèm offset `+07:00` | | `InvalidDateRangeError` | `.max_days` — số ngày tối đa server chấp nhận | | `PartialFetchError` | `.data` (phần lấy được) và `.failures` (mã → ngoại lệ) | ## Cây ngoại lệ [#cây-ngoại-lệ] ```text FinLensError ├── ConfigurationError cấu hình client sai: thiếu khoá, base URL hỏng ├── UnsupportedOperationError có trong API nhưng chưa khả dụng ở bản này │ ├── AuthError không xác thực được khoá │ ├── InvalidApiKeyError khoá không tồn tại hoặc đã bị thu hồi │ ├── ApiKeyExpiredError khoá hết hạn │ ├── AccountExpiredError gói dịch vụ hết hạn (khoá vẫn còn hiệu lực) │ └── AccountInactiveError tài khoản inactive hoặc banned │ ├── TierError gói hiện tại không cho phép thao tác này │ ├── DatasetNotInTierError bộ dữ liệu ngoài gói │ └── SymbolNotInTierError mã chứng khoán ngoài gói │ ├── QuotaError chạm một giới hạn sử dụng │ ├── RateLimitError vượt giới hạn tần suất │ └── DailyQuotaExceededError hết hạn mức request trong ngày │ ├── ValidationError tham số truyền vào không hợp lệ │ ├── InvalidSymbolError mã sai định dạng hoặc không tồn tại │ ├── InvalidDateRangeError khoảng thời gian sai hoặc quá dài │ ├── InvalidIntervalError interval không hợp lệ hoặc nhập nhằng │ ├── CompanyTypeMismatchError các mã thuộc nhiều loại hình doanh nghiệp │ └── UnitMismatchError ghép các bảng khác đơn vị │ ├── TransportError lỗi mạng, trước khi có response hợp lệ │ ├── ConnectionFailedError không kết nối được │ │ └── TlsVerificationError không xác thực được chứng chỉ TLS │ ├── RequestTimeoutError hết thời gian chờ │ └── ServerError backend trả 5xx sau khi đã thử lại │ ├── DataError có response nhưng nội dung không đúng hợp đồng │ ├── DecodingError không giải mã được payload │ ├── SchemaMismatchError server trả schema client không hiểu │ ├── NoDataError tài nguyên không tồn tại │ └── PartialFetchError một phần các mã thất bại │ ├── UpgradeRequiredError bản client này không còn được hỗ trợ └── IncompatibleApiVersionError client và backend khác major của hợp đồng ``` `AuthError`, `TierError`, `QuotaError`, `ValidationError`, `TransportError` và `DataError` vừa là lớp cha vừa là lớp bắt được: bắt lớp cha là bắt trọn nhánh, kể cả những lớp con được thêm về sau. `TlsVerificationError` là ví dụ — nó là lớp con của `ConnectionFailedError`, nên code chỉ bắt lớp cha vẫn nhận được nó mà không phải sửa gì. ## Nên bắt ở mức nào [#nên-bắt-ở-mức-nào] Bắt **lớp cha** khi bạn chỉ cần biết "có lỗi". Bắt **lớp lá** khi mỗi loại lỗi dẫn tới một hành động khác nhau. Phân biệt bằng **`.code`** khi cùng một lớp mà hai mã cần hai cách xử lý. | Bạn đang viết gì | Khuyến nghị | | --------------------------------------- | ----------------------------------------------------------------------------------------- | | Notebook, script phân tích chạy một lần | Một khối `except finlens.FinLensError`, in `exc` ra rồi dừng. Đủ dùng | | Job chạy định kỳ, không có người trực | Tách ba nhóm: **thử lại được**, **cần người can thiệp**, **lỗi trong code của bạn** | | Ứng dụng phục vụ người khác | Bắt `FinLensError` ở biên, hiển thị `exc.message`, ghi log `exc.code` và `exc.request_id` | | Lời gọi nhiều mã | Đừng bọc `try`. Dùng tham số `on_error` — xem mục dưới | Bảng phân loại cho nhóm job định kỳ: | Nhóm | Lớp | Nên làm gì | | ---------------------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | | Thử lại được | `RateLimitError`, `RequestTimeoutError`, `ServerError`, `ConnectionFailedError` | Chờ rồi chạy lại. Với `RateLimitError` thì chờ đúng `.retry_after` giây | | Chờ vô ích | `TlsVerificationError`, `AuthError`, `TierError`, `UpgradeRequiredError` | Báo cho người. Nguyên nhân nằm ở máy bạn, ở tài khoản, hoặc ở phiên bản — thử lại không đổi được gì | | Hết hạn mức | `DailyQuotaExceededError` | Chạy lại **sau** `.resets_at`, không sớm hơn | | Lỗi trong code của bạn | `ValidationError` và các con | Sửa code. Chạy lại y nguyên sẽ ra đúng lỗi đó | Hai dòng đầu giao nhau ở một chỗ: `TlsVerificationError` **là** một `ConnectionFailedError`. Nếu bạn bắt lớp cha để thử lại thì phải đặt nhánh `TlsVerificationError` **lên trước**, không thì một lỗi vĩnh viễn sẽ bị thử lại mãi mà không bao giờ khác đi. ```python import time import finlens client = finlens.client() try: df = client.eod.stock.investor.flow("HPG", start="2024-01-01") except finlens.RateLimitError as exc: time.sleep(exc.retry_after or 60) except finlens.DailyQuotaExceededError as exc: print("Hạn mức đặt lại lúc", exc.resets_at) except finlens.AuthError as exc: print("Kiểm tra lại khoá API:", exc.message) except finlens.FinLensError as exc: print(exc.code, exc.message, exc.request_id) ``` Thứ tự `except` đi từ **hẹp tới rộng**. Đặt `FinLensError` lên trên cùng thì mọi nhánh phía dưới không bao giờ chạy. ## `ValidationError` vẫn là `ValueError` [#validationerror-vẫn-là-valueerror] `ValidationError` kế thừa **cả** `FinLensError` **và** `ValueError`, và đó là chủ đích: code cũ viết `except ValueError` quanh lời gọi FinLens vẫn tiếp tục chạy sau khi nâng lên 1.x. ```python try: df = client.eod.stock.ohlcv("HPG", interval="1M") except ValueError as exc: # vẫn bắt được print(exc) ``` Nhưng khi viết mới thì bắt `finlens.ValidationError`: nó chỉ bắt lỗi tham số của FinLens, không nuốt luôn `ValueError` từ code khác của bạn. Ba lỗi tham số hay gặp nhất: * **`InvalidIntervalError`** — `interval` chỉ nhận `1d`, `1w`, `1mo`, `3mo`, `6mo`, `1y`. `1M` và `1m` bị **từ chối thẳng** thay vì đoán ý: trong từ vựng cũ hai token đó chỉ khác nhau ở chữ hoa nhưng lệch nhau 43.200 lần. * **`InvalidDateRangeError`** — khoảng thời gian vượt giới hạn. Giới hạn thật do server quyết định, đọc bằng `client.limits()`, không phải hằng số trong thư viện. * **`CompanyTypeMismatchError`** — các mã thuộc nhiều loại hình doanh nghiệp khác nhau (phi tài chính, ngân hàng, chứng khoán, bảo hiểm). Cây chỉ tiêu báo cáo tài chính của chúng khác nhau nên không gộp vào một bảng được. ## Nhiều mã trong một lời gọi: `on_error` [#nhiều-mã-trong-một-lời-gọi-on_error] Khi bạn xin 50 mã và 1 mã hỏng, 49 mã còn lại không được mất theo. Đó là việc của tham số `on_error`, có ở mọi hàm nhận nhiều mã. | Giá trị | Hành vi | | ------------------- | ---------------------------------------------------------------------- | | `"warn"` (mặc định) | Giữ phần thành công, phát `PartialDataWarning`. Chương trình chạy tiếp | | `"raise"` | Ném `PartialFetchError` — **mang theo** phần đã lấy được ở `.data` | | `"ignore"` | Giữ phần thành công, không nói gì cả | Cả ba trường hợp đều ghi lại chi tiết vào `df.attrs["finlens"]`: ```python df = client.eod.stock.ohlcv(ma_list, start="2024-01-01") # on_error="warn" if df.attrs["finlens"]["partial"]: for symbol, ly_do in df.attrs["finlens"]["failed"].items(): print(symbol, ly_do["code"], ly_do["message"]) ``` Với `on_error="raise"`, dữ liệu đi kèm ngoại lệ nên bạn không phải gọi lại từ đầu: ```python try: df = client.eod.stock.ohlcv(ma_list, on_error="raise") except finlens.PartialFetchError as exc: df = exc.data # 49 mã thành công, vẫn dùng được print(exc.failures) # {"XYZ": InvalidSymbolError(...)} ``` `exc.failures` ánh xạ **mã chứng khoán → ngoại lệ tương ứng**, nên mỗi mã hỏng vẫn giữ đủ `.code` và `.message` của riêng nó. pandas không chuyển `attrs` qua các phép ghép bảng. Đọc `partial`, `failed`, `units` **trước** khi ghép, hoặc lưu lại giá trị bạn cần. Đây là thông tin đi kèm dữ liệu, không phải một cơ chế bảo vệ. Kết quả **không có dòng nào** không phải lỗi. Một khoảng ngày nghỉ, hay một mã mới niêm yết, trả về DataFrame rỗng với đúng cột và đúng dtype — không cảnh báo, không ngoại lệ. `NoDataError` chỉ dành cho trường hợp server báo rõ rằng tài nguyên không tồn tại. ## `TlsVerificationError`: máy bạn nằm sau proxy kiểm tra TLS [#tlsverificationerror-máy-bạn-nằm-sau-proxy-kiểm-tra-tls] Rất phổ biến trong mạng doanh nghiệp: proxy kiểm tra TLS hoặc phần mềm diệt virus chèn vào giữa kết nối bằng một CA riêng, mà bundle chứng chỉ mặc định của Python không có CA đó. Đây là lỗi **vĩnh viễn**, khác hẳn một lỗi kết nối thường: thử lại không bao giờ cứu được, và cách sửa nằm ở máy bạn chứ không ở phía FinLens. Vì vậy thư viện không thử lại nó. ```python client = finlens.client(ca_bundle="/duong/dan/toi/ca-bundle.pem") ``` Hoặc đặt biến môi trường một lần cho cả máy: ```bash # Linux / macOS export FINLENS_CA_BUNDLE="/duong/dan/toi/ca-bundle.pem" # Windows PowerShell $env:FINLENS_CA_BUNDLE = "C:\certs\ca-bundle.pem" ``` File CA bundle do bộ phận IT của bạn cấp — đó là chứng chỉ gốc của chính proxy đang đứng giữa. Ở bản 0.1.x, lỗi chứng chỉ bị báo cáo thành "backend đang không phản hồi", gửi người đọc đi kiểm đúng chỗ không có vấn đề gì. Nếu bạn đang gặp thông báo đó trong khi `curl` cùng lúc vẫn chạy, hãy nâng cấp bằng `pip install -U finlens` rồi đọc lại thông báo mới. `TlsVerificationError` kế thừa `ConnectionFailedError`, nên code đang bắt lớp cha không phải sửa gì. ## `SchemaMismatchError`: response sai hình dạng [#schemamismatcherror-response-sai-hình-dạng] Ném ra khi server trả về một cấu trúc mà phiên bản client này không hiểu. Hai nguyên nhân, theo thứ tự khả năng: 1. **`FINLENS_BASE_URL` đang trỏ nhầm chỗ** — thường là một endpoint cũ hoặc một backend cục bộ đang chạy phiên bản khác. Kiểm biến môi trường trước tiên. 2. **Client quá cũ so với backend.** Nâng cấp bằng `pip install -U finlens`. Ở bản 0.1.x, một response sai hình dạng trả về **bảng rỗng trong im lặng**. Người dùng đọc "khối ngoại mua ròng 0 đồng" trong khi thật ra client không hiểu được response — không ngoại lệ, không cảnh báo. Nay nó ném lỗi. Một traceback to rõ ràng tốt hơn một con số sai trông rất thật. ## Bảng tra mã lỗi [#bảng-tra-mã-lỗi] Ánh xạ là **nhiều-đối-một**: nhiều mã có thể trỏ về cùng một lớp. Bắt theo lớp, phân biệt theo mã. | Mã | Lớp ngoại lệ | Thông báo bạn thấy | | ---------------------------------- | ----------------------------- | ------------------------------------------------------------------- | | `FL_CONFIG` | `ConfigurationError` | Cấu hình client không hợp lệ | | `FL_AUTH_INVALID_KEY` | `InvalidApiKeyError` | API key không hợp lệ hoặc đã bị thu hồi | | `FL_AUTH_KEY_EXPIRED` | `ApiKeyExpiredError` | API key đã hết hạn vào ... | | `FL_AUTH_ACCOUNT_EXPIRED` | `AccountExpiredError` | Gói FinLens của bạn đã hết hạn vào ... Vui lòng gia hạn để tiếp tục | | `FL_AUTH_ACCOUNT_INACTIVE` | `AccountInactiveError` | Tài khoản đang ở trạng thái ... | | `FL_TIER_DATASET` | `DatasetNotInTierError` | Bộ dữ liệu ... cần gói ... (bạn đang dùng ...) | | `FL_TIER_SYMBOL` | `SymbolNotInTierError` | Mã ... cần gói ... (bạn đang dùng ...) | | `FL_QUOTA_RATE` | `RateLimitError` | Vượt giới hạn tần suất. Thử lại sau ... giây | | `FL_QUOTA_DAILY` | `DailyQuotaExceededError` | Đã dùng hết hạn mức ... request/ngày. Đặt lại lúc ... | | `FL_VALIDATION_SYMBOL` | `InvalidSymbolError` | Mã ... không tồn tại | | `FL_VALIDATION_DATE_RANGE` | `InvalidDateRangeError` | Khoảng thời gian quá lớn: yêu cầu ... ngày, tối đa ... | | `FL_VALIDATION_INTERVAL` | `InvalidIntervalError` | Interval ... không hợp lệ. Giá trị hợp lệ: ... | | `FL_VALIDATION_INTERVAL_AMBIGUOUS` | `InvalidIntervalError` | Interval ... nhập nhằng: có thể là một phút hoặc một tháng | | `FL_VALIDATION_COMPANY_TYPE` | `CompanyTypeMismatchError` | Các mã thuộc nhiều loại hình doanh nghiệp ... | | `FL_VALIDATION_UNIT_MISMATCH` | `UnitMismatchError` | Không thể ghép các bảng khác đơn vị: ... và ... | | `FL_DATA_EMPTY` | `NoDataError` | Không có dữ liệu cho ... | | `FL_DATA_SCHEMA` | `SchemaMismatchError` | Server trả về schema mà phiên bản client này không hiểu | | `FL_DATA_PARTIAL` | `PartialFetchError` | .../... mã thất bại | | `FL_TRANSPORT_CONNECT` | `ConnectionFailedError` | Không kết nối được tới ... | | `FL_TRANSPORT_TLS` | `TlsVerificationError` | Xác thực chứng chỉ TLS thất bại khi nối tới ... | | `FL_TRANSPORT_TIMEOUT` | `RequestTimeoutError` | Request hết thời gian chờ sau ... giây | | `FL_SERVER` | `ServerError` | Lỗi phía server | | `FL_VERSION_UPGRADE_REQUIRED` | `UpgradeRequiredError` | Phiên bản client này không còn được hỗ trợ. Tối thiểu là ... | | `FL_VERSION_API_INCOMPATIBLE` | `IncompatibleApiVersionError` | Client dùng contract major ..., server dùng ... | Dấu `...` là chỗ thông báo thật điền giá trị cụ thể của lời gọi. Một mã không có trong bảng này vẫn được ánh xạ về một lớp trong cây theo nhóm của nó — **không bao giờ** thành một `RuntimeError` trần. Đó là lý do `except finlens.FinLensError` giữ được lời hứa của mình kể cả khi backend thêm mã mới. ## Cảnh báo khác lỗi [#cảnh-báo-khác-lỗi] Cảnh báo **không dừng chương trình**. Chúng đi qua module `warnings` của Python, nên bạn tắt hay bật từng loại một cách chọn lọc. ```text FinLensWarning (UserWarning) ├── UpgradeAvailableWarning có bản client mới hơn trên PyPI ├── QuotaLowWarning hạn mức sắp cạn. Chỉ phát một lần mỗi client ├── PartialDataWarning một phần các mã thất bại, với on_error="warn" ├── DataQualityWarning dữ liệu trả về có vấn đề đã biết └── TierLimitWarning yêu cầu đã bị cắt bớt cho vừa gói dịch vụ FinLensDeprecationWarning (DeprecationWarning) một phần của API công khai sắp bị gỡ bỏ ``` Tắt một loại, giữ nguyên các loại còn lại: ```python import warnings import finlens warnings.filterwarnings("ignore", category=finlens.QuotaLowWarning) ``` Hoặc làm ngược lại — biến cảnh báo thành lỗi để nó không thể bị bỏ qua. Hữu ích trong job chạy tự động, nơi không ai đọc stderr: ```python warnings.filterwarnings("error", category=finlens.PartialDataWarning) ``` Lúc đó `PartialDataWarning` sẽ được ném ra như một ngoại lệ và dừng chương trình — khác với `on_error="raise"` ở chỗ bạn không nhận được `.data`. Tắt toàn bộ cảnh báo của FinLens mà không đụng tới cảnh báo của thư viện khác: ```python warnings.filterwarnings("ignore", category=finlens.FinLensWarning) ``` Bản 0.1.x gọi `warnings.filterwarnings("ignore")` ngay lúc import, tức là tắt **mọi** cảnh báo trong toàn bộ tiến trình của bạn — kể cả cảnh báo của pandas, numpy và code của chính bạn. Bản 1.x không làm vậy nữa. `FinLensDeprecationWarning` kế thừa `DeprecationWarning` chứ không kế thừa `FinLensWarning`, theo đúng quy ước Python: mặc định ẩn với người dùng cuối, hiện ra khi chạy `python -W default`. ## Khi cần báo lỗi [#khi-cần-báo-lỗi] Gửi kèm ba thứ, chúng cắt ngắn phần lớn cuộc trao đổi qua lại: ```python import finlens print(finlens.__version__) print(finlens.build_info()) # commit và thời điểm build của binary bạn đang chạy ``` Cộng thêm `exc.request_id` của lời gọi hỏng — đó là thứ cho phép tra lại đúng request đó ở phía FinLens. Danh sách thay đổi từng phiên bản: [Nhật ký thay đổi](/python-sdk/changelog). ### Câu hỏi thường gặp **Bắt lỗi của thư viện finlens bằng cách nào?** Dùng `except finlens.FinLensError`. Ở bản 1.x mọi lớp lỗi công khai của thư viện Python finlens đều kế thừa `FinLensError`, nên một khối `except` là đủ và không cần `except Exception`. Ngoại lệ bắt được mang `.code` (mã ổn định như `FL_QUOTA_DAILY`), `.message` bằng tiếng Việt, `.request_id`, `.status_code`, `.detail` và `.doc_url`; `str(exc)` gộp sẵn ba thứ quan trọng nhất. Luôn rẽ nhánh theo `.code`, đừng so khớp `.message` — nội dung thông báo được phép đổi chữ, còn `code` thì không. **Vượt hạn mức khi gọi API dữ liệu chứng khoán bằng Python thì bắt lỗi nào?** Với thư viện Python finlens, cả hai trường hợp đều nằm dưới `finlens.QuotaError`. Vượt giới hạn tần suất là `RateLimitError` (mã `FL_QUOTA_RATE`), mang thêm `.retry_after` là số giây nên chờ. Hết hạn mức trong ngày là `DailyQuotaExceededError` (mã `FL_QUOTA_DAILY`), mang `.resets_at` là thời điểm hạn mức được đặt lại kèm offset `+07:00` — chạy lại sau mốc đó, không sớm hơn. Trước khi cạn, thư viện phát `QuotaLowWarning` một lần cho mỗi client. **Một mã lỗi FL_ có tương ứng một lớp ngoại lệ riêng không?** Không, ánh xạ là nhiều-đối-một: nhiều mã có thể trỏ về cùng một lớp ngoại lệ của thư viện Python finlens. Ví dụ `FL_VALIDATION_INTERVAL` và `FL_VALIDATION_INTERVAL_AMBIGUOUS` cùng cho `InvalidIntervalError`. Vì vậy nên bắt theo lớp rồi phân biệt theo `.code`. Một mã không có trong bảng tra vẫn được ánh xạ về một lớp trong cây theo nhóm của nó, không bao giờ thành `RuntimeError` trần — đó là lý do `except finlens.FinLensError` vẫn đúng khi máy chủ thêm mã mới. **Gọi nhiều mã cùng lúc mà một mã hỏng thì chuyện gì xảy ra?** Tham số `on_error` quyết định, và mặc định là `"warn"`: thư viện Python finlens giữ phần lấy được, phát `PartialDataWarning`, rồi ghi chi tiết vào `df.attrs["finlens"]["partial"]` và `df.attrs["finlens"]["failed"]` (mã chứng khoán ánh xạ sang `code` và `message`). Đặt `on_error="raise"` thì nhận `PartialFetchError`, ngoại lệ này mang theo phần đã lấy được ở `.data` và ánh xạ mã sang ngoại lệ ở `.failures`, nên không phải gọi lại từ đầu. `on_error="ignore"` giữ dữ liệu và không cảnh báo gì. **Lỗi xác thực chứng chỉ TLS khi kết nối tới FinLens sửa thế nào?** Đó là `finlens.TlsVerificationError`, mã `FL_TRANSPORT_TLS`, thường gặp khi máy bạn nằm sau proxy kiểm tra TLS hoặc phần mềm diệt virus dùng CA riêng. Cách sửa là trỏ thư viện tới CA bundle do bộ phận IT cấp: `finlens.client(ca_bundle="/duong/dan/ca-bundle.pem")`, hoặc đặt biến môi trường `FINLENS_CA_BUNDLE`. Đây là lỗi vĩnh viễn nên thư viện không thử lại và nó cũng không làm mở circuit breaker. Lớp này kế thừa `ConnectionFailedError`, nên code đang bắt lớp cha không phải sửa gì. **Code cũ viết except ValueError quanh lời gọi finlens có còn chạy không?** Còn. `finlens.ValidationError` kế thừa cả `FinLensError` lẫn `ValueError`, và đó là chủ đích để code viết cho bản cũ không gãy khi nâng lên 1.x: các lỗi tham số như `InvalidSymbolError`, `InvalidDateRangeError`, `InvalidIntervalError`, `CompanyTypeMismatchError` và `UnitMismatchError` vẫn lọt vào `except ValueError`. Khi viết mới thì nên bắt `finlens.ValidationError` — nó chỉ bắt lỗi tham số của finlens chứ không nuốt luôn `ValueError` từ code khác của bạn. --- # Dashboard FinLens: sắp xếp widget và đồng bộ mã cổ phiếu URL: https://docs.finlens.vn/webapp/bat-dau Mô tả: Cách dùng Dashboard FinLens: kéo thả và phóng to widget, chia ô so sánh, đồng bộ mã cùng ngày cho mọi widget, và lưu bố cục riêng bằng Workspace. Tóm tắt: Dashboard FinLens là bàn làm việc gồm nhiều widget mà người dùng tự sắp xếp như cửa sổ trên màn hình. Nền tảng có bốn bảng dựng sẵn: Bảng Thị trường cho góc nhìn toàn thị trường, Bảng Cổ phiếu cho một mã, Watchlist cho danh mục theo dõi, và Workspace là bố cục trống để tự kéo widget vào. Mỗi widget là một tab nằm trong một khung: kéo tên tab sang khung khác để di chuyển, kéo tới cạnh khung để tách ô mới đặt hai widget cạnh nhau, hoặc phóng to ra toàn màn hình. Điểm khiến Dashboard nhanh là cơ chế đồng bộ: đổi mã hoặc đổi ngày một lần trên thanh tiêu đề thì hàng loạt widget bên dưới cập nhật theo, và có thể tắt đồng bộ để mỗi widget giữ mốc thời gian riêng khi cần so hai phiên khác nhau. Sản phẩm: webapp ⏱ Đọc 7 phút · 🟢 Cơ bản · 🔧 Cần: tài khoản FinLens ## Dashboard là gì? [#dashboard-là-gì] Mỗi **widget** là một ô hiển thị một loại thông tin: một biểu đồ, một bảng số liệu, hay một sổ lệnh. Bạn có thể đặt nhiều widget cạnh nhau, kéo-thả để sắp xếp, phóng to ô đang xem — giống như sắp xếp nhiều cửa sổ trên một màn hình làm việc. FinLens có vài **bảng (dashboard)** dựng sẵn, mỗi bảng là một bộ widget phục vụ một mục tiêu: Toàn cảnh — Sức khỏe chỉ số, dòng tiền, độ rộng, xếp hạng RS — góc nhìn toàn thị trường. Một mã — Biểu đồ, sổ lệnh, dòng tiền, kỹ thuật & báo cáo tài chính của 1 mã. Theo dõi — Danh mục mã bạn quan tâm, kèm các chỉ số nhanh. Tùy biến — Bố cục trống để bạn tự kéo widget vào và lưu lại theo ý mình. Mỗi bảng dựng sẵn đã đủ dùng. Hãy bắt đầu với bố cục mặc định, rồi thêm/bớt widget khi đã quen. Mọi thay đổi bố cục đều có thể hoàn tác bằng cách tải lại bảng. ## Thanh tiêu đề — trung tâm điều khiển [#thanh-tiêu-đề--trung-tâm-điều-khiển] Thanh trên cùng của Dashboard là nơi điều khiển chung cho *tất cả* widget bên dưới. Từ trái sang phải, các phần quan trọng: 🔎 Ô tìm mã — Gõ mã (vd HPG). Mọi widget gắn theo mã sẽ đổi theo. 📅 Bộ chọn ngày — Chọn ngày/khoảng ngày dùng chung cho các widget. 🧩 Kho Widgets — Mở danh mục để thêm biểu đồ/bảng vào bảng hiện tại. 🟢 Trạng thái — Cho biết dữ liệu thời gian thực đang kết nối hay không. 🌙 Giao diện — Chuyển nền sáng ↔ tối cho dễ nhìn theo môi trường. 🔔 Thông báo — Chuông hiển thị danh sách thông báo; bấm để xem chi tiết. Ô tìm mã và bộ chọn ngày là hai nút bạn dùng nhiều nhất: đổi **một lần** ở đây, hàng loạt widget bên dưới cập nhật theo — không cần chỉnh từng ô. ## Thêm widget từ Kho Widgets [#thêm-widget-từ-kho-widgets] Khi muốn xem thêm một loại biểu đồ/bảng chưa có trên bảng: 1. Bấm **Kho Widgets** trên thanh tiêu đề. 2. Lọc theo loại (**biểu đồ, bảng, tin tức, sổ lệnh…**) hoặc gõ tìm theo tên cho nhanh. 3. Bấm **thêm** ở widget mong muốn — nó xuất hiện thành một tab mới trên bảng. 4. Kéo tab vừa thêm đến vị trí bạn muốn (xem mục kế tiếp). Các widget chuyên sâu (dòng tiền nhóm NĐT, RRG, Top mua bán ròng…) cần gói FinLens Pro. Nếu một mục bị khóa, bạn sẽ thấy gợi ý nâng cấp khi thêm. ## Sắp xếp, phóng to & đóng widget [#sắp-xếp-phóng-to--đóng-widget] Mỗi widget là một **tab** nằm trong một **khung (tabset)**. Bạn tự do bố trí: 1. **Di chuyển:** kéo phần tên tab và thả vào khung khác. 2. **Chia ô:** kéo tab tới *cạnh* một khung (trái/phải/trên/dưới) để tách thành ô mới — đặt 2 widget cạnh nhau để so sánh. 3. **Phóng to:** bấm nút phóng to **⛶** ở góc khung để xem một widget toàn màn hình; bấm lại để thu về. 4. **Đổi tên:** nhấp đúp vào tên tab để đặt lại tên cho dễ nhớ. 5. **Đóng:** bấm dấu **×** trên tab để gỡ widget khỏi bảng. Kéo đường viền giữa hai khung để chỉnh **độ rộng/cao**. Với widget có nhiều dữ liệu (sổ lệnh, bảng BCTC), phóng to **⛶** sẽ dễ đọc hơn hẳn. ## Đồng bộ mã & ngày [#đồng-bộ-mã--ngày] Đây là điểm khiến Dashboard FinLens nhanh: các widget có thể **dùng chung** mã cổ phiếu và mốc thời gian từ thanh tiêu đề. * **Đồng bộ mã:** ở Bảng Cổ phiếu, đổi mã ở ô tìm mã → tất cả widget của mã đó (biểu đồ, sổ lệnh, dòng tiền, BCTC…) cùng nhảy sang mã mới. * **Đồng bộ ngày (bật mặc định):** chọn ngày/khoảng ngày ở thanh tiêu đề → các widget theo ngày cùng cập nhật. Tiện khi muốn soi cả bảng tại một phiên. * **Tách ngày riêng (cục bộ):** tắt đồng bộ để mỗi widget tự chọn ngày của nó — khi đó từng widget hiện bộ chọn ngày riêng. Hữu ích khi muốn so một widget ở phiên này với widget khác ở phiên khác. Một số widget chạy **trong phiên (intraday)** chỉ có dữ liệu thời gian thực cho *ngày hiện tại*; chọn ngày quá khứ sẽ hiển thị bản ghi cuối ngày của ngày đó. Mỗi bài widget bên dưới sẽ nói rõ widget nào là intraday. ## Lưu bố cục riêng với Workspace [#lưu-bố-cục-riêng-với-workspace] Nếu bạn có cách bố trí ưa thích, **Workspace** cho phép dựng một bảng trống và tự kéo widget vào theo ý mình. Mỗi widget trong Workspace còn nhớ **cấu hình riêng** của nó (mã, ngày, bộ lọc bạn đặt) và được lưu lại — lần sau mở lên vẫn nguyên trạng. Bảng dựng sẵn đồng bộ mã/ngày từ thanh tiêu đề. Trong Workspace, **mỗi widget có thể gắn một mã/ngày riêng** — ví dụ đặt cạnh nhau dòng tiền của HPG, FPT, VCB để so sánh trực tiếp. ## Mẹo nhanh [#mẹo-nhanh] * **Chế độ tối** giúp đỡ mỏi mắt khi theo bảng lâu — màu xanh (tăng) / đỏ (giảm) vẫn giữ nguyên quy ước. * **Chuông thông báo** 🔔 là nơi xem lại các tính năng mới; số đỏ là số thông báo chưa đọc. * Thấy chấm **“Live”** nghĩa là dữ liệu realtime đang chảy; nếu “Offline”, hãy kiểm tra kết nối mạng rồi tải lại. * Lỡ tay làm rối bố cục? Chỉ cần **tải lại trang** để về bố cục mặc định của bảng. Đã nắm thao tác cơ bản? Sang [Bài 2 — Tổng quan thị trường](/webapp/thi-truong-tong-quan) để bắt đầu đọc các widget đầu tiên, hoặc nhảy thẳng tới [Bài 5 — Sổ lệnh & Terminal](/webapp/co-phieu-terminal) nếu bạn giao dịch theo từng mã. ## Bài liên quan [#bài-liên-quan] Đọc sức khỏe thị trường: chỉ số, P/E, động lượng MA, độ rộng. Khối ngoại, Shark, phân loại nhà đầu tư, thanh khoản intraday. Biểu đồ, ba bước giá và bảng khớp lệnh realtime. ### Câu hỏi thường gặp **Làm sao đổi mã cổ phiếu cho tất cả biểu đồ cùng lúc?** Ô tìm mã trên thanh tiêu đề Dashboard điều khiển chung cho mọi widget gắn theo mã. Gõ mã cổ phiếu một lần, chẳng hạn HPG, thì biểu đồ, sổ lệnh, dòng tiền và báo cáo tài chính của mã đó cùng nhảy sang mã mới, không cần chỉnh từng widget. Bộ chọn ngày hoạt động tương tự cho các widget theo ngày. Đây là hai nút được dùng nhiều nhất khi làm việc trên Bảng Cổ phiếu. **Có thể lưu lại bố cục biểu đồ riêng của mình không?** Workspace cho phép dựng một bảng trống rồi tự kéo widget vào theo ý mình, và bố cục đó được lưu lại nên lần sau mở lên vẫn nguyên trạng. Khác biệt quan trọng so với bảng dựng sẵn: trong Workspace mỗi widget nhớ cấu hình riêng gồm mã, ngày và bộ lọc đã đặt, nên có thể đặt cạnh nhau dòng tiền của HPG, FPT và VCB để so sánh trực tiếp. Bảng dựng sẵn thì mọi widget cùng đồng bộ mã và ngày từ thanh tiêu đề. **Lỡ làm rối bố cục widget thì khôi phục thế nào?** Chỉ cần tải lại trang là bảng trở về bố cục mặc định. Mọi thay đổi bố cục đều có thể hoàn tác bằng cách này, nên không cần ngại thử kéo thả hay tách ô. Với các bảng dựng sẵn, bố cục mặc định đã đủ dùng cho phần lớn nhu cầu; nên bắt đầu từ đó rồi thêm bớt widget khi đã quen. Riêng bố cục tự dựng trong Workspace thì được lưu lại và không bị tải lại trang xóa mất. **Vì sao widget hiển thị dữ liệu cuối ngày khi chọn ngày quá khứ?** Một số widget chạy trong phiên chỉ có dữ liệu thời gian thực cho ngày hiện tại, gồm sổ lệnh, bảng khớp lệnh, Dòng tiền Shark, Thanh khoản lũy kế và Độ rộng thị trường theo mốc 5 phút. Khi chọn ngày quá khứ, các widget này hiển thị bản ghi cuối ngày của ngày đó thay vì diễn biến từng phút. Chấm trạng thái trên thanh tiêu đề cho biết dữ liệu thời gian thực đang kết nối hay không. --- # Dòng tiền một mã cổ phiếu: ai đang mua, ai đang bán URL: https://docs.finlens.vn/webapp/co-phieu-dong-tien Mô tả: Đọc dòng tiền lũy kế của một mã trên FinLens: bóc tách theo nhóm nhà đầu tư, mua bán chủ động trong phiên và so sánh dòng tiền của mã với cả ngành. Tóm tắt: Nhóm widget dòng tiền theo mã của FinLens Web cho biết ai đang mua bán một cổ phiếu cụ thể và mạnh đến đâu. Widget Dòng tiền lũy kế lấy giá trị mua trừ giá trị bán mỗi ngày rồi cộng dồn từ đầu khoảng thời gian đã chọn, nên đường đi lên phản ánh tiền vào ròng bền bỉ chứ không phải một phiên đơn lẻ. Tab nhóm nhà đầu tư bóc tách dòng tiền đó theo khối ngoại, cá nhân trong nước, tổ chức trong nước và tự doanh công ty chứng khoán. Widget Mua Bán chủ động cộng dồn chênh lệch giữa mua chủ động và bán chủ động trong phiên, tính bằng tỷ đồng. Widget Mã vs Ngành vẽ song song dòng tiền lũy kế của riêng mã và của cả ngành, khi đường của mã vượt lên trên nghĩa là mã đang khỏe hơn mặt bằng ngành. Sản phẩm: webapp ⏱ Đọc 10 phút · 🟡 Trung cấp · 📍 Bảng Cổ phiếu Các widget dòng tiền theo mã nằm ở **Bảng Cổ phiếu** và đồng bộ theo mã bạn chọn. Đây là cách nhìn "tiền thật" bổ sung cho biểu đồ giá: một mã có thể đi ngang về giá nhưng dòng tiền lũy kế vẫn âm thầm tích lũy (hoặc rút ra). ## Dòng tiền lũy kế (cumulative cash flow) là gì? [#dòng-tiền-lũy-kế-cumulative-cash-flow-là-gì] Mỗi ngày, một nhóm nhà đầu tư **mua vào** và **bán ra** một lượng tiền. Phần chênh lệch là **dòng tiền ròng ngày**: ```text // Cho từng ngày Ròng ngày = Giá trị MUA − Giá trị BÁN // Cộng dồn từ đầu khoảng đến hôm nay Lũy kế = Σ (Ròng ngày) // cumsum ``` Đường lũy kế **đi lên** = tiền đang chảy *vào* mã (mua nhiều hơn bán cộng dồn). Đường **đi xuống** = tiền đang chảy *ra*. Độ dốc cho biết lực mạnh hay yếu. Giá trị mua/bán bình quân được **điều chỉnh theo tỷ lệ chia tách/cổ tức** (adjRatio), nên đường lũy kế liền mạch kể cả khi mã đã chia cổ phiếu trong khoảng xem. ## Dòng tiền lũy kế của mã (tổng thị trường) [#dòng-tiền-lũy-kế-của-mã-tổng-thị-trường] > 📍 Bảng Cổ phiếu · Tên widget: **"Dòng tiền lũy kế"** Biểu đồ kết hợp **đường giá** (tham chiếu) và **đường dòng tiền ròng lũy kế** của toàn bộ thị trường đối với mã. Trục thời gian theo khoảng ngày bạn chọn. | Đường / cột | Ý nghĩa | | ------------------------- | ---------------------------------------------------- | | **Dòng tiền lũy kế** | Σ(mua − bán) cộng dồn — đường chính cần đọc | | **Giá** | Giá cổ phiếu để đối chiếu (phân kỳ giá vs dòng tiền) | | **Giá mua/bán bình quân** | Giá trị bình quân của bên mua / bên bán mỗi ngày | Widget Dòng tiền lũy kế của mã *Widget Dòng tiền lũy kế — đường lũy kế (tổng thị trường) chồng lên đường giá.* **Giá giảm nhưng dòng tiền lũy kế vẫn tăng** → có lực mua âm thầm gom hàng (tích lũy) dù giá chưa phản ánh. Ngược lại **giá tăng nhưng lũy kế đi xuống** → đà tăng thiếu tiền hỗ trợ, dễ đảo chiều. ## Dòng tiền lũy kế theo nhóm nhà đầu tư [#dòng-tiền-lũy-kế-theo-nhóm-nhà-đầu-tư] > 📍 Bảng Cổ phiếu · Tab nhóm NĐT trong widget dòng tiền Cùng công thức lũy kế nhưng **bóc tách theo 4 nhóm nhà đầu tư**, để biết *tiền của ai* đang vào/ra mã: | Nhóm | Là ai | Hàm ý khi lũy kế tăng mạnh | | ---------------------- | -------------------------------- | -------------------------------------------------- | | **Nước ngoài** | Khối ngoại (quỹ, NĐT nước ngoài) | Dòng vốn ngoại tin tưởng — thường ổn định, dài hạn | | **Tổ chức trong nước** | Quỹ, công ty trong nước | "Tay to" nội địa gom hàng | | **Cá nhân trong nước** | NĐT cá nhân (nhỏ lẻ) | Dòng tiền đám đông — biến động nhanh hơn | | **Tự doanh** | Tự doanh công ty chứng khoán | Vị thế ngắn hạn của CTCK | Dòng tiền lũy kế theo nhóm nhà đầu tư *Tab nhóm nhà đầu tư — chuyển giữa Nước ngoài / Tổ chức / Cá nhân / Tự doanh.* Tổng dòng tiền các nhóm thường **bù trừ nhau**: nếu khối ngoại + tổ chức gom mạnh trong khi cá nhân bán ra, đó là tín hiệu "tiền thông minh" mua từ tay nhỏ lẻ — thường tích cực. Ngược lại nếu chỉ cá nhân đỡ giá còn tổ chức/ngoại rút, cần thận trọng. ## Mua/bán chủ động trong phiên (intraday) [#muabán-chủ-động-trong-phiên-intraday] > 📍 Bảng Cổ phiếu · Tên widget: **"Mua/Bán chủ động"** · ⏱ trong phiên Trong khi widget lũy kế nhìn theo *ngày*, widget này nhìn **trong một phiên**, theo từng phút (gộp dữ liệu 1 phút từ 08:55 đến hết phiên). Lệnh được phân loại: ```text // Phân loại lệnh khớp (BuySellActive) Mua chủ động = lệnh khớp ở giá bên bán (người mua "với giá") Bán chủ động = lệnh khớp ở giá bên mua (người bán "dìm giá") cValue = Σ (mua chủ động − bán chủ động) // lũy kế trong phiên, tỷ đồng ``` Widget thể hiện: **khối lượng/giá trị mua chủ động** (dương) và **bán chủ động** (âm) theo thời gian, cùng đường **cValue** — chênh lệch chủ động lũy kế trong phiên (tỷ đồng). Mua bán chủ động trong phiên *Widget Mua/Bán chủ động — mua chủ động (xanh, dương) vs bán chủ động (đỏ, âm) + đường cValue lũy kế.* * **cValue dương & tăng dần** = bên mua liên tục chủ động khớp — lực cầu thực, thường đẩy giá lên. * **cValue âm sâu** = bên bán chủ động áp đảo — áp lực xả hàng. * Đối chiếu với [bảng khớp lệnh ở Bài 5](/webapp/co-phieu-terminal) để soi từng lệnh lớn. ## So sánh dòng tiền mã với ngành [#so-sánh-dòng-tiền-mã-với-ngành] > 📍 Bảng Cổ phiếu · Tên widget: **"Mã vs Ngành"** Một mã có thể tăng dòng tiền chỉ vì *cả ngành* đang được mua. Widget này đặt **dòng tiền lũy kế của mã** cạnh **dòng tiền lũy kế của ngành** (gộp toàn bộ mã cùng ngành ICB), trên cùng trục thời gian trong phiên. ```text // Hai đường so sánh trong phiên symbolValue = dòng tiền lũy kế của riêng mã sectorValue = dòng tiền lũy kế của cả ngành symbolValue > sectorValue → mã khỏe hơn mặt bằng ngành ``` *Widget Mã vs Ngành — đường dòng tiền của mã so với mặt bằng dòng tiền ngành.* **Mã vượt ngành** = dòng tiền chảy vào mã mạnh hơn trung bình ngành → mã đang được ưu tiên, có "câu chuyện riêng". **Mã thua ngành** = chỉ "ăn theo" sóng ngành, lực cầu riêng yếu. ## Kết hợp đọc dòng tiền một mã [#kết-hợp-đọc-dòng-tiền-một-mã] **1) Xu hướng tiền:** *Dòng tiền lũy kế (tổng)* đang vào hay ra? Có phân kỳ với giá không? **2) Tiền của ai:** *Theo nhóm NĐT* — ngoại/tổ chức gom hay cá nhân đỡ? **3) Sức mạnh trong phiên:** *Mua/bán chủ động* — cValue nghiêng về đâu hôm nay? **4) Bối cảnh ngành:** *Mã vs Ngành* — mã dẫn dắt hay ăn theo? Tiếp theo: [Bài 7 — Kỹ thuật & thống kê mùa vụ](/webapp/co-phieu-ky-thuat) (Trend MA, SMA tối ưu, Pivot, Risk Metrics, heatmap mùa vụ). Xem dòng tiền ở cấp **thị trường & ngành** tại [Bài 3](/webapp/thi-truong-dong-tien). ## Bài liên quan [#bài-liên-quan] Trend MA, SMA tối ưu, Pivot, Risk Metrics, heatmap mùa vụ. Order book, khớp lệnh realtime, bước giá & bubble volume. Dòng tiền ròng chỉ số, ngành, khối ngoại, Shark, phân loại NĐT. ### Câu hỏi thường gặp **Dòng tiền lũy kế của một cổ phiếu được tính thế nào?** Mỗi ngày lấy giá trị mua trừ giá trị bán để ra dòng tiền ròng của ngày đó, rồi cộng dồn liên tiếp từ đầu khoảng thời gian đã chọn. Cách cộng dồn giúp nhìn ra xu hướng tích lũy thay vì nhiễu của từng phiên riêng lẻ: đường đi lên đều đặn cho thấy tiền vào ròng bền bỉ, còn đường đi ngang dù giá tăng lại là dấu hiệu đà tăng thiếu dòng tiền hậu thuẫn. Widget Dòng tiền lũy kế trên Bảng Cổ phiếu hiển thị đường này. **Làm sao biết một cổ phiếu khỏe hơn hay yếu hơn ngành của nó?** Widget Mã vs Ngành vẽ hai đường dòng tiền lũy kế song song trong phiên: một đường của riêng mã đang xem và một đường của cả ngành. Khi đường của mã nằm trên đường ngành, nghĩa là dòng tiền vào mã đó mạnh hơn mặt bằng chung của ngành và mã đang được ưu tiên. Ngược lại nếu ngành hút tiền mà mã thì không, đó là dấu hiệu mã bị bỏ lại dù câu chuyện ngành đang tốt. **Nhóm nhà đầu tư nào được tách riêng khi xem dòng tiền cổ phiếu?** Tab nhóm nhà đầu tư trong widget dòng tiền bóc tách thành khối ngoại, nhà đầu tư cá nhân trong nước, tổ chức trong nước và tự doanh công ty chứng khoán. Mỗi nhóm có đường lũy kế riêng nên so sánh được hành vi giữa các nhóm trên cùng một mã, chẳng hạn khối ngoại bán ra trong khi tổ chức trong nước gom vào. Dữ liệu nhóm nhà đầu tư nội thường về sau khi kết phiên nên không có theo thời gian thực. **Giá trị mua bán chủ động trong phiên đo bằng đơn vị gì?** Widget Mua Bán chủ động cộng dồn chênh lệch giữa giá trị mua chủ động và giá trị bán chủ động từ đầu phiên, kết quả tính bằng tỷ đồng. Mua chủ động là lệnh khớp ở giá bên bán còn bán chủ động là lệnh khớp ở giá bên mua, nên hiệu số này phản ánh bên nào đang sốt ruột hơn ngay trong lúc phiên diễn ra. Đây là widget chạy trong phiên, chỉ có dữ liệu thời gian thực cho ngày hiện tại. --- # Phân tích kỹ thuật cổ phiếu: Trend MA, Pivot và mùa vụ URL: https://docs.finlens.vn/webapp/co-phieu-ky-thuat Mô tả: Công cụ kỹ thuật cho một mã trên FinLens: tín hiệu Trend MA, backtest chiến lược SMA cắt nhau, Pivot Points, chỉ số rủi ro và thống kê lợi nhuận theo mùa vụ. Tóm tắt: Nhóm widget kỹ thuật của FinLens Web phân tích một cổ phiếu theo xu hướng, rủi ro và tính mùa vụ. Widget Trend MA so giá đóng cửa với từng đường trung bình động, cả SMA lẫn EMA ở nhiều chu kỳ, rồi quy thành tín hiệu Mua khi giá nằm trên MA và Bán khi nằm dưới. Widget SMA tối ưu chạy backtest chiến lược hai đường SMA cắt nhau và đo phần vượt trội so với mua và nắm giữ bằng chênh lệch lợi nhuận tích lũy theo log return. Widget Pivot Points dựng các mốc hỗ trợ và kháng cự. Widget Chỉ số rủi ro đo mức biến động. Ba widget mùa vụ gồm heatmap lợi nhuận theo tháng tính bằng phần trăm thay đổi giá cuối tháng, lịch lợi nhuận theo ngày, và xác suất tăng theo từng thứ trong tuần kèm lợi nhuận trung bình cùng trung vị. Sản phẩm: webapp ⏱ Đọc 12 phút · 🟡 Trung cấp · 📍 Bảng Cổ phiếu Các widget dưới đây nằm ở **Bảng Cổ phiếu** và đồng bộ theo mã. Đây là góc nhìn **kỹ thuật & thống kê** — bổ trợ cho dòng tiền ([Bài 6](/webapp/co-phieu-dong-tien)) và terminal ([Bài 5](/webapp/co-phieu-terminal)). ## Trend MA — xu hướng theo đường trung bình [#trend-ma--xu-hướng-theo-đường-trung-bình] > 📍 Bảng Cổ phiếu · Tên widget: **"Trend MA"** Bảng tổng hợp vị trí giá so với các đường trung bình động **SMA & EMA** ở nhiều chu kỳ (5, 10, 20, 50, 100, 200 phiên), tính trên \~200 ngày gần nhất. Mỗi đường cho một tín hiệu: ```text // Với từng đường MA (mỗi chu kỳ, cả SMA và EMA) Giá > MA → Mua (giá trên trung bình → xu hướng tăng) Giá < MA → Bán (giá dưới trung bình → xu hướng giảm) Giá ≈ MA → Trung lập ``` Widget Trend MA *Widget Trend MA — tín hiệu Mua/Bán/Trung lập theo SMA & EMA các chu kỳ 5→200.* **Đa số đường ngắn & dài đều "Mua"** = xu hướng tăng đồng thuận, mạnh. Khi đường ngắn (5/10/20) "Bán" còn đường dài (100/200) vẫn "Mua" → có thể là nhịp điều chỉnh trong xu hướng tăng lớn. ## SMA tối ưu — chiến lược cắt nhau (backtest) [#sma-tối-ưu--chiến-lược-cắt-nhau-backtest] > 📍 Bảng Cổ phiếu · Tên widget: **"SMA tối ưu"** Widget này **backtest chiến lược 2 đường SMA cắt nhau** trên \~756 phiên (\~3 năm) và tìm ra **cặp chu kỳ tối ưu** (MA ngắn & MA dài) cho riêng mã. Quy tắc: ```text // Chiến lược dual-SMA crossover MA ngắn cắt LÊN MA dài → tín hiệu MUA (giữ vị thế) MA ngắn cắt XUỐNG MA dài → tín hiệu BÁN (thoát) // So sánh lợi nhuận tích lũy (log returns) outperformance = Lợi nhuận chiến lược − Lợi nhuận mua & nắm giữ ``` Widget SMA tối ưu backtest *Widget SMA tối ưu — cặp MA tối ưu, đường lợi nhuận chiến lược vs mua & nắm giữ.* * **outperformance > 0**: chiến lược cắt nhau thắng "mua và giữ" trong quá khứ → mã có tính xu hướng rõ, hợp giao dịch theo trend. * **outperformance ≤ 0**: mã đi ngang/nhiễu nhiều, chiến lược MA không hiệu quả — nên ưu tiên cách tiếp cận khác. Cặp MA "tối ưu" được chọn dựa trên **dữ liệu quá khứ** — hiệu quả lịch sử *không đảm bảo* lặp lại. Dùng để hiểu tính chất mã, không phải tín hiệu mua/bán tuyệt đối. ## Pivot Points — hỗ trợ & kháng cự [#pivot-points--hỗ-trợ--kháng-cự] > 📍 Bảng Cổ phiếu · Tên widget: **"Pivot Points"** Tính các mức **hỗ trợ (S1–S3)** và **kháng cự (R1–R3)** quanh điểm trục **PP**, theo **5 phương pháp** phổ biến để bạn đối chiếu: | Phương pháp | Đặc điểm | | ------------- | -------------------------------------------------- | | **Classic** | Cổ điển, dựa trên cao–thấp–đóng cửa kỳ trước | | **Fibonacci** | Các mức theo tỷ lệ Fibonacci (0.382 / 0.618 / 1.0) | | **Camarilla** | Mức sát giá hơn, hợp giao dịch ngắn hạn | | **Woodie** | Trọng số giá đóng cửa nhiều hơn | | **DeMark** | Dựa trên tương quan đóng cửa vs mở cửa | Các vùng được tham chiếu thêm bằng **đỉnh/đáy cục bộ** phát hiện tự động trên \~600 phiên gần nhất, nên các mức bám sát hành vi giá thực tế của mã. Widget Pivot Points *Widget Pivot Points — PP, R1–R3 (kháng cự), S1–S3 (hỗ trợ) theo 5 phương pháp.* Mức được **nhiều phương pháp cùng chỉ tới** (cụm hỗ trợ/kháng cự "chụm") thường *đáng tin hơn* mức chỉ một phương pháp đưa ra. Dùng để đặt mục tiêu chốt lời / cắt lỗ hợp lý. ## Chỉ số rủi ro (Risk Metrics) [#chỉ-số-rủi-ro-risk-metrics] > 📍 Bảng Cổ phiếu · Tên widget: **"Chỉ số rủi ro"** · Terminal cạnh phải Bộ chỉ số đo **rủi ro & hiệu quả** của mã trên \~300 phiên (lãi suất phi rủi ro giả định 2%). Mỗi chỉ số kèm nhãn Tốt / Trung bình / Xấu để đọc nhanh: | Chỉ số | Đo điều gì | Đọc thế nào | | --------------------------- | --------------------------------- | ----------------------------- | | **Volatility** (Biến động) | Độ dao động giá năm hóa (σ×√252) | Càng thấp càng ổn định | | **Downside Vol** | Biến động chỉ tính phần giảm | Thấp = ít rủi ro giảm | | **Beta** | Độ nhạy với thị trường (VNINDEX) | >1 nhạy hơn TT, \<1 phòng thủ | | **Max Drawdown** | Mức sụt giảm sâu nhất từ đỉnh | Càng nhỏ (gần 0) càng tốt | | **Sharpe** | Lợi nhuận vượt trội / tổng rủi ro | Càng cao càng tốt (>1 tốt) | | **Sortino** | Lợi nhuận vượt trội / rủi ro giảm | Càng cao càng tốt | | **Liquidity** (Thanh khoản) | Khả năng mua/bán dễ dàng | Cao = dễ vào/ra vị thế | Widget Risk Metrics *Widget Chỉ số rủi ro — Volatility, Beta, Max Drawdown, Sharpe, Sortino… kèm nhãn Tốt/Trung bình/Xấu.* **Sharpe/Sortino cao + Max Drawdown nhỏ** = mã sinh lời tốt với rủi ro kiểm soát được — chất lượng. **Beta cao + Volatility cao** = mã "nóng", lời/lỗ nhanh, hợp khẩu vị rủi ro cao và quản trị vị thế chặt. ## Heatmap lợi nhuận theo tháng (mùa vụ) [#heatmap-lợi-nhuận-theo-tháng-mùa-vụ] > 📍 Bảng Cổ phiếu · Tên widget: **"Lợi nhuận theo tháng"** Ma trận màu **10 năm × 12 tháng**: mỗi ô là **% thay đổi giá trong tháng đó** (so cuối tháng với cuối tháng trước). Ô xanh = tháng tăng, đỏ = tháng giảm, đậm = biên độ lớn. ```text // Mỗi ô (năm, tháng) Lợi nhuận tháng (%) = (Giá cuối tháng − Giá cuối tháng trước) / Giá cuối tháng trước × 100 ``` Heatmap lợi nhuận theo tháng *Widget Lợi nhuận theo tháng — ma trận 10 năm × 12 tháng, xanh (tăng) / đỏ (giảm).* Nhìn **theo cột (tháng)** để bắt *tính mùa vụ*: nếu một tháng nào đó xanh gần như mọi năm → mã có xu hướng tích cực mùa đó. Đây là thống kê tham khảo, không phải quy luật chắc chắn. ## Calendar heatmap — lịch lợi nhuận theo ngày [#calendar-heatmap--lịch-lợi-nhuận-theo-ngày] > 📍 Bảng Cổ phiếu · Tên widget: **"Lịch lợi nhuận"** Dạng "đóng góp" kiểu lịch GitHub: **mỗi ô là một phiên giao dịch**, tô màu theo lợi nhuận ngày đó, gom theo từng năm. Cho cái nhìn tổng thể về **nhịp tăng/giảm dày-thưa** qua thời gian. Calendar heatmap lợi nhuận theo ngày *Widget Lịch lợi nhuận — mỗi ô một phiên, màu theo lợi nhuận ngày, xếp theo năm.* * **Cụm ô xanh đậm liền nhau** = giai đoạn tăng mạnh kéo dài. * **Mảng đỏ dày** = giai đoạn điều chỉnh/giảm sâu — hữu ích khi nhìn lại lịch sử biến động của mã. ## Xác suất tăng theo thứ trong tuần [#xác-suất-tăng-theo-thứ-trong-tuần] > 📍 Bảng Cổ phiếu · Tên widget: **"Xác suất tăng theo thứ"** Thống kê trên \~3 năm: với mỗi **thứ (Hai → Sáu)**, tính tỷ lệ phiên tăng giá, cùng lợi nhuận trung bình & trung vị của thứ đó. ```text // Cho từng thứ (Mon..Fri) Xác suất tăng (%) = Số phiên tăng / Tổng số phiên × 100 + Lợi nhuận trung bình & trung vị mỗi thứ ``` Xác suất tăng theo thứ trong tuần *Widget Xác suất tăng theo thứ — tỷ lệ phiên tăng & lợi nhuận TB cho từng ngày trong tuần.* Đây là **thống kê mô tả**, phản ánh quá khứ với mẫu hữu hạn. Chênh lệch nhỏ giữa các thứ thường là *nhiễu* — đừng giao dịch chỉ vì "thứ Tư hay tăng". Coi như bối cảnh tham khảo bên cạnh phân tích chính. ## Kết hợp & lưu ý chung [#kết-hợp--lưu-ý-chung] **Xu hướng:** *Trend MA* + *SMA tối ưu* xác nhận mã đang trend hay đi ngang. **Điểm vào/ra:** *Pivot Points* cho vùng hỗ trợ/kháng cự cụ thể. **Khẩu vị rủi ro:** *Risk Metrics* xem mã có hợp chiến lược của bạn. **Bối cảnh thời điểm:** bộ *heatmap mùa vụ* + *xác suất theo thứ*. Luôn đối chiếu với [dòng tiền (Bài 6)](/webapp/co-phieu-dong-tien) — kỹ thuật cho "khi nào", dòng tiền cho "có tiền thật đỡ không". Tiếp theo: [Bài 8 — Báo cáo tài chính, cổ tức & sự kiện](/webapp/co-phieu-tai-chinh) để soi sức khỏe doanh nghiệp đằng sau giá. Hoặc quay lại [trang mục lục](/webapp) để xem các bài còn lại. ## Bài liên quan [#bài-liên-quan] Lũy kế khối ngoại/cá nhân/tổ chức/tự doanh, mua-bán chủ động, so ngành. Order book, khớp lệnh realtime, bước giá & bubble volume. KQKD (TTM), cân đối kế toán, lưu chuyển tiền tệ, cổ tức, sự kiện. ### Câu hỏi thường gặp **Chiến lược hai đường trung bình cắt nhau có thực sự hiệu quả với cổ phiếu này không?** Widget SMA tối ưu trả lời bằng backtest thay vì phỏng đoán. Chiến lược được đặt là mua khi đường trung bình ngắn cắt lên đường dài và thoát khi cắt xuống, sau đó so lợi nhuận tích lũy của chiến lược với lợi nhuận của việc chỉ mua và nắm giữ, tính theo log return. Phần chênh lệch chính là mức vượt trội; nếu nó âm thì chiến lược cắt nhau kém hơn việc mua rồi giữ nguyên, một kết quả khá thường gặp với các mã có xu hướng dài. **Cổ phiếu có tính mùa vụ theo tháng không?** Heatmap lợi nhuận theo tháng của FinLens tính phần trăm thay đổi giữa giá cuối tháng và giá cuối tháng trước cho từng ô năm và tháng, nhờ vậy nhìn ra tháng nào lặp lại xu hướng tăng hoặc giảm qua nhiều năm. Bổ sung cho nó là widget lịch lợi nhuận theo ngày và widget xác suất tăng theo thứ trong tuần, tính bằng số phiên tăng chia tổng số phiên kèm lợi nhuận trung bình và trung vị của từng thứ. Đây là thống kê quá khứ, không phải dự báo. **Widget Trend MA quy tín hiệu mua bán theo quy tắc nào?** Với từng đường trung bình động, cả SMA lẫn EMA và ở nhiều chu kỳ khác nhau, widget so giá đóng cửa hiện tại với giá trị đường đó. Giá nằm trên đường trung bình được quy thành tín hiệu Mua vì phản ánh xu hướng tăng, nằm dưới thành tín hiệu Bán, còn xấp xỉ bằng thì để trung lập. Tập hợp tín hiệu của nhiều chu kỳ cho thấy sự đồng thuận giữa khung ngắn hạn và dài hạn, thay vì dựa vào một đường duy nhất. **Xác suất tăng theo thứ trong tuần tính ra sao?** Widget lấy toàn bộ lịch sử giao dịch của mã, nhóm các phiên theo thứ từ Thứ Hai đến Thứ Sáu, rồi với mỗi thứ tính tỷ lệ số phiên tăng trên tổng số phiên của thứ đó. Kèm theo là lợi nhuận trung bình và lợi nhuận trung vị của từng thứ, hai con số này chênh nhau nhiều cho thấy kết quả bị vài phiên đột biến kéo lệch. Đây là quan sát thống kê trên dữ liệu quá khứ và không đảm bảo lặp lại trong tương lai. --- # Đọc báo cáo tài chính doanh nghiệp niêm yết và cổ tức URL: https://docs.finlens.vn/webapp/co-phieu-tai-chinh Mô tả: Xem kết quả kinh doanh và lợi nhuận TTM, cân đối kế toán, lưu chuyển tiền tệ, lịch sử cổ tức tiền mặt cùng cổ phiếu thưởng và sự kiện doanh nghiệp trên FinLens. Tóm tắt: Nhóm widget tài chính của FinLens Web trình bày sức khỏe doanh nghiệp đằng sau giá cổ phiếu. Widget Kết quả kinh doanh cho doanh thu và lợi nhuận theo quý, còn bản TTM cộng quý hiện tại với ba quý liền trước thành tổng bốn quý gần nhất và đo tăng trưởng bằng cách so với TTM của bốn quý trước đó. Widget Cân đối kế toán trình bày tài sản và nguồn vốn. Widget Lưu chuyển tiền tệ tách ba dòng kinh doanh, đầu tư và tài chính, với lưu chuyển thuần bằng tổng ba dòng này. Widget Bảng báo cáo tài chính cho bản đầy đủ. Hai widget cổ tức hiển thị cổ tức tiền mặt qua các năm và tỷ lệ cổ tức bằng cổ phiếu, quy về phần trăm theo số cổ phiếu thưởng trên số cổ phiếu đang nắm. Widget Sự kiện doanh nghiệp liệt kê các mốc quyền. Sản phẩm: webapp ⏱ Đọc 12 phút · 🟡 Trung cấp · 📍 Bảng Cổ phiếu Các widget tài chính nằm ở **Bảng Cổ phiếu** và đồng bộ theo mã. Dữ liệu được lấy theo **loại doanh nghiệp** — Công ty thường, Ngân hàng, Chứng khoán, Bảo hiểm — nên các chỉ tiêu hiển thị sẽ khác nhau đôi chút giữa các nhóm này. ## Kết quả kinh doanh & TTM [#kết-quả-kinh-doanh--ttm] > 📍 Bảng Cổ phiếu · Tên widget: **"Kết quả kinh doanh"** & **"Kết quả kinh doanh TTM"** · TTM cần PRO Biểu đồ cột kết hợp đường: **cột** là số tuyệt đối (Doanh thu thuần, Lợi nhuận ròng), **đường** (trục phải) là **tốc độ tăng trưởng %**. Có nút chuyển **Quý / Năm**. | Thành phần | Ý nghĩa | | ------------------------------- | ------------------------------------------------------------ | | **Doanh thu thuần** (cột) | Tổng doanh thu sau khấu trừ — quy mô kinh doanh | | **Lợi nhuận ròng** (cột) | Lãi sau thuế (NPAT) — phần thực sự về cho cổ đông | | **Tăng trưởng DT / LN** (đường) | % thay đổi so với kỳ liền trước (QoQ) hoặc cùng kỳ năm trước | Widget Kết quả kinh doanh *Widget Kết quả kinh doanh — cột doanh thu/lợi nhuận + đường tăng trưởng %, chuyển Quý/Năm.* ### TTM — Trailing Twelve Months (12 tháng gần nhất) [#ttm--trailing-twelve-months-12-tháng-gần-nhất] Số liệu theo quý hay "giật cục" do tính mùa vụ. **TTM** cộng dồn **4 quý gần nhất** để có bức tranh 12 tháng "trượt", mượt hơn và cập nhật hơn báo cáo năm: ```text // Doanh thu / lợi nhuận TTM tại mỗi quý TTM = Quý hiện tại + 3 quý liền trước // tổng 4 quý gần nhất // Tăng trưởng TTM = so với TTM của 4 quý trước (YoY) Tăng trưởng TTM (%) = (TTM nay − TTM 4 quý trước) / TTM 4 quý trước × 100 ``` Widget Kết quả kinh doanh TTM *Widget Kết quả kinh doanh TTM — đường TTM mượt, luôn theo quý (không có nút Quý/Năm).* Dùng **TTM** để bắt xu hướng *thật* của doanh nghiệp (loại nhiễu mùa vụ) và để tính P/E cập nhật. Dùng **biểu đồ Quý** để soi quý gần nhất đột biến hay suy yếu. ## Cân đối kế toán [#cân-đối-kế-toán] > 📍 Bảng Cổ phiếu · Tên widget: **"Cân đối kế toán"** Biểu đồ cột + đường thể hiện quy mô và cơ cấu nguồn vốn qua các kỳ (chuyển Quý/Năm): | Thành phần | Ý nghĩa | | ------------------------------- | ------------------------------------- | | **Tổng tài sản** (cột) | Toàn bộ tài sản doanh nghiệp đang nắm | | **Vốn chủ sở hữu** (cột) | Phần thuộc về cổ đông (tài sản − nợ) | | **Tăng trưởng tài sản** (đường) | % mở rộng quy mô qua từng kỳ | Widget Cân đối kế toán *Widget Cân đối kế toán — tổng tài sản & vốn chủ sở hữu + đường tăng trưởng tài sản.* Khoảng cách giữa **Tổng tài sản** và **Vốn chủ sở hữu** chính là **nợ**. Tài sản tăng nhanh nhưng vốn chủ sở hữu đứng yên → doanh nghiệp mở rộng bằng *vay nợ*, cần xem khả năng trả nợ (đối chiếu lưu chuyển tiền tệ). ## Lưu chuyển tiền tệ [#lưu-chuyển-tiền-tệ] > 📍 Bảng Cổ phiếu · Tên widget: **"Lưu chuyển tiền tệ"** Biểu đồ **cột chồng** tách dòng tiền theo 3 hoạt động + dòng tiền thuần trong kỳ (chuyển Quý/Năm): | Dòng tiền | Ý nghĩa | | ----------------------------- | --------------------------------------------------------------- | | **Hoạt động kinh doanh** | Tiền tạo ra từ hoạt động cốt lõi — quan trọng nhất, nên *dương* | | **Hoạt động đầu tư** | Mua/bán tài sản, đầu tư — thường âm khi doanh nghiệp mở rộng | | **Hoạt động tài chính** | Vay/trả nợ, phát hành, trả cổ tức | | **Lưu chuyển thuần trong kỳ** | Tổng 3 dòng trên — tô màu theo dấu (xanh dương / đỏ âm) | ```text Lưu chuyển thuần = Kinh doanh + Đầu tư + Tài chính ``` Widget Lưu chuyển tiền tệ *Widget Lưu chuyển tiền tệ — cột chồng 3 hoạt động + dòng tiền thuần trong kỳ.* Doanh nghiệp khỏe thường có **dòng tiền kinh doanh dương & bền**. Nếu lợi nhuận trên báo cáo cao nhưng dòng tiền kinh doanh liên tục âm → lãi "trên giấy" (phải thu/tồn kho phình to), cần thận trọng. ## Bảng báo cáo tài chính đầy đủ [#bảng-báo-cáo-tài-chính-đầy-đủ] > 📍 Bảng Cổ phiếu · Tên widget: **"Bảng báo cáo tài chính"** · PRO Khi cần chi tiết tới từng dòng, widget này hiển thị **BCTC dạng bảng nhiều kỳ** — cột là các kỳ, hàng là từng chỉ tiêu (có thể bung/thu theo cấp). Thanh công cụ cho phép tùy chỉnh: | Bộ chọn | Lựa chọn | | ------------- | ---------------------------------------------------------------------- | | **Loại BCTC** | Cân đối kế toán · Kết quả kinh doanh · LCTT trực tiếp · LCTT gián tiếp | | **Đơn vị** | Đồng · Triệu · Tỷ (mặc định) · % tỷ lệ (với CĐKT & KQKD) | | **Báo cáo** | BCTC Quý · BCTC Năm | | **Số kỳ** | 5 · 10 · 15 · 20 kỳ hiển thị | Cột chỉ tiêu được ghim bên trái, các hàng cha có thể **bấm để bung con**. Số âm hiển thị màu đỏ. Chế độ **"% tỷ lệ"** quy mỗi dòng về phần trăm so với gốc (ví dụ % trên tổng tài sản / tổng doanh thu) để so cơ cấu. Bảng báo cáo tài chính đầy đủ *Widget Bảng báo cáo tài chính — nhiều kỳ theo cột, chỉ tiêu phân cấp bung/thu, đổi loại/đơn vị/số kỳ.* **Ngân hàng, Chứng khoán, Bảo hiểm** dùng mẫu BCTC riêng (cấu trúc chỉ tiêu khác công ty thường) — FinLens tự áp đúng mẫu theo loại doanh nghiệp của mã, bạn không cần chọn thủ công. ## Cổ tức qua các năm [#cổ-tức-qua-các-năm] > 📍 Bảng Cổ phiếu · Tên widget: **"Cổ tức tiền mặt qua các năm"** & **"Tỷ lệ cổ tức cổ phiếu qua các năm"** Hai biểu đồ cột thống kê chính sách trả cổ tức của doanh nghiệp theo từng năm: * **Cổ tức tiền mặt** — cột theo năm, đơn vị **VND/cổ phiếu**. Cộng dồn các đợt chi trong cùng năm. * **Tỷ lệ cổ tức cổ phiếu** — cột theo năm, đơn vị **%** (cổ phiếu thưởng / chia tách). ```text // Cổ tức cổ phiếu được quy về % Tỷ lệ (%) = (Số CP thưởng / Số CP nắm giữ) × 100 // ví dụ tỷ lệ 20/100 = 20% (sở hữu 100 cp nhận thêm 20 cp) ``` Cổ tức tiền mặt qua các năm *Widget Cổ tức tiền mặt qua các năm — cột VND/cp mỗi năm.* Tỷ lệ cổ tức cổ phiếu qua các năm *Widget Tỷ lệ cổ tức cổ phiếu qua các năm — cột % cổ phiếu thưởng/chia tách mỗi năm.* **Cổ tức tiền mặt đều đặn nhiều năm** = doanh nghiệp ổn định, dòng tiền tốt — hợp khẩu vị "ăn cổ tức". **Tỷ suất cổ tức** (cổ tức tiền mặt ÷ thị giá) thay đổi theo giá nên không cố định trong widget — bạn tự ước tính theo giá hiện tại. ## Sự kiện doanh nghiệp (Corporate Actions) [#sự-kiện-doanh-nghiệp-corporate-actions] > 📍 Bảng Cổ phiếu · Tên widget: **"Sự kiện doanh nghiệp"** Bảng liệt kê lịch sử & lịch sắp tới các sự kiện ảnh hưởng quyền lợi cổ đông, sắp theo **ngày giao dịch không hưởng quyền (GDKHQ)** mới nhất trước: | Cột | Ý nghĩa | | ------------------------- | ---------------------------------------------------------------------------- | | **Ngày GDKHQ** | Ngày giao dịch không hưởng quyền — mua từ ngày này *không* còn nhận quyền | | **Ngày ĐKCC / Thực hiện** | Ngày chốt danh sách / ngày chi trả thực tế | | **Sự kiện** | Loại: Cổ tức tiền mặt · Cổ tức cổ phiếu · Khác (chia tách, phát hành quyền…) | | **Tiền mặt (VNĐ)** | Cổ tức tiền mặt mỗi cổ phiếu của đợt | | **Tỷ lệ** | Tỷ lệ cổ phiếu thưởng / chia tách (vd 20/100, 2:1) | Bảng sự kiện doanh nghiệp *Widget Sự kiện doanh nghiệp — GDKHQ, ngày thực hiện, loại sự kiện (nhãn màu), tiền mặt & tỷ lệ.* Vào ngày GDKHQ, giá tham chiếu bị **điều chỉnh giảm** tương ứng cổ tức/cổ phiếu thưởng — đây là kỹ thuật, *không phải* mã "rớt giá". Các widget dòng tiền & giá của FinLens dùng giá điều chỉnh để biểu đồ liền mạch. ## Kết hợp & lưu ý chung [#kết-hợp--lưu-ý-chung] **1) Tăng trưởng:** *Kết quả kinh doanh (TTM)* — doanh thu & lợi nhuận có tăng bền không? **2) Sức khỏe bảng cân đối:** *Cân đối kế toán* — tài sản/vốn/nợ cân đối ra sao? **3) Chất lượng lợi nhuận:** *Lưu chuyển tiền tệ* — lãi có ra tiền thật? **4) Chi tiết:** *Bảng BCTC* khi cần soi từng chỉ tiêu & cơ cấu %. **5) Cổ đông nhận gì:** *Cổ tức* + *Sự kiện* để biết lịch sử trả & quyền sắp tới. Tiếp theo: [Bài 9 — Investment Ideas, báo cáo & tin tức](/webapp/khuyen-nghi) (khuyến nghị CTCK, vùng giá mục tiêu). Ghép phân tích cơ bản này với [kỹ thuật (Bài 7)](/webapp/co-phieu-ky-thuat) và [dòng tiền (Bài 6)](/webapp/co-phieu-dong-tien) để có cái nhìn toàn diện. ## Bài liên quan [#bài-liên-quan] Khuyến nghị CTCK, vùng giá mục tiêu, danh sách báo cáo, tin tức. Trend MA, SMA tối ưu, Pivot, Risk Metrics, heatmap mùa vụ. Lũy kế theo nhóm NĐT, mua-bán chủ động, so ngành. ### Câu hỏi thường gặp **TTM trong báo cáo tài chính nghĩa là gì?** TTM viết tắt của Trailing Twelve Months, tức tổng của bốn quý gần nhất tính đến quý hiện tại. Cách tính là lấy quý hiện tại cộng ba quý liền trước, nhờ vậy loại bỏ được tính mùa vụ của từng quý riêng lẻ và cho bức tranh sát với một năm hoạt động đầy đủ. Tăng trưởng TTM đo bằng chênh lệch giữa TTM hiện tại và TTM của bốn quý trước, chia cho TTM bốn quý trước rồi nhân một trăm. Trên FinLens Web, widget Kết quả kinh doanh TTM yêu cầu gói Pro. **Lưu chuyển tiền thuần của doanh nghiệp gồm những phần nào?** Widget Lưu chuyển tiền tệ tách dòng tiền thành ba nhóm theo chuẩn báo cáo tài chính: dòng tiền từ hoạt động kinh doanh, từ hoạt động đầu tư và từ hoạt động tài chính. Lưu chuyển thuần trong kỳ bằng tổng của cả ba dòng này. Đọc kèm nhau sẽ biết doanh nghiệp đang tạo tiền từ hoạt động cốt lõi hay phải dựa vào vay nợ và phát hành thêm, một khác biệt mà chỉ nhìn lợi nhuận trên báo cáo kết quả kinh doanh sẽ không thấy. **Tỷ lệ cổ tức bằng cổ phiếu 20/100 nghĩa là gì?** Cổ tức bằng cổ phiếu được quy về phần trăm bằng cách lấy số cổ phiếu thưởng chia số cổ phiếu đang nắm giữ rồi nhân một trăm. Tỷ lệ 20/100 nghĩa là sở hữu 100 cổ phiếu sẽ nhận thêm 20 cổ phiếu, tương đương 20 phần trăm. Widget Tỷ lệ cổ tức cổ phiếu qua các năm hiển thị lịch sử các đợt chia này, đặt cạnh widget Cổ tức tiền mặt qua các năm để thấy doanh nghiệp thiên về trả tiền mặt hay pha loãng bằng cổ phiếu. **Xem lịch sự kiện quyền của cổ phiếu ở đâu?** Widget Sự kiện doanh nghiệp trên Bảng Cổ phiếu liệt kê các mốc quyền của mã đang xem, gồm những sự kiện làm thay đổi quyền lợi cổ đông như chia cổ tức, phát hành thêm hay chia tách. Đây là thông tin cần đối chiếu khi đọc biểu đồ giá lịch sử, vì các sự kiện này tạo ra bước nhảy giá không phản ánh diễn biến cung cầu thật. Dữ liệu này nằm cùng nhóm với hai widget cổ tức qua các năm. --- # Sổ lệnh 3 bước giá và bảng khớp lệnh thời gian thực URL: https://docs.finlens.vn/webapp/co-phieu-terminal Mô tả: Đọc Trading Terminal của FinLens: sổ lệnh ba bước giá mua bán, bảng khớp lệnh chạy realtime, phân bố khối lượng theo giá và bubble volume trong phiên. Tóm tắt: Trading Terminal của FinLens Web gom mọi thứ cần cho việc theo dõi một mã vào cùng màn hình. Panel Biểu đồ giao dịch dùng nền TradingView cho nến và chỉ báo. Widget Sổ lệnh hiển thị ba bước giá mua và ba bước giá bán tốt nhất theo thời gian thực. Widget Khớp lệnh chạy bảng từng lệnh khớp trong phiên. Panel Bước giá và Khối lượng gom khối lượng theo từng mức giá và tách thành ba phần: mua chủ động, bán chủ động và phần không xác định chiều. Panel Bubble Volume đặt mỗi lệnh thành một bong bóng với trục ngang là thời điểm trong phiên từ 09:15 đến 11:30 và 13:00 đến 15:00, trục dọc là khối lượng với mua chủ động mang dấu dương còn bán chủ động mang dấu âm, kích thước bong bóng thể hiện giá trị giao dịch tính bằng triệu đồng. Sản phẩm: webapp ⏱ Đọc 11 phút · 🟡 Trung cấp · 📍 Bảng Cổ phiếu · ⭐ PRO Trading Terminal nằm ở **Bảng Cổ phiếu** (một số panel yêu cầu gói **PRO**). Mọi panel **đồng bộ theo mã** bạn chọn ở thanh tiêu đề: đổi mã một lần, toàn bộ biểu đồ, sổ lệnh, khớp lệnh cập nhật theo. ## Bố cục Trading Terminal [#bố-cục-trading-terminal] > 📍 Bảng Cổ phiếu · Chế độ: **Trading Terminal** Terminal là màn hình đa panel có thể kéo-thả, gồm các khu vực chính: | Khu vực | Nội dung | | ------------- | ------------------------------------------------------------------------------ | | **Hàng trên** | Dòng tiền ròng intraday & lũy kế · Bước giá & khối lượng · RRG · Bubble Volume | | **Hàng giữa** | **Biểu đồ TradingView** (chính) + tab so sánh dòng tiền theo nhóm NĐT | | **Hàng dưới** | Khối lượng mua chủ động · Khối lượng bán chủ động | | **Cạnh phải** | Chỉ số rủi ro · Tin tức · Báo cáo phân tích · Watchlist | | **Cạnh dưới** | Sự kiện quyền · Pivot Points · Trend MA · Screener | Bố cục Trading Terminal *Trading Terminal — bố cục đa panel, kéo-thả & đổi kích thước tự do.* Mỗi panel có thể **kéo tab sang vị trí khác**, **đổi kích thước** bằng cách kéo viền, hoặc **phóng to** `⛶` khi cần tập trung. Bố cục được lưu lại cho lần sau (xem [Bài 1 — Workspace](/webapp/bat-dau)). ## Biểu đồ TradingView [#biểu-đồ-tradingview] > 📍 Terminal · hàng giữa · Panel: **"Biểu đồ giao dịch"** Biểu đồ nến chuyên nghiệp với kho chỉ báo & công cụ vẽ đầy đủ của TradingView, nhận **dữ liệu giá realtime** trong phiên. Dùng để xem xu hướng, kẻ trendline, thêm MA/RSI/MACD, đánh dấu vùng hỗ trợ/kháng cự. Biểu đồ TradingView trong terminal *Panel TradingView — nến + chỉ báo, có thể phủ overlay SMA tối ưu.* * Đổi **khung thời gian** (1 phút → 1 ngày → tuần) ngay trên biểu đồ. * Lưu bộ chỉ báo & bản vẽ theo template để dùng lại cho mọi mã. * Có thể phủ **SMA tối ưu** (xem [Bài 7](/webapp/co-phieu-ky-thuat)) lên nến để đối chiếu tín hiệu. ## Sổ lệnh — 3 bước giá mua/bán (Order book) [#sổ-lệnh--3-bước-giá-muabán-order-book] > 📍 Bảng Cổ phiếu · Tên widget: **"Sổ lệnh"** · ⭐ PRO · ⏱ realtime Hiển thị **3 mức giá tốt nhất** ở mỗi bên: bên **mua (Bid)** và bên **bán (Ask)**, cập nhật theo từng tick. Đây là "độ sâu" gần nhất của thị trường — cho biết áp lực cung-cầu ngay tại mức giá hiện tại. ĐẶT MUA (Bid) KL Giá 1 ▲ KL Giá 2 KL Giá 3 ĐẶT BÁN (Ask) Giá 1 ▼ KL Giá 2 KL Giá 3 KL Widget Sổ lệnh order book *Widget Sổ lệnh — 3 bước giá Bid (xanh) / Ask (đỏ) + thanh khối lượng tỷ lệ.* **Các thành phần:** * **Cột Giá & Khối lượng** ở mỗi bước. **Thanh khối lượng** chạy nền sau con số, dài theo tỷ lệ KL — Bid mọc từ phải, Ask mọc từ trái — để liếc nhanh bên nào "dày" hơn. * **Màu nhấp nháy** khi giá đổi: xanh (tăng), đỏ (giảm), vàng (tham chiếu). * **Đầu widget**: giá khớp gần nhất, giá tham chiếu (TC, vàng), thay đổi điểm & %. * **Chân widget**: chênh lệch Bid–Ask (spread), tổng KL, giá cao/thấp/TB phiên, KL mua/bán của khối ngoại. **Bên Bid dày hơn hẳn Ask** = lực mua chờ lớn, giá khó giảm sâu (đỡ giá). Ngược lại Ask dày = áp lực bán treo nhiều, giá khó vượt. Nhưng cẩn thận lệnh "ảo" — đối chiếu với *bảng khớp lệnh* để xem lệnh nào thực sự được khớp. ## Bảng khớp lệnh realtime (Matched orders) [#bảng-khớp-lệnh-realtime-matched-orders] > 📍 Bảng Cổ phiếu · Tên widget: **"Khớp lệnh"** · ⏱ realtime Dòng chảy **từng lệnh khớp** theo thời gian thực: mỗi dòng là một giao dịch vừa khớp, mới nhất trên cùng. Danh sách được *ảo hóa* (virtualized) để chạy mượt dù có hàng nghìn lệnh trong phiên. | Cột | Ý nghĩa | | ------------- | ---------------------------------------------- | | **Thời gian** | Giờ khớp (HH:MM:SS) | | **Giá** | Giá khớp, tô màu theo so với tham chiếu | | **+/−** | Thay đổi điểm so với giá tham chiếu | | **KL** | Khối lượng khớp | | **M/B** | M = Mua chủ động · B = Bán chủ động · K = Khác | Widget Bảng khớp lệnh realtime *Widget Khớp lệnh — từng lệnh khớp realtime, lọc Mua/Bán & KL tối thiểu, tổng mua/bán chủ động ở chân bảng.* **Bộ lọc & điều khiển:** * **Chọn ngày**: xem realtime cho hôm nay, hoặc tải lại lịch sử khớp lệnh của một phiên quá khứ. * **Lọc chiều lệnh**: *Tất cả · Mua · Bán* — chỉ hiện lệnh mua chủ động hoặc bán chủ động. * **Lọc khối lượng** "KL ≥": ẩn lệnh nhỏ, chỉ xem lệnh lớn đáng chú ý. * **Cờ "Live"** (chấm xanh) báo dữ liệu đang chạy realtime; nhãn "Lịch sử" cho ngày quá khứ. Chân bảng hiển thị **tổng khối lượng Mua chủ động (xanh)** và **Bán chủ động (đỏ)** của cả phiên. Con số này được cộng dồn *độc lập* với danh sách hiển thị — kể cả khi bạn lọc hoặc danh sách ảo hóa không vẽ hết dòng, tổng vẫn đúng cho toàn phiên. So sánh hai tổng để biết phe nào đang chủ động áp đảo. ## Bước giá & Khối lượng (phân bố theo giá) [#bước-giá--khối-lượng-phân-bố-theo-giá] > 📍 Terminal · hàng trên · Panel: **"Bước giá & Khối lượng"** Biểu đồ thanh ngang cho biết **tại mỗi mức giá trong phiên đã khớp bao nhiêu khối lượng**, tách theo mua chủ động / bán chủ động / không xác định. ```text // Gom khối lượng khớp theo từng mức giá Mua chủ động (xanh) = Σ KL tại giá đó có BuySellActive = 2 Bán chủ động (đỏ) = Σ KL tại giá đó có BuySellActive = 1 Không xác định (xanh dương) = phần còn lại ``` Widget Bước giá khối lượng *Panel Bước giá & Khối lượng — thanh ngang phân bố KL theo từng mức giá, tách mua/bán chủ động.* * **Mức giá có thanh dài nhất** = vùng giao dịch tập trung nhất phiên — thường là vùng giá "đồng thuận", đóng vai trò hỗ trợ/kháng cự kỹ thuật. * Tại một mức giá mà **xanh (mua chủ động) áp đảo đỏ** → người mua sẵn sàng "với giá" để khớp, lực cầu thực. ## Bubble Volume — khối lượng theo thời gian [#bubble-volume--khối-lượng-theo-thời-gian] > 📍 Terminal · hàng trên · Panel: **"Bubble Volume"** Biểu đồ bong bóng theo trục thời gian trong phiên: mỗi chấm là một cụm giao dịch. Vị trí và kích thước cho biết **khi nào** và **mạnh đến đâu**. ```text // Tọa độ mỗi bong bóng x = thời điểm trong phiên (09:15–11:30, 13:00–15:00) y = khối lượng (mua chủ động dương, bán chủ động âm) kích thước = giá trị giao dịch (triệu đồng) ``` Widget Bubble Volume *Panel Bubble Volume — bong bóng mua (xanh, trên) / bán (đỏ, dưới) theo giờ. Chấm to = giá trị lớn.* * **Bong bóng xanh lớn đầu phiên** = lực mua mạnh xuất hiện sớm — thường định hình xu hướng ngày. * **Bong bóng đỏ lớn cuối phiên** (ATC) = áp lực bán/chốt lời cuối ngày, cần theo dõi phiên sau. * Hover vào bong bóng để xem giờ, khối lượng (KLGD) và giá trị (GTGD) chính xác. ## Kết hợp đọc terminal trong phiên [#kết-hợp-đọc-terminal-trong-phiên] **1) Xu hướng:** *TradingView* — giá đang ở vùng nào, phá vỡ hay tích lũy? **2) Cung-cầu tức thời:** *Sổ lệnh* — bên Bid hay Ask đang dày hơn? **3) Lệnh thật:** *Khớp lệnh* — tổng Mua chủ động vs Bán chủ động nghiêng về đâu? Có lệnh lớn nào không? **4) Bối cảnh phiên:** *Bước giá* + *Bubble Volume* — KL tập trung ở vùng giá nào, mạnh vào lúc nào? Tiếp theo: [Bài 6 — Dòng tiền theo mã](/webapp/co-phieu-dong-tien) để xem dòng tiền lũy kế & mua/bán chủ động của riêng mã, hoặc [Bài 7 — Kỹ thuật & mùa vụ](/webapp/co-phieu-ky-thuat). ## Bài liên quan [#bài-liên-quan] Lũy kế khối ngoại/cá nhân/tổ chức/tự doanh, mua-bán chủ động, so ngành. Trend MA, SMA tối ưu, Pivot, Risk Metrics, heatmap mùa vụ. Top ảnh hưởng, Relative Strength, top mua bán ròng, P/E loại trừ. ### Câu hỏi thường gặp **Xem sổ lệnh và bảng khớp lệnh cổ phiếu Việt Nam theo thời gian thực ở đâu?** Trading Terminal trên FinLens Web có widget Sổ lệnh hiển thị ba bước giá mua và ba bước giá bán tốt nhất cập nhật liên tục, cùng widget Khớp lệnh chạy bảng từng lệnh vừa khớp trong phiên. Cả hai chạy theo thời gian thực nên chỉ có dữ liệu đầy đủ cho ngày giao dịch hiện tại; chọn ngày quá khứ sẽ hiển thị bản ghi cuối ngày. Widget Sổ lệnh yêu cầu gói FinLens Pro. **Phân bố khối lượng theo giá cho biết điều gì?** Panel Bước giá và Khối lượng gom toàn bộ khối lượng khớp trong phiên theo từng mức giá, rồi tách làm ba phần: khối lượng mua chủ động, khối lượng bán chủ động, và phần không xác định được chiều. Nhờ vậy thấy được vùng giá nào tập trung nhiều giao dịch nhất và tại vùng đó bên mua hay bên bán chiếm ưu thế. Những vùng giá tích tụ khối lượng lớn thường trở thành mốc hỗ trợ hoặc kháng cự trong các phiên sau. **Bubble Volume trong biểu đồ nghĩa là gì?** Bubble Volume đặt mỗi giao dịch thành một bong bóng trên mặt phẳng thời gian và khối lượng. Trục ngang là thời điểm trong phiên, chạy từ 09:15 đến 11:30 và từ 13:00 đến 15:00. Trục dọc là khối lượng, trong đó mua chủ động vẽ về phía dương còn bán chủ động vẽ về phía âm. Kích thước bong bóng tỷ lệ với giá trị giao dịch tính bằng triệu đồng, nên một bong bóng lớn nằm lệch hẳn về một phía cho thấy lệnh lớn đang vào ở thời điểm đó. **Trading Terminal bố trí gồm những phần nào?** Trading Terminal chia màn hình theo hàng. Hàng trên đặt các panel phân tích khối lượng gồm Bước giá và Khối lượng cùng Bubble Volume. Hàng giữa là panel Biểu đồ giao dịch dựng trên nền TradingView với đầy đủ nến, chỉ báo và công cụ vẽ. Sổ lệnh cùng bảng Khớp lệnh nằm ở khu vực riêng để theo dõi cung cầu theo thời gian thực, còn cạnh phải có thể đặt thêm widget Chỉ số rủi ro. --- # Hướng dẫn dùng FinLens Web — phân tích cổ phiếu Việt Nam URL: https://docs.finlens.vn/webapp Mô tả: Cách dùng nền tảng finlens.vn: sắp xếp widget trên Dashboard, đọc độ rộng thị trường, dòng tiền nhóm nhà đầu tư, kỹ thuật, báo cáo tài chính và bộ lọc cổ phiếu. Tóm tắt: FinLens Web tại finlens.vn là nền tảng phân tích chứng khoán Việt Nam chạy trên trình duyệt, dựng theo mô hình bàn làm việc gồm nhiều widget người dùng tự kéo thả và sắp xếp. Bộ tài liệu gồm 10 bài hướng dẫn theo chủ đề: thao tác Dashboard cơ bản; ba nhóm widget thị trường gồm độ rộng MA và P/E VNINDEX, dòng tiền theo nhóm nhà đầu tư, xếp hạng RS và Relative Rotation Graph; bốn nhóm widget cổ phiếu gồm Trading Terminal với sổ lệnh ba bước giá, dòng tiền theo mã, chỉ báo kỹ thuật và thống kê mùa vụ, báo cáo tài chính TTM; cùng công cụ khuyến nghị đồng thuận của công ty chứng khoán và bộ lọc Screener. Dữ liệu phủ các sàn HOSE, HNX và UPCOM. Sản phẩm: webapp FinLens Web tại [finlens.vn](https://finlens.vn) là một **bàn làm việc** gồm nhiều ô (widget) bạn tự sắp xếp — giống nhiều cửa sổ trên một màn hình. Mỗi widget hiển thị một loại thông tin: biểu đồ, bảng số liệu hay sổ lệnh. Đọc bài [Tổng quan Dashboard](/webapp/bat-dau) trước để nắm bố cục, cách thêm widget và đồng bộ mã — nền tảng cho mọi bài còn lại. ## Bắt đầu [#bắt-đầu] Bài 1 · Bắt đầu — Bố cục bàn làm việc, thanh tiêu đề, thêm/di chuyển/phóng to widget, lưu bố cục bằng Workspace. ## Nhóm widget thị trường [#nhóm-widget-thị-trường] Bài 2 — Tổng quan chỉ số, động lượng MA, P/E VNINDEX và bộ độ rộng thị trường (MA / RSI / tăng-giảm). Bài 3 — Dòng tiền ròng chỉ số/ngành, khối ngoại, dòng tiền Shark, phân loại nhà đầu tư, thanh khoản lũy kế trong phiên. Bài 4 — Top ảnh hưởng chỉ số, Top 20 RS, top mua bán ròng, RRG, P/E loại trừ. ## Nhóm widget cổ phiếu [#nhóm-widget-cổ-phiếu] Bài 5 — Bố cục terminal, biểu đồ TradingView, sổ lệnh 3 bước giá, bảng khớp lệnh thời gian thực, bubble volume. Bài 6 — Dòng tiền lũy kế theo nhóm nhà đầu tư, mua/bán chủ động, so sánh dòng tiền của mã với ngành. Bài 7 — Trend MA, SMA tối ưu, Pivot Points, Risk Metrics, heatmap lợi nhuận tháng, xác suất tăng theo ngày. Bài 8 — Kết quả kinh doanh (kể cả TTM), cân đối kế toán, lưu chuyển tiền tệ, cổ tức qua các năm, sự kiện doanh nghiệp. ## Công cụ [#công-cụ] Bài 9 — Tổng quan Investment Ideas, phân bổ khuyến nghị, vùng giá mục tiêu, báo cáo công ty chứng khoán, tin tức thị trường. Bài 10 — Tạo và quản lý danh mục theo dõi, lọc cổ phiếu theo tiêu chí, nối kết quả lọc vào các widget khác. Giá cổ phiếu và chỉ số hiển thị ở đơn vị **nghìn đồng** (23.4 nghĩa là 23.400 VND). Chi tiết tại [Quy ước dữ liệu FinLens](/platform). ## Muốn hỏi thay vì bấm? [#muốn-hỏi-thay-vì-bấm] Cùng bộ dữ liệu đằng sau các widget này còn truy vấn được bằng câu hỏi tiếng Việt, qua [FinLens MCP](/mcp) — máy chủ Model Context Protocol nối Claude, ChatGPT và Gemini vào dữ liệu chứng khoán Việt Nam. Hợp khi bạn cần một câu trả lời tổng hợp từ nhiều widget cùng lúc, hoặc muốn AI đọc giúp báo cáo tài chính. Lập trình viên cần dữ liệu thô để tự tính thì dùng [thư viện Python `finlens`](/python-sdk). ### Câu hỏi thường gặp **Có phần mềm nào xem dòng tiền và độ rộng thị trường chứng khoán Việt Nam không?** FinLens Web tại finlens.vn cung cấp các widget đọc dòng tiền và độ rộng thị trường ngay trên trình duyệt, không cần cài đặt. Nhóm widget thị trường gồm Độ rộng MA thị trường đo tỷ lệ cổ phiếu đứng trên MA20/50/100/200, Dòng tiền ròng chỉ số tách theo khối ngoại và nhà đầu tư trong nước, Dòng tiền Shark lọc các lệnh lớn mua bán chủ động trong phiên, cùng Top mua bán ròng và Relative Rotation Graph để tìm nhóm ngành dẫn dắt. **Dashboard của FinLens Web hoạt động thế nào?** Dashboard là một bàn làm việc gồm nhiều ô gọi là widget, mỗi ô hiển thị một biểu đồ, bảng số liệu hoặc sổ lệnh. Người dùng kéo thả để sắp xếp, tách ô để đặt hai widget cạnh nhau so sánh, hoặc phóng to một widget ra toàn màn hình. Thanh tiêu đề điều khiển chung cho mọi widget bên dưới: đổi mã cổ phiếu một lần thì toàn bộ widget gắn theo mã cùng nhảy sang mã mới, chọn ngày một lần thì các widget theo ngày cùng cập nhật. **Nên đọc bài hướng dẫn FinLens Web nào trước?** Bộ tài liệu FinLens Web có 10 bài xếp từ cơ bản đến chuyên sâu. Người mới nên đọc bài Tổng quan Dashboard tại /webapp/bat-dau để nắm bố cục và cách đồng bộ mã cùng ngày, sau đó sang bài độ rộng thị trường tại /webapp/thi-truong-tong-quan. Người giao dịch theo từng mã có thể nhảy thẳng tới Trading Terminal tại /webapp/co-phieu-terminal, còn người cần lọc cổ phiếu thì đọc /webapp/watchlist-screener. **FinLens Web khác gì so với FinLens MCP và thư viện Python?** Ba sản phẩm dùng chung nguồn dữ liệu nhưng khác cách truy cập. FinLens Web hợp khi cần nhìn biểu đồ và bảng giá trực quan trên trình duyệt. FinLens MCP tại /mcp hợp khi muốn hỏi Claude, ChatGPT hoặc Gemini bằng câu tiếng Việt và nhận câu trả lời tổng hợp từ nhiều nguồn cùng lúc. Thư viện Python tại /python-sdk hợp khi cần lấy dữ liệu thô về pandas DataFrame để tự tính toán hoặc dựng mô hình. --- # Khuyến nghị đồng thuận CTCK và giá mục tiêu cổ phiếu URL: https://docs.finlens.vn/webapp/khuyen-nghi Mô tả: Xem đồng thuận của các công ty chứng khoán cho từng mã trên FinLens: phân bổ Mua Nắm giữ Bán, giá mục tiêu bình quân theo trọng số thời gian và kỳ vọng tăng giá. Tóm tắt: Nhóm widget khuyến nghị của FinLens Web tổng hợp báo cáo phân tích của nhiều công ty chứng khoán thành một góc nhìn đồng thuận cho từng cổ phiếu. Widget Phân bổ khuyến nghị đếm số báo cáo theo từng mức và lấy nhóm nhiều nhất làm đồng thuận, khi hòa thì ưu tiên theo thứ tự Mua trước Nắm giữ rồi Theo dõi. Widget Vùng giá mục tiêu tính bình quân có trọng số theo độ mới của báo cáo, với trọng số bằng một chia cho một cộng số ngày kể từ ngày công bố, nên báo cáo mới ảnh hưởng nhiều hơn báo cáo cũ. Kỳ vọng tăng giá tính bằng giá mục tiêu đồng thuận chia giá hiện tại trừ một rồi nhân một trăm. Widget Danh sách báo cáo và Top khuyến nghị toàn thị trường bổ sung phần tra cứu. Các widget này yêu cầu gói Premium. Sản phẩm: webapp ⏱ Đọc 11 phút · 🟡 Trung cấp · 📍 Bảng Cổ phiếu & Thị trường Cụm Investment Ideas (cho một mã) nằm ở **Bảng Cổ phiếu**; **Top khuyến nghị** (xếp hạng nhiều mã) nằm ở **Bảng Thị trường**. Tin tức & báo cáo xuất hiện ở cả hai dạng panel cạnh viền. Tất cả mức khuyến nghị & giá mục tiêu trong các widget này đến từ **báo cáo của các CTCK**, được FinLens tổng hợp lại — *không phải* khuyến nghị của FinLens. Hãy xem như một nguồn tham khảo, đối chiếu với phân tích của riêng bạn. ## Tổng quan Investment Ideas [#tổng-quan-investment-ideas] > 📍 Bảng Cổ phiếu · Tên widget: **"Tổng quan Investment Ideas"** · PREMIUM Thẻ tóm tắt nhanh "phán quyết" của giới phân tích về mã, gồm khuyến nghị đồng thuận, số CTCK theo dõi, số báo cáo, ngày cập nhật, và 3 ô số liệu chính: | Ô số liệu | Ý nghĩa | | --------------------------- | --------------------------------------------------------------- | | **Giá hiện tại** | Giá & % thay đổi (tô xanh/đỏ) | | **Giá mục tiêu đồng thuận** | Giá mục tiêu bình quân + **Upside kỳ vọng** (% so giá hiện tại) | | **Vùng mục tiêu** | Khoảng thấp – cao của giá mục tiêu + số báo cáo gần nhất | *Widget Tổng quan Investment Ideas — đồng thuận, giá mục tiêu, upside & vùng mục tiêu.* ## Phân bổ khuyến nghị [#phân-bổ-khuyến-nghị] > 📍 Bảng Cổ phiếu · Tên widget: **"Phân bổ khuyến nghị"** · PREMIUM FinLens chuẩn hóa muôn vàn cách diễn đạt của các CTCK về **4 nhóm** rồi đếm số báo cáo mỗi nhóm, thể hiện bằng thanh tỷ lệ: | Nhóm | Gồm các cách diễn đạt | | -------- | ------------------------------------------------------------------------------------- | | Mua | Mua, Tăng tỷ trọng, Tích lũy, Khả quan, Buy, Add, Accumulate, Overweight, Outperform… | | Nắm giữ | Giữ, Nắm giữ, Trung lập, Duy trì, Hold, Neutral, Maintain… | | Theo dõi | Theo dõi, Không xác định, No rating, Under review… | | Khác | Các diễn đạt còn lại | ```text // Đồng thuận = nhóm có nhiều báo cáo nhất Consensus = nhóm có count lớn nhất // Hòa → ưu tiên: Mua > Nắm giữ > Theo dõi > Khác ``` Widget Phân bổ khuyến nghị *Widget Phân bổ khuyến nghị — thanh tỷ lệ Mua/Nắm giữ/Theo dõi/Khác, bấm để lọc danh sách báo cáo.* Bấm vào một nhóm (vd "Mua") sẽ **lọc danh sách báo cáo** ở widget bên dưới chỉ còn các báo cáo nhóm đó — tiện khi muốn đọc lý do của riêng phe Mua hoặc phe Nắm giữ. ## Vùng giá mục tiêu [#vùng-giá-mục-tiêu] > 📍 Bảng Cổ phiếu · Tên widget: **"Vùng giá mục tiêu"** · PREMIUM Biểu đồ thanh ngang thể hiện **dải giá mục tiêu** (thấp → cao) mà các CTCK đưa ra, kèm 2 dấu mốc: **giá hiện tại** (chấm đỏ) và **giá mục tiêu đồng thuận** (kim cương xanh). Giá mục tiêu đồng thuận **không phải trung bình đơn giản** — báo cáo càng mới càng có trọng số cao (giảm dần theo số ngày): ```text // Trọng số mỗi báo cáo theo độ "mới" weight = 1 / (1 + số_ngày_kể_từ_công_bố) Giá mục tiêu đồng thuận = Σ(target × weight) / Σ(weight) // Kỳ vọng tăng giá Upside (%) = (Giá mục tiêu đồng thuận / Giá hiện tại − 1) × 100 ``` Widget Vùng giá mục tiêu *Widget Vùng giá mục tiêu — dải thấp–cao, chấm đỏ (giá hiện tại), kim cương xanh (đồng thuận).* **Giá hiện tại nằm dưới đầu thấp của dải** → đa số CTCK thấy còn dư địa tăng. **Giá hiện tại vượt đầu cao** → thị trường đã vượt kỳ vọng phân tích, cần thận trọng. Dải càng *hẹp* = các CTCK càng đồng thuận. ## Danh sách báo cáo CTCK [#danh-sách-báo-cáo-ctck] > 📍 Bảng Cổ phiếu · Tên widget: **"Danh sách báo cáo"** · PREMIUM Danh sách từng báo cáo phân tích về mã, mỗi thẻ gồm: **tên CTCK**, **tiêu đề**, **nhãn khuyến nghị** (màu theo nhóm), **ngày công bố**, **giá mục tiêu** và đoạn tóm tắt. Bấm "Xem chi tiết" để mở toàn văn. Widget Danh sách báo cáo CTCK *Widget Danh sách báo cáo — thẻ báo cáo theo CTCK, nhãn khuyến nghị & giá mục tiêu, mở toàn văn.* Danh sách này **đồng bộ với bộ lọc** ở widget "Phân bổ khuyến nghị": chọn nhóm Mua/Nắm giữ/… ở trên sẽ thu hẹp danh sách tương ứng. Panel **"Báo cáo phân tích"** cạnh viền còn cho tìm báo cáo theo mã CK bất kỳ. ## Top khuyến nghị toàn thị trường [#top-khuyến-nghị-toàn-thị-trường] > 📍 Bảng Thị trường · Tên widget: **"Top khuyến nghị"** Bảng xếp hạng **các mã được khuyến nghị Mua nhiều nhất** trong một khoảng thời gian, tổng hợp từ báo cáo của tất cả CTCK. Bộ lọc: **cửa sổ thời gian** (30/60/90/180/365 ngày), **số mã** (20/50/100), ngày chốt (As of) và mã ngành ICB. | Cột | Ý nghĩa | | ----------------------------- | ------------------------------------------------------------- | | **Rank / Ticker / Ngành** | Hạng, mã, ngành ICB | | **Khuyến nghị** | "MUA" hoặc **"MUA mạnh"** (khi ≥3 CTCK & ≥3 báo cáo Mua) | | **Số khuyến nghị mua** | Số báo cáo Mua trong cửa sổ | | **Số CTCK** | Số công ty chứng khoán khác nhau cùng khuyến nghị | | **Giá hiện tại / Target Avg** | Giá hiện tại & giá mục tiêu bình quân | | **Upside (%)** | (Target Avg / Giá hiện tại − 1) × 100 | | **Báo cáo mới nhất** | Ngày báo cáo gần nhất | Widget Top khuyến nghị thị trường *Widget Top khuyến nghị — xếp hạng mã được Mua nhiều nhất, kèm số CTCK, target & upside.* "**MUA mạnh**" (nhiều CTCK đồng loạt khuyến nghị) đáng chú ý hơn một báo cáo lẻ. Nhưng **upside cao** đôi khi do giá đã giảm sâu hoặc giá mục tiêu cũ chưa cập nhật — luôn xem *"Báo cáo mới nhất"* để biết khuyến nghị còn "tươi" không. ## Tin tức & báo cáo (panel cạnh viền) [#tin-tức--báo-cáo-panel-cạnh-viền] > 📍 Bảng Cổ phiếu & Thị trường · Panel: **"Tin tức thị trường"**, **"Báo cáo phân tích"** Dòng tin cuộn vô hạn, tự làm mới \~5 phút/lần, hiển thị thời gian tương đối (vd "5m", "2h", "1d", "Vừa xong"). Bấm một tin để mở toàn văn. * **Tin tức thị trường** — tổng hợp tin từ nhiều nguồn, lọc theo chủ đề/nguồn/thẻ (tag mã). * **Báo cáo phân tích** — danh sách báo cáo CTCK, **tìm theo mã CK**, đánh dấu 🔥 báo cáo "hot", mở xem PDF. Panel Tin tức và Báo cáo *Panel Tin tức thị trường & Báo cáo phân tích — cuộn vô hạn, tự làm mới, mở toàn văn/PDF.* ## Kết hợp & lưu ý chung [#kết-hợp--lưu-ý-chung] **1) Bức tranh nhanh:** *Tổng quan* + *Phân bổ* — đồng thuận đang nghiêng đâu? **2) Định giá:** *Vùng giá mục tiêu* — còn dư địa tăng (upside) không? **3) Lý do:** *Danh sách báo cáo* — đọc luận điểm gốc của CTCK. **4) Toàn cục:** *Top khuyến nghị* — mã của bạn có lọt nhóm được ưa thích? **5) Bối cảnh:** *Tin tức* để bắt sự kiện mới có thể làm khuyến nghị lỗi thời. Đối chiếu với [tài chính (Bài 8)](/webapp/co-phieu-tai-chinh) & [kỹ thuật (Bài 7)](/webapp/co-phieu-ky-thuat) trước khi quyết định. Bài cuối của loạt: [Bài 10 — Watchlist & Bộ lọc cổ phiếu (Screener)](/webapp/watchlist-screener) — tạo danh mục theo dõi & lọc mã theo tiêu chí. Hoặc quay lại [trang mục lục](/webapp). ## Bài liên quan [#bài-liên-quan] Tạo danh mục theo dõi & lọc cổ phiếu theo tiêu chí. KQKD (TTM), cân đối kế toán, lưu chuyển tiền tệ, cổ tức, sự kiện. Trend MA, SMA tối ưu, Pivot, Risk Metrics, heatmap mùa vụ. ### Câu hỏi thường gặp **Giá mục tiêu đồng thuận của một cổ phiếu được tính thế nào?** FinLens không lấy trung bình đơn thuần mà dùng bình quân có trọng số theo độ mới của báo cáo. Trọng số của mỗi báo cáo bằng một chia cho một cộng số ngày kể từ ngày công bố, nên báo cáo vừa ra có ảnh hưởng lớn hơn hẳn báo cáo từ nhiều tháng trước. Giá mục tiêu đồng thuận là tổng của giá mục tiêu nhân trọng số, chia cho tổng trọng số. Cách này tránh việc một khuyến nghị cũ đã lỗi thời vẫn kéo lệch con số chung. **Upside của cổ phiếu nghĩa là gì?** Upside là mức kỳ vọng tăng giá, tính bằng giá mục tiêu đồng thuận chia cho giá hiện tại, trừ một rồi nhân một trăm để ra phần trăm. Con số này cho biết theo đánh giá chung của các công ty chứng khoán thì cổ phiếu còn dư địa tăng bao nhiêu so với thị giá. Cần đọc kèm số lượng báo cáo tạo nên đồng thuận đó, vì upside cao dựa trên một hai báo cáo có độ tin cậy khác hẳn upside dựa trên nhiều báo cáo cùng chiều. **Khi các công ty chứng khoán không thống nhất thì đồng thuận xác định ra sao?** Widget Phân bổ khuyến nghị đếm số báo cáo rơi vào từng mức rồi lấy nhóm có số lượng lớn nhất làm mức đồng thuận. Trường hợp hai nhóm bằng nhau, thứ tự ưu tiên được áp dụng là Mua trước, rồi Nắm giữ, rồi Theo dõi, cuối cùng là các mức khác. Biểu đồ phân bổ vẫn hiển thị đầy đủ số lượng từng nhóm nên người đọc thấy được mức độ đồng thuận là áp đảo hay chỉ nhỉnh hơn chút ít. **Tìm cổ phiếu được nhiều công ty chứng khoán khuyến nghị mua ở đâu?** Widget Top khuyến nghị nằm trên Bảng Thị trường xếp hạng các mã theo mức độ được khuyến nghị trên toàn thị trường, thay vì chỉ xem từng mã một. Đi kèm là widget Danh sách báo cáo liệt kê các báo cáo phân tích của từng mã, và panel Báo cáo phân tích cùng Tin tức thị trường đặt cạnh viền màn hình để theo dõi liên tục. Nhóm widget khuyến nghị yêu cầu gói FinLens Premium. --- # Dòng tiền chứng khoán: khối ngoại, tự doanh và lệnh lớn URL: https://docs.finlens.vn/webapp/thi-truong-dong-tien Mô tả: Cách đọc dòng tiền thị trường trên FinLens: khối ngoại và tự doanh lũy kế theo ngành, dòng tiền Shark lọc lệnh lớn, mua bán chủ động và thanh khoản trong phiên. Tóm tắt: Nhóm widget dòng tiền của FinLens Web cho biết ai đang mua và ai đang bán trên thị trường chứng khoán Việt Nam. Widget Dòng tiền ròng chỉ số tách giá trị mua trừ bán theo từng nhóm nhà đầu tư gồm khối ngoại, cá nhân trong nước và tổ chức trong nước, rồi cộng dồn qua khoảng thời gian đã chọn. Widget Dòng tiền ròng ngành đo mua bán chủ động theo ngành, trong đó lệnh khớp ở giá bên bán tính là mua chủ động còn khớp ở giá bên mua tính là bán chủ động. Widget Dòng tiền Shark lọc riêng các lệnh có giá trị đơn lẻ vượt ngưỡng người dùng đặt. Widget Thanh khoản lũy kế cộng dồn giá trị ròng từng tick từ đầu phiên và hiển thị ba đường VNINDEX, VN30 và MidCap bằng hiệu của hai chỉ số đó. Đơn vị quy về tỷ đồng. Sản phẩm: webapp ⏱ Đọc 12 phút · 🟡 Trung cấp · 📍 Bảng Thị trường Tất cả widget trong bài nằm ở **Bảng Thị trường**. Nếu chưa thấy, bấm `Kho Widgets` trên thanh tiêu đề và thêm theo tên. Phần lớn widget dòng tiền **đồng bộ ngày** với thanh điều khiển trên dashboard — thay ngày ở trên, tất cả cập nhật cùng lúc. ## Dòng tiền ròng chỉ số [#dòng-tiền-ròng-chỉ-số] > 📍 Bảng Thị trường · Tên widget: **"Dòng tiền ròng chỉ số"** Biểu đồ **thanh + đường lũy kế** cho thấy từng ngày mỗi nhóm nhà đầu tư mua ròng hay bán ròng bao nhiêu tỷ đồng trên toàn VNINDEX, và đường lũy kế tích lũy qua khoảng thời gian bạn chọn. Dữ liệu lấy từ bảng giao dịch nhà đầu tư theo ngày (*eod\_investor\_trades\_vnindex\_daily\_agg*). Ba nhóm được theo dõi: | Nhóm | Ký hiệu | Ý nghĩa | | ---------------------- | ------------------ | ------------------------------------------------------------------ | | **Khối ngoại** | foreign | Mọi tổ chức và cá nhân nước ngoài giao dịch trên sàn Việt Nam | | **Cá nhân trong nước** | localIndividual | Nhà đầu tư cá nhân Việt Nam — chiếm phần lớn khối lượng thị trường | | **Tổ chức trong nước** | localInstitutional | Quỹ nội, công ty bảo hiểm, quỹ hưu trí trong nước | ```text // Dòng tiền ròng mỗi ngày, quy về tỷ đồng netForeign[t] = foreignBuyValue[t] − foreignSellValue[t] netLocalIndividual[t] = localIndividualBuyValue[t] − localIndividualSellValue[t] netLocalInstitutional[t]= localInstitutionalBuyValue[t] − localInstitutionalSellValue[t] // Lũy kế qua cả khoảng thời gian đã chọn cNetForeign = Σ netForeign cNetLocalIndividual = Σ netLocalIndividual cNetLocalInstitutional= Σ netLocalInstitutional ``` Widget Dòng tiền ròng chỉ số *Widget Dòng tiền ròng chỉ số — thanh ròng mỗi ngày và đường lũy kế theo nhóm NĐT.* **Cách đọc:** * **Thanh xanh** = ngày mua ròng (net dương); **thanh đỏ** = ngày bán ròng (net âm). * **Đường lũy kế** tăng dài hạn → nhóm đó đang tích lũy liên tục; đường giảm → nhóm đang rút vốn. * Cá nhân trong nước thường là bên *bán* khi khối ngoại mua mạnh, và ngược lại — đây là cơ chế cân bằng tự nhiên của thị trường. * Chọn khoảng thời gian dài (6 tháng–1 năm) để thấy xu hướng tích lũy/phân phối thực sự. Nhìn **đường lũy kế khối ngoại liên tục giảm** (bán ròng kéo dài) mà VNINDEX vẫn tăng → thị trường đang được nội lực nâng đỡ, không phụ thuộc dòng ngoại. Khi ngoại bắt đầu mua trở lại, sức bật thường rất mạnh. ## Dòng tiền ròng ngành (mua/bán chủ động) [#dòng-tiền-ròng-ngành-muabán-chủ-động] > 📍 Bảng Thị trường · Tên widget: **"Dòng tiền ròng ngành"** Biểu đồ **drilldown hình cột**: click vào một ngành → xem chi tiết từng cổ phiếu trong ngành đó. Dựa trên **mua/bán chủ động** (active buy/sell) — là các lệnh khớp với bên chủ động mua đẩy giá lên hoặc chủ động bán đẩy giá xuống. ```text // Dòng tiền ròng mua chủ động của ngành trong ngày netActive[ngành] = Σ value[BuySellActive=2] − Σ value[BuySellActive=1] // BuySellActive: 2 = mua chủ động (uptick), 1 = bán chủ động (downtick) // Đơn vị: tỷ đồng; dữ liệu lấy từ bảng nội ngày (intraday_icb_agg_daily) ``` Widget Dòng tiền ròng ngành *Widget Dòng tiền ròng ngành — click ngành để drilldown xuống cổ phiếu.* **Cách đọc:** * **Cột xanh cao** = ngành được bên mua chủ động dẫn dắt mạnh — tín hiệu tiền thực sự chảy vào, không chỉ bên bán rút đi. * **Drilldown**: nhấp vào ngành → thấy mã nào đang kéo toàn ngành lên hoặc xuống. Hữu ích để tách "con tàu cả ngành tăng" vs "1-2 bluechip kéo điểm". * Widget này dùng ngày giao dịch đơn lẻ (không phải khoảng). Chuyển ngày để so sánh các phiên liền nhau. **Mua/bán chủ động** khác với mua/bán ròng theo nhóm NĐT: chủ động phản ánh *ai khởi xướng giao dịch* (đặt lệnh thị trường / lệnh tốt hơn spread), không phân biệt người đó là ngoại hay nội. Đây là thước đo áp lực cung-cầu thực sự trên thị trường. ## Khối ngoại theo ngành [#khối-ngoại-theo-ngành] > 📍 Bảng Thị trường · Tên widget: **"Khối ngoại ngành"** Tương tự widget trên nhưng chỉ tính **riêng khối ngoại**: mua ròng hay bán ròng của tổ chức/cá nhân nước ngoài tại từng ngành, với drilldown xuống mã cụ thể. ```text // Dòng tiền ròng khối ngoại theo ngành, tỷ đồng netForeign[ngành] = buyForeignValue − sellForeignValue // Nguồn: bảng EOD ngành (eod_icb_agg_v1), chia 10⁹ → tỷ đồng ``` Widget Khối ngoại theo ngành *Widget Khối ngoại ngành — mua/bán ròng ngoại từng ngành, click để xem cổ phiếu.* * **Ngành ngoại mua ròng mạnh liên tục** (nhiều ngày xanh khi lướt qua các ngày) → có thể là ngành đang được định hướng đầu tư quốc tế ưa thích. * So sánh với *Dòng tiền ròng ngành* (mua chủ động): nếu ngoại mua ròng nhưng mua chủ động toàn ngành âm → khả năng nội đang bán ra đối ứng, áp lực cung nội vẫn còn. * Drilldown: xem khối ngoại đang mua tập trung vào mã nào trong ngành đó. ## Giá vs Dòng tiền ngành (biểu đồ phân tán) [#giá-vs-dòng-tiền-ngành-biểu-đồ-phân-tán] > 📍 Bảng Thị trường · Tên widget: **"Giá vs Dòng tiền"** Biểu đồ phân tán **4 góc phần tư**: mỗi chấm là một ngành (*level 2 ICB*), đặt trên hai trục: * **Trục X (ngang)**: % thay đổi giá của ngành so với phiên trước — ngành tăng giá ở bên phải, giảm giá ở bên trái. * **Trục Y (dọc)**: dòng tiền ròng mua chủ động (net active value, tỷ đồng) — tiền chảy vào ở trên, chảy ra ở dưới. ↗ Mạnh nhất — Tích lũy Giá tăng + Tiền vào (net > 0). Xu hướng được xác nhận bởi dòng tiền. ↙ Phân kỳ — Quan sát Giá giảm + Tiền vào (net > 0). Có thể đang bị bán kỹ thuật trong khi "cá lớn" tích lũy. ↗ Phục hồi kỹ thuật Giá tăng + Tiền ra (net \< 0). Giá tăng nhưng bên bán vẫn chủ động — thận trọng, có thể chỉ bounce. ↘ Yếu nhất — Phân phối Giá giảm + Tiền ra (net \< 0). Bên bán áp đảo hoàn toàn — tránh hoặc chờ đáy. Widget Giá vs Dòng tiền *Widget Giá vs Dòng tiền ngành — 4 góc phần tư phân loại sức mạnh ngành.* Widget này dùng **dữ liệu ngày đơn lẻ** (phiên hiện tại hoặc ngày được chọn). Một phiên không phản ánh xu hướng — kết hợp với biểu đồ dòng tiền nhiều ngày để xác nhận. Ngành ở góc "tích lũy" 3–5 ngày liên tiếp mới thực sự đáng chú ý. ## Thanh khoản lũy kế mua/bán chủ động (trong phiên) [#thanh-khoản-lũy-kế-muabán-chủ-động-trong-phiên] > 📍 Bảng Thị trường · Tên widget: **"Thanh khoản lũy kế"** · ⏱ trong phiên Theo dõi **theo thời gian thực** từng phút trong phiên: dòng tiền ròng mua chủ động của VNINDEX, VN30 và MidCap tích lũy từ đầu phiên đến thời điểm hiện tại. ```text // Mỗi tick trong phiên net_value[t] = buy_value[t] − sell_value[t] // Lũy kế từ đầu phiên cValue[T] = Σ net_value[t] , t ∈ [09:00 → T] // Hiển thị 3 đường: VNINDEX · VN30 · MidCap (= VNINDEX − VN30) ``` Widget Thanh khoản lũy kế intraday *Widget Thanh khoản lũy kế — đường lũy kế ròng VNINDEX, VN30, MidCap trong phiên.* **Cách đọc:** * **Đường lũy kế dốc lên** = tiền mua chủ động liên tục áp đảo — phiên có bên mua dẫn dắt. * **Đường phẳng hoặc lắc ngang** = cung cầu cân bằng, chờ phá vỡ. * **VN30 tích lũy dương mạnh, MidCap âm** → tiền tập trung vào bluechip, hàng vừa bị bỏ lại — phiên "chọn lọc". * **MidCap tích lũy dương hơn VN30** → dòng tiền lan rộng ra midcap, thường là tín hiệu phiên tốt theo chiều rộng. * Khi đường lũy kế **đột ngột dốc xuống gần cuối phiên** (ATC) → áp lực bán cuối phiên mạnh, cần theo dõi sang phiên sau. VNINDEX + VN30 + MidCap *cùng* dốc lên từ đầu phiên, không có đảo chiều lớn → bên mua kiểm soát hoàn toàn, phiên "sạch". Ngược lại, lũy kế liên tục lắc + âm → tránh giao dịch đuổi giá trong ngày. ## Dòng tiền Shark (lệnh lớn mua/bán chủ động) [#dòng-tiền-shark-lệnh-lớn-muabán-chủ-động] > 📍 Bảng Thị trường · Tên widget: **"Dòng tiền Shark"** · ⏱ trong phiên Biểu đồ **bong bóng theo thời gian**: mỗi chấm là một lệnh khớp có giá trị từ ngưỡng bạn đặt trở lên (mặc định 500 triệu hoặc 1 tỷ đồng/lệnh). Chấm xanh = lệnh mua chủ động lớn; chấm đỏ = lệnh bán chủ động lớn. ```text // Lọc lệnh "Shark" — lệnh có giá trị đơn lẻ ≥ ngưỡng Điều kiện: value ≥ start_value AND BuySellActive ≠ 3 // Tọa độ mỗi chấm x = thời điểm khớp lệnh (trong phiên) y = khối lượng lệnh (cổ phiếu) z = giá trị lệnh (VND) → kích thước bong bóng ``` Widget Dòng tiền Shark *Widget Dòng tiền Shark — bong bóng mua (xanh) / bán (đỏ) theo giờ trong phiên. Chấm càng to = giá trị càng lớn.* **Cách đọc:** * **Cụm chấm xanh to xuất hiện sớm trong phiên** (9:00–10:30) → "tay to" đặt lệnh mua đầu phiên, thường tự tin về xu hướng ngày. * **Chấm đỏ lớn gần cuối phiên** (AMP, ATC) → cảnh báo bán tháo hoặc phân phối, cần theo dõi kỹ. * **Điều chỉnh ngưỡng**: tăng ngưỡng (vd 2 tỷ) để chỉ xem lệnh "mega" — ít điểm hơn nhưng rõ tín hiệu "cá mập" thực sự. * Hover vào chấm để xem **tên mã, thời điểm, khối lượng, và giá trị lệnh** chính xác. Lệnh "Shark" chỉ là lệnh khớp đơn lẻ giá trị lớn — có thể từ nhiều nguồn: quỹ, tự doanh, cá nhân giàu, hay thậm chí thuật toán chia nhỏ sau đó chạy nhanh. Quan trọng là *cụm* lệnh, không phải lệnh đơn lẻ. Nhiều chấm xanh lớn trải đều cả phiên đáng tin hơn 1 chấm to duy nhất. ## Phân loại NĐT theo ngành (Tự doanh & Nước ngoài lũy kế) [#phân-loại-nđt-theo-ngành-tự-doanh--nước-ngoài-lũy-kế] > 📍 Bảng Thị trường · Tên widget: **"Dòng tiền phân loại NĐT"** Hai biểu đồ song song theo dõi **lũy kế dòng tiền qua nhiều ngày** của *Tự doanh* (proprietary trading) và *Nước ngoài* tại một ngành cụ thể, kết hợp với đường giá để phát hiện phân kỳ. ### Dòng tiền Tự doanh lũy kế (cumProps) [#dòng-tiền-tự-doanh-lũy-kế-cumprops] ```text // Tự doanh: lấy từ bảng AggTdByIcbDaily theo mã ICB ngành NetValue_TD[t] = buy_value[t] − sell_value[t] cumulativeNetTD = Σ NetValue_TD (lũy kế từ ngày bắt đầu) cumulativeBuyValueTD = Σ buy_value cumulativeSellValueTD = Σ sell_value ``` Widget Tự doanh lũy kế *Widget Tự doanh lũy kế — dòng tiền tự doanh tích lũy + đường giá ngành.* ### Dòng tiền Nước ngoài lũy kế (cumForeign) [#dòng-tiền-nước-ngoài-lũy-kế-cumforeign] ```text // Ngoại: lấy từ bảng eod_icb_agg_v1 theo mã ICB ngành netForeign[t] = buyForeignValue[t] − sellForeignValue[t] cumulativeNetForeign = Σ netForeign (lũy kế từ ngày bắt đầu) cumulativeBuyForeignValue = Σ buyForeignValue cumulativeSellForeignValue = Σ sellForeignValue ``` Widget Nước ngoài lũy kế *Widget Nước ngoài lũy kế — dòng tiền ngoại tích lũy + đường giá ngành.* **Cách đọc chung cho cả hai:** * **Đường giá tăng, đường lũy kế cũng tăng** → xu hướng được xác nhận — tự doanh/ngoại đang mua cùng chiều với giá. * **Giá tăng nhưng lũy kế giảm (phân kỳ âm)** → nhóm NĐT này đang *bán ròng* dù giá đang lên — cảnh báo có thể sắp đảo chiều. * **Giá giảm nhưng lũy kế tăng (phân kỳ dương)** → nhóm NĐT này đang tích lũy trong khi giá điều chỉnh — có thể là cơ hội. * **Chọn ngành** bằng bộ lọc trong widget (ICB code). Nên chọn ngành bạn đang quan tâm, so sánh tự doanh vs ngoại cùng ngành để thấy ai đang "dẫn dắt" ai. **Tự doanh (proprietary)** là bộ phận giao dịch bằng vốn của chính công ty chứng khoán, không phải thay mặt khách hàng. Họ thường có thông tin tốt hơn, phản ứng nhanh hơn. Khi tự doanh và ngoại *cùng mua* một ngành kéo dài → tín hiệu tích lũy từ "bên thông tin tốt". ## Kết hợp đọc dòng tiền — Quy trình 5 bước [#kết-hợp-đọc-dòng-tiền--quy-trình-5-bước] **1) Bức tranh toàn cảnh:** Mở *Dòng tiền ròng chỉ số* — khối ngoại đang mua hay bán ròng tuần này? **2) Theo ngành:** Chuyển sang *Dòng tiền ròng ngành* — tiền chảy vào ngành nào mạnh nhất hôm nay? **3) Kiểm tra ngoại:** Trong các ngành đó, *khối ngoại* có cùng chiều không? Hay tiền nội đang dẫn dắt? **4) Xác nhận giá:** Mở *Giá vs Dòng tiền* — ngành có nằm ở góc "tích lũy" (giá tăng + tiền vào) không? **5) Trong phiên:** Theo dõi *Thanh khoản lũy kế* — tiền đang chảy ổn định hay đang thoái lui? Tiếp theo: [Bài 4 — Xếp hạng & RRG](/webapp/thi-truong-xep-hang) để tìm ngành và cổ phiếu dẫn dắt, hoặc quay lại [Bài 2 — Tổng quan & Độ rộng](/webapp/thi-truong-tong-quan) để kết hợp dòng tiền với breadth. ## Bài liên quan [#bài-liên-quan] Chỉ số, P/E, động lượng MA, breadth MA/RSI và tăng-giảm theo phiên. Top ảnh hưởng, Top 20 RS, Relative Rotation Graph — tìm nhóm dẫn dắt. Thêm widget, kéo-thả, đồng bộ mã & ngày, Workspace. ### Câu hỏi thường gặp **Mua chủ động và bán chủ động khác nhau thế nào?** Mua chủ động là lệnh khớp ở giá bên bán, tức người mua chấp nhận trả theo giá đang chào bán để được khớp ngay. Bán chủ động là lệnh khớp ở giá bên mua, tức người bán chấp nhận hạ xuống giá đang chờ mua. Chênh lệch giữa hai dòng này phản ánh bên nào đang sốt ruột hơn, nên được dùng làm thước đo áp lực thật trong phiên thay vì chỉ nhìn khối lượng tổng. FinLens tính dòng tiền ròng chủ động theo ngành bằng tổng giá trị mua chủ động trừ tổng giá trị bán chủ động. **Làm sao theo dõi lệnh lớn của tổ chức trong phiên?** Widget Dòng tiền Shark lọc riêng những lệnh có giá trị đơn lẻ vượt ngưỡng do người dùng đặt, đồng thời loại các lệnh không xác định chiều mua bán. Nhờ vậy có thể tách hành vi của lệnh lớn khỏi nhiễu của lệnh nhỏ lẻ, xem tiền lớn đang gom hay xả trong lúc phiên diễn ra. Đây là widget chạy trong phiên nên chỉ có dữ liệu thời gian thực cho ngày hiện tại; chọn ngày quá khứ sẽ hiển thị bản ghi cuối ngày. **Xem khối ngoại mua bán ròng theo ngành ở đâu?** Widget Khối ngoại ngành tính giá trị mua trừ giá trị bán của nhà đầu tư nước ngoài cho từng ngành, lấy từ dữ liệu cuối ngày và quy về tỷ đồng. Đi kèm là widget Dòng tiền phân loại nhà đầu tư hiển thị dòng tiền tự doanh và nước ngoài lũy kế theo ngành, giúp thấy xu hướng tích lũy dài hơn thay vì biến động một phiên. Ghép với widget Giá vs Dòng tiền sẽ biết ngành nào tăng giá nhờ tiền vào thật và ngành nào tăng mà không có dòng tiền hậu thuẫn. **MidCap trong widget thanh khoản lũy kế được tính thế nào?** Widget Thanh khoản lũy kế cộng dồn giá trị ròng của từng tick từ đầu phiên và hiển thị ba đường. Đường MidCap không phải một chỉ số riêng mà được suy ra bằng cách lấy VNINDEX trừ VN30, tức phần thị trường nằm ngoài nhóm ba mươi mã vốn hóa lớn nhất. Cách tách này cho thấy dòng tiền đang tập trung vào nhóm trụ hay lan sang nhóm vốn hóa vừa và nhỏ, một tín hiệu thường đi trước sự luân chuyển của thị trường. --- # Độ rộng thị trường & P/E VNINDEX: đọc sức khỏe thật URL: https://docs.finlens.vn/webapp/thi-truong-tong-quan Mô tả: Chỉ số tăng chưa chắc thị trường khỏe. Cách đọc độ rộng MA, độ rộng RSI, tỷ lệ tăng giảm trong phiên và P/E VNINDEX để biết đà tăng có nội lực hay không. Tóm tắt: Nhóm widget Bảng Thị trường của FinLens Web trả lời câu hỏi thị trường có thực sự khỏe hay chỉ vài mã trụ kéo điểm. Widget Độ rộng MA thị trường tính tỷ lệ phần trăm cổ phiếu có giá đóng cửa nằm trên MA20, MA50, MA100 và MA200, vẽ kèm đường VNINDEX để phát hiện phân kỳ. Widget Độ rộng RSI đo tỷ lệ cổ phiếu có RSI từ 70 trở lên và từ 30 trở xuống mỗi ngày. Widget Độ rộng thị trường đếm số mã tăng giảm theo từng mốc 5 phút trong phiên theo công thức (số mã tăng trừ số mã giảm) chia tổng hai nhóm. Widget P/E VNINDEX lấy tổng vốn hóa chia tổng lợi nhuận ròng bốn quý gần nhất, còn Động lượng MA vẽ mỗi cổ phiếu thành một chấm theo phần trăm lệch MA và z-score. Sản phẩm: webapp ⏱ Đọc 10 phút · 🟢 Cơ bản – Trung cấp · 📍 Bảng Thị trường Tất cả widget trong bài nằm ở **Bảng Thị trường**. Nếu chưa thấy, bấm `Kho Widgets` trên thanh tiêu đề và thêm theo tên. Phần lớn widget tổng hợp **toàn thị trường** nên không phụ thuộc mã bạn chọn. ## Tổng quan chỉ số [#tổng-quan-chỉ-số] > 📍 Bảng Thị trường · Tên widget: **“Tổng quan chỉ số”** Thẻ nhanh cho các chỉ số chính (VNINDEX, VN30, HNX, UPCOM…): **giá trị hiện tại**, **thay đổi điểm & %** và một đường *sparkline* nhỏ thể hiện diễn biến gần đây. Đây là nơi liếc 2 giây để biết thị trường xanh hay đỏ. Widget Tổng quan chỉ số *Widget Tổng quan chỉ số — giá trị, thay đổi và sparkline từng chỉ số.* * **Màu xanh** = chỉ số tăng so với tham chiếu; **đỏ** = giảm; **vàng** = đứng giá. * **Sparkline** giúp phân biệt “tăng đều” với “giật cục” — cùng +0,5% nhưng hình dạng khác nhau kể câu chuyện khác nhau. ## Biểu đồ kỹ thuật (TradingView) [#biểu-đồ-kỹ-thuật-tradingview] > 📍 Bảng Thị trường · Tên widget: **“Biểu đồ kỹ thuật”** Biểu đồ nến đầy đủ cho chỉ số/cổ phiếu, với kho chỉ báo và công cụ vẽ của TradingView. Dùng để xem xu hướng, kẻ trendline, thêm MA/RSI/MACD… như một bảng giá chuyên nghiệp. Widget Biểu đồ kỹ thuật *Widget Biểu đồ kỹ thuật — nến + chỉ báo TradingView.* Đổi khung thời gian (1 phút → 1 ngày → 1 tuần) ngay trên biểu đồ. Phóng to widget `⛶` để có không gian vẽ thoải mái. ## Động lượng MA (biểu đồ phân tán) [#động-lượng-ma-biểu-đồ-phân-tán] > 📍 Bảng Thị trường · Tên widget: **“Động lượng MA”** Mỗi **chấm là một cổ phiếu**, đặt trên hai trục đo độ "căng" của giá so với đường trung bình động (MA) bạn chọn (MA20/50/200…): ```text // Trục X — giá đang lệch MA bao nhiêu % pct_change = (Giá đóng cửa − MA) / MA // Trục Y — độ lệch đó "bất thường" tới mức nào (số lần độ lệch chuẩn) z_score = (Giá đóng cửa − MA) / Độ lệch chuẩn (STD) ``` Widget Động lượng MA *Widget Động lượng MA — X: % lệch MA, Y: z-score. Chọn sàn & loại MA ở góc trên.* **Cách đọc:** * **Bên phải** (pct\_change > 0) = giá đang trên MA (xu hướng tăng ngắn hạn); **bên trái** = dưới MA. * **Càng lên cao** (z\_score lớn) = mức tăng càng *mạnh bất thường* so với dao động thường ngày — có thể quá mua; **càng xuống thấp** = quá bán. * Chọn **sàn** (HOSE/HNX/UPCOM) và **loại MA** ở góc trên để đổi “thước đo”. z-score chuẩn hóa theo độ biến động của từng mã, nên so sánh được giữa cổ phiếu “trầm” và cổ phiếu “nóng”. Một mã +5% nhưng z-score thấp có thể bình thường với nó; +2% nhưng z-score cao lại là động thái đáng chú ý. ## P/E VNINDEX — thị trường đang đắt hay rẻ? [#pe-vnindex--thị-trường-đang-đắt-hay-rẻ] > 📍 Bảng Thị trường · Tên widget: **“P/E VNINDEX”** Đường P/E của *toàn thị trường* theo thời gian, vẽ cạnh đường VNINDEX để bạn so định giá với giá. ```text // P/E toàn thị trường mỗi ngày P/E = Tổng vốn hóa thị trường / Tổng lợi nhuận ròng 4 quý gần nhất (TTM) ``` Widget P/E VNINDEX *Widget P/E VNINDEX — P/E toàn thị trường so với đường chỉ số.* * **P/E cao so với vùng lịch sử của chính nó** = thị trường đang được định giá đắt (kỳ vọng cao); **thấp** = rẻ tương đối. * Đừng đọc con số tuyệt đối một mình — hãy so với *dải dao động nhiều năm* ngay trên biểu đồ để biết đang ở mép trên hay mép dưới. P/E dùng lợi nhuận TTM (đã xảy ra), nên ở đáy khủng hoảng lợi nhuận sụt làm P/E *nhìn cao giả tạo*, và ở đỉnh chu kỳ lợi nhuận cao làm P/E *nhìn rẻ giả tạo*. Luôn đọc kèm bối cảnh chu kỳ. ## Độ rộng MA thị trường [#độ-rộng-ma-thị-trường] > 📍 Bảng Thị trường · Tên widget: **“Độ rộng MA thị trường”** Trả lời câu hỏi: **bao nhiêu % cổ phiếu đang đứng TRÊN đường trung bình động?** Bốn đường tương ứng MA20 / MA50 / MA100 / MA200, kèm đường VNINDEX để đối chiếu. ```text % trên MA(n) = (Số cổ phiếu có giá đóng cửa > MA(n)) / (Số cổ phiếu đủ điều kiện) × 100 ``` Widget Độ rộng MA thị trường *Widget Độ rộng MA — % cổ phiếu trên MA20/50/100/200 + VNINDEX.* * **MA20/50** = sức khỏe ngắn–trung hạn; **MA100/200** = xu hướng dài hạn. * **> 70–80%** trên MA = thị trường lan tỏa mạnh (đa số cổ phiếu tăng) — nhưng quá cao kéo dài dễ là vùng quá mua. **\< 20–30%** = bán tháo diện rộng, thường gần vùng quá bán. * **Phân kỳ cảnh báo:** VNINDEX lập đỉnh mới nhưng % trên MA *đi xuống* → đà tăng do vài mã lớn gánh, nội lực yếu dần. ## Độ rộng RSI thị trường [#độ-rộng-rsi-thị-trường] > 📍 Bảng Thị trường · Tên widget: **“Độ rộng RSI thị trường”** Đo mức độ **quá mua / quá bán trên diện rộng**: tỷ lệ cổ phiếu có RSI ≥ 70 (quá mua) và RSI ≤ 30 (quá bán) mỗi ngày. Widget Độ rộng RSI thị trường *Widget Độ rộng RSI — % cổ phiếu RSI ≥ 70 và ≤ 30.* * **% RSI ≥ 70 tăng vọt** = hưng phấn lan rộng — cẩn trọng nhịp điều chỉnh; **% RSI ≤ 30 tăng vọt** = hoảng loạn bán — thường gần đáy ngắn hạn. * Dùng như “nhiệt kế cảm xúc” bổ trợ cho độ rộng MA: MA cho biết *xu hướng*, RSI cho biết *mức căng cảm xúc*. ## Độ rộng thị trường (tăng – giảm trong phiên) [#độ-rộng-thị-trường-tăng--giảm-trong-phiên] > 📍 Bảng Thị trường · Tên widget: **“Độ rộng thị trường”** · ⏱ trong phiên Theo **từng mốc 5 phút** trong phiên, đếm số mã tăng / giảm / đứng giá của một sàn và quy về một chỉ số độ rộng dao động quanh 0: ```text Độ rộng = (Số mã tăng − Số mã giảm) / (Số mã tăng + Số mã giảm) ``` Widget Độ rộng thị trường *Widget Độ rộng thị trường — tăng/giảm theo 5 phút, chọn sàn HOSE/HNX/UPCOM.* * **> 0** = số mã tăng áp đảo (phiên tích cực); **\< 0** = bên giảm áp đảo. * **Chỉ số tăng nhưng độ rộng âm** = chỉ vài mã trụ kéo điểm, phần lớn cổ phiếu vẫn đỏ → “xanh vỏ đỏ lòng”, cần thận trọng. * Đây là widget **trong phiên**: dữ liệu thời gian thực cho ngày hiện tại; chọn ngày quá khứ để xem lại diễn biến phiên đó. ## Kết hợp 3 lớp để đọc “sức khỏe thật” [#kết-hợp-3-lớp-để-đọc-sức-khỏe-thật] **1)** Liếc *Tổng quan chỉ số* xem xanh/đỏ. **2)** Mở *Độ rộng MA*: đa số cổ phiếu còn trên MA không? Có phân kỳ với chỉ số không? **3)** Soi *Độ rộng tăng-giảm* trong phiên: điểm số có được hậu thuẫn bởi số đông cổ phiếu, hay chỉ vài mã trụ? Ba lớp khớp nhau → tín hiệu đáng tin hơn nhiều so với chỉ nhìn điểm số. Tiếp theo: [Bài 3 — Dòng tiền thị trường](/webapp/thi-truong-dong-tien) để biết tiền đang chảy vào đâu, và [Bài 4 — Xếp hạng & RRG](/webapp/thi-truong-xep-hang) để tìm nhóm/cổ phiếu dẫn dắt. ## Bài liên quan [#bài-liên-quan] Thêm widget, kéo-thả, đồng bộ mã & ngày, Workspace. Khối ngoại, Shark, phân loại nhà đầu tư, thanh khoản intraday. Top ảnh hưởng, Top 20 RS, Relative Rotation Graph. ### Câu hỏi thường gặp **Bao nhiêu phần trăm cổ phiếu trên MA thì thị trường được coi là khỏe?** Theo cách đọc widget Độ rộng MA thị trường, tỷ lệ trên 70 đến 80 phần trăm cổ phiếu đứng trên đường trung bình cho thấy thị trường lan tỏa mạnh với đa số cổ phiếu tăng, nhưng duy trì quá cao và quá lâu thì dễ rơi vào vùng quá mua. Ngược lại dưới 20 đến 30 phần trăm phản ánh bán tháo diện rộng và thường gần vùng quá bán. MA20 cùng MA50 cho biết sức khỏe ngắn và trung hạn, còn MA100 cùng MA200 phản ánh xu hướng dài hạn. **Chỉ số tăng nhưng cổ phiếu vẫn đỏ là hiện tượng gì?** Đó là tình trạng thường gọi là xanh vỏ đỏ lòng, phát hiện được bằng widget Độ rộng thị trường theo mốc 5 phút. Chỉ số độ rộng dao động quanh 0 theo công thức số mã tăng trừ số mã giảm chia cho tổng hai nhóm. Khi chỉ số điểm tăng mà độ rộng lại âm, nghĩa là chỉ vài mã vốn hóa lớn kéo điểm còn phần lớn cổ phiếu vẫn giảm. Một dấu hiệu cùng bản chất là VNINDEX lập đỉnh mới trong khi tỷ lệ cổ phiếu trên MA đi xuống, cho thấy nội lực yếu dần. **Xem P/E toàn thị trường Việt Nam ở đâu và đọc thế nào?** Widget P/E VNINDEX vẽ đường P/E của toàn thị trường theo thời gian cạnh đường chỉ số, tính bằng tổng vốn hóa thị trường chia tổng lợi nhuận ròng bốn quý gần nhất. Không nên đọc con số tuyệt đối một mình mà phải so với dải dao động nhiều năm hiển thị ngay trên biểu đồ để biết đang ở mép trên hay mép dưới. Lưu ý P/E dùng lợi nhuận đã xảy ra nên ở đáy khủng hoảng lợi nhuận sụt làm P/E nhìn cao giả tạo, còn ở đỉnh chu kỳ thì ngược lại. **z-score trong biểu đồ Động lượng MA có ý nghĩa gì?** Widget Động lượng MA vẽ mỗi cổ phiếu thành một chấm với trục ngang là phần trăm lệch so với đường trung bình và trục dọc là z-score, tính bằng chênh lệch giữa giá đóng cửa và MA chia cho độ lệch chuẩn. Vì z-score chuẩn hóa theo mức biến động riêng của từng mã nên so sánh được giữa cổ phiếu trầm lắng và cổ phiếu nóng. Một mã tăng 5 phần trăm nhưng z-score thấp có thể là bình thường với nó, còn tăng 2 phần trăm mà z-score cao lại là động thái đáng chú ý. --- # Xếp hạng RS, RRG và top cổ phiếu ảnh hưởng chỉ số URL: https://docs.finlens.vn/webapp/thi-truong-xep-hang Mô tả: Tìm cổ phiếu dẫn dắt bằng RS Rating và Relative Rotation Graph, xem mã nào đang kéo hoặc kéo tụt VNINDEX, và bóc tách ảnh hưởng bluechip khỏi định giá chỉ số. Tóm tắt: Nhóm widget xếp hạng của FinLens Web giúp tìm nhóm dẫn dắt và nhóm tụt hậu trên thị trường chứng khoán Việt Nam. Widget Top cổ phiếu ảnh hưởng tính đóng góp của từng mã vào điểm chỉ số bằng phần trăm thay đổi giá nhân tỷ trọng vốn hóa, lấy mười mã đóng góp dương và mười mã âm lớn nhất. Widget Top RS xếp hạng phần trăm hiệu suất giá so với toàn thị trường trên thang 0 đến 100, trình bày dạng heatmap theo ngày và lọc được theo khối lượng trung bình 20 phiên. Widget RRG vẽ hai trục RS-Ratio đo sức mạnh tương đối và RS-Momentum đo đà của sức mạnh đó, kèm vệt đuôi qua các phiên gần nhất. Widget P/E loại trừ và VNINDEX loại bỏ ảnh hưởng cho phép gỡ các mã vốn hóa lớn khỏi phép tính để xem phần còn lại của thị trường thực sự ra sao. Sản phẩm: webapp ⏱ Đọc 12 phút · 🟡 Trung cấp · 📍 Bảng Thị trường Các widget trong bài giúp trả lời câu hỏi **"ai đang dẫn dắt?"** — ở cấp cổ phiếu và ngành. Tất cả nằm ở **Bảng Thị trường**; nếu chưa thấy, bấm `Kho Widgets` và thêm theo tên. ## Top cổ phiếu ảnh hưởng chỉ số [#top-cổ-phiếu-ảnh-hưởng-chỉ-số] > 📍 Bảng Thị trường · Tên widget: **"Top cổ phiếu ảnh hưởng"** Xếp hạng những cổ phiếu **kéo chỉ số lên nhiều nhất** và **kéo xuống nhiều nhất** trong một phiên. "Ảnh hưởng" ở đây là số *điểm chỉ số* mà mỗi mã đóng góp — đã tính sẵn theo tỷ trọng vốn hóa. ```text // Đóng góp của một mã = số điểm chỉ số mã đó tạo ra trong phiên contribution ≈ (% thay đổi giá của mã) × (tỷ trọng vốn hóa trong chỉ số) // Lấy top 10 đóng góp dương + top 10 đóng góp âm, theo ngày & sàn ``` Widget Top cổ phiếu ảnh hưởng *Widget Top cổ phiếu ảnh hưởng — 10 mã kéo chỉ số lên (xanh) & 10 mã kéo xuống (đỏ).* * **Thanh xanh dài** = mã đóng góp nhiều điểm tăng cho chỉ số; **thanh đỏ** = mã làm chỉ số mất điểm. * Khi VNINDEX tăng nhưng chỉ **1–2 mã trụ** (VIC, VHM, VCB…) đóng góp gần hết → đà tăng "mỏng", dễ đảo chiều khi trụ quay đầu. * Chọn **sàn** (VNINDEX / HNX / UPCOM) và **ngày** ở góc widget. ## Top ngành ảnh hưởng [#top-ngành-ảnh-hưởng] > 📍 Bảng Thị trường · Tên widget: **"Top ngành ảnh hưởng"** Giống widget trên nhưng gộp theo **ngành**: cộng dồn đóng góp của tất cả cổ phiếu trong cùng ngành để xem nhóm ngành nào đang nâng đỡ hoặc đè chỉ số. ```text // Đóng góp của ngành = tổng đóng góp các mã trong ngành đó sector_contribution = Σ contribution(các mã thuộc ngành) // Top 10 ngành dương + top 10 ngành âm theo ngày ``` Widget Top ngành ảnh hưởng *Widget Top ngành ảnh hưởng — nhóm ngành nâng đỡ (xanh) & đè (đỏ) chỉ số.* Dùng cặp *Top cổ phiếu* + *Top ngành* để xác định: chỉ số tăng nhờ **cả ngành lan tỏa** (lành mạnh) hay chỉ **vài mã trụ** trong một ngành kéo (mong manh hơn). ## Top 20 RS — Sức mạnh tương đối (Relative Strength) [#top-20-rs--sức-mạnh-tương-đối-relative-strength] > 📍 Bảng Thị trường · Tên widget: **"Top RS"** · heatmap Bảng nhiệt (heatmap) xếp hạng những cổ phiếu **khỏe hơn phần còn lại của thị trường**. Mỗi mã có điểm **RS Rating từ 0 đến 100**: 100 = mạnh nhất thị trường, 50 = trung bình, dưới 20 = yếu nhất. ```text // RS Rating: xếp hạng phần trăm hiệu suất giá so với toàn thị trường rs_rating ∈ [0, 100] → 100 = top đầu, 50 = trung vị, 0 = đáy // Heatmap: hàng = mã (top theo RS), cột = ngày → màu đậm nhạt theo RS // Có thể lọc theo khối lượng TB 20 phiên để loại mã thanh khoản thấp ``` Widget Top RS heatmap *Widget Top RS — heatmap RS Rating theo từng mã & ngày. Càng xanh đậm = càng mạnh.* **Cách đọc:** * **Mã giữ RS cao (> 80) nhiều phiên liên tục** = leader thực sự — dòng tiền ưu tiên, thường dẫn sóng. * **Màu chuyển từ nhạt sang đậm** theo thời gian = mã đang *tăng tốc* sức mạnh tương đối — đáng theo dõi sớm. * **RS tụt nhanh** dù giá chưa giảm nhiều = mã bắt đầu yếu hơn thị trường, cảnh báo phân phối. **RS so sánh tương đối**, không phải tuyệt đối. Trong thị trường giảm, một mã RS 90 vẫn có thể đỏ — nhưng nó giảm *ít hơn* phần còn lại, nên khi thị trường hồi, nó thường bật mạnh nhất. RS cao là tiêu chí lọc "leader" kinh điển của phương pháp CANSLIM. ## Top mua bán ròng (Top Net Flow) [#top-mua-bán-ròng-top-net-flow] > 📍 Bảng Thị trường · Tên widget: **"Top mua bán ròng"** Hai bảng cạnh nhau: **Top mua ròng** (trái, xanh) và **Top bán ròng** (phải, đỏ) — xếp hạng cổ phiếu được mua/bán ròng mạnh nhất theo nhóm dòng tiền bạn chọn, trong khoảng ngày. | Loại dòng tiền (flowType) | Công thức giá trị ròng | | --------------------------------------------- | --------------------------------------------------------- | | **Mua/bán chủ động** (active) | buyValue − sellValue (lệnh chủ động trong phiên, tỷ đồng) | | **Nước ngoài** (foreign) | buyForeignValue − sellForeignValue | | **Tự doanh** (proprietary) | propTradingNetValue | | **Cá nhân trong nước** (local\_individual) | localIndividualBuy − localIndividualSell | | **Tổ chức trong nước** (local\_institutional) | localInstitutionalBuy − localInstitutionalSell | ```text // Cộng dồn giá trị ròng theo mã trong cả khoảng ngày, rồi xếp hạng net_value[mã] = Σ (buy − sell) theo flowType, từ fromDate → toDate Top mua ròng = N mã net dương lớn nhất · Top bán ròng = N mã net âm nhất ``` Widget Top mua bán ròng *Widget Top mua bán ròng — 2 bảng: mua ròng (xanh) & bán ròng (đỏ). Chọn loại dòng tiền & số dòng (5/10/20).* * **Đổi loại dòng tiền** (5 lựa chọn) ở góc widget để xem ai đang gom — ngoại, tự doanh hay cá nhân. * **Đổi số dòng** 5 / 10 / 20; **đổi khoảng ngày** theo thanh đồng bộ dashboard. * Mã xuất hiện ở Top mua ròng *đồng thời* RS cao → tín hiệu cộng hưởng mạnh: vừa được mua, vừa khỏe hơn thị trường. ## RRG — Relative Rotation Graph [#rrg--relative-rotation-graph] > 📍 Bảng Thị trường · Tên widget: **"RRG"** Biểu đồ **xoay vòng sức mạnh**: đặt từng cổ phiếu/ngành lên hệ trục so với một *chuẩn so sánh* (thường là VNINDEX), để thấy ai đang dẫn dắt, ai đang suy yếu — và **hướng di chuyển** của chúng theo thời gian. ```text // Hai trục của RRG Trục X — RS-Ratio : sức mạnh tương đối so với chuẩn (> 100 = mạnh hơn) Trục Y — RS-Momentum : đà của sức mạnh đó (> 100 = đang tăng tốc) // Vệt đuôi (tail) = đường đi qua các phiên gần nhất ``` ↗ Leading — Dẫn dắt Mạnh hơn chuẩn & còn tăng tốc. Nhóm đang dẫn sóng. ↖ Improving — Cải thiện Yếu hơn chuẩn nhưng đang mạnh lên. Ứng viên xoay vòng kế tiếp. ↘ Weakening — Suy yếu Mạnh hơn chuẩn nhưng mất đà. Leader cũ bắt đầu hụt hơi. ↙ Lagging — Tụt hậu Yếu hơn chuẩn & còn yếu thêm. Tránh hoặc chờ đảo chiều. Widget RRG *Widget RRG — 4 góc phần tư xoay theo chiều kim đồng hồ: Leading → Weakening → Lagging → Improving.* Một nhóm khỏe mạnh đi theo vòng: **Improving → Leading → Weakening → Lagging → Improving…** Quan sát *vệt đuôi*: chấm đang đi từ Lagging sang Improving (góc trái) là tín hiệu xoay vòng sớm; từ Leading sang Weakening là cảnh báo chốt lời. Đừng chỉ nhìn vị trí — nhìn **hướng đi**. ## P/E loại trừ — gỡ ảnh hưởng bluechip khỏi định giá [#pe-loại-trừ--gỡ-ảnh-hưởng-bluechip-khỏi-định-giá] > 📍 Bảng Thị trường · Tên widget: **"P/E loại trừ"** Vẽ hai đường P/E: **P/E hiện tại** của toàn chỉ số và **P/E sau khi loại trừ** một số mã bạn chọn (vd nhóm ngân hàng, hoặc các mã có lợi nhuận bất thường). Giúp trả lời: "định giá thị trường có bị méo bởi vài mã không?" ```text // P/E sau khi gỡ bỏ các mã được chọn P/E (loại trừ) = (Vốn hóa chỉ số − Vốn hóa mã loại trừ) ÷ (LN ròng TTM chỉ số − LN ròng TTM mã loại trừ) // Vốn hóa = Giá × Số CP lưu hành · TTM = lợi nhuận 4 quý gần nhất ``` Widget P/E loại trừ *Widget P/E loại trừ — so P/E toàn chỉ số với P/E sau khi gỡ các mã đã chọn.* * **Hai đường lệch nhau lớn** = các mã loại trừ đang "kéo méo" định giá chung — phần còn lại của thị trường đắt/rẻ khác hẳn con số P/E tổng. * Bật tùy chọn **"chỉ tính khi lợi nhuận dương"** để tránh P/E âm/vô nghĩa do mã thua lỗ. * Ví dụ thực tế: loại nhóm ngân hàng (vốn hóa lớn, P/E thấp) → P/E phần còn lại thường cao hơn nhiều. ## VNINDEX loại bỏ ảnh hưởng [#vnindex-loại-bỏ-ảnh-hưởng] > 📍 Bảng Thị trường · Tên widget: **"VNINDEX loại bỏ ảnh hưởng"** Vẽ chỉ số **thực tế** cạnh chỉ số **giả định nếu gỡ bỏ một vài mã**. Trả lời câu hỏi "nếu không có VIC/VHM/VCB thì VNINDEX đang ở đâu?" ```text // Chỉ số giả định khi bỏ các mã được chọn Index (loại bỏ) = Index thực tế − Σ (đóng góp lũy kế của các mã chọn) // Mỗi mã: cộng dồn điểm đóng góp qua từng phiên rồi trừ khỏi chỉ số ``` Widget VNINDEX loại bỏ ảnh hưởng *Widget VNINDEX loại bỏ ảnh hưởng — chỉ số thật vs chỉ số khi gỡ các mã được chọn.* **Khoảng cách giữa hai đường nới rộng dần** = các mã loại bỏ đang gánh phần lớn đà tăng (hoặc giảm) của chỉ số. Nếu gỡ vài trụ mà chỉ số "phẳng" hoặc giảm → đà tăng phụ thuộc nặng vào trụ, độ rộng thực sự yếu (đối chiếu thêm [Bài 2 — Độ rộng](/webapp/thi-truong-tong-quan)). ## Kết hợp đọc — Quy trình tìm leader [#kết-hợp-đọc--quy-trình-tìm-leader] **1) Khỏe hơn thị trường:** Mở *Top RS* — lọc mã giữ RS cao nhiều phiên. **2) Có tiền vào:** Đối chiếu *Top mua bán ròng* — mã đó có nằm trong Top mua ròng không? **3) Đang xoay vòng đúng hướng:** Xem *RRG* — mã/ngành ở góc Leading hoặc đang đi từ Improving sang Leading. **4) Kéo được chỉ số:** Kiểm tra *Top cổ phiếu/ngành ảnh hưởng* — mã/ngành đó có trong nhóm nâng đỡ chỉ số không? Tiếp theo: [Bài 5 — Trading Terminal & Sổ lệnh](/webapp/co-phieu-terminal) để đi sâu vào một mã cụ thể, hoặc xem lại [Bài 3 — Dòng tiền thị trường](/webapp/thi-truong-dong-tien). ## Bài liên quan [#bài-liên-quan] Khối ngoại, Shark, phân loại nhà đầu tư, thanh khoản intraday. Bố cục terminal, sổ lệnh, bảng khớp lệnh realtime, bubble volume. Chỉ số, P/E, động lượng MA, breadth MA/RSI và tăng-giảm theo phiên. ### Câu hỏi thường gặp **Cổ phiếu nào đang kéo VNINDEX tăng hoặc giảm nhiều nhất?** Widget Top cổ phiếu ảnh hưởng trả lời trực tiếp câu hỏi này. Đóng góp của một mã vào điểm chỉ số được tính xấp xỉ bằng phần trăm thay đổi giá nhân với tỷ trọng vốn hóa của mã đó trong chỉ số, sau đó lấy mười mã đóng góp dương và mười mã đóng góp âm lớn nhất theo ngày và theo sàn. Widget Top ngành ảnh hưởng cộng đóng góp của các mã trong cùng ngành để cho biết nhóm ngành nào đang gánh hoặc kéo tụt chỉ số. **RS Rating là gì và bao nhiêu thì được coi là mạnh?** RS Rating là xếp hạng phần trăm hiệu suất giá của một cổ phiếu so với toàn thị trường, nằm trên thang từ 0 đến 100. Giá trị 100 nghĩa là mã đó thuộc nhóm dẫn đầu, 50 là mức trung vị, còn 0 là đáy bảng. Widget Top RS trình bày dạng heatmap với hàng là mã và cột là ngày nên thấy được mã nào duy trì sức mạnh bền và mã nào chỉ mạnh nhất thời. Có thể lọc theo khối lượng trung bình 20 phiên để loại các mã thanh khoản thấp gây nhiễu. **Biểu đồ RRG đọc như thế nào?** Relative Rotation Graph đặt mỗi ngành hoặc mỗi mã lên hai trục: trục ngang là RS-Ratio đo sức mạnh tương đối so với chuẩn với mốc 100, trục dọc là RS-Momentum đo đà của sức mạnh đó cũng lấy mốc 100. Vượt 100 ở trục ngang nghĩa là đang mạnh hơn thị trường, vượt 100 ở trục dọc nghĩa là sức mạnh đang tăng tốc. Vệt đuôi nối các phiên gần nhất cho thấy hướng di chuyển, nhờ đó nhận ra nhóm đang vào pha dẫn dắt hay đang suy yếu dần. **Vì sao cần tính P/E sau khi loại trừ một số cổ phiếu lớn?** Một vài mã vốn hóa rất lớn có thể chi phối cả định giá lẫn điểm số của chỉ số, khiến bức tranh chung bị méo. Widget P/E loại trừ lấy vốn hóa chỉ số trừ vốn hóa các mã được chọn, chia cho lợi nhuận ròng bốn quý gần nhất của chỉ số đã trừ phần tương ứng, cho ra mức định giá của phần thị trường còn lại. Widget VNINDEX loại bỏ ảnh hưởng làm điều tương tự với đường chỉ số, dựng chỉ số giả định khi bỏ các mã đó ra. --- # Bộ lọc cổ phiếu Screener và danh mục theo dõi Watchlist URL: https://docs.finlens.vn/webapp/watchlist-screener Mô tả: Lọc cổ phiếu theo tiêu chí cơ bản, kỹ thuật và dòng tiền khối ngoại trên FinLens, tạo danh mục Watchlist theo dõi giá realtime và nối kết quả lọc vào widget khác. Tóm tắt: Hai công cụ nền tảng của FinLens Web để làm việc với nhiều mã cùng lúc là Watchlist và Screener. Widget Watchlist Manager nằm ở panel viền của mọi bảng, cho phép gom các mã quan tâm thành danh mục kèm giá theo thời gian thực, hiệu suất và xếp hạng, đồng thời có phần nâng cao hiển thị vùng giá Fibonacci và dòng tiền. Screener có cả dạng panel gọn tên là Screener nhanh và trang đầy đủ tại đường dẫn dashboard screener, lọc cổ phiếu theo nhiều nhóm điều kiện gồm tiêu chí cơ bản như sàn niêm yết, vốn hóa và phần trăm thay đổi giá, tiêu chí kỹ thuật như RSI, MACD và tín hiệu breakout, cùng tiêu chí dòng tiền khối ngoại. Bộ lọc lưu lại được để dùng lần sau, và kết quả lọc nối thẳng sang các widget khác để phân tích tiếp. Sản phẩm: webapp ⏱ Đọc 11 phút · 🟢 Cơ bản → Trung cấp · 📍 Bảng Cổ phiếu, Thị trường & trang Screener Watchlist và Screener xuất hiện ở nhiều nơi: panel **Watchlist Manager** & **Screener nhanh** cạnh viền các bảng, và **trang Screener đầy đủ** tại `/dashboard/screener`. Cả hai gắn với tài khoản của bạn, đồng bộ khi đăng nhập. ## Watchlist — danh mục theo dõi [#watchlist--danh-mục-theo-dõi] > 📍 Mọi Bảng (panel viền) · Tên widget: **"Watchlist Manager"** Tạo nhiều danh mục theo dõi, mỗi danh mục là một nhóm mã bạn quan tâm. Thanh công cụ trên cùng: | Thao tác | Cách dùng | | ------------------------ | ----------------------------------------------------------------- | | **Chọn watchlist** | Dropdown chuyển giữa các danh mục đã tạo | | **+ Tạo** | "Tạo watchlist" — đặt tên danh mục mới | | **✏️ Đổi tên · 🗑️ Xóa** | Sửa tên hoặc xóa danh mục đang chọn | | **Thêm mã** | Hộp đa chọn, tìm theo mã hoặc tên công ty, chọn nhiều mã cùng lúc | Mỗi dòng mã hiển thị: **logo + mã**, **giá đóng cửa**, **thay đổi (±)** & **%**, cùng **hiệu suất** và **xếp hạng** theo kỳ bạn chọn. Giá **cập nhật realtime** với hiệu ứng nhấp nháy (xanh khi tăng, đỏ khi giảm). | Bộ chọn hiệu suất | Kỳ | | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -- | | **1 tuần · 2 tuần · 1 tháng (mặc định) · 3 tháng · 6 tháng · 1 năm** — đổi kỳ để xem lợi nhuận & xếp hạng nội bộ danh mục (hạng 1 = mã tăng tốt nhất). | | Widget Watchlist Manager *Widget Watchlist Manager — danh mục theo dõi với giá realtime, hiệu suất & xếp hạng theo kỳ.* **Kéo–thả để sắp xếp:** giữ biểu tượng tay nắm ở đầu mỗi dòng để đổi thứ tự mã trong danh mục. Thứ tự được lưu lại cho lần sau. Bấm 🗑️ trên dòng để bỏ một mã khỏi danh mục. ## Watchlist nâng cao: vùng giá Fibonacci & dòng tiền [#watchlist-nâng-cao-vùng-giá-fibonacci--dòng-tiền] Ngoài bảng giá, dữ liệu watchlist còn nuôi một vài góc nhìn nâng cao cho cả nhóm mã: * **Vùng giá & Fibonacci** — với mỗi mã, hệ thống tính đỉnh/đáy 1 năm và các mức thoái lui Fibonacci (23.6%, 38.2%, 50%, 61.8%); màu xanh/đỏ cho biết giá hiện tại đang trên hay dưới từng mức. * **Dòng tiền lũy kế nhóm** — gộp dòng tiền ròng (mua − bán) trong phiên của cả danh mục, để xem tiền đang vào/ra rổ mã bạn theo dõi. Mức Fibonacci là **vùng hỗ trợ/kháng cự tham khảo** dựa trên biên độ 1 năm — kết hợp với [Pivot Points (Bài 7)](/webapp/co-phieu-ky-thuat) để xác định vùng giá quan trọng. Dòng tiền nhóm bổ trợ cho [dòng tiền theo mã (Bài 6)](/webapp/co-phieu-dong-tien). ## Screener — bộ lọc cổ phiếu [#screener--bộ-lọc-cổ-phiếu] > 📍 /dashboard/screener · Tên widget: **"Screener nhanh"** (panel) · trang đầy đủ Screener lọc ra danh sách mã thỏa **các điều kiện bạn đặt**. Quy trình xây bộ lọc: 1. **Chọn logic**: `AND` (thỏa tất cả điều kiện) hoặc `OR` (thỏa ít nhất một). 2. **Thêm điều kiện**: bấm "Thêm điều kiện" → hộp chọn trường lọc, tìm theo tên hoặc duyệt theo nhóm. 3. **Đặt giá trị**: mỗi trường có ô nhập phù hợp — số (toán tử ≥ ≤ > \< = ≠ và "Trong khoảng"), đa chọn (sàn/ngành), hoặc tham số (loại & chu kỳ đường MA). 4. **Xem kết quả**: bảng kết quả tự chạy, cập nhật mỗi 60 giây. *Trình xây bộ lọc Screener — chọn logic AND/OR, thêm điều kiện, đặt giá trị từng trường.* Bảng kết quả (lưới AG Grid) hiển thị các cột sắp xếp được: | Cột | Ý nghĩa | | -------------------------------------- | ---------------------------------- | | **Mã CK · Giá · Khối lượng** | Mã, giá đóng cửa, khối lượng | | **Thay đổi** | % thay đổi trong ngày (tô xanh/đỏ) | | **1 tuần · 1 tháng · 6 tháng · 1 năm** | Lợi nhuận theo các kỳ | Bảng kết quả Screener *Bảng kết quả Screener — danh sách mã thỏa điều kiện, số mã & cập nhật mỗi 60 giây.* ## Các nhóm điều kiện lọc [#các-nhóm-điều-kiện-lọc] Trường lọc được tổ chức theo nhóm trong hộp "Thêm điều kiện". Một số nhóm tiêu biểu: | Nhóm | Ví dụ trường lọc | | ---------------------------- | -------------------------------------------------------------------------------- | | **Cơ bản** | Sàn (HOSE/HNX/UPCOM), ngành ICB, tỷ lệ sở hữu (tổ chức, khối ngoại) | | **Giá & thay đổi** | Giá đóng cửa, % thay đổi ngày / 1 tuần / 1 / 3 / 6 tháng / 1 năm | | **Khối lượng & thanh khoản** | Khối lượng, KLTB 5/10/63 phiên, tỷ lệ mua chủ động | | **Khối ngoại** | KL/giá trị mua ròng nước ngoài (tỷ đồng) | | **Đường trung bình (MA)** | SMA/EMA 5–200, giá cắt lên/xuống MA, MA cắt nhau | | **Chỉ báo kỹ thuật** | RSI(14), MFI(14), MACD (cắt tín hiệu/zero), Bollinger Bands (chạm dải trên/dưới) | | **Breakout / chuỗi** | Vượt đỉnh / thủng đáy 1/3/6/12 tháng, chuỗi tăng-giảm, RS score, beta | Sàn = HOSE *(AND)* · % thay đổi 1 tháng ≥ 10% · RSI(14) trong khoảng 50–70 · Khối lượng ≥ KLTB 20 phiên · Vượt đỉnh 3 tháng = Đúng → ra danh sách mã đang tăng tốc có thanh khoản & vừa phá đỉnh. Một số trường (chỉ báo kỹ thuật, breakout) là **tín hiệu trạng thái** tính trên dữ liệu cuối phiên gần nhất. Có thể đặt **ngày chốt (As of)** để lọc theo một ngày trong quá khứ — hữu ích khi kiểm chứng bộ lọc. ## Lưu & quản lý bộ lọc [#lưu--quản-lý-bộ-lọc] Bộ lọc bạn dày công xây có thể **lưu lại để dùng lại**: | Thao tác | Ý nghĩa | | ----------------------------- | --------------------------------------------------- | | **Chọn bộ lọc** | Dropdown nạp bộ lọc đã lưu (của bạn & của hệ thống) | | **+ Thêm · ✏️ Sửa · 🗑️ Xóa** | Tạo mới / đổi tên / xóa bộ lọc | | **⭐ Mặc định** | Đặt một bộ lọc làm mặc định khi mở Screener | | **Lưu** | Cập nhật điều kiện vào bộ lọc đang chọn | Các nhãn trên dropdown: **"Mặc định"** (bộ lọc mặc định của bạn) và **"Hệ thống"** (bộ lọc dựng sẵn của FinLens — dùng làm mẫu để học rồi nhân bản chỉnh sửa). Mẹo: bắt đầu từ một **bộ lọc "Hệ thống"** gần ý bạn, chỉnh vài điều kiện rồi **Lưu thành bộ lọc mới** của riêng mình — nhanh hơn xây từ đầu. ## Kết nối kết quả vào các widget khác [#kết-nối-kết-quả-vào-các-widget-khác] Screener không phải ốc đảo — panel **"Screener nhanh"** nhúng bảng kết quả ngay cạnh viền Bảng Cổ phiếu / Thị trường, nên bạn vừa lọc vừa làm việc: * Mở panel Screener nhanh, chọn một bộ lọc đã lưu → danh sách mã hiện ngay (tối đa \~20 dòng ở chế độ gọn). * Nút **"Cấu hình bộ lọc screener"** mở trang Screener đầy đủ (`/dashboard/screener`) để chỉnh điều kiện chi tiết. * Thấy mã ưng ý trong kết quả → chọn mã đó trên thanh tiêu đề để toàn bộ widget của Bảng Cổ phiếu (giá, dòng tiền, tài chính…) đồng bộ theo, hoặc thêm vào Watchlist để theo dõi tiếp. **Screener** (lọc ra ứng viên) → **Watchlist** (gom & theo dõi) → chọn mã → **các widget phân tích** (dòng tiền, kỹ thuật, tài chính, khuyến nghị) để soi sâu từng mã trước khi quyết định. ## Kết hợp & kết thúc loạt bài [#kết-hợp--kết-thúc-loạt-bài] Từ thao tác cơ bản & tổng quan thị trường, dòng tiền, xếp hạng/RS, terminal & sổ lệnh, dòng tiền theo mã, kỹ thuật & mùa vụ, báo cáo tài chính, khuyến nghị, đến Watchlist & Screener — bạn đã có đủ công cụ để tự xây quy trình phân tích của mình. Quay lại [trang mục lục](/webapp) để xem lại bất kỳ bài nào, mở [Bảng Cổ phiếu](https://finlens.vn/dashboard/stock) để thực hành, hoặc khám phá [tài liệu MCP](https://finlens.vn/docs/mcp) nếu bạn muốn truy cập dữ liệu FinLens qua AI. ## Bài liên quan [#bài-liên-quan] Bố cục, thanh tiêu đề, thêm/di chuyển widget, lưu Workspace. Khuyến nghị CTCK, vùng giá mục tiêu, top khuyến nghị, tin tức. Lũy kế theo nhóm NĐT, mua-bán chủ động, so ngành. ### Câu hỏi thường gặp **Lọc cổ phiếu Việt Nam theo RSI và MACD ở đâu?** Screener của FinLens Web hỗ trợ nhóm điều kiện kỹ thuật gồm RSI, MACD và tín hiệu breakout, đặt cạnh nhóm điều kiện cơ bản như sàn niêm yết, vốn hóa, phần trăm thay đổi giá, và nhóm điều kiện dòng tiền khối ngoại. Có thể kết hợp nhiều nhóm trong cùng một bộ lọc để thu hẹp danh sách. Screener có hai dạng: panel Screener nhanh dùng ngay trong Dashboard và trang đầy đủ tại đường dẫn dashboard screener với không gian rộng hơn. **Có lưu lại bộ lọc cổ phiếu để dùng lần sau không?** Screener cho phép lưu và quản lý các bộ lọc đã dựng, nên không phải đặt lại điều kiện mỗi lần mở. Đây là điểm hữu ích khi theo một chiến lược cố định, chẳng hạn lọc cổ phiếu vốn hóa vừa có RSI vượt ngưỡng và khối ngoại mua ròng, và muốn chạy lại đúng bộ tiêu chí đó vào mỗi phiên. Kết quả lọc còn nối được sang các widget khác để xem tiếp biểu đồ, dòng tiền hay báo cáo tài chính của từng mã trong danh sách. **Watchlist của FinLens hiển thị những thông tin gì?** Widget Watchlist Manager gom các mã quan tâm thành danh mục theo dõi kèm giá cập nhật theo thời gian thực, hiệu suất và xếp hạng của từng mã. Phần nâng cao bổ sung vùng giá Fibonacci và thông tin dòng tiền, nên có thể đánh giá nhanh mã nào đang ở vùng giá đáng chú ý mà không cần mở từng biểu đồ. Watchlist nằm ở panel viền của mọi bảng nên luôn truy cập được trong lúc đang làm việc trên bảng khác. **Sau khi lọc ra danh sách cổ phiếu thì phân tích tiếp thế nào?** Kết quả từ Screener nối thẳng được sang các widget khác trên Dashboard, nên chọn một mã trong danh sách là chuyển ngay sang xem biểu đồ, sổ lệnh, dòng tiền lũy kế hoặc báo cáo tài chính của mã đó. Quy trình thường dùng là lọc bằng Screener để thu hẹp danh sách, đưa các mã lọt lưới vào Watchlist để theo dõi liên tục, rồi mở Bảng Cổ phiếu soi từng mã bằng nhóm widget dòng tiền và kỹ thuật.