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

ashare-lake:本地 A 股資料湖與 AI agent 查詢

ashare-lake 將 A 股資料以 Parquet 儲存在本機,提供 39 個資料集、下市紀錄、時間點查詢,以及供 AI agent 使用的 MCP 伺服器。

本地 A 股資料湖,是將中國大陸股票市場的歷史資料以欄式 Parquet 檔案儲存在自己的磁碟上,可透過 DuckDB 或 Polars 讀取,而不是逐頁呼叫資料供應商的端點。ashare-lake 是一項開源專案,負責建立這套資料湖,並提供維持資料更新的每日工作,以及讓 AI agent 查詢資料的 Model Context Protocol 伺服器。這裡值得專文介紹的原因,在於它採用兩項設計:保留已下市的股票,且可依過去某個日期讀取基本面資料。

為什麼 AI agent 需要本地 A 股資料湖

研究中國股票的 agent 若沒有本地資料副本,只有兩條路可走。它可以擷取財經網頁,把 context window 浪費在 HTML 上,最後產出下個月無人能重現的數字。或者,它可以呼叫需要註冊的資料供應商;但這類服務通常限制資料列數,並將每個結果綁定至特定帳戶。

最容易被低估的是規模。我們自己的資料倉儲以分鐘頻率保存美國市場行情,普通一週的資料量如下:

查詢美國分鐘線一週概況:每個交易時段的股票代號與柱數,2026年7月20日至24日
每個數據背後的精確 SQL 語法
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

Jul 20,行情資料產生了 1.79 百萬筆分鐘 K 線,涵蓋 11737 檔標的;面板中的另外四個交易時段也是如此。一個全國性市場、一週、單一解析度。另一個市場若累積十年的日線資料、基本面資料、指數成分資料與資金流向紀錄,也會呈現同樣的規模;若透過 HTTP 分頁讀取,將耗盡 agent 的執行資源。

本地資料湖能同時改變兩件事。讀取資料時,執行的是檔案掃描,而不是受配額限制的請求;此外,今天撰寫的查詢在六個月後仍會回傳相同資料列,這是讓 backtest 可供查核的必要條件。我們關於AI agent 的市場資料技能以及建構在市場資料上的 SQL API的筆記,也對美國市場資料提出相同論點。

安裝,並固定至單一版本

Python 3.10 或更新版本。請固定版本:2026年7月27日至8月2日期間發布了六個版本,因此在 agent 的設定腳本中未固定版本的安裝,會隨時變動。程式碼位於 rootSunc/ashare-lake,採用 Apache 2.0 授權。

  • pip install ashare-lake==0.5.0 安裝截至2026年8月初的目前版本。
  • asl --version 顯示已安裝的組建。
  • asl config init --data-root /path/to/ashare-lake 寫入隨套件提供的範例 TOML,並填入你的資料根目錄;不需要簽出 repository。--config 設定輸出路徑,--force 會覆寫現有內容。
  • asl doctor 離線執行檢查,在任何資料移動前先完成驗證。
  • asl servers test 探測上游報價主機。asl sources 探測每個來源,並使用 --vantagecnoverseaslocal

到此為止。下一個指令會執行回補;不要一邊閱讀一邊啟動它。

回填作業的內容

asl init 建立目錄結構並填入歷史資料。專案文件指出,完整執行需要數小時的實際執行時間,並會占用數 GB 的磁碟空間;此外,還需要連線至上游 Tongdaxin 報價主機,這正是 asl servers test 所驗證的項目。asl init --profile quick 則改為處理最近三年的資料,幾分鐘內即可完成;在該期間內曾交易過的所有名稱都會保留,包括其後已退出市場者。之後由 asl run daily 執行增量作業,asl status --datasets 回報各資料集的涵蓋範圍與資料新鮮度,asl serve 則在 127.0.0.1:8787 提供唯讀儀表板。

此 repository 完全不附帶資料。每個 Parquet 檔案都會在你的機器上建立,且每一列都記錄來源及抓取時間,以保留列層級的資料 lineage。

39 個資料集有哪些?

這些資料集按層次排列,從參考資料向外延伸:包括 36 個整理後的資料表,以及 3 個衍生資料表。

  • 參考資料:金融工具、涵蓋 2016年至2027年的交易日曆、交易狀態。
  • 市場資料:日線行情、指數行情、1分鐘與5分鐘行情、逐筆成交資料、商品行情、調整因子、下市事件。
  • 公司事件:公司行動、公告索引、財報披露時程。
  • 基本面與估值:財務報表項目、估值指標、分析師共識。
  • 資金流:資金流向、融資融券、北向資金流向與持股、大宗交易披露的龍虎榜、鉅額交易、機構持股。
  • 市場結構與產業:板塊成分股、指數成分股、產業成員、產業指數。
  • 總體經濟:總體經濟指標、市場廣度、經濟日曆。
  • 市場情緒與輪動:情緒分數、熱門排名、板塊行情、板塊資金流向、新聞標題、即時新聞快訊。
  • 風險與法遵:股份解禁時程、監管事件。

資料集所處的層次,反映作者重視的內容。調整因子與下市事件和日線行情一樣,均列在市場資料層,而不是放在附錄中。對任何以歷史資料測試交易想法的人而言,這項安排是整個專案中最有價值的部分。

本地資料如何處理存活者偏誤

存活者偏誤發生於研究樣本只取自目前仍掛牌的標的。所有曾合併、下市或轉為私人公司的企業,都會悄悄從樣本中消失;而消失的標的通常並非績效最佳者。

我們的資料倉庫可以量化美國市場中的這個缺口,計算方式相同,只是使用不同的代碼。對每一年,先取出在3月第2週出現過分鐘線資料的所有代號,再檢查其中哪些代號在2026年7月最後兩週仍有交易:

查詢存續情況實測:2026年3月美國股票代號群組至7月底仍在交易的比例
每個數據背後的精確 SQL 語法
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

2016當週交易的8101個代號中,50.1%個在2026年7月底仍出現在交易紀錄中,4040個則已消失。2025群組的結果為86.7%。若以今日仍掛牌的標的向前回溯10年建立篩選條件,隨著回溯時間拉長,會排除市場中逐漸擴大的比重。

一個常見且過於樂觀的假設是,消失的標的全都是仙股。將2021年3月的群組依當月平均每日美元成交量分級後,結果並非如此:

查詢誰已離開交易盤面:2021年3月股票代號按每日美元成交額分類,並與2026年7月底進行比對
每個數據背後的精確 SQL 語法
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

under $1M級距流失的比重最高,3968個標的中有57.5%個消失。成交最活躍的級距也不例外:2021年3月每日交易金額為$1B or more89個代號中,有3.4%個在2026年7月底前退出市場。無論是合併、收購私有化、破產或退出指數,在價格資料表中的結果都相同:資料列停止出現。

ashare-lake 將此視為首要問題。其 instruments 資料集保留已下市的代號,而非只篩選仍在交易的標的;delisting_events 資料表則記錄每個標的退出市場的原因;Python API 中的universe="all_a"可解析包含這些標的的歷史快照。該專案文件指出,2016年至2021年間,僅納入存活標的的回測結果與納入下市標的的回測結果,差距約達兩倍。這正好映照出我們在回測中的前視偏誤筆記所說的陷阱:樣本集合悄悄掌握了未來資訊。

即時點資料讀取

load("financial_statement_items", as_of="2018-04-30")會回傳截至該日期或更早日期公布的每個項目最新版本,而不是之後重編的數值。K線資料帶有adjust參數:hfq代表向後調整,qfq代表在查詢區間內進行標準化,或使用未調整價格。若因子是以市場當時尚未公布的數值建立,便無法衡量任何實際可交易的資訊;這是檢查任何LLM 生成的 alpha 因子流程時,首先應確認的事項。

註冊為 MCP server

Model Context Protocol 是 agent 取得工具的方式。asl mcp 透過 stdio 傳遞協定,而 client 會啟動該程序:

  • claude mcp add ashare-lake -- asl mcp --config /abs/path/to/ashare-lake.toml
  • 其他 MCP client 也會使用相同的兩個部分:以 asl 作為命令,並將 mcp --config 加上絕對路徑作為引數。路徑必須是絕對路徑,因為 client 可能會從任何目錄啟動該程序。

系統會提供六項工具,依問題類型而非資料集分類:describe_lake 用於查詢現有內容及其讀取方式;resolve_symbol 用於將名稱轉換為代碼,也包括已下市名稱;query_bars;帶有 as_of 引數的 query_fundamentals;用於其他所有查詢的 query_dataset;以及可跨資料集執行單一唯讀 DuckDB SELECT 的 run_sql。加入 --live 旗標後,server 可直接從上游來源回覆代碼查詢及未調整的每日行情資料,而不必寫入資料湖。

先了解這些限制

  • 僅支援 A 股。不涵蓋香港、美國上市標的,也不涵蓋中國大陸以外的市場。
  • 這是個人專案。Issue 與 pull request 僅會獲得盡力處理,文件也明確說明不保證可用性:上游網站可能變更,IP 也可能遭封鎖,導致資料擷取中斷,直到有人修補為止。
  • Apache 2.0 授權適用於程式碼,不適用於資料。每個上游來源均有自己的使用條款,維護者不授予重新散布或轉售所建立 Parquet 檔案的權利。任何商業用途前,請先閱讀來源條款。
  • 讀取這些來源不需要帳戶或 token;這正是其吸引力所在,也使其更為脆弱。
  • Windows 支援於 0.3.0 版本加入,Python 最低版本則在 0.3.1 版提升至 3.10。
這些專案資訊的來源

0.5.0 版本、六個發布日期及 Python 最低版本,取自專案的 PyPI 發布歷史與 CHANGELOG,資料查閱日期為2026年8月4日。資料集目錄、下架與 point-in-time 行為、CLI 旗標、MCP 工具清單,以及授權與支援說明,取自儲存庫文件:docs/datasets/catalog.mddocs/reference/cli.mddocs/reference/mcp.mddocs/legal-and-data-sources.md。軟體更新速度快於文章,因此請以所安裝版本的文件為準。兩個存活偏誤面板衡量的是我們自有資料倉儲中的美國 symbols,而非中國上市標的;其用途是說明運作機制,不代表對 A 股市場的測量。

常見問答

建立本機 A 股資料湖需要 API key 嗎?

不需要。它讀取的上游來源不要求註冊或 token,資料湖本身則存放在你的電腦上。每個來源都有各自的使用條款,在進行任何商業用途前都必須確認。

ashare-lake 回補完整歷史資料需要多久?

文件顯示,完整歷史資料回補需要數小時的實際執行時間,並占用數 GB 磁碟空間;整個過程都需要維持與上游報價主機的正常連線。asl init --profile quick 可在數分鐘內涵蓋最近三年資料,且仍包含後來下市的標的。

本機 A 股資料湖是否包含已下市股票?

包含。已下市的股票代號會保留在 instruments 資料集中,delisting_events 資料表則記錄每個標的的下市結果;universe="all_a" 會建立包含這些標的的歷史快照。我們上方對美國市場所做的測量,也顯示只保留存續標的的母體會遺漏多少資料。

AI agent 能直接查詢 ashare-lake 嗎?

可以。asl mcp 透過 Model Context Protocol 提供六項工具,其中一項是唯讀 SQL 工具,因此 agent 查詢的是本機 Parquet,而不是進行網頁抓取。請使用 claude mcp add ashare-lake -- asl mcp --config /abs/path/to/ashare-lake.toml 進行註冊。

ashare-lake 能取代 AkShare 或 Baostock 嗎?

不能。它位於這些工具之上。這些函式庫負責從上游取得資料;本專案則將取得的資料儲存、建立版本並進行調節,整理成具備逐列資料來源追蹤能力、且每個資料集各有一份契約的精選 Parquet。


上方每一項數據都是根據真實市場資料執行的已儲存、具版本控管的查詢。展開任一面板即可查看 SQL,或在 Strasmore terminal 上對你自己的標的母體執行相同的存活者偏誤檢查。

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