CW Market Overview tải dữ liệu chứng quyền có bảo đảm (CW) của toàn thị trường HOSE từ các nguồn công khai, tính định giá, biến động và rủi ro, ghi vào một file Excel và dựng một file dashboard HTML duy nhất gồm 4 tab. Bài này mô tả đủ chi tiết để bạn dựng lại một hệ thống tương tự từ đầu: lấy dữ liệu ở đâu, tính từng con số thế nào, lưu trung gian ra sao, ráp dashboard bằng cách nào, và nên làm theo thứ tự nào.
Mục lục
- 1. Hệ thống làm gì
- 2. Kiến trúc và ba chế độ chạy
- 3. Cây thư mục
- 4. Nguồn dữ liệu và cách gọi
- 5. Một ngày dữ liệu cho mọi nguồn
- 6. Công thức cho từng CW
- 7. Biến động: HV, Yang-Zhang, GARCH, IV hằng ngày
- 8. Dữ liệu trung gian và workbook
- 9. Ráp dashboard thành một file
- 10. Nội dung và công thức từng tab
- 11. Bảng tham số
- 12. Dựng lại từ đầu: lộ trình 8 chặng
- 13. Vận hành và lỗi thường gặp
- 14. Dữ liệu nội bộ, bản quyền và miễn trừ
1. Hệ thống làm gì
Đầu vào là bảng giá và thống kê công khai. Đầu ra là ba thứ:
- CW Dashboard.html: một file tự chứa (dữ liệu nhúng sẵn), 4 tab, đổi Sáng/Tối và EN/VI, mở bằng trình duyệt, gửi được qua email.
- CW Market Overview.xlsx: sheet Horizon (mỗi CW một dòng, 35 cột chỉ số) và RawData (dữ liệu thô từng nguồn).
- GARCH Volatility Result/: tham số, dự báo và kiểm định của mô hình GARCH / GJR-GARCH.
| Tab | Trả lời câu hỏi | Nội dung chính |
|---|---|---|
| 1. Competitor Overview | Thị trường đang thế nào, mỗi tổ chức phát hành (TCPH) đứng ở đâu? | KPI thị trường · thị phần theo TCPH · định giá so với mức phân phối · phân phối theo lô của TCPH nhà · treemap mua/bán ròng · bảng toàn bộ CW |
| 2. Client Overview | Nhà đầu tư mua gì, bán gì? | Dòng tiền nhà đầu tư theo kỳ, theo mã cơ sở, theo ngày · sở thích theo moneyness, kỳ hạn, đòn bẩy hiệu dụng tại thời điểm giao dịch |
| 3. Volatility | IV của từng CW đang đi đâu, phiên tới nên quote thế nào? | 3.1 kiểm tra trước phiên tới · 3.2 theo dõi IV và tín hiệu · 3.3 lịch sử IV · 3.4 IV các TCPH trên cùng mã cơ sở |
| 4. Risk & Events | Sổ CW của TCPH nhà rủi ro bao nhiêu, sắp có sự kiện gì, tạo lập thị trường tốt không? | 4.1 Greeks quy ra tiền, kịch bản ±7% · 4.2 lịch đáo hạn, sự kiện quyền, CW mới · 4.3 chất lượng chào giá trong phiên |
KAFI_. Muốn dùng cho TCPH khác chỉ cần đổi hằng số này và từ khoá nhận diện trong cấu hình.2. Kiến trúc và ba chế độ chạy
Hệ thống chia ba lớp, mỗi lớp chỉ đọc đầu ra của lớp trước. Nhờ vậy có thể dựng lại dashboard mà không tải lại dữ liệu, và sửa giao diện mà không chạm vào phần tính toán.
| Lớp | Việc làm | Đầu ra |
|---|---|---|
| Thu thập | Gọi API công khai, chọn một ngày dữ liệu chung, cắt mọi nguồn về ngày đó, lưu cache theo bước | data/cache/*.pkl, data/*.csv, data/quotes/ |
| Tính toán | Bảng master từng CW (IV, delta, đòn bẩy…), HV, Yang-Zhang, GARCH, tự doanh | Sheet Horizon, RawData, workbook GARCH |
| Trình bày | Các module src/dashboard/*.py biến Excel + CSV thành JSON, nhúng vào khuôn HTML | CW Dashboard.html |
2.1 Các bước của main.py
| Bước | Việc làm | File |
|---|---|---|
| 0 | Chọn ngày dữ liệu (as-of), mục 5 | as_of.py |
| 1 | Tải bảng CW HOSE, cắt giá về ngày as-of | api_client.py, as_of.py |
| 2 | Số lượng CW niêm yết (chỉ tải mã mới, mã cũ đọc lại từ Excel) | api_client.py |
| 3 | Bảng cổ phiếu VNALL (giá cơ sở) | api_client.py |
| 4 | Giá trị khớp lệnh cơ sở, ADV 1 tháng / 3 tháng / từ đầu năm | underlying_liquidity.py |
| 5 | Lịch sử giá cơ sở, HV và Yang-Zhang theo kỳ hạn gốc của CW | historical_loader.py |
| 5b | Lịch sử giá đóng cửa từng CW → data/cw_daily.csv | cw_history.py |
| 5c | Bảng giá trong phiên từ LiveDragon → giá chào cuối phiên data/quotes/ và chất lượng chào giá data/quotes_mm/ | vdsc_quotes.py |
| 6 | Tự doanh của TCPH theo từng CW, luỹ kế và theo ngày | proprietary_trading.py |
| 7 | Bảng master: IV, delta, hoà vốn, đòn bẩy, % phân phối | cw_processor.py, option_pricing.py |
| 8 | GARCH / GJR-GARCH cho từng mã cơ sở, quy về kỳ hạn CW | garch_pipeline.py, volatility_models.py |
| RT | Ảnh chụp phiên mới nhất nếu đã có phiên đóng mới hơn ngày as-of | realtime.py |
| 9 | Ghi Excel, CSV trung gian, bảng DATA CHECK, rồi dựng dashboard | excel_exporter.py, dashboard/build.py |
2.2 Ba chế độ chạy
| File bấm đúp | Khi nào | Làm gì | Thời gian |
|---|---|---|---|
Run CW Market Overview.bat | Mỗi ngày, sau 15:00 | Chạy đủ các bước trên, ghi Excel, dựng dashboard | Lần đầu 10–40 phút (tải lịch sử); sau đó vài phút |
Run Live.bat | Trong giờ giao dịch | Chạy đầy đủ một lần, rồi cứ N phút lấy lại bảng giá, tính lại phần Real-time và dựng lại dashboard; trang đang mở tự tải lại, giữ tab và bộ lọc. Tự dừng 14:50 | Vài giây mỗi vòng |
Rebuild Dashboard.bat | Sau khi sửa giao diện hoặc tham số hiển thị | Không gọi API, dựng lại dashboard từ dữ liệu đã lưu | Dưới 1 phút |
Dashboard có hai góc nhìn chuyển bằng nút: Sync (mọi số liệu cùng một ngày as-of) và Real-time (giá của phiên mới nhất; các số chỉ công bố sau phiên như tự doanh vẫn giữ ngày Sync và được ghi rõ ngày).
3. Cây thư mục
CW_Market_Overview/ ├─ Run CW Market Overview.bat chạy đầy đủ (Sync) ├─ Run Live.bat cập nhật trong phiên ├─ Rebuild Dashboard.bat chỉ dựng lại dashboard ├─ main.py điều phối các bước 0 → 9 ├─ live.py vòng lặp chế độ Live ├─ build_dashboard.py lệnh cho Rebuild ├─ CW Market Overview.xlsx khuôn Excel: Horizon, RawData ├─ config/api_config.py MỌI THAM SỐ (mục 11) ├─ src/ │ ├─ ensure_python.bat tìm / tự cài Python lần đầu │ ├─ as_of.py chọn ngày dữ liệu, bảng DATA CHECK │ ├─ api_client.py gọi SSI │ ├─ step_cache.py cache kết quả từng bước theo ngày │ ├─ historical_loader.py lịch sử giá, HV, Yang-Zhang │ ├─ underlying_liquidity.py giá trị khớp, ADV │ ├─ cw_history.py giá đóng cửa CW theo ngày │ ├─ vdsc_quotes.py giá chào trong phiên (LiveDragon) │ ├─ proprietary_trading.py tự doanh (VNDIRECT) │ ├─ option_pricing.py Black-Scholes, IV, delta │ ├─ cw_processor.py bảng master từng CW │ ├─ volatility_models.py GARCH, GJR-GARCH, backtest │ ├─ garch_pipeline.py GARCH theo kỳ hạn CW │ ├─ iv_monitor.py giải IV dạng mảng, tín hiệu IV │ ├─ realtime.py ảnh chụp phiên mới nhất │ ├─ kafi_inventory.py tồn kho nội bộ (tuỳ chọn) │ ├─ raw_data.py, excel_exporter.py, workbook_io.py ghi Excel │ └─ dashboard/ │ ├─ build.py ráp dashboard │ ├─ market_data.py tab 1 │ ├─ client_data.py tab 2 │ ├─ vol_data.py, iv_db.py tab 3 (IV hằng ngày) │ ├─ kafi_batches.py phân phối theo lô │ ├─ kafi_extra.py CW đã hết ngày giao dịch nhưng chưa đáo hạn │ ├─ events_data.py sự kiện quyền (tự phát hiện) │ ├─ mm_data.py chất lượng chào giá │ └─ template/ head.html · body.html · app.js.html · settings.js.html · logo └─ data/ CSV trung gian, cache, quotes, realtime (mục 8)
4. Nguồn dữ liệu và cách gọi
4.1 Bảy địa chỉ đang dùng
| # | Dữ liệu | Địa chỉ | Tham số | Trường dùng tới |
|---|---|---|---|---|
| 1 | Bảng CW HOSE | GET https://iboard-query.ssi.com.vn/stock/cw/hose | — | data.coveredWarrantData[]: stockSymbol, underlyingSymbol, issuerName, exercisePrice, exerciseRatio (“1.7245:1”), firstTradingDate, lastTradingDate, maturityDate, tradingDate, refPrice, ceiling, floor, matchedPrice, best1Bid, best1Offer, nmTotalTradedQty, nmTotalTradedValue |
| 2 | Bảng cổ phiếu | GET https://iboard-query.ssi.com.vn/stock/group/VNALL | — | data[]: stockSymbol, refPrice, matchedPrice, nmTotalTradedValue, tradingDate |
| 3 | Giá lịch sử nến ngày (CW và cổ phiếu) | GET https://iboard-api.ssi.com.vn/statistics/charts/history | resolution=1D, symbol, from, to (Unix giây) | data.t/o/h/l/c/v (mảng song song; giá theo nghìn đồng) |
| 4 | Số lượng niêm yết | GET https://iboard-query.ssi.com.vn/stock/{symbol} | — | data.listedShare |
| 5 | Lịch sử giao dịch cổ phiếu | GET https://iboard-api.ssi.com.vn/statistics/company/ssmi/stock-info | symbol, page, pageSize, fromDate, toDate (dd/mm/yyyy) | tradingDate, close, totalMatchVal; paging |
| 6 | Tự doanh theo mã CW | GET https://api-finfo.vndirect.com.vn/v4/proprietary_trading | q=code:<mã CW> hoặc q=date:YYYY-MM-DD, sort=date, page, size | code, type, date, buyingVol, buyingVal, sellingVol, sellingVal; totalPages |
| 7 | Bảng giá trong phiên (mọi ảnh chụp: 3 mức giá mua/bán tốt nhất, giá khớp) | GET https://livedragon.vdsc.com.vn/general/intradayBoard.rv (lấy cookie JSESSIONID), rồi POST …/general/intradaySearch.rv | stockCode, boardDate (dd/mm/yyyy); header X-Requested-With: XMLHttpRequest | list[]: TradeTime, BidPrice1–3, OfferPrice1–3, BidVol1–3, OfferVol1–3, MatchedPrice, MatchedTotalVol (giá theo nghìn đồng). Máy chủ chỉ giữ khoảng 3 tháng |
4.2 Quy tắc chung
- Gửi header giống trình duyệt (
User-Agent,Accept). VNDIRECT cần thêmReferervàOrigin=https://dstock.vndirect.com.vn. - SSI trả
"code": "SUCCESS"khi thành công. API có phân trang thì lặppagetới hết. - Đơn vị: giá lịch sử SSI và giá LiveDragon theo nghìn đồng (nhân 1.000). Mốc thời gian nến ngày là 00:00 giờ Việt Nam: đổi sang múi Asia/Ho_Chi_Minh trước khi lấy ngày.
- Tỷ lệ chuyển đổi dạng chữ “1.7245:1”: lấy số trước dấu hai chấm.
- Tự doanh: lượng CW nhà đầu tư nắm = luỹ kế
sellingVol − buyingVolcủa TCPH. Không dùngnetVolcủa VNDIRECT vì ngược dấu. Lỗi mạng phải gọi lại (tối đa 3 lần), không được biến thành số 0. - Tải bù, không tải lại: mỗi lần chạy chỉ tải phần còn thiếu (mã mới, ngày mới). Dữ liệu LiveDragon phải lưu lại hằng ngày vì máy chủ chỉ giữ khoảng 3 tháng.
- Tìm lại một API khi nó đổi: mở trang bảng giá bằng Chrome, F12 → Network → Fetch/XHR, thao tác trên trang, chọn yêu cầu mới, xem Headers và Response, chuột phải → Copy as cURL để thử lại.
4.3 Ví dụ gọi nhanh
import requests
H = {"User-Agent": "Mozilla/5.0", "Accept": "application/json, text/plain, */*"}
# 1. Bảng CW
cw = requests.get("https://iboard-query.ssi.com.vn/stock/cw/hose", headers=H, timeout=30).json()
rows = cw["data"]["coveredWarrantData"]
print(len(rows), "CW", rows[0]["stockSymbol"], rows[0]["exerciseRatio"])
# 6. Tự doanh một mã CW
HV = {**H, "Referer": "https://dstock.vndirect.com.vn/", "Origin": "https://dstock.vndirect.com.vn"}
p = requests.get("https://api-finfo.vndirect.com.vn/v4/proprietary_trading",
params={"q": f"code:{rows[0]['stockSymbol']}", "sort": "date", "page": 1, "size": 100},
headers=HV, timeout=30).json()
# 7. Bảng giá trong phiên của một CW, một ngày
s = requests.Session(); s.headers.update({**H, "X-Requested-With": "XMLHttpRequest",
"Referer": "https://livedragon.vdsc.com.vn/general/intradayBoard.rv"})
s.get("https://livedragon.vdsc.com.vn/general/intradayBoard.rv", timeout=20) # cookie
snap = s.post("https://livedragon.vdsc.com.vn/general/intradaySearch.rv",
data={"stockCode": rows[0]["stockSymbol"], "boardDate": "16/10/2026"}, timeout=30).json()
print(len(snap.get("list") or []), "ảnh chụp")4.4 Nguồn nội bộ (tuỳ chọn)
Hai biểu đồ dùng số chính xác hơn nếu có dữ liệu nội bộ của TCPH nhà; không có thì hệ thống tự ước tính:
| Dữ liệu | Định dạng tối thiểu | Không có thì |
|---|---|---|
| Tồn kho CW của TCPH theo ngày | Excel/CSV: Ngày · Mã CW · Tồn kho (gồm lệnh chờ thanh toán T+2) | Lượng lưu hành ước tính = số niêm yết − (tự doanh mua − tự doanh bán luỹ kế) |
| Cổ phiếu phòng hộ đang nắm | Nhập tay trong cấu hình: {"<mã cơ sở>": <số cổ phiếu>} | Delta Exposure = Delta CW (coi như chưa phòng hộ) |
| IV quét trong phiên (nếu có công cụ quét riêng) | SQLite: thời điểm · mã CW · IV | Tự tính IV từ giá chào (mục 7.4) |
5. Một ngày dữ liệu cho mọi nguồn
Mọi con số trong Excel và chế độ Sync phải mô tả cùng một phiên đã đóng. Quy tắc trong as_of.py:
- Ngày làm việc, chạy từ 15:00 trở đi → ứng viên là hôm nay. Chạy trước 15:00 hoặc cuối tuần → ngày làm việc liền trước.
- Ứng viên chỉ được dùng khi mọi nguồn đã có ngày đó: tự doanh VNDIRECT (thường công bố muộn nhất; kiểm tra bằng
q=date:YYYY-MM-DD&size=5), nến ngày của CW, nến ngày của cổ phiếu, stock-info. - Thiếu một nguồn → lùi một ngày làm việc và kiểm tra lại, tối đa 7 lần.
- Chốt ngày xong thì cắt mọi nguồn về ngày đó: giá và khối lượng CW, giá cơ sở, thanh khoản, lịch sử cho HV/GARCH, tự doanh luỹ kế, số ngày còn lại.
- In bảng DATA CHECK: mỗi nguồn một dòng, OK nếu đúng ngày, XX nếu lệch. Dashboard từ chối dựng nếu workbook và các CSV khác ngày.
6. Công thức cho từng CW
Ký hiệu: S giá cơ sở, K giá thực hiện, CR tỷ lệ chuyển đổi (số CW đổi 1 cổ phiếu), W giá CW, T = số ngày lịch còn lại / 365, r lãi suất phi rủi ro (mặc định 7%, một mức cho mọi CW), N(·) hàm phân phối chuẩn tích luỹ, n(·) hàm mật độ.
| Chỉ số (cột Horizon) | Công thức | Ghi chú |
|---|---|---|
| DTE | Ngày đáo hạn − ngày as-of (ngày lịch) | Đáo hạn = ngày giao dịch cuối + 2 ngày làm việc |
| Breakeven price | K + W × CR | |
| % Increase to Breakeven | Breakeven / S − 1 | Cơ sở phải tăng bao nhiêu để hoà vốn |
| Intrinsic Value | max(S − K, 0) / CR | Giá trị nội tại mỗi CW |
| Status | ITM nếu S > K, OTM nếu S < K, còn lại ATM | Moneyness = S/K − 1 |
| Leverage | S / (W × CR) | Đòn bẩy đơn thuần |
| Đòn bẩy hiệu dụng (dashboard) | Leverage × N(d1) | σ = IV của CW, không có thì HV. Đây là % thay đổi giá CW khi cơ sở +1% |
| CW price theory | Black-Scholes với σ = HV | So sánh với giá thị trường |
| IV | Nghiệm σ của BS(σ) = W, tìm bằng Brent trong [0,0001; 5] | W dưới giá trị nội tại chiết khấu → không có nghiệm, để trống |
| Delta | N(d1) / CR với σ = IV | Số cổ phiếu tương đương mỗi CW |
| IV-HV | IV − HV | |
| Net sold | Luỹ kế (tự doanh bán − tự doanh mua) từ ngày giao dịch đầu | Lượng nhà đầu tư nắm giữ ước tính |
| % distribution | min(Net sold / số niêm yết, 100%) | Mức phân phối |
6.1 Ví dụ tính tay
Một CW giả định: S = 30.000 đ, K = 32.000 đ, CR = 4, W = 900 đ, còn 120 ngày, r = 7%.
| Chỉ số | Tính | Kết quả |
|---|---|---|
| Moneyness | 30.000 / 32.000 − 1 | −6,25% (OTM) |
| Hoà vốn | 32.000 + 900 × 4 | 35.600 đ; cơ sở cần tăng 18,7% |
| Giá trị nội tại | max(30.000 − 32.000, 0) / 4 | 0 đ: toàn bộ 900 đ là giá trị thời gian |
| IV | Giải BS(σ) = 900 | 60,3% |
| N(d1) | d1 = 0,0529 | 0,521 |
| Delta mỗi CW | 0,521 / 4 | 0,130 cổ phiếu |
| Đòn bẩy đơn thuần | 30.000 / (900 × 4) | 8,33x |
| Đòn bẩy hiệu dụng | 8,33 × 0,521 | 4,34x |
7. Biến động: HV, Yang-Zhang, GARCH, IV hằng ngày
7.1 HV và Yang-Zhang theo kỳ hạn gốc
Mỗi CW có kỳ hạn gốc = ngày đáo hạn − ngày giao dịch đầu (ví dụ 12 tháng). HV đo trên đúng khoảng ngày lịch đó, tính ngược từ ngày as-of; ít hơn 20 lợi suất thì lấy 20 phiên gần nhất.
7.2 GARCH và GJR-GARCH
- Tải khoảng 5 năm giá cơ sở, ước lượng trên 750 phiên gần nhất, phân phối Student-t (thư viện
arch). - Bỏ những ngày có |lợi suất| > 7,5% (thường do sự kiện quyền chưa điều chỉnh).
- Giới hạn persistence α + β + γ/2 ≤ 0,99 để vol dài hạn không bùng nổ.
- Dự báo vol bình quân cho các kỳ hạn 21, 63, 126, 189, 252, 315 phiên; mỗi CW lấy kỳ hạn khớp với kỳ hạn gốc của nó.
- Tuỳ chọn backtest walk-forward: huấn luyện tối thiểu 500 phiên, ước lượng lại mỗi 20 phiên, chấm điểm bằng QLIKE, kiểm định Diebold-Mariano và VaR Kupiec.
7.3 IV hằng ngày cho tab 3
IV trong bảng master dùng giá đóng cửa, dễ nhiễu vì phiên ATC. Tab 3 dùng một chuỗi IV hằng ngày ổn định hơn, ưu tiên theo thứ tự:
- Có công cụ quét IV trong phiên (ví dụ 10 phút/lần, giá giữa bid/ask): IV ngày = trung bình các lần quét; ngày có ít hơn 3 lần quét thì bỏ.
- Không có: tự tính từ giá giữa (Bid + Ask)/2 của ảnh chụp chào giá chặt cuối cùng trước 14:30 (chênh lệch ≤ max(3 bước giá, 6% giá giữa)). Giá cơ sở lấy cùng thời điểm: giá khớp cuối trước 14:30 của cổ phiếu, quy đổi theo hệ số điều chỉnh của SSI.
- Không có giá chào hai chiều thì dùng giá đóng cửa của ngày có khớp lệnh.
8. Dữ liệu trung gian và workbook
Dashboard không đọc API mà đọc các file dưới đây. Đây là “hợp đồng” giữa lớp tính toán và lớp trình bày: giữ đúng tên cột thì có thể thay phần lấy dữ liệu mà không sửa dashboard.
| File | Cột | Nội dung |
|---|---|---|
data/pdt_cache.csv | CW, PDT Buy Volume, PDT Buy Value, PDT Sell Volume, PDT Sell Value, Net Sold, PDT Trading Days, Net Sold Today, Net Value Today, As-of | Tự doanh luỹ kế đến ngày as-of |
data/pdt_daily.csv | CW, date, buyingVol, buyingVal, sellingVol, sellingVal, As-of | Tự doanh từng ngày (tab 2, phân phối theo lô) |
data/cw_eod.csv | CW, Close, Prev Close, Ceiling, Floor, Volume, Bid, Ask, As-of | Giá CW ngày as-of |
data/underlying_daily.csv | Ticker, Date, Close, As-of | Giá đóng cửa cơ sở (đã điều chỉnh) |
data/cw_daily.csv | CW, Date, Close, Volume, As-of | Lịch sử giá đóng cửa CW |
data/cw_listing.csv | CW, First trading date, Last trading date | Vòng đời CW, kể cả mã đã hết hạn |
data/cw_terms.csv | CW, Ticker, Issuer, ltd, K, CR, listed, seen | Điều khoản đã biết của mọi CW, để tính cả CW đã rời bảng giá nhưng chưa đáo hạn |
data/quotes/YYYY-MM-DD.csv | CW, Date, Bid, Ask, BidVol, AskVol, QuoteTime, Last, Close, Volume | Mỗi mã một dòng mỗi phiên: giá chào chặt cuối cùng trước 14:30 (cả CW và cổ phiếu cơ sở) |
data/quotes_mm/YYYY-MM-DD.csv | CW, Date, Snaps, Sec, Two, SprTk, SprRel, Tk1, DepB, DepA, EffTk, EffRel, EffVol, Ok{n}_{x} | Chất lượng chào giá trong phiên, lưu dạng TỔNG (giây, giây × giá trị) để cộng dồn chính xác (mục 10.4) |
data/realtime/ | horizon.csv, cw_eod.csv, underlying_daily.csv, meta.json | Ảnh chụp phiên mới nhất cho chế độ Real-time |
data/cache/ | *.pkl, web_data.json | Kết quả từng bước theo ngày; JSON của dashboard |
8.1 Sheet Horizon
Dòng 7 là tiêu đề, dữ liệu từ dòng 8. Code tìm cột theo tên, không theo vị trí, nên có thể chèn cột hoặc đổi định dạng trong Excel. 35 cột theo thứ tự:
CW · Ticker · Issuer · Last trading date · Listed volume · DTE · Conversion ratio · Delta · CW price trading · CW price theory · Strike price · Spot price · Breakeven price · % Increase to Breakeven · Intrinsic Value / CW Price · Status · Leverage · HV · IV · IV-HV · Yang-Zhang vol · GARCH · GJR-GARCH · Market trading value · Market ADV 1 months · Market ADV 3 months · YTD Market ADV · CW trading volume · CW trading value · Buy volume · Buy value · Sell volume · Sell value · Net sold · % distribution
Ghi Excel qua chính ứng dụng Excel (thư viện xlwings) để giữ nguyên định dạng, công thức và biểu đồ của khuôn. Trước khi ghi: hỏi đóng file nếu đang mở, sao lưu bản cũ (giữ 30 bản trong data/backup/), ghi ra file tạm rồi mới thay.
9. Ráp dashboard thành một file
Ý tưởng: Python tính sẵn mọi thứ thành JSON; khuôn HTML có các chỗ giữ chỗ dạng __TÊN__; build.py thay chỗ giữ chỗ bằng JSON rồi ghép thành một file. Trình duyệt chỉ việc vẽ và lọc, không cần máy chủ.
build.pykiểm tra các file đầu vào cùng ngày as-of, rồi lần lượt gọi từng module. Mỗi module đọcdata/cache/web_data.json, thêm một khoá, ghi lại. Module phụ lỗi thì chỉ in WARNING, dashboard vẫn dựng (phần đó trống).- Đọc 4 khuôn:
head.html(CSS, biến màu sáng/tối),body.html(bố cục 4 tab),app.js.html(toàn bộ JavaScript),settings.js.html(đổi giao diện, từ điển EN→VI). - Thay chỗ giữ chỗ bằng
json.dumps(..., ensure_ascii=False), ghi ra file tạm rồi đổi tên (không bao giờ để lại file dở dang).
| Chỗ giữ chỗ | Module tạo | Nội dung |
|---|---|---|
__K__, __COMP__, __CLIENT__, __CWS__ | market_data.py | KPI thị trường, chỉ số theo TCPH, nhóm sản phẩm, danh sách CW (tab 1) |
__RT__ | market_data.py | Bộ số liệu tương tự cho chế độ Real-time |
__CL2__, __FIRST__ | client_data.py | Dòng tiền nhà đầu tư theo ngày và nhóm; ngày giao dịch đầu từng CW (tab 2) |
__KB__, __KBRT__ | kafi_batches.py | Phân phối theo lô của TCPH nhà (Sync / Real-time) |
__VOL__, __IVR__ | vol_data.py, iv_db.py | Chuỗi IV hằng ngày từng CW, giá cơ sở, lãi suất (tab 3) |
__XK__ | kafi_extra.py | CW của TCPH nhà đã rời bảng giá nhưng chưa đáo hạn (tab 4) |
__EV__ | events_data.py | Sự kiện quyền phát hiện từ dữ liệu giá (tab 4) |
__MMQ__ | mm_data.py | Chất lượng chào giá trong phiên (tab 4.3) |
__ASOF__ | build.py | Ngày as-of |
9.1 Những kỹ thuật giúp file nhẹ và dễ sửa
- Chuỗi IV dạng mảng gọn: mỗi CW-ngày là một mảng
[chỉ số ngày, S, W, bid, ask, close, IV, IV P10, IV P90, vega, nguồn, số lần quét]thay vì đối tượng có tên trường, giảm dung lượng nhiều lần. - Biểu đồ SVG tự vẽ bằng chuỗi HTML, không phụ thuộc thư viện hay mạng.
- Bảng sắp xếp dùng chung: một hàm
sortTable(id, cột, dòng, {key, asc}), mỗi cột khai báo khoá, tiêu đề, hàm hiển thị, hàm tô màu. - Song ngữ không sửa HTML: giao diện viết bằng tiếng Anh;
settings.js.htmlgiữ từ điển cụm từ Anh → Việt và một MutationObserver dịch mọi nút chữ mới xuất hiện. Thêm nhãn mới thì thêm một dòng vào từ điển. - Sáng/Tối: mọi màu là biến CSS, đổi bằng thuộc tính
data-themetrên thẻ html; lựa chọn được trình duyệt ghi nhớ. - Chế độ Live: khi dựng từ
live.py, trang được chèn giờ cập nhật kế tiếp và tự tải lại đúng lúc đó, giữ tab đang xem qua phần#của địa chỉ.
10. Nội dung và công thức từng tab
10.1 Tab 1 · Competitor Overview
| Phần | Công thức chính |
|---|---|
| KPI thị trường | Số CW, số TCPH, số mã cơ sở · giá trị niêm yết = Σ số niêm yết × W · giá trị nhà đầu tư nắm = Σ min(max(Net sold, 0), số niêm yết) × W · giá trị giao dịch · % CW có giao dịch · số ITM/OTM/ATM · trung vị (IV − GARCH) |
| Thị phần theo TCPH | Tỷ trọng theo số mã, theo giá trị nắm giữ, theo giá trị giao dịch, theo Net sold · trung vị % phân phối, đòn bẩy, giá, DTE · tỷ lệ CW “chết” (phân phối < 5%) · 3 mã cơ sở lớn nhất |
| Định giá so với phân phối | IV tương đối = IV của CW − trung vị IV các CW cùng mã cơ sở. Đặt cạnh % phân phối để thấy TCPH định giá rẻ có phân phối tốt hơn không |
| Nhóm sản phẩm | Chia CW theo moneyness (OTM >20%, 10–20%, 0–10%, ITM 0–10%, >10%), đòn bẩy hiệu dụng (<4x, 4–6x, 6–8x, >8x), DTE (≤30, 31–90, 91–180, >180 ngày), giá CW, IV tương đối. Mỗi nhóm: % cung, % nắm giữ, % giao dịch, vòng quay = KL giao dịch / KL nắm giữ, chỉ số ưa chuộng = % nắm giữ / % cung |
| Phân phối theo lô | Mỗi lô phát hành của TCPH nhà: % phân phối(t) = Σ lượng lưu hành / Σ số niêm yết. Có tồn kho nội bộ thì lưu hành = niêm yết − tồn kho; sau ngày tồn kho cuối thì nối tiếp bằng tự doanh |
| Bảng toàn bộ CW | Mọi cột của Horizon kèm % thay đổi giá, trạng thái trần/sàn (biên độ ±7% giá cơ sở chia CR, làm tròn bước 10 đ) |
10.2 Tab 2 · Client Overview
“Nhà đầu tư” là phía đối diện của tự doanh TCPH: nhà đầu tư mua = TCPH bán. Mỗi giao dịch tự doanh trong ngày được gắn đặc điểm của CW tại ngày đó: moneyness theo giá cơ sở ngày đó, DTE ngày đó, đòn bẩy hiệu dụng = S / (giá bình quân × CR) × N(d1) với σ = HV 60 phiên tại ngày đó. Cộng theo kỳ chọn (Hôm nay, 1 tuần, 1 tháng, 3 tháng hoặc tự chọn) ra dòng tiền mua, bán, ròng theo nhóm, theo mã cơ sở và theo ngày.
10.3 Tab 3 · Volatility
| Phần | Cách tính |
|---|---|
| 3.1 Kiểm tra trước phiên tới | Giá tham chiếu = giá đóng cửa cơ sở phiên trước; trần/sàn = ±7% làm tròn theo bước giá HOSE (10 đ dưới 10.000, 50 đ dưới 50.000, 100 đ từ 50.000). Định giá CW tại sàn · giá chọn · trần với IV tham chiếu. Nhập giá chào của TCPH khác thì suy ra IV ngầm và dãy sàn/trần tương ứng |
| 3.2 Tín hiệu IV | ΔIV = IV hôm nay − hôm qua (điểm vol). Ngưỡng nhiễu = max(IV_JUMP_PTS, bước giá / vega). |ΔIV| < ngưỡng → Normal; giảm → IV Cut, tăng → IV Increase; cùng chiều ≥ 5 phiên và tổng ≥ 2 × ngưỡng → Persistent IV Decay/Expansion. Ngày không đủ tin cậy (không có IV ngày, vega ≤ 0, giá trị thời gian quá nhỏ) → Low Reliability |
| Phân vị IV | Trung vị IV các CW tin cậy của cùng mã cơ sở hôm nay so với chính nó trong tối đa 252 phiên gần nhất. Không bị méo bởi sự kiện quyền hay mức IV lúc niêm yết |
| 3.3 Lịch sử IV | Đường IV theo ngày từng CW, giá cơ sở trục phải; ngắt nét ở ngày thiếu dữ liệu |
| 3.4 IV theo TCPH | Các CW cùng mã cơ sở, so IV của từng TCPH theo DTE |
10.4 Tab 4 · Risk & Events
4.1 Rủi ro sổ CW của TCPH nhà. Tính cho mọi CW còn lưu hành, kể cả CW đã qua ngày giao dịch cuối nhưng chưa đáo hạn. OI = lượng lưu hành (số niêm yết − tồn kho, hoặc ước tính từ tự doanh). σ = IV; dùng HV nếu CW ITM sâu (moneyness > 15%), giá trị thời gian < 5% giá CW, hoặc không có IV; không có cả hai và ITM thì delta = 1/CR.
| Chỉ số | Công thức (đơn vị đồng) |
|---|---|
| Giá trị thị trường CW lưu hành (khoản phải trả) | OI × W, tách thành nội tại = OI × max(S − K, 0)/CR và giá trị thời gian = phần còn lại |
| Delta CW | −OI × N(d1)/CR × S |
| Delta Exposure | Delta CW + số cổ phiếu phòng hộ × S |
| Gamma (1%) | ½ × (−OI × Γ/CR) × (S × 1%)², Γ = n(d1) / (S·σ·√T): lãi lỗ bậc hai khi cơ sở biến động 1% |
| Vega | OI × S·n(d1)·√T / 100 / CR: giá trị nghĩa vụ tăng thêm khi IV +1 điểm |
| Theta | −OI × Θ/CR, Θ = [−S·n(d1)·σ/(2√T) − rK·e−rT·N(d2)] / 365: TCPH hưởng mỗi ngày lịch |
| Kịch bản ±7% | Chưa phòng hộ: −OI × [W(S × 1,07) − W(S)]; đã phòng hộ: cộng thêm OI × Δ/CR × (S × 0,07) |
Ví dụ tiếp mục 6.1 với OI = 2.000.000 CW: khoản phải trả 1,80 tỷ (toàn bộ là giá trị thời gian) · Delta CW −7,82 tỷ (cần khoảng 260.500 cổ phiếu để phòng hộ) · Gamma (1%) −0,86 triệu · Vega 34,3 triệu mỗi điểm IV · Theta +9,77 triệu/ngày · cơ sở +7%: chưa phòng hộ −588 triệu, đã phòng hộ −41 triệu.
4.2 Lịch sự kiện. CW đáo hạn trong 30/45/90 ngày và giá trị thanh toán dự kiến; CW mới niêm yết 30 ngày; sự kiện quyền của mã cơ sở được phát hiện từ dữ liệu giá, không cần lịch ngoài: hệ số = giá điều chỉnh (SSI) / giá chưa điều chỉnh (LiveDragon) mỗi ngày, lấy trung vị trượt 3 ngày; hệ số đổi hơn 0,5% → ngày giao dịch không hưởng quyền, tỷ lệ = hệ số trước / hệ số sau.
4.3 Chất lượng tạo lập thị trường. Tính theo thời gian trên toàn phiên liên tục (9:15–11:30, 13:00–14:30, bỏ 5 phút đầu mỗi nửa phiên), không dùng một ảnh chụp cuối ngày. Mỗi trạng thái bảng giá có trọng số bằng số giây nó tồn tại. Loại các giây không thể chào hai chiều: cổ phiếu cơ sở trắng một bên (đứng trần/sàn), hoặc CW chào bán ở giá sàn 10 đ.
| Chỉ số | Công thức (cộng dồn trên mọi CW-ngày của nhóm) |
|---|---|
| % thời gian chào hai chiều | Σ giây có Bid > 0 và Ask > Bid / Σ giây hợp lệ |
| % thời gian đạt chuẩn | Σ giây hai chiều có chênh lệch ≤ N bước giá và khối lượng mỗi bên ≥ X CW / Σ giây hợp lệ (N, X đặt trong cấu hình) |
| Chênh lệch bình quân | Σ (Ask − Bid)/bước giá × giây / Σ giây hai chiều; và theo % giá giữa |
| % thời gian cách 1 bước | Σ giây chênh lệch đúng 1 bước / Σ giây hai chiều |
| Khối lượng tại giá tốt nhất | Σ (BidVol1 + OfferVol1)/2 × giây / Σ giây hai chiều |
| Chênh lệch hiệu dụng | Σ khối lượng khớp × 2|giá khớp − giá giữa ảnh chụp trước| / bước giá ÷ Σ khối lượng khớp |
| TCPH nhà so với TCPH khác | Trên cùng mã cơ sở: % đạt chuẩn của TCPH nhà − % đạt chuẩn của các TCPH khác gộp lại (điểm %); kèm TCPH tốt nhất |
11. Bảng tham số
Mọi tham số nằm trong một file config/api_config.py, chia mục [A]–[I]. Code đọc bằng getattr(config, "TÊN", mặc_định), nên thiếu dòng nào thì dùng mặc định, và bản cũ của file cấu hình vẫn chạy với code mới.
| Tham số | Ý nghĩa | Mặc định | Sau khi đổi |
|---|---|---|---|
[A] CW_API_URL… | Địa chỉ các API ở mục 4 | có sẵn | Run |
API_TIMEOUT | Số giây chờ mỗi lần gọi | 30 | Run |
[B] RISK_FREE_RATE | r trong Black-Scholes, một mức cho mọi CW | 0.07 | Run |
DIVIDEND_YIELD, TRADING_DAYS | Tỷ suất cổ tức q; số phiên/năm | 0 · 252 | Run |
[C] KAFI_ISSUER_KEYWORDS, ISSUER_ALIASES | Nhận diện TCPH nhà; gộp tên khác nhau của cùng TCPH | có sẵn | Rebuild |
KAFI_BATCHES, KAFI_DEFAULT_BATCH | Danh sách lô phát hành và các mã thuộc lô | — | Rebuild |
[D] KAFI_INVENTORY_FILE, KAFI_INVENTORY_UNTIL, KAFI_INVENTORY_BRIDGE | File tồn kho nội bộ; dùng đến ngày nào; có nối tiếp bằng tự doanh không | None · None · True | Rebuild |
KAFI_HEDGE_SHARES, KAFI_HEDGE_DATE | Cổ phiếu phòng hộ đang nắm (nhập tay) và ngày của số liệu | {} · None | Rebuild |
[E] REALTIME_SNAPSHOT, REFRESH_ALL, GARCH_BACKTEST | Chụp phiên mới nhất; bỏ cache; chạy backtest | True · False · False | Run |
[F] IV_HISTORY_DAYS, IV_WINDOW_SESSIONS | Số ngày lịch sử giá CW; số phiên hiển thị | 200 · 60 | Run / Rebuild |
IV_JUMP_PTS, IV_MIN_VEGA | Ngưỡng nhiễu tín hiệu IV; vega tối thiểu | 1.0 · 10 | Rebuild |
QUOTES_DAYS, QUOTES_WORKERS | Số ngày tải bù giá chào; số luồng song song | 100 · 4 | Run |
MM_MAX_TICKS, MM_MIN_VOL, MM_SKIP_MIN, MM_SESSIONS | Ngưỡng “đạt chuẩn” (bước giá, CW mỗi bên); phút bỏ đầu nửa phiên; số phiên hiển thị | 3 · 1000 · 5 · 20 | Rebuild (MM_SKIP_MIN: xoá data/quotes_mm rồi Run) |
[G] IV_SOURCE, IV_DB_FILE, IV_MIN_SCANS | Nguồn IV hằng ngày: auto / db / local; file IV quét; số lần quét tối thiểu | auto · None · 3 | Rebuild |
[H] MARKET_CLOSE, MAX_STEP_BACK | Giờ chốt; số ngày được lùi | 15:00 · 7 | Run |
MIN_HV_RETURNS, GARCH_WINDOW, GARCH_HORIZONS, GARCH_MAX_PERSISTENCE, GARCH_MAX_ABS_RETURN_PCT | Tham số HV và GARCH (mục 7) | 20 · 750 · [21…315] · 0.99 · 7.5 | Run, REFRESH_ALL một lần |
[I] LIVE_EVERY_MIN | Số phút giữa hai lần cập nhật ở chế độ Live | 10 | Chạy lại Live |
12. Dựng lại từ đầu: lộ trình 8 chặng
Thứ tự dưới đây đi từ phần có giá trị ngay đến phần nâng cao. Mỗi chặng có một phép kiểm tra; qua được mới làm chặng sau. Làm một mình mất vài tuần; làm cùng trợ lý AI thì mỗi chặng thường gói gọn trong một buổi.
| Chặng | Làm gì | Kiểm tra xong khi |
|---|---|---|
| 1. Lấy bảng giá | Gọi API 1 và 2, tách tỷ lệ chuyển đổi, đổi ngày, ghi CSV | Số CW khớp với bảng giá trên web; tỷ lệ là số |
| 2. Định giá | Viết Black-Scholes, giải IV, delta, các cột ở mục 6 | Ví dụ mục 6.1 ra đúng IV 60,3%, đòn bẩy hiệu dụng 4,34x |
| 3. Một ngày as-of + cache | Quy tắc mục 5, lưu kết quả từng bước theo ngày | Chạy 2 lần trong ngày, lần 2 không gọi lại API; chạy 10:00 ra ngày hôm trước |
| 4. Lịch sử và biến động | API 3 và 5: HV, Yang-Zhang theo kỳ hạn gốc, ADV; sau đó GARCH | HV của một mã khớp với tính tay trong Excel trên cùng dữ liệu |
| 5. Tự doanh và phân phối | API 6: luỹ kế và theo ngày, Net sold, % phân phối | Tổng Net sold của một CW khớp với cộng tay trên trang dstock |
| 6. Excel | Ghi Horizon theo tên cột qua xlwings, sao lưu trước khi ghi | Mở Excel thấy đủ 35 cột, định dạng khuôn còn nguyên |
| 7. Dashboard tab 1–2 | Module JSON + khuôn HTML + build.py (mục 9) | Mở file không mạng vẫn hiện đủ; KPI khớp tổng trong Excel |
| 8. Tab 3–4, Live | API 7 và lưu giá chào hằng ngày; IV hằng ngày, tín hiệu, Greeks, sự kiện, chất lượng chào giá; vòng lặp Live | Tín hiệu không bật trên ngày có sự kiện quyền; Greeks khớp ví dụ mục 10.4 |
12.1 Mẫu yêu cầu khi làm cùng trợ lý AI
Dán bài viết này vào cuộc trò chuyện, rồi yêu cầu từng chặng một. Ví dụ cho chặng 2:
Dựa trên mục 6 của tài liệu đính kèm, viết file option_pricing.py gồm: - black_scholes_call(S, K, T, r, sigma, CR) trả giá MỘT CW (đã chia CR) - implied_volatility(W, S, K, T, r, CR): Brent trong [0.0001, 5]; không có nghiệm thì trả NaN - call_delta(S, K, T, r, sigma) trả N(d1) Viết kèm test: S=30000, K=32000, CR=4, W=900, T=120/365, r=0.07 phải ra IV ≈ 0.603, N(d1) ≈ 0.521. Chỉ dùng numpy, scipy.
Ba nguyên tắc giúp mỗi chặng ra đúng ngay:
- Luôn nêu đơn vị (đồng hay nghìn đồng, ngày lịch hay phiên) và dấu (ai bán, ai mua).
- Yêu cầu kèm một phép kiểm tra bằng số cụ thể như cột thứ ba ở bảng trên.
- Giữ tên cột của các file trung gian ở mục 8, để các chặng sau ghép vào không phải sửa lại.
13. Vận hành và lỗi thường gặp
| Bạn muốn | Bấm | Ghi chú |
|---|---|---|
| Số liệu cuối ngày | Run CW Market Overview.bat | Sau 15:00. Đọc log: DATA CHECK toàn OK, không có WARNING |
| Theo dõi trong phiên | Run Live.bat | Để cửa sổ mở; trang tự tải lại |
| Chỉ đổi giao diện / tham số hiển thị | Rebuild Dashboard.bat | Không tải lại dữ liệu |
| Hiện tượng | Nguyên nhân | Xử lý |
|---|---|---|
| Log báo lùi ngày as-of | Một nguồn chưa có số hôm nay (thường là tự doanh) | Bình thường; chạy lại sau 15:30 |
| DASHBOARD NOT BUILT · date mismatch | Workbook và CSV khác ngày | Chạy Run, không dùng Rebuild |
| Dashboard trống sau Rebuild | Chưa chạy Run lần nào | Chạy Run |
| Timeout, HTTP 403 | Mạng chậm hoặc gọi quá dày | Tăng API_TIMEOUT, giảm QUOTES_WORKERS |
| IV một mã nhảy bất thường vài tuần | Sự kiện quyền làm lệch giá cơ sở với giá chào | Kiểm tra mục 4.2; hệ số điều chỉnh phải được áp vào giá cơ sở |
| Tab 4.3 hiện bảng giá chào cuối ngày | Chưa có dữ liệu data/quotes_mm | Chạy Run sau 15:00; lần đầu tải lại khoảng 3 tháng, 30–40 phút |
| SyntaxError trong api_config | Thiếu dấu ngoặc kép hoặc dấu phẩy | Xem số dòng được báo, sửa hoặc khôi phục bản sao |
| Số liệu lạ sau khi sửa code | Cache cũ | Đặt REFRESH_ALL = True một lần |
14. Dữ liệu nội bộ, bản quyền và miễn trừ
- Tồn kho, tiểu khoản, số cổ phiếu phòng hộ và đường dẫn thư mục nội bộ là dữ liệu của tổ chức. Không đưa vào bài viết, không đăng dashboard có các số này ra ngoài; chỉ chia sẻ trong nội bộ theo quy định của đơn vị.
- Dữ liệu thị trường thuộc SSI, VNDIRECT, VDSC và Sở Giao dịch Chứng khoán TP.HCM; chỉ dùng trong phạm vi điều khoản của từng nơi.
- Ví dụ số trong bài (CW 30.000/32.000, OI 2 triệu CW) là giả định, không phản ánh vị thế của tổ chức nào.
- Mô hình Black-Scholes (Black & Scholes, 1973), GARCH (Bollerslev, 1986), GJR-GARCH (Glosten, Jagannathan & Runkle, 1993), Yang-Zhang (Yang & Zhang, 2000) là kiến thức công khai. Thư viện dùng kèm: pandas, numpy, scipy (BSD), arch (NCSA), xlwings (BSD), openpyxl (MIT), requests (Apache 2.0).
- Bài viết là chia sẻ kỹ thuật, không phải khuyến nghị đầu tư. Kiểm tra kỹ số liệu trước khi dùng cho báo cáo chính thức.

