Các thay đổi qua từng phiên bản vnstock-js
Bản vá cho môi trường serverless và cách báo lỗi mạng.
import "vnstock-js" không còn làm sập app trên Vercel, AWS Lambda hay Cloudflare. Trước đây chỉ cần nạp package là ném ENOENT: mkdir '/home/.../.vnstock-js' và mọi route trả 500, kể cả app không hề dùng watchlist. Nguyên nhân: instance watchlist được tạo ở cấp module, mà storage lại tạo thư mục trong home ngay lúc khởi tạo, trong khi serverless không có home ghi được.
Storage nay không đụng ổ đĩa lúc khởi tạo. Thư mục chỉ tạo ở lần ghi đầu tiên, và nếu home không ghi được thì tự chuyển sang thư mục tạm thay vì ném lỗi.
Request đứt giữa chừng không còn bị báo là HTTP 200: OK. Phản hồi lớn có thể đứt khi đang tải thân dữ liệu, sau khi header 200 đã về, khiến thư viện đọc nhầm thành lỗi HTTP thành công. Ngoài thông báo vô nghĩa, request kiểu này còn không được thử lại lần nào. Nay nhận diện đúng là lỗi truyền tải, ném NetworkError và thử lại theo backoff.
Không breaking. Chạy trên máy cá nhân không thấy khác biệt.
Nhóm API mức thị trường: độ rộng, thanh khoản, khối ngoại, bối cảnh cho AI.
market.breadth({ exchange }): số mã tăng, giảm, đứng giá, trần, sàn. Sàn nhận HOSE (mặc định), HNX, UPCOM, ALL.market.liquidity({ index, asOf }): giá trị giao dịch toàn sàn, kèm phiên trước và % thay đổi.market.foreignFlow({ exchange, top }) và stock.foreignFlow(symbol): mua, bán, ròng của khối ngoại, kèm top mua bán ròng.market.overview({ exchange }): gộp chỉ số, thanh khoản, độ rộng, khối ngoại trong một lời gọi.market.aiContext({ exchange, asOf }): regime thị trường, thanh khoản so với trung bình 20 phiên, độ rộng, khối ngoại.asOf cho stock.aiContext() và stock.toAIPrompt(): tính chỉ báo tại cuối một phiên quá khứ.init({ ratios: true }): tải bộ chỉ số theo quý dựng sẵn từ GitHub, cache 24h. Sàng lọc theo ROE, ROA, biên lợi nhuận không gọi mạng lần nào.vnstock market và vnstock foreign [symbol].Đơn vị tiền nhóm thị trường là tỷ VND, output kèm trường unit.
VNINDEX trước trả 1.66901, nay trả 1669.01 điểm. Nếu code đang nhân 1000 để bù thì bỏ đi.goldPriceGiaVangNet() trả dữ liệu đã chuẩn hoá. Field đổi tên: type_code thành code, type thành name, buy thành buyPrice, sell thành sellPrice.screening.screen() bắt buộc có phạm vi: phải truyền group hoặc exchange, không thì ném InvalidParameterError.screening chuyển sang REST. Endpoint GraphQL cũ trả body rỗng nên screen() trả mảng rỗng, người dùng đọc nhầm thành "không mã nào khớp". Bản mới lọc theo bảng giá trước rồi mới gọi chỉ số cho các mã sống sót.cause giữ nguyên đối tượng axios chứa socket trỏ vòng, nên JSON.stringify(err) ném lỗi và log qua Sentry hay pino bị hỏng.asOf lệch một ngày, do biên end của endpoint là loại trừ.vnstock market từng bị hiểu nhầm là mã chứng khoán.QuoteHistory.value: giá trị giao dịch từng bar, đơn vị triệu VND.QuoteHistory.symbol: mở khoá batch nhiều mã cho quote.history({ symbols: [...] }). Một request cho cả danh sách thay vì N request, giảm nguy cơ 429.Không breaking, cả hai đều là trường optional.
get_dividends và get_corporate_events: lịch cổ tức và sự kiện doanh nghiệp (ĐHCĐ, phát hành, niêm yết, giao dịch nội bộ).macd, bollinger, atr: ba indicator này có từ 1.4.0 nhưng quên re-export, buộc phải import qua subpath. Nay import thẳng từ vnstock-js.superTrend(candles, opts?): chỉ báo theo xu hướng, mặc định period=10, multiplier=3.ichimoku(candles, opts?) và ichimokuFutureCloud(): mây Ichimoku, bản thứ hai cho projection 26 phiên tới.aiContext nay kèm superTrend và ichimoku, và phân loại xu hướng có tính tới hai chỉ báo này.VciAdapter({ cache }): cache TTL cho các endpoint ít đổi. Mặc định bật, tắt bằng { cache: false }.RateLimitError và retry với backoff 30s, 60s, 120s thay vì báo lỗi chung.goldPriceSJC() deprecated: endpoint trả 403 từ IP ngoài Việt Nam. Dùng goldPriceBTMC() hoặc goldPriceGiaVangNet().Chuyển định vị từ SDK dữ liệu sang bộ công cụ nghiên cứu cho AI.
vnstock mcp): dùng được với Claude Desktop, Cursor, VS Code. 11 tool song ngữ.macd, bollinger, atr.stock.aiContext(symbol): JSON có cấu trúc gồm xu hướng, snapshot chỉ báo, kháng cự hỗ trợ, z-score khối lượng, hiệu suất 1d/7d/30d/90d.stock.toAIPrompt(symbol, { lang }): bản văn xuôi cho LLM không dùng MCP.quickQuote, recentHistory, compareSymbols, topMovers.vnstock.watchlist: CRUD, lưu tại ~/.vnstock-js/watchlist.json.Không breaking. Code 1.3.x chạy y nguyên.
news: tin tức tài chính Việt Nam từ news-crawler. news.byDate(date?), news.bySource(source, date?), news.search(keyword, date?).listing.allSymbols() vẫn bỏ qua vì endpoint trả 403.screening chưa chuyển REST, để dành bản sau.VNSTOCK_NO_UPDATE_CHECK=1.history --range 1d tính đúng Change % cho phiên cũ nhất, nhờ fetch thêm buffer 10 phiên để có mốc so sánh.Bản vá cho CLI sau khi release 1.3.0.
history --range 7d giờ trả đúng ~7 phiên (trước đây trả ~365 phiên do VCI API bỏ qua start khi countBack mặc định lớn). Handler tự tính countBack theo khoảng ngày và filter lại kết quả.56.291760000000004k.symbols --exchange HOSE giờ hoạt động (trước đây trả rỗng vì data lưu HSX). Directory.getByExchange tự map HOSE → HSX.symbols mặc định trả đầy đủ (trước đây tự cắt ở 50). --limit N chỉ áp dụng khi user chỉ định.vnstock -v cho --version (trước đây dùng -V hoa mặc định của commander). Version đọc từ package.json thay vì hardcode. --verbose ở sub-command bỏ alias -v để tránh xung đột.history và symbols: ví dụ VCB 2026-04-07 → 2026-04-14 (5 phiên) và HOSE (702 mã).docs/local-test.md: hướng dẫn npm link, watch mode, npm pack, debug CLI trước khi release.npm run dev: tsc --watch để auto rebuild khi sửa code.await init() bắt buộc trước khi dùng symbol lookup hoặc calendar API. Symbol và holiday data không còn bundle trong package, fetch runtime từ raw GitHub để luôn mới.
import { init } from "vnstock-js";
await init(); // gọi 1 lần lúc khởi động app
init() nhận options: symbolsUrl, holidaysUrl, ttl, force, cacheDir, noCache, timeout.
raw.githubusercontent.com/ttqteo/vnstock-js/master/data/*.json~/.vnstock-js/cache/, TTL mặc định 24hNotInitializedError và DataUnavailableError error typesnpm i -g vnstock-js hoặc npx vnstock-js <command>:
vnstock quote <SYMBOL>: snapshot 1 mãvnstock history <SYMBOL> [--from 7d|1w|1m|1y] [--range 7d] [--limit N]: OHLCVvnstock search <QUERY>: tìm mã theo tên/tickervnstock symbols [--exchange HOSE|HNX|UPCOM]: liệt kê mã--json, --csv, --no-color, -v, --verbose. Non-TTY auto plain text.unsubscribe() giờ gửi unsub message cho server. Message routing phân biệt quote/JSON/plain text. Loại bỏ WebSocket ping() vô nghĩa (browser không còn reset oan ~40s).deadManTimeout (mặc định 60s).RealtimeClientOptions.heartbeatInterval và heartbeatTimeout, thay bằng deadManTimeout?: number.data/*.json không còn bundle trong npm package.isTradeDay, nextTradeDay, prevTradeDay, holidays, giờ giao dịch sàn HOSERetry-After header rồi retrystock.search(query, { limit }) -- tìm mã cổ phiếu offlinelisting.search(), listing.getBySymbol(), listing.getByExchange(), listing.getByIndustry(), listing.allLocal()market.calendar.isTradeDay(date), nextTradeDay(date), prevTradeDay(date), holidays(year), session()fetchWithRetry hỗ trợ rateLimitWait option (mặc định 5s)SymbolInfo, TradingSession typesnpm run update-symbolsdata/symbols.json và data/holidays.json trong npm packageVnstockError, NetworkError, RateLimitError, ApiError, InvalidSymbolError, InvalidParameterError, ParseErrorRealtimeClient dùng EventEmitter pattern, auto-reconnect với exponential backoff, heartbeat, subscribe queueStockDataAdapter interface + VciAdapter, chuẩn bị cho multi-source sau nàyVnstockRealtime.connect/subscribe/parseData) thay bằng realtime.create() + RealtimeClient event emitterrealtime giờ là top-level export, không còn trên Vnstock class hay stock objectfetchWithRetry wrap axios errors thành custom error classesInvalidParameterError thay vì throw new Errorxlsx (2 CVE: Prototype Pollution + ReDoS)period giờ optional)ScreenResultQuoteHistory typeBreaking changes so với v0.5.x. Refactor toàn bộ kiến trúc.
stock.screening) -- lọc theo PE, ROE, vốn hóastock.price() -> stock.quote()stock.company() giờ là factory method trả về Company instanceVnstockTypes trỏ sang normalized typesparseData() trả về RealtimeQuote với field names mớistock.price -> stock.quotetrading.topGainers, trading.topLosers