Data lake locale A-share per AI agent
ashare-lake crea sul disco un data lake locale A-share con trentanove dataset, titoli delisted, query point-in-time e server MCP per AI agent.
Un data lake locale per le A-share è lo storico del mercato azionario della Cina continentale archiviato sul proprio disco come file Parquet colonnari, leggibili con DuckDB o Polars, invece di interrogare un endpoint del vendor una pagina alla volta. ashare-lake è un progetto open source che realizza questo archivio, insieme al job giornaliero che lo mantiene aggiornato e a un server Model Context Protocol che consente a un agente AI di interrogarlo. Due scelte progettuali meritano un approfondimento: i titoli delisted vengono conservati e i fondamentali possono essere letti alla data storica desiderata.
Perché un AI agent ha bisogno di un data lake locale sulle azioni cinesi
Un agent che analizza le azioni cinesi senza una copia locale ha due possibilità. Può fare scraping delle pagine finanziarie, consumando la context window con l’HTML e producendo numeri che nessuno potrà riprodurre il mese prossimo. Oppure può chiamare un vendor con accesso subordinato alla registrazione, che limita il numero di righe e lega ogni risultato a un account.
La scala è l’aspetto più spesso sottovalutato. Il nostro data warehouse contiene i dati del mercato statunitense con risoluzione al minuto, e una settimana ordinaria appare così:
L'esatto SQL dietro ogni numero
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 sessionSu Jul 20 il mercato ha prodotto 1.79 milioni di barre a un minuto su 11737 ticker, e le altre quattro sedute nel pannello mostrano lo stesso schema. Un solo mercato nazionale, una settimana, una sola risoluzione. Un decennio di barre giornaliere, dati fondamentali, composizione degli indici e dati sui flussi di capitale relativi a un altro mercato ha la stessa struttura, e trasferirlo pagina per pagina via HTTP esaurisce l’esecuzione di un agent.
Un data lake locale cambia due aspetti contemporaneamente. Le letture diventano una scansione di file anziché una richiesta soggetta a quota, e una query scritta oggi restituisce le stesse righe tra sei mesi. Questo è ciò che serve perché un backtest possa essere verificato. Le nostre note sulle competenze sui market data per gli AI agent e su una SQL API sui market data sostengono la stessa tesi per i dati statunitensi.
Installalo e fissa una versione
Python 3.10 o successivo. Fissa la versione: tra il 27 luglio e il 2 agosto 2026 sono state pubblicate sei release, quindi un’installazione senza versione fissata nello script di configurazione di un agent è soggetta a variazioni. Il codice si trova in rootSunc/ashare-lake ed è distribuito con licenza Apache 2.0.
pip install ashare-lake==0.5.0installa la release corrente all’inizio di agosto 2026.asl --versionvisualizza la build installata.asl config init --data-root /path/to/ashare-lakescrive il file TOML di esempio incluso nel pacchetto, compilando la directory principale dei dati; non serve fare il checkout del repository.--configimposta il percorso di output,--forcesovrascrive il file.asl doctoresegue i controlli offline, prima di spostare qualsiasi dato.asl servers testverifica gli host upstream delle quotazioni.asl sourcesverifica ogni fonte, con un--vantagepari acn,overseasolocal.
Fermati qui. Il comando successivo esegue il backfill e non va avviato mentre stai ancora leggendo.
Cosa fa il backfill
asl init crea la struttura delle directory e completa lo storico. La documentazione del progetto indica per un’esecuzione completa diverse ore di tempo effettivo e diversi GB di spazio su disco. Serve inoltre una connessione attiva a un host upstream di quotazioni Tongdaxin, verificata da asl servers test. asl init --profile quick copre invece gli ultimi tre anni in pochi minuti e mantiene comunque tutti i titoli negoziati in quella finestra, compresi quelli che nel frattempo hanno lasciato il mercato. asl run daily è il job incrementale successivo, asl status --datasets riporta la copertura e l’aggiornamento di ogni dataset, mentre asl serve pubblica una dashboard di sola lettura su 127.0.0.1:8787.
Il repository non include alcun dato. Ogni file Parquet viene creato sul computer dell’utente. Ogni riga contiene informazioni di lineage che indicano quale fonte l’ha prodotta e quando è stata acquisita.
Quali sono i 39 dataset?
Sono organizzati per livelli, partendo dai dati di riferimento: 36 tabelle curate e 3 tabelle derivate.
- Riferimenti: strumenti finanziari, calendario di trading dal 2016 al 2027, stato delle negoziazioni.
- Dati di mercato: barre giornaliere, barre degli indici, barre a 1 e 5 minuti, tick delle transazioni, barre delle commodity, fattori di rettifica, eventi di delisting.
- Eventi societari: corporate actions, indice degli annunci, calendario delle comunicazioni sugli utili.
- Fondamentali e valutazioni: voci di bilancio, metriche di valutazione, consenso degli analisti.
- Flussi di capitale: flussi dei fondi, margin trading, flussi e partecipazioni northbound, il dragon-tiger board con le comunicazioni sugli ordini di grande entità, block trades, partecipazioni degli investitori istituzionali.
- Struttura e settori: componenti dei settori, componenti degli indici, componenti dei comparti industriali, indice dei comparti industriali.
- Macro: indicatori macroeconomici, ampiezza del mercato, calendario economico.
- Sentiment e rotazione: punteggi di sentiment, classifica dei titoli più seguiti, barre dei settori, flussi dei fondi per settore, titoli delle notizie, flash news wire.
- Rischio e compliance: calendario dello sblocco delle azioni, eventi regolamentari.
La collocazione di un dataset indica quali aspetti l’autore considera importanti. I fattori di rettifica e gli eventi di delisting sono inclusi nel livello dei dati di mercato, accanto alle barre giornaliere, invece di essere relegati in un’appendice. Per chi testa strategie sui dati storici, questa scelta rappresenta metà del valore del progetto.
Come un archivio locale gestisce il survivorship bias
Il survivorship bias si verifica quando l’universo di uno studio viene costruito sui titoli ancora quotati oggi. Le società che si sono fuse, sono diventate private o sono state delistate scompaiono senza lasciare traccia. E i titoli che scompaiono raramente sono quelli con le performance migliori.
Il nostro warehouse può quantificare questo vuoto per il mercato statunitense, applicando la stessa aritmetica a un universo diverso. Per ogni anno, prendiamo tutti i simboli per i quali è stata registrata almeno una barra a un minuto nella seconda settimana di marzo. Poi verifichiamo quali risultavano ancora negoziati nelle ultime due settimane di luglio 2026:
L'esatto SQL dietro ogni numero
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 yearDei 8101 simboli negoziati quella settimana nel 2016, 50.1% risultavano ancora presenti sul mercato alla fine di luglio 2026, mentre 4040 non lo erano. La coorte 2025 registra 86.7%. Se si applica a ritroso, sui 10 anni precedenti, uno screen costruito sulle quotazioni odierne, la quota di mercato esclusa aumenta progressivamente.
L’ipotesi più comoda è che i titoli scomparsi fossero tutti penny stock. La suddivisione in fasce della coorte di marzo 2021, basata sul controvalore medio giornaliero degli scambi in quel mese, mostra invece un quadro diverso:
L'esatto SQL dietro ogni numero
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)La fascia under $1M ha perso la quota maggiore: 57.5% dei 3968 titoli. Anche la fascia più liquida non era immune: 3.4% dei 89 simboli che scambiavano $1B or more al giorno nel marzo 2021 non erano più presenti alla fine di luglio 2026. Fusioni, take-private, bancarotte e uscite dagli indici producono tutti lo stesso risultato in una tabella dei prezzi: le righe si interrompono.
ashare-lake tratta questo aspetto come un problema prioritario. Il dataset degli strumenti conserva i simboli delistati invece di filtrare solo quelli ancora attivi. Una tabella delisting_events registra come si è conclusa la storia di ciascun titolo. Inoltre, universe="all_a" nell'API Python risolve uno snapshot storico che li include. La documentazione del progetto segnala una differenza di circa due volte tra un backtest basato solo sui titoli sopravvissuti e uno che include i delisting nel periodo dal 2016 al 2021. È l’immagine speculare della trappola descritta nei nostri appunti sul look-ahead bias nel backtesting: un universo che conosce il futuro senza dichiararlo.
Letture point-in-time
load("financial_statement_items", as_of="2018-04-30") restituisce l’ultima versione di ciascuna voce annunciata entro quella data, non il valore successivamente ricalcolato. Le barre includono un argomento adjust: hfq per l’aggiustamento backward, qfq per la normalizzazione all’interno dell’intervallo della query, oppure i prezzi raw. Un fattore calibrato su valori che il mercato non aveva ancora pubblicato non misura nulla. È il primo controllo da effettuare in qualsiasi pipeline di fattori alpha generati da un LLM.
Registrazione come server MCP
Il Model Context Protocol è il meccanismo con cui un agent acquisisce gli strumenti. asl mcp comunica tramite stdio e il client avvia il processo:
claude mcp add ashare-lake -- asl mcp --config /abs/path/to/ashare-lake.toml- Qualsiasi altro client MCP usa gli stessi due elementi:
aslcome comando emcp --configpiù un percorso assoluto come argomenti. Il percorso deve essere assoluto, perché il client può avviare il processo da qualsiasi directory.
Sono disponibili sei strumenti, organizzati in base alla domanda a cui rispondono e non al dataset: describe_lake per sapere quali dati sono disponibili e come leggerli, resolve_symbol per associare un nome a un codice, inclusi i nomi di titoli delistati, query_bars, query_fundamentals con il relativo argomento as_of, query_dataset per tutto il resto e run_sql per eseguire una singola query DuckDB SELECT in sola lettura sui diversi dataset. Un flag --live consente al server di rispondere alle ricerche dei simboli e di fornire le barre giornaliere non rettificate dalla fonte upstream, senza scrivere nel lake.
Limiti da conoscere subito
- Solo A-shares. Sono esclusi Hong Kong, le quotazioni statunitensi e tutto ciò che è al di fuori della Cina continentale.
- È un progetto personale. Issue e pull request ricevono attenzione compatibilmente con il tempo disponibile. La documentazione chiarisce inoltre che non vi è alcuna garanzia di disponibilità: i siti upstream possono cambiare e un IP può essere bloccato, interrompendo l’acquisizione finché qualcuno non applica una correzione.
- Apache 2.0 copre il codice, non i dati. Ogni fonte upstream mantiene i propri termini e il maintainer non concede alcun diritto di redistribuire o rivendere i file Parquet creati. Prima di qualsiasi uso commerciale, leggete i termini delle fonti.
- Per le fonti consultate non servono account o token. È un vantaggio, ma anche un elemento di fragilità.
- Il supporto a Windows è arrivato con la versione 0.3.0, mentre con la 0.3.1 la versione minima di Python è passata a 3.10.
Da dove provengono queste informazioni sul progetto
La versione 0.5.0, le sei date di rilascio e la versione minima di Python provengono dalla cronologia delle release del progetto su PyPI e dal CHANGELOG, consultati il 4 agosto 2026. Il catalogo dei dataset, il comportamento relativo al delisting e ai dati point-in-time, i flag della CLI, l’elenco degli strumenti MCP e le indicazioni su licenza e supporto provengono dalla documentazione del repository: docs/datasets/catalog.md, docs/reference/cli.md, docs/reference/mcp.md e docs/legal-and-data-sources.md. Il software cambia più rapidamente degli articoli, quindi controllate la documentazione relativa alla versione che installate. I due pannelli sulla survivorship misurano simboli statunitensi nel nostro data warehouse, non quotazioni cinesi, e costituiscono un’illustrazione del meccanismo, non una misurazione del mercato A-share.
FAQ
Serve una API key per creare un data lake locale di azioni A?
Non con questo progetto. Le fonti upstream che legge non richiedono registrazione né token, e il lake risiede sul tuo computer. Ogni fonte mantiene i propri termini di utilizzo, che devono essere verificati prima di qualsiasi attività commerciale.
Quanto richiede il backfill di ashare-lake?
La documentazione indica che il backfill dell’intera storia richiede diverse ore di tempo effettivo e diversi GB di spazio su disco. Per tutta la durata dell’operazione è necessaria una connessione funzionante a un host upstream per le quotazioni. asl init --profile quick copre gli ultimi tre anni in pochi minuti e include ancora i titoli che nel frattempo sono stati delistati.
Un data lake locale di azioni A include i titoli delistati?
Questo sì. I simboli delistati restano nel dataset degli strumenti, una tabella delisting_events registra come si è conclusa la storia di ciascun titolo e universe="all_a" costruisce uno snapshot storico che li include. La nostra misurazione sul mercato USA riportata sopra mostra quanto esclude un universo composto soltanto dai sopravvissuti.
Un agente AI può interrogare direttamente ashare-lake?
Sì. asl mcp espone sei strumenti tramite il Model Context Protocol, tra cui uno strumento SQL di sola lettura. In questo modo l’agente interroga i file Parquet locali invece di eseguire scraping. Registralo con claude mcp add ashare-lake -- asl mcp --config /abs/path/to/ashare-lake.toml.
ashare-lake sostituisce AkShare o Baostock?
No. Si colloca al di sopra di queste librerie. AkShare e Baostock acquisiscono i dati dalle fonti upstream; questo progetto archivia, versiona e riconcilia i dati acquisiti in file Parquet curati, con tracciabilità a livello di riga e un contratto per ogni dataset.
Ogni dato numerico riportato sopra proviene da una query archiviata e versionata su dati di mercato reali. Espandi un pannello per leggere l’SQL oppure esegui lo stesso controllo del survivorship bias sul tuo universo nel terminale Strasmore.