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

Lokaal A-share data lake voor AI-agents opbouwen

Bouw een lokaal A-share data lake op uw eigen schijf met negenendertig datasets. Beheer delisting records, point-in-time queries en een MCP server voor uw AI-agents.

Een lokaal A-share data lake
Een lokaal A-share data lake is de historische data van de Chinese vasteland-aandelenmarkt die als kolomgeoriënteerde Parquet-bestanden op uw eigen schijf staat. Deze zijn leesbaar via DuckDB of Polars, in plaats van via een vendor-endpoint dat u pagina voor pagina moet aanroepen. ashare-lake is een open-sourceproject dat zo’n data lake opbouwt, inclusief de dagelijkse taak die de data actueel houdt en een Model Context Protocol-server waarmee een AI-agent de data kan bevragen. Twee ontwerpkeuzes maken dit project het vermelden waard: geschrapte namen (delisted names) worden bewaard en fundamentele gegevens kunnen worden ingezien zoals die op een datum in het verleden bekend waren.

Waarom een AI-agent een lokaal A-share datameer nodig heeft

Een agent die onderzoek doet naar Chinese aandelen zonder lokale kopie, heeft twee opties. Hij schraapt financiële pagina's, waarbij hij zijn contextvenster verspilt aan HTML en cijfers produceert die volgende maand door niemand meer te reproduceren zijn. Of hij roept een leverancier aan met een registratievereiste, die het aantal rijen beperkt en elk resultaat koppelt aan een account.

De schaal is het aspect dat vaak wordt onderschat. Ons eigen datawarehouse bevat de Amerikaanse tape op minuutresolutie, en een doorsnee week ziet er als volgt uit:

QueryEén week US minute tape: symbolen en bars per sessie, 20-24 juli 2026
De exacte SQL achter elk getal
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

Op Jul 20 produceerde de tape 1.79 miljoen minuutbars over 11737 symbolen, en de vier andere sessies in het panel herhalen dit beeld. Eén nationale markt, één week, één resolutie. Een decennium aan dagelijkse bars, fundamentals, indexsamenstellingen en geldstroomgegevens voor een andere markt heeft dezelfde omvang, en het ophalen daarvan via HTTP put het werkgeheugen van een agent volledig uit.

Een lokaal datameer verandert twee zaken tegelijk. Leesacties worden een bestandsscan in plaats van een quotum, en een query die vandaag wordt geschreven, geeft over zes maanden dezelfde rijen terug; dit is essentieel voor de controleerbaarheid van een backtest. Onze aantekeningen over marktdata-vaardigheden voor AI-agenten en over een SQL API voor marktdata onderbouwen hetzelfde argument voor Amerikaanse data.

Installatie en versiebeheer

Python 3.10 of nieuwer. Pin de versie vast: tussen 27 juli en 2 augustus 2026 verschenen zes releases. Een niet-gepinde installatie in het setup-script van een agent is een bewegend doelwit. De code bevindt zich op rootSunc/ashare-lake onder de Apache 2.0-licentie.

  • pip install ashare-lake==0.5.0 installeert de huidige release van begin augustus 2026.
  • asl --version toont de geïnstalleerde build.
  • asl config init --data-root /path/to/ashare-lake schrijft het verpakte voorbeeld-TOML-bestand met uw ingevulde data root; een repository-checkout is niet nodig. --config stelt het uitvoerpad in, --force overschrijft bestaande bestanden.
  • asl doctor voert de controles offline uit, voordat er data wordt verplaatst.
  • asl servers test peilt de upstream quote-hosts. asl sources peilt elke bron, met een --vantage van cn, overseas of local.

Stop hier. Het volgende commando is de backfill; dit is geen actie die u moet uitvoeren terwijl u nog aan het lezen bent.

Wat de backfill doet

asl init creëert de mappenstructuur en vult de historie aan. Volgens de documentatie van het project kost een volledige run uren aan 'wall time' en neemt deze enkele gigabytes aan schijfruimte in beslag. Bovendien is een actieve verbinding met een upstream Tongdaxin-quotehost vereist, wat door asl servers test wordt geverifieerd. asl init --profile quick bestrijkt in plaats daarvan de afgelopen drie jaar, duurt slechts enkele minuten en behoudt elk aandeel dat binnen dat venster is verhandeld, inclusief de namen die inmiddels van de markt zijn verdwenen. asl run daily is de daaropvolgende incrementele taak, asl status --datasets rapporteert de dekking en actualiteit per dataset, en asl serve plaatst een read-only dashboard op 127.0.0.1:8787.

De repository bevat zelf geen data. Elk Parquet-bestand wordt op uw eigen machine opgebouwd, waarbij per rij de herkomst wordt vastgelegd: welke bron deze heeft geproduceerd en wanneer de data is opgehaald.

Wat zijn de negenendertig datasets?

Ze zijn gelaagd opgebouwd, van referentiedata naar buiten toe: zesendertig gecureerde tabellen en drie afgeleide tabellen.

  • Referentie: instrumenten, een handelskalender die de periode van tweeduizendzestien tot tweeduizendzevenentwintig beslaat, handelsstatus.
  • Marktdata: dagkoersen, indexkoersen, één-minuut- en vijf-minuutkoersen, trade ticks, grondstoffenkoersen, correctiefactoren, delisting-events.
  • Bedrijfsevenementen: corporate actions, een aankondigingsindex, het schema voor de publicatie van kwartaalcijfers.
  • Fundamentele en waarderingsdata: posten uit jaarrekeningen, waarderingsratio's, analistenconsensus.
  • Kapitaalstromen: fund flow, margin trading, northbound flows en holdings, de dragon-tiger board voor disclosures van grote orders, block trades, institutionele belangen.
  • Structuur en sector: sectorleden, indexsamenstellingen, industriële leden, sectorindex.
  • Macro: macro-indicatoren, market breadth, een economische kalender.
  • Sentiment en rotatie: sentimentscores, hot rank, sectorkoersen, sector fund flow, nieuwskoppen, een flash news wire.
  • Risico en compliance: het schema voor share unlocks, toezichthoudende gebeurtenissen.

De positie van een dataset geeft aan wat de auteur belangrijk vindt. Correctiefactoren en delisting-events bevinden zich in de marktdata-laag naast de dagkoersen, en zijn niet in een bijlage geplaatst. Die positionering is het deel van het project dat de meeste waarde biedt voor iedereen die ideeën toetst aan historische data.

Hoe een lokaal meer omgaat met survivorship bias

Survivorship bias ontstaat wanneer het universum van een onderzoek uitsluitend bestaat uit namen die vandaag de dag nog genoteerd staan. Elk bedrijf dat is gefuseerd, privaat is gegaan of van de beurs is gehaald, ontbreekt geruisloos, en de namen die verdwijnen zijn zelden de winnaars.

Ons warehouse kan dat gat voor de Amerikaanse markt kwantificeren; dezelfde rekenkunde in een ander alfabet. Neem voor elk jaar elk symbool dat een minute bar liet zien in de tweede week van maart, en controleer vervolgens welke daarvan nog steeds actief waren in de laatste twee weken van juli 2026:

QuerySurvivorship, gemeten: maart-cohorten van US symbolen die eind juli 2026 nog verhandeld worden
De exacte SQL achter elk getal
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

Van de 8101 symbolen die in die week in 2016 verhandelden, waren er 50.1% nog steeds op de tape in eind juli 2026, en 4040 niet. Het 2025 cohort leest 86.7%. Draai een screen die is gebouwd op basis van de huidige noteringen achterwaarts over die 10 jaar en het laat naarmate de tijd verstrijkt een steeds groter deel van de markt wegvallen.

De comfortabele aanname is dat de ontbrekende namen allemaal penny stocks waren. Het sorteren van het cohort van maart 2021 in categorieën op basis van het gemiddelde dagelijkse dollarvolume in die maand wijst op iets anders:

QueryWie verliet de tape: maart 2021 symbolen naar dagelijks dollar volume, getoetst aan eind juli 2026
De exacte SQL achter elk getal
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

De under $1M categorie verloor het grootste aandeel, 57.5% van de 3968 namen. De meest actieve categorie was niet vrijgesteld: 3.4% van de 89 symbolen die in maart 2021 $1B or more per dag verhandelden, waren tegen eind juli 2026 vertrokken. Fusies, take-privates, faillissementen en index-exits eindigen allemaal op dezelfde manier in een prijstabel: de rijen stoppen.

ashare-lake behandelt dit als een fundamenteel probleem. De dataset met instrumenten behoudt delisted symbolen in plaats van te filteren op actieve namen, een delisting_events tabel legt vast hoe elke verdwenen naam is geëindigd, en universe="all_a" in de Python API genereert een historische snapshot die deze namen bevat. De documentatie van het project rapporteert een verschil van ongeveer twee keer tussen een backtest met alleen survivors en een backtest inclusief delisting over de periode 2016 tot 2021. Dat is het spiegelbeeld van de valkuil in onze look-ahead bias in backtesting notities: een universum dat stilletjes de toekomst kent.

Point-in-time reads

load("financial_statement_items", as_of="2018-04-30") retourneert de laatste versie van elk postonderdeel dat op of vóór die datum is aangekondigd, niet het cijfer zoals dat later is herzien. Bars bevatten een adjust argument: hfq voor backward adjustment, qfq genormaliseerd binnen het queryvenster, of raw prices. Een factor die is gefit op cijfers die de markt nog niet had gepubliceerd, meet niets; dit is het eerste wat moet worden gecontroleerd in elke LLM generated alpha factor pipeline.

Registratie als MCP-server

Het Model Context Protocol is de wijze waarop een agent tools selecteert. asl mcp communiceert via stdio en de client start het proces:

  • claude mcp add ashare-lake -- asl mcp --config /abs/path/to/ashare-lake.toml
  • Elke andere MCP-client vereist dezelfde twee onderdelen: asl als commando en mcp --config plus een absoluut pad als argumenten. Het pad moet absoluut zijn, aangezien de client het proces vanuit elke willekeurige directory kan starten.

Er zijn zes tools beschikbaar, georganiseerd op vraag in plaats van op dataset: describe_lake voor de aanwezige data en de leeswijze, resolve_symbol voor het koppelen van een naam aan een code (inclusief geschrapte namen), query_bars, query_fundamentals met het as_of-argument, query_dataset voor alle overige zaken, en run_sql voor een enkelvoudige, alleen-lezen DuckDB SELECT over datasets heen. Een --live-vlag stelt de server in staat om symbol-lookups en niet-gecorrigeerde dagkoersen van upstream te beantwoorden zonder naar de lake te schrijven.

Beperkingen die u vooraf moet kennen

  • Uitsluitend A-shares. Geen noteringen in Hongkong of de VS, en niets buiten het vasteland van China.
  • Een persoonlijk project. Issues en pull requests krijgen aandacht op basis van 'best-effort', en de documentatie stelt duidelijk dat er geen beschikbaarheidsgarantie is: bronwebsites wijzigen en een IP-adres kan worden geblokkeerd, waardoor de data-ingest stopt totdat iemand een patch aanbrengt.
  • Apache 2.0 dekt de code, niet de data. Elke bron hanteert zijn eigen voorwaarden en de beheerder verleent geen recht om de door u gegenereerde Parquet-bestanden te herdistribueren of door te verkopen. Lees de voorwaarden van de bron vóór commercieel gebruik.
  • Er is geen account of token nodig voor de bronnen die het uitleest; dat is zowel de aantrekkingskracht als de kwetsbaarheid.
  • Ondersteuning voor Windows werd toegevoegd in 0.3.0 en de minimale Python-versie werd in 0.3.1 verhoogd naar 3.10.
Waar deze projectfeiten vandaan komen

Versie 0.5.0, de zes releasedata en de minimale Python-versie zijn afkomstig uit de PyPI-releasehistorie en de CHANGELOG van het project, geraadpleegd op 4 augustus 2026. De datasetcatalogus, het gedrag rondom delisting en point-in-time, de CLI-vlaggen, de lijst met MCP-tools en de bewoordingen over licenties en ondersteuning zijn afkomstig uit de documentatie van de repository: docs/datasets/catalog.md, docs/reference/cli.md, docs/reference/mcp.md en docs/legal-and-data-sources.md. Software ontwikkelt zich sneller dan artikelen; controleer daarom de documentatie voor de versie die u installeert. De twee survivorship-panels meten Amerikaanse symbolen in ons eigen warehouse, niet Chinese noteringen, en dienen als illustratie van het mechanisme in plaats van als meting van de A-share markt.

Veelgestelde vragen

Heeft u een API-sleutel nodig om een lokaal A-share data lake op te bouwen?

Niet voor dit project. De upstream-bronnen die het uitleest, vereisen geen registratie of token, en het lake zelf staat op uw eigen machine. Elke bron hanteert eigen gebruiksvoorwaarden; deze zijn van belang voordat u commerciële activiteiten ontplooit.

Hoe lang duurt het backfillen van het ashare-lake?

Volgens de documentatie duurt een volledige historische backfill enkele uren aan verwerkingstijd en neemt deze enkele gigabytes aan schijfruimte in beslag, waarbij gedurende het hele proces een actieve verbinding met een upstream quote-host vereist is. asl init --profile quick bestrijkt de afgelopen drie jaar in enkele minuten en bevat nog steeds namen die inmiddels van de beurs zijn gehaald.

Bevat een lokaal A-share data lake ook gedeliste aandelen?

Dit lake wel. Gedeliste symbolen blijven in de instrumentendataset staan, een delisting_events-tabel legt vast hoe elk aandeel is geëindigd, en universe="all_a" bouwt een historisch snapshot waarin deze zijn opgenomen. Onze eigen Amerikaanse meting hierboven toont de omvang van wat een universum met enkel overlevende aandelen weglaat.

Kan een AI-agent ashare-lake direct bevragen?

Ja. asl mcp stelt zes tools beschikbaar via het Model Context Protocol, waaronder een read-only SQL-tool, zodat de agent lokale Parquet-bestanden bevraagt in plaats van te scrapen. Registreer deze met claude mcp add ashare-lake -- asl mcp --config /abs/path/to/ashare-lake.toml.

Is ashare-lake een vervanging voor AkShare of Baostock?

Nee. Het bevindt zich daarboven. Die bibliotheken halen data op bij de bron; dit project slaat de data op, beheert versies en reconcilieert de opgehaalde gegevens tot gecureerde Parquet-bestanden met lineage op rij-niveau en één contract per dataset.


Elk cijfer hierboven is een opgeslagen, geversioneerde query over actuele marktdata. Vouw een paneel uit om de SQL te lezen of voer dezelfde survivorship-check uit op uw eigen universum via de Strasmore-terminal.

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