- Sổ lệnh mua/bán top 3 (bid/offer)
- Giá khớp, khối lượng khớp
- Giá trần, sàn, tham chiếu
- Room khối ngoại
- Chỉ số (VN-INDEX, VN30…)
- Giao dịch thỏa thuận
Trang này dành cho cổ phiếu cơ sở (endpoint
/stream/normal). Nếu bạn cần bảng giá phái sinh, xem trang 7.2 — endpoint, channel ID và data type đều khác.Demo tương tác
Địa chỉ WSSKết nối
/ws/thesis/v1/stream/normal
WSS
Xác thực (Authentication)
Sau khi kết nối WebSocket thành công, bạn phải gửi auth message trước khi subscribe bất kỳ kênh nào. Token OpenAPI cần được base64 encode trước khi gửi. Format auth message gửi tới server (xxx = base64 của token_openapi):
Nếu auth thành công, server trả về:
d|33|15 — nghĩa là nếu client không gửi heartbeat trong 15 giây thì kết nối sẽ bị ngắt.
Đăng ký kênh (Subscribe)
Sau khi auth thành công, bạn có 4 cách đăng ký dữ liệu tuỳ nhu cầu: theo mã, theo sàn, theo chỉ số, và theo thỏa thuận.1. Theo mã cổ phiếu (tk)
Message subscribe theo mã gửi tới server:d|s|tk|bp+bi+tm+mp+op+fe|FPT,VCS,PNJ,PTB
Bảng channel codes tương ứng với channel ID mà server trả về:
2. Theo sàn (ro)
Message subscribe theo sàn gửi tới server:d|s|ro|bp+bi+tm+mp+op+fe|1,2 — server sẽ trả về các channel s|1, s|2, s|3, s|4, s|5, s|6 như trên.
3. Theo chỉ số (si)
Message subscribe theo chỉ số gửi tới server:d|s|si|rt|1,2 — server trả về channel s|8 (rt / stock index).
Bảng mã sàn / chỉ số (dùng cho cả ro và si):
4. Theo giao dịch thỏa thuận (pt)
Message subscribe thỏa thuận gửi tới server:d|s|pt|ptm+ptb+pts|1,2,3 — server trả về channel s|16 (pta) và s|17 (ptm). Mã sàn: 1-HOSE, 2-HNX, 3-UPCOM.
Huỷ đăng ký (Unsubscribe)
Để huỷ đăng ký, bạn dùng actionu thay vì s. Cú pháp giống hoàn toàn lệnh subscribe.
Format chung của message unsubscribe gửi tới server:
Ví dụ
Huỷ theo mã — message gửi tới server:Lấy dữ liệu snapshot (Request)
Ngoài subscribe (nhận realtime liên tục), bạn có thể gửi lệnh request để lấy snapshot hiện tại một lần duy nhất mà không cần subscribe. Dùng actionr.
Format message request gửi tới server (lưu ý phần properties để trống — 2 dấu pipe liên tiếp ||):
Ví dụ
Request snapshot theo mã — message gửi tới server:s|38 (Tickers snapshot) chứa toàn bộ thông tin hiện tại của các mã bạn yêu cầu.
Request snapshot theo sàn — message gửi tới server:
Request chỉ trả về 1 lần (one-shot). Nếu bạn cần dữ liệu liên tục, hãy dùng subscribe. Request hữu ích khi khởi tạo UI hoặc đồng bộ lại state sau reconnect.
Lịch sử khớp trong ngày — tmh (Ticker Match History)
Ngoài các channel cơ bản (bi, op, fe, bp, mp, tm), bạn có thể subscribe thêm tmh để nhận lịch sử khớp lệnh trong ngày (tick-by-tick).
Ví dụ subscribe có thêm tmh — message gửi tới server:
tmh, server trả về channel s|22 (TickerMatchHis) chứa lịch sử khớp lệnh trong ngày cho mỗi mã.
Channel 22 — Ticker Match History (tmh)
Khi mới subscribe, server sẽ push toàn bộ lịch sử khớp lệnh trong ngày (backfill). Sau đó tiếp tục push realtime mỗi khi có khớp mới.
Heartbeat — Giữ kết nối
Client PHẢI gửi heartbeat text frame mỗi 2 giây. Nếu server không nhận heartbeat trong 15 giây → ngắt kết nối. Message heartbeat gửi tới server:Cấu trúc Message
Server gửi 2 loại message, phân biệt qua prefix:
Các control message thường gặp từ server:
Format data message mà server trả về:
Channel ID & Data Schema
Channel 1 — Bid Info (Sổ lệnh mua — Top 3)
Channel 2 — Offer Info (Sổ lệnh bán — Top 3)
Channel 3 — Foreign Exchange (Khối ngoại)
Channel 4 — Base Price (Giá trần/sàn/tham chiếu)
Channel 5 — Matched Price (Thông tin phiên)
Channel 6 — Ticker Match (Giao dịch khớp)
Channel 8 — Stock Index (Chỉ số)
Channel 16 — PT Advertisement (Chào mua/bán thỏa thuận)
Channel 17 — PT Match (Khớp thỏa thuận)
So sánh Channel ID: Cổ phiếu vs Phái sinh
Sequence Diagram — Luồng hoàn chỉnh
Xử lý lỗi & Reconnect
Nguyên nhân disconnect
Chiến lược reconnect (khuyến nghị)
Dùng exponential backoff:delay = min(2^attempt, 30) giây. Tối đa 10 lần thử, sau đó dừng lại và alert.
Ngoài giờ giao dịch
Phiên cơ sở: 9:00–11:30 (sáng) và 13:00–14:45 (chiều), có phiên ATC đến ~14:45–15:00 tuỳ sàn. Ngoài giờ thì bạn vẫn connect bình thường, heartbeat vẫn cần gửi, nhưng sẽ không có data message nào. Khi phiên sau mở, data tự chảy lại — không cần reconnect.Code hoàn chỉnh
FAQ — Câu hỏi thường gặp
Tại sao bị disconnect sau 15-20 giây?
Tại sao bị disconnect sau 15-20 giây?
99% là do library tự gửi RFC ping frame. Phải disable auto-ping và tự gửi
d|p||| mỗi 2s.matchPrice là chuỗi (string) hay số (number)?
matchPrice là chuỗi (string) hay số (number)?
Bảng giá cơ sở trả string cho hầu hết trường giá và khối lượng (bi, op, fe, tm). Riêng bp, mp, rt trả number. Khuyến nghị: cast rõ ràng khi parse.
Muốn nhận toàn bộ một sàn thay vì từng mã thì làm sao?
Muốn nhận toàn bộ một sàn thay vì từng mã thì làm sao?
Dùng lệnh
ro — ví dụ d|s|ro|bp+bi+tm+mp+op+fe|1,2 để nhận toàn bộ VN-INDEX và VN30-INDEX.Chỉ số (VN-INDEX...) lấy ở channel nào?
Chỉ số (VN-INDEX...) lấy ở channel nào?
Subscribe bằng
d|s|si|rt|1,2 và đọc channel s|8 (rt / stock index).Connect ngoài giờ giao dịch có được không?
Connect ngoài giờ giao dịch có được không?
Được. Connection sống bình thường (vẫn cần heartbeat), nhưng không có data cho đến khi phiên mở (9:00).
Token expire thì sao?
Token expire thì sao?
Token hiệu lực tối đa 8 giờ. Server ngắt connection khi token hết hạn. Client cần detect disconnect → refresh token → reconnect.