Local A-Share Data Lake for AI Agents
ashare-lake dey build local A-share data lake for your disk, with 39 datasets, delisting records, point-in-time queries, and MCP server for agents.
Local A-share data lake na Chinese mainland equity market history wey dey sit for your own disk as columnar Parquet files. DuckDB or Polars fit read am, instead of vendor endpoint wey you dey call one page at a time. ashare-lake na open-source project wey dey build one, plus daily job wey dey keep am current and Model Context Protocol server wey allow AI agent query am. Two design choices make am worth this post: delisted names remain inside, and you fit read fundamentals as of any past date.
Why AI agent need local A-share data lake
Agent wey dey research Chinese equities without local copy get two options. E fit scrape finance pages, use e context window process HTML, then produce numbers wey nobody fit reproduce next month. Or e fit call vendor wey require registration, but vendor go cap the rows and tie every result to one account.
Na scale be the part people dey underestimate. Our own warehouse carry US tape for minute resolution, and one normal week of am look like this:
The exact SQL behind every number
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 sessionFor Jul 20, the tape produce 1.79 million minute bars across 11737 symbols, and the four other sessions for the panel repeat the same pattern. Na one national market, one week and one resolution. Ten years of daily bars, fundamentals, index membership and money-flow records for another market get the same shape. If agent dey page all of am over HTTP, e go burn through the run.
Local lake dey change two things at once. Reads become file scan instead of quota. And query wey you write today go return the same rows six months from now. Na wetin backtest need so person fit check the result. Our notes on market data skills for AI agents and SQL API over market data make the same point for US data.
Install am, pin am to one version
Python 3.10 or newer. Pin the version: six releases land between July 27 and August 2, 2026, so install wey no get pinned version inside agent setup script fit change anytime. The code dey rootSunc/ashare-lake under Apache 2.0.
pip install ashare-lake==0.5.0dey install the current release as of early August 2026.asl --versiondey show the installed build.asl config init --data-root /path/to/ashare-lakedey write the packaged example TOML with your data root filled in, and you no need checkout repository.--configdey set the output path, while--forcedey overwrite am.asl doctordey run its checks offline, before any data move.asl servers testdey check the upstream quote hosts.asl sourcesdey check each source, with a--vantageofcn,overseas, orlocal.
Stop for here. The next command na the backfill, and you no suppose run am while you dey read.
Wetin the backfill dey do
asl init dey create the directory layout and fill the history. The project docs talk say one full run fit take hours of wall time and several GB for disk. E also need live connection to upstream Tongdaxin quote host, and na asl servers test dey verify that connection. asl init --profile quick dey cover the latest three years instead, within minutes. E still keep every name wey trade inside that period, including names wey don comot from the market since then. asl run daily na the incremental job wey run afterwards. asl status --datasets dey report coverage and freshness for each dataset. asl serve dey put read-only dashboard for 127.0.0.1:8787.
The repository no come with any data. Na your machine dey build every Parquet file. Each row get row-level lineage wey record the source wey produce am and when dem fetch am.
Wetin be the 39 datasets?
Dem dey arranged in layers, starting from reference data: 36 curated tables and 3 derived ones.
- Reference: instruments, trading calendar wey cover 2016 to 2027, trading status.
- Market data: daily bars, index bars, 1-minute and 5-minute bars, trade ticks, commodity bars, adjustment factors, delisting events.
- Corporate events: corporate actions, announcement index, earnings disclosure schedule.
- Fundamentals and valuation: financial statement items, valuation metrics, analyst consensus.
- Capital flow: fund flow, margin trading, northbound flows and holdings, dragon-tiger board of large-order disclosures, block trades, institutional holdings.
- Structure and industry: sector members, index constituents, industry members, industry index.
- Macro: macro indicators, market breadth, economic calendar.
- Sentiment and rotation: sentiment scores, hot rank, sector bars, sector fund flow, news headlines, flash news wire.
- Risk and compliance: share unlock schedule, regulatory events.
Where dataset dey sit tell you wetin the author value. Adjustment factors and delisting events dey inside market-data layer beside daily bars. Dem no dey parked for appendix. That placement na the part of the project wey get the most value for anybody wey dey test ideas with historical data.
How local lake dey handle survivorship bias
Survivorship bias na wetin you get when the names wey still dey listed today na dem study universe come from. Every company wey merge, go private, or delist disappear quietly. And the names wey disappear hardly dey be the winners.
Our warehouse fit measure that gap for US market. Na the same arithmetic, but different alphabet. For every year, take every symbol wey print one-minute bar for the second week of March. Then check which ones still dey print for the last two weeks of July 2026:
The exact SQL behind every number
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 yearOut of the 8101 symbols wey dey trade that week for 2016, 50.1% still dey on the tape by late July 2026, while 4040 no dey again. The 2025 cohort show 86.7%. If you run screen wey build from today listings go backward across those 10 years, e go drop bigger share of the market as e dey go.
The easy assumption be say all the missing names na penny stocks. But when we sort the March 2021 cohort into tiers based on their average daily dollar volume that month, the result different:
The exact SQL behind every number
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)The under $1M tier lose the biggest share: 57.5% out of 3968 names. Even the busiest tier no escape. 3.4% out of the 89 symbols wey trade $1B or more per day for March 2021 don comot by late July 2026. Mergers, take-privates, bankruptcies, and index exits all end the same way for price table: the rows stop.
ashare-lake treats this as serious problem. The instruments dataset keep delisted symbols instead of filtering only live ones. A delisting_events table records how each departed name end, while universe="all_a" for the Python API resolves historical snapshot wey include dem. The project docs report roughly two-fold gap between survivor-only backtest and one wey include delisted names from 2016 to 2021. Na the opposite side of the trap for our look-ahead bias for backtesting notes: universe wey quietly know the future.
Point-in-time reads
load("financial_statement_items", as_of="2018-04-30") returns the latest version of each line item announced on or before that date, no be the number wey dem later restate. Bars get adjust argument: hfq for backward adjustment, qfq normalized inside the query window, or raw prices. Factor wey fit on numbers wey market never publish at that time no measure anything. Na the first thing to check for any LLM-generated alpha factor pipeline.
Registering am as MCP server
Model Context Protocol na how agent dey pick tools. asl mcp dey communicate am through stdio, and client dey launch the process:
claude mcp add ashare-lake -- asl mcp --config /abs/path/to/ashare-lake.toml- Any other MCP client still need the same two things:
aslas the command, plusmcp --configand an absolute path as the arguments. The path must be absolute because client fit start the process from any directory.
Six tools dey available. Dem organize am by the question wey dem answer, no be by dataset: describe_lake dey show wetin exist and how to read am; resolve_symbol dey convert name to code, including delisted names; query_bars; query_fundamentals with im as_of argument; query_dataset for every other request; and run_sql for one read-only DuckDB SELECT across datasets. A --live flag allow the server answer symbol lookups and unadjusted daily bars from upstream without writing anything to the lake.
Limits wey you suppose know first
- Na A-shares only. No Hong Kong, no US listings, and nothing outside mainland China.
- Na personal project. Dem dey attend to issues and pull requests as much as dem fit, and the docs talk am plainly say availability no dey guaranteed: upstream sites fit change, and IP fit get block, wey go stop ingest until person patch am.
- Apache 2.0 cover the code, no be the data. Each upstream source still get its own terms, and maintainer no grant right to redistribute or resell the Parquet files wey you build. Read the source terms before any commercial use.
- You no need account or token for the sources wey e reads. Na the attraction, and na also the weak point.
- Windows support enter for 0.3.0, and the Python floor move to 3.10 for 0.3.1.
Where these project facts come from
Version 0.5.0, the six release dates, and the Python floor come from the project PyPI release history and CHANGELOG, wey dem read on August 4, 2026. The dataset catalog, delisting and point-in-time behaviour, CLI flags, MCP tool list, plus licensing and support wording come from the repository docs: docs/datasets/catalog.md, docs/reference/cli.md, docs/reference/mcp.md, and docs/legal-and-data-sources.md. Software dey move faster than posts, so check the docs for the version wey you install. The two survivorship panels measure US symbols for our own warehouse, no be Chinese listings, and dem dey show how the mechanic work, no be measurement of the A-share market.
FAQ
You need API key to build local A-share data lake?
No be this one. The upstream sources wey e dey read no need registration or token, and the lake itself dey your machine. Each source get its own terms of use, and you need check them before any commercial work.
How long ashare-lake backfill dey take?
The docs talk say full history backfill fit take hours of wall time and several GB disk space. You need stable connection to upstream quote host throughout. asl init --profile quick covers the latest three years within minutes and still includes names wey don delist since then.
Local A-share data lake dey include delisted stocks?
This one dey include dem. Delisted symbols still dey inside the instruments dataset. A delisting_events table records how each name end, while universe="all_a" builds historical snapshot wey includes dem. Our US measurement above shows how much survivor-only universe dey leave out.
AI agent fit query ashare-lake directly?
Yes. asl mcp exposes six tools through Model Context Protocol. One of them na read-only SQL tool, so the agent queries local Parquet instead of scraping. Register am with claude mcp add ashare-lake -- asl mcp --config /abs/path/to/ashare-lake.toml.
ashare-lake replace AkShare or Baostock?
No. E dey sit above dem. Those libraries fetch data from upstream, while this project stores, versions and reconciles wetin dem fetch into curated Parquet. E also keeps row-level lineage and one contract for each dataset.
Every figure above na stored, versioned query from real market data. Expand any panel to read the SQL, or run the same survivorship check on your own universe for the Strasmore terminal.