Strasmore Research
Deep Dives · Matt ConnorBy Matt Connor · · Updated 2026-08-08

Data lake A-share nội bộ cho AI agent

ashare-lake xây dựng data lake A-share trên ổ đĩa của bạn, gồm 39 bộ dữ liệu, hồ sơ hủy niêm yết, truy vấn point-in-time và MCP server cho agent.

Một data lake A-share nội bộ là toàn bộ dữ liệu lịch sử của thị trường cổ phiếu Trung Quốc đại lục, được lưu trên ổ đĩa của bạn dưới dạng các tệp Parquet dạng cột. Bạn có thể đọc dữ liệu bằng DuckDB hoặc Polars, thay vì gọi một endpoint của nhà cung cấp theo từng trang. ashare-lake là một dự án mã nguồn mở xây dựng data lake này, kèm theo tác vụ hằng ngày để cập nhật dữ liệu và một máy chủ Model Context Protocol cho phép tác nhân AI truy vấn. Hai lựa chọn thiết kế khiến dự án đáng được giới thiệu ở đây: dữ liệu của các mã đã hủy niêm yết vẫn được giữ lại, và dữ liệu cơ bản có thể được truy xuất theo trạng thái tại một ngày trong quá khứ.

Vì sao một AI agent cần data lake nội địa cho dữ liệu cổ phiếu A-share

Một agent nghiên cứu cổ phiếu Trung Quốc nhưng không có bản sao dữ liệu nội bộ sẽ chỉ có hai lựa chọn. Một là thu thập dữ liệu từ các trang tài chính, tiêu tốn context window cho HTML và tạo ra những con số không ai có thể tái lập vào tháng sau. Hai là gọi đến nhà cung cấp yêu cầu đăng ký tài khoản, nơi giới hạn số dòng dữ liệu và gắn mọi kết quả với một tài khoản.

Quy mô là yếu tố thường bị đánh giá thấp. Kho dữ liệu của chúng tôi lưu trữ dữ liệu thị trường Mỹ ở độ phân giải theo phút. Một tuần thông thường trong kho có quy mô như sau:

Truy vấnMột tuần tape theo phút của Mỹ: ticker và số bar mỗi phiên, 20–24/7/2026
Câu lệnh SQL chính xác đằng sau mỗi con số
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS session,
       formatDateTime(toDate(toTimeZone(window_start, 'America/New_York')), '%b %e') AS session_label,
       uniqExact(ticker) AS tickers_count,
       round(count() / 1000000, 2) AS minute_bars_millions
FROM global_markets.delayed_stocks_minute_aggs
WHERE toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-07-20')
  AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-24')
GROUP BY session, session_label
ORDER BY session
Run this yourself

Trong Jul 20, thị trường tạo ra 1.79 triệu minute bars trên 11737 mã. Bốn phiên còn lại trong bảng cũng có quy mô tương tự. Một thị trường quốc gia, một tuần, một độ phân giải. Với một thị trường khác, dữ liệu theo ngày trong một thập kỷ, dữ liệu fundamentals, thành phần chỉ số và dữ liệu dòng tiền cũng có quy mô tương tự. Việc phân trang khối dữ liệu đó qua HTTP sẽ nhanh chóng tiêu tốn toàn bộ một lượt chạy của agent.

Data lake nội bộ đồng thời thay đổi hai yếu tố. Hoạt động đọc dữ liệu trở thành một lần quét tệp thay vì phụ thuộc vào hạn mức truy vấn. Một truy vấn được viết hôm nay cũng trả về cùng các dòng dữ liệu sau sáu tháng. Đây là điều cần thiết để một backtest có thể được kiểm chứng. Các ghi chú của chúng tôi về kỹ năng dữ liệu thị trường cho AI agentSQL API trên dữ liệu thị trường cũng đưa ra lập luận tương tự đối với dữ liệu Mỹ.

Cài đặt và cố định một phiên bản

Python 3.10 trở lên. Hãy cố định phiên bản: có sáu bản phát hành trong khoảng từ ngày 27 tháng 7 đến ngày 2 tháng 8 năm 2026, nên việc cài đặt không cố định phiên bản trong script thiết lập của agent sẽ khiến môi trường luôn có thể thay đổi. Mã nguồn nằm tại rootSunc/ashare-lake theo giấy phép Apache 2.0.

  • pip install ashare-lake==0.5.0 cài đặt bản phát hành hiện tại vào đầu tháng 8 năm 2026.
  • asl --version in thông tin bản build đã cài đặt.
  • asl config init --data-root /path/to/ashare-lake ghi tệp TOML mẫu đi kèm, đã điền thư mục gốc dữ liệu của bạn, mà không cần checkout repository. --config đặt đường dẫn đầu ra, còn --force cho phép ghi đè.
  • asl doctor chạy các bước kiểm tra ở chế độ offline trước khi dữ liệu được di chuyển.
  • asl servers test kiểm tra các máy chủ quote upstream. asl sources kiểm tra từng nguồn, với --vantagecn, overseas hoặc local.

Dừng ở đó. Lệnh tiếp theo là backfill, không nên chạy ngay trong lúc bạn còn đang đọc.

Backfill hoạt động như thế nào

asl init tạo cấu trúc thư mục và bổ sung dữ liệu lịch sử. Tài liệu của dự án cho biết một lần chạy đầy đủ có thể mất hàng giờ và chiếm vài GB dung lượng ổ đĩa. Lệnh này cũng cần kết nối trực tiếp đến máy chủ dữ liệu giá Tongdaxin upstream. asl servers test dùng để xác minh kết nối đó. asl init --profile quick chỉ xử lý ba năm gần nhất và hoàn tất trong vài phút. Lệnh này vẫn giữ lại mọi mã từng giao dịch trong khoảng thời gian đó, kể cả những mã đã rời thị trường. asl run daily là tác vụ cập nhật gia tăng sau đó. asl status --datasets báo cáo độ bao phủ và độ mới của từng bộ dữ liệu. asl serve cung cấp dashboard chỉ đọc tại 127.0.0.1:8787.

Repository không chứa sẵn dữ liệu. Mọi tệp Parquet đều được tạo trên máy của bạn. Mỗi dòng đều có thông tin truy xuất nguồn gốc, ghi rõ nguồn dữ liệu đã cung cấp dòng đó và thời điểm dữ liệu được lấy.

39 bộ dữ liệu là gì?

Chúng được tổ chức theo từng lớp, bắt đầu từ dữ liệu tham chiếu và mở rộng ra bên ngoài: 36 bảng được tuyển chọn và 3 bảng dẫn xuất.

  • Dữ liệu tham chiếu: công cụ tài chính, lịch giao dịch bao phủ giai đoạn 2016–2027, trạng thái giao dịch.
  • Dữ liệu thị trường: dữ liệu OHLCV theo ngày, dữ liệu OHLCV của chỉ số, dữ liệu OHLCV theo khung 1 phút và 5 phút, trade ticks, dữ liệu OHLCV hàng hóa, hệ số điều chỉnh, các sự kiện hủy niêm yết.
  • Sự kiện doanh nghiệp: corporate actions, chỉ mục thông báo, lịch công bố kết quả kinh doanh.
  • Dữ liệu cơ bản và định giá: các khoản mục trên báo cáo tài chính, chỉ số định giá, đồng thuận của chuyên viên phân tích.
  • Dòng vốn: dòng tiền vào quỹ, giao dịch ký quỹ, dòng vốn và tỷ lệ nắm giữ của nhà đầu tư qua Stock Connect hướng Bắc, bảng Dragon-Tiger về công bố giao dịch lệnh lớn, giao dịch thỏa thuận, tỷ lệ nắm giữ của tổ chức.
  • Cấu trúc và ngành: các mã thành viên ngành, các cổ phiếu cấu thành chỉ số, các mã thành viên ngành, chỉ số ngành.
  • Vĩ mô: các chỉ báo vĩ mô, độ rộng thị trường, lịch kinh tế.
  • Tâm lý và luân chuyển: điểm số tâm lý, xếp hạng cổ phiếu hot, dữ liệu OHLCV của ngành, dòng tiền vào ngành, tiêu đề tin tức, luồng tin nhanh.
  • Rủi ro và tuân thủ: lịch cổ phiếu bị hạn chế giao dịch được mở khóa, các sự kiện pháp lý.

Vị trí của một bộ dữ liệu cho thấy tác giả coi trọng điều gì. Hệ số điều chỉnh và các sự kiện hủy niêm yết nằm trong lớp dữ liệu thị trường, bên cạnh dữ liệu theo ngày, thay vì bị đẩy vào phần phụ lục. Với bất kỳ ai kiểm định ý tưởng trên dữ liệu lịch sử, cách sắp xếp này là một trong những giá trị lớn nhất của dự án.

Một hồ địa phương xử lý sai lệch do chỉ xét các doanh nghiệp còn tồn tại như thế nào

Survivorship bias xảy ra khi phạm vi của một nghiên cứu chỉ được lấy từ các mã vẫn còn niêm yết hiện nay. Mọi công ty đã sáp nhập, trở thành công ty tư nhân hoặc bị hủy niêm yết đều âm thầm biến mất. Những mã biến mất này hiếm khi là các mã có kết quả tốt nhất.

Kho dữ liệu của chúng tôi có thể định lượng khoảng thiếu hụt đó trên thị trường Mỹ, với cùng một phép tính nhưng dùng một bảng chữ cái khác. Với mỗi năm, hãy lấy mọi mã có dữ liệu minute bar trong tuần thứ hai của tháng Ba. Sau đó kiểm tra xem mã nào trong số đó vẫn còn giao dịch trong hai tuần cuối tháng Bảy năm 2026:

Truy vấnĐo lường khả năng tồn tại: các nhóm ticker Mỹ tháng 3 vẫn giao dịch vào cuối tháng 7/2026
Câu lệnh SQL chính xác đằng sau mỗi con số
WITH on_tape_now AS (
    SELECT ticker
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-07-20')
      AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
    GROUP BY ticker
),
cohort AS (
    SELECT toYear(toTimeZone(window_start, 'America/New_York')) AS cohort_year,
           ticker
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE toYear(toTimeZone(window_start, 'America/New_York')) BETWEEN 2016 AND 2025
      AND toMonth(toTimeZone(window_start, 'America/New_York')) = 3
      AND toDayOfMonth(toTimeZone(window_start, 'America/New_York')) BETWEEN 10 AND 14
    GROUP BY cohort_year, ticker
)
SELECT c.cohort_year AS year,
       count() AS names_on_tape_count,
       countIf(n.ticker != '') AS still_trading_count,
       count() - countIf(n.ticker != '') AS gone_count,
       round(100 * countIf(n.ticker != '') / count(), 1) AS still_trading_pct
FROM cohort AS c
LEFT JOIN on_tape_now AS n ON c.ticker = n.ticker
GROUP BY year
ORDER BY year
Run this yourself

Trong số 8101 mã giao dịch trong tuần đó của năm 2016, có 50.1% mã vẫn còn xuất hiện trên tape vào cuối tháng Bảy năm 2026 và 4040 mã đã biến mất. Nhóm 2025 cho kết quả 86.7%. Nếu chạy một bộ lọc bắt đầu từ danh sách niêm yết hiện nay rồi truy ngược qua 10 năm đó, tỷ trọng thị trường bị loại bỏ sẽ ngày càng lớn.

Giả định dễ thấy là các mã biến mất đều là penny stock. Nhưng khi chia nhóm tháng Ba năm 2021 thành các tầng theo dollar volume trung bình mỗi ngày trong tháng đó, kết quả lại cho thấy điều ngược lại:

Truy vấnAi rời tape: ticker tháng 3/2021 theo khối lượng giao dịch hằng ngày tính bằng USD, đối chiếu với cuối tháng 7/2026
Câu lệnh SQL chính xác đằng sau mỗi con số
WITH on_tape_now AS (
    SELECT ticker
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-07-20')
      AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
    GROUP BY ticker
),
march_2021 AS (
    SELECT ticker,
           sum(toFloat64(close) * toFloat64(volume))
             / uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS avg_daily_dollar_volume
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2021-03-01')
      AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2021-03-31')
    GROUP BY ticker
)
SELECT multiIf(d.avg_daily_dollar_volume >= 1000000000, '$1B or more',
               d.avg_daily_dollar_volume >= 100000000, '$100M to $1B',
               d.avg_daily_dollar_volume >= 10000000, '$10M to $100M',
               d.avg_daily_dollar_volume >= 1000000, '$1M to $10M',
               'under $1M') AS liquidity_bucket,
       count() AS names_count,
       countIf(n.ticker = '') AS gone_count,
       round(100 * countIf(n.ticker = '') / count(), 1) AS gone_pct
FROM march_2021 AS d
LEFT JOIN on_tape_now AS n ON d.ticker = n.ticker
GROUP BY liquidity_bucket
ORDER BY min(d.avg_daily_dollar_volume)
Run this yourself

Tầng under $1M mất tỷ trọng lớn nhất, với 57.5% trong số 3968 mã biến mất. Tầng giao dịch sôi động nhất cũng không ngoại lệ: 3.4% trong số 89 mã có giá trị giao dịch $1B or more mỗi ngày vào tháng Ba năm 2021 đã biến mất trước cuối tháng Bảy năm 2026. Sáp nhập, đưa doanh nghiệp về tư nhân, phá sản và bị loại khỏi chỉ số đều kết thúc theo cùng một cách trong bảng giá: các dòng dữ liệu dừng lại.

ashare-lake xem đây là một vấn đề cốt lõi. Bộ dữ liệu instruments giữ lại các mã đã bị hủy niêm yết thay vì chỉ lọc các mã còn giao dịch. Bảng delisting_events ghi nhận cách mỗi mã rời thị trường. Trong Python API, universe="all_a" truy xuất một snapshot lịch sử có bao gồm các mã này. Tài liệu của dự án cho biết chênh lệch giữa backtest chỉ dùng các mã còn tồn tại và backtest bao gồm cả mã bị hủy niêm yết vào khoảng two-fold trong giai đoạn 2016–2021. Đây là mặt đối lập của cái bẫy được nêu trong ghi chú về look-ahead bias trong backtesting của chúng tôi: một universe âm thầm biết trước tương lai.

Dữ liệu tại từng thời điểm

load("financial_statement_items", as_of="2018-04-30") trả về phiên bản mới nhất của từng chỉ tiêu được công bố vào hoặc trước ngày đó, thay vì con số được điều chỉnh lại sau này. Các bar có tham số adjust: hfq để điều chỉnh ngược, qfq để chuẩn hóa trong phạm vi thời gian của truy vấn, hoặc dùng giá thô. Một factor được xây dựng từ các con số mà thị trường chưa từng công bố sẽ không đo lường được điều gì. Đây là điều đầu tiên cần kiểm tra trong mọi pipeline tạo alpha factor bằng LLM.

Đăng ký dưới dạng MCP server

Model Context Protocol là cơ chế để agent tiếp nhận các công cụ. asl mcp giao tiếp qua stdio, còn client sẽ khởi chạy tiến trình:

  • claude mcp add ashare-lake -- asl mcp --config /abs/path/to/ashare-lake.toml
  • Mọi MCP client khác cũng sử dụng hai thành phần tương tự: asl làm lệnh, và mcp --config cùng với đường dẫn tuyệt đối làm đối số. Đường dẫn phải là đường dẫn tuyệt đối vì client có thể khởi chạy tiến trình từ bất kỳ thư mục nào.

Sáu công cụ được cung cấp và sắp xếp theo câu hỏi cần giải đáp, thay vì theo dataset: describe_lake dùng để xem dữ liệu hiện có và cách đọc; resolve_symbol dùng để chuyển tên thành mã, bao gồm cả các mã đã bị hủy niêm yết; query_bars; query_fundamentals với đối số as_of; query_dataset cho mọi nhu cầu khác; và run_sql để chạy một câu lệnh DuckDB SELECT chỉ đọc trên nhiều dataset. Cờ --live cho phép server truy vấn trực tiếp từ nguồn upstream để trả lời yêu cầu tra cứu mã và cung cấp dữ liệu giá theo ngày chưa điều chỉnh, mà không ghi dữ liệu vào lake.

Các giới hạn cần biết trước

  • Chỉ bao phủ cổ phiếu A. Không bao gồm Hong Kong, các mã niêm yết tại Mỹ hay bất kỳ thị trường nào ngoài Trung Quốc đại lục.
  • Đây là một dự án cá nhân. Các issue và pull request được xử lý trong khả năng cho phép. Tài liệu cũng nêu rõ rằng không có cam kết về tính sẵn sàng: các trang nguồn có thể thay đổi, hoặc một IP có thể bị chặn, khiến quá trình thu thập dữ liệu dừng lại cho đến khi có người cập nhật mã.
  • Apache 2.0 áp dụng cho mã nguồn, không áp dụng cho dữ liệu. Mỗi nguồn upstream vẫn giữ các điều khoản riêng. Người duy trì không cấp quyền phân phối lại hoặc bán các tệp Parquet mà bạn tạo ra. Hãy đọc điều khoản của nguồn trước khi sử dụng cho mục đích thương mại.
  • Các nguồn mà dự án truy vấn không yêu cầu tài khoản hoặc token. Đây là ưu điểm, nhưng cũng là điểm dễ phát sinh rủi ro.
  • Windows được hỗ trợ từ phiên bản 0.3.0, còn phiên bản Python tối thiểu được nâng lên 3.10 từ phiên bản 0.3.1.
Các thông tin về dự án này lấy từ đâu

Phiên bản 0.5.0, sáu ngày phát hành và phiên bản Python tối thiểu được lấy từ lịch sử phát hành trên PyPI và CHANGELOG của dự án, được kiểm tra vào ngày 4 tháng 8 năm 2026. Danh mục dataset, cơ chế delisting và point-in-time, các cờ CLI, danh sách công cụ MCP, cùng nội dung về cấp phép và hỗ trợ được lấy từ tài liệu trong repository: docs/datasets/catalog.md, docs/reference/cli.md, docs/reference/mcp.mddocs/legal-and-data-sources.md. Phần mềm thay đổi nhanh hơn các bài viết, vì vậy hãy kiểm tra tài liệu tương ứng với phiên bản bạn cài đặt. Hai biểu đồ survivorship sử dụng các ticker của Mỹ trong kho dữ liệu riêng của chúng tôi, không phải các mã niêm yết tại Trung Quốc. Đây là minh họa cho cơ chế, không phải phép đo thị trường cổ phiếu A.

Câu hỏi thường gặp

Có cần API key để xây dựng data lake cổ phiếu A-share cục bộ không?

Không cần với dự án này. Các nguồn upstream mà dự án đọc không yêu cầu đăng ký hoặc token, còn data lake được lưu trên máy của bạn. Mỗi nguồn có điều khoản sử dụng riêng, cần được xem xét trước khi dùng cho mục đích thương mại.

Mất bao lâu để backfill dữ liệu cho ashare-lake?

Tài liệu dự án cho biết việc backfill toàn bộ lịch sử có thể mất vài giờ theo thời gian thực và cần vài GB dung lượng đĩa. Kết nối ổn định với máy chủ báo giá upstream phải được duy trì trong suốt quá trình. asl init --profile quick bao phủ ba năm gần nhất chỉ trong vài phút và vẫn bao gồm các mã đã bị hủy niêm yết.

Data lake cổ phiếu A-share cục bộ có bao gồm cổ phiếu đã bị hủy niêm yết không?

Có. Các ticker đã bị hủy niêm yết vẫn nằm trong dataset instruments. Bảng delisting_events ghi lại cách mỗi mã kết thúc giao dịch, còn universe="all_a" xây dựng snapshot lịch sử có bao gồm các mã đó. Phép đo của chúng tôi đối với thị trường Mỹ ở trên cho thấy một tập dữ liệu chỉ gồm các mã còn tồn tại đã bỏ sót quy mô thông tin như thế nào.

AI agent có thể truy vấn trực tiếp ashare-lake không?

Có. asl mcp cung cấp sáu công cụ thông qua Model Context Protocol, trong đó có một công cụ SQL chỉ đọc. Nhờ vậy, agent truy vấn các tệp Parquet cục bộ thay vì scraping. Đăng ký công cụ này bằng claude mcp add ashare-lake -- asl mcp --config /abs/path/to/ashare-lake.toml.

ashare-lake có thể thay thế AkShare hoặc Baostock không?

Không. Dự án này nằm ở lớp phía trên chúng. Các thư viện đó lấy dữ liệu từ upstream, còn dự án này lưu trữ, quản lý phiên bản và đối soát dữ liệu đã lấy vào các tệp Parquet được tuyển chọn, kèm lineage ở cấp hàng và một contract cho mỗi dataset.


Mọi con số ở trên đều đến từ các truy vấn được lưu trữ và quản lý phiên bản trên dữ liệu thị trường thực. Hãy mở rộng bất kỳ panel nào để xem SQL, hoặc chạy cùng phép kiểm tra survivorship trên tập dữ liệu của bạn trong terminal Strasmore.

#market-data#mcp#a-shares#open-source#ai-agents