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

Локальне сховище A-акцій для AI-агентів

ashare-lake створює локальне сховище даних A-акцій: 39 наборів даних, записи про delisting, запити на минулу дату та MCP-сервер для AI-агентів.

Локальне сховище даних щодо A-акцій — це історія фондового ринку материкового Китаю, збережена на власному диску у вигляді колонкових Parquet-файлів, які можна читати через DuckDB або Polars. Це альтернатива vendor endpoint, до якого звертаються сторінка за сторінкою. ashare-lake — це open-source проєкт, який створює таке сховище, щоденне завдання для його актуалізації та сервер Model Context Protocol, що дає AI-агенту змогу виконувати запити до даних. Дві особливості архітектури заслуговують окремої згадки: у сховищі зберігаються delisted компанії, а фундаментальні показники можна переглядати станом на минулу дату.

Чому AI-агенту потрібне локальне сховище даних щодо акцій A-share

Агент, який досліджує китайські акції без локальної копії даних, має два варіанти. Він може збирати дані з фінансових сторінок, витрачаючи контекстне вікно на HTML і отримуючи цифри, які ніхто не зможе відтворити наступного місяця. Або він може звернутися до постачальника з обов’язковою реєстрацією. У такому разі кількість рядків обмежена, а кожен результат прив’язаний до облікового запису.

Масштаб — це аспект, який часто недооцінюють. У нашому сховищі зберігаються дані американського ринку з хвилинною деталізацією. Звичайний тиждень має такий вигляд:

ЗапитОдин тиждень хвилинних даних США: тикери та кількість барів за сесію, 20–24 липня 2026 року
Точний 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 мільйонів хвилинних барів за 11737 тикерами. Чотири інші сесії на панелі мають аналогічні показники. Один національний ринок, один тиждень, одна деталізація. Десятирічний масив денних барів, фундаментальних показників, даних про склад індексів і рух коштів для іншого ринку має таку саму структуру. Передавання такого обсягу через HTTP за один запуск вичерпує ресурси агента.

Локальне сховище змінює одразу два параметри. Читання перетворюється на сканування файлів, а не використання квоти. Крім того, запит, написаний сьогодні, через шість місяців повертає ті самі рядки. Саме це потрібно, щоб результати backtest можна було перевірити. У наших матеріалах про навички роботи з ринковими даними для AI-агентів і про SQL API для ринкових даних наведено такий самий аргумент щодо даних американського ринку.

Встановлення з фіксацією версії

Python 3.10 або новішої версії. Зафіксуйте версію: у період із 27 липня до 2 серпня 2026 року вийшло шість релізів, тому встановлення без фіксації версії у setup-скрипті агента нестабільне. Код розміщено в rootSunc/ashare-lake за ліцензією Apache 2.0.

  • pip install ashare-lake==0.5.0 встановлює поточний реліз станом на початок серпня 2026 року.
  • asl --version виводить інформацію про встановлену збірку.
  • asl config init --data-root /path/to/ashare-lake записує упакований приклад TOML із зазначеним кореневим каталогом даних; клонування репозиторію не потрібне. --config задає шлях виведення, --force перезаписує наявний файл.
  • asl doctor запускає перевірки офлайн, до переміщення будь-яких даних.
  • asl servers test перевіряє доступність upstream-хостів із котируваннями. asl sources перевіряє кожне джерело із застосуванням --vantage зі значенням cn, overseas або local.

На цьому зупиніться. Наступна команда запускає backfill, і її не слід виконувати поспіхом під час читання.

Що робить початкове завантаження

asl init створює структуру каталогів і заповнює історичні дані. Документація проєкту вказує, що повний запуск займає кілька годин реального часу й потребує кількох GB дискового простору. Також потрібне активне з’єднання з upstream-сервером котирувань Tongdaxin — саме його перевіряє asl servers test. Натомість asl init --profile quick охоплює останні три роки й виконується за лічені хвилини. При цьому зберігаються всі назви, за якими торгували в цьому періоді, включно з тими, що згодом залишили ринок. asl run daily — це подальше інкрементальне завдання, asl status --datasets показує повноту охоплення та актуальність даних для кожного dataset, а asl serve запускає read-only dashboard за адресою 127.0.0.1:8787.

Репозиторій не містить жодних даних. Кожен Parquet-файл створюється на вашій машині, а в кожному рядку зберігається інформація про походження даних: яке джерело його надало та коли відбулося завантаження.

Які існують 39 наборів даних?

Вони структуровані за рівнями — від довідкових даних назовні: 36 опрацьованих таблиць і 3 похідні.

  • Довідкові дані: інструменти, торговий календар на період із 2016 до 2027 року, статус торгів.
  • Ринкові дані: денні бари, бари індексів, 1-хвилинні та 5-хвилинні бари, тикові дані угод, бари товарних активів, коефіцієнти коригування, події делістингу.
  • Корпоративні події: корпоративні дії, індекс оголошень, календар розкриття фінансових результатів.
  • Фундаментальні показники та оцінка: статті фінансової звітності, оціночні метрики, консенсус-прогнози аналітиків.
  • Рух капіталу: потоки коштів фондів, маржинальна торгівля, північні потоки та позиції, дошка Dragon-Tiger із розкриттям великих ордерів, блокові угоди, позиції інституційних інвесторів.
  • Структура та галузі: учасники секторів, склад індексів, учасники галузей, галузеві індекси.
  • Макроекономіка: макроіндикатори, ширина ринку, економічний календар.
  • Настрої та ротація: оцінки настроїв, рейтинг популярності, секторні бари, потоки коштів у сектори, заголовки новин, стрічка термінових новин.
  • Ризики та комплаєнс: календар розблокування акцій, регуляторні події.

Розташування набору даних показує, що саме автор вважає важливим. Коефіцієнти коригування та події делістингу розміщені в рівні ринкових даних поруч із денними барами, а не винесені в додаток. Для тих, хто тестує торгові ідеї на історичних даних, саме це розміщення є найціннішою частиною проєкту.

Як локальне сховище даних враховує survivorship bias

Survivorship bias виникає, коли сукупність для дослідження формують лише з назв, які досі котируються. Компанії, що об’єдналися, стали приватними або були делістинговані, непомітно випадають із вибірки. А зниклі назви рідко виявляються переможцями.

Наше сховище даних дає змогу оцінити цей пробіл на ринку США. Арифметика та сама, лише позначення інші. Для кожного року візьмімо всі символи, за якими були хвилинні бари в другий тиждень березня, а потім перевірмо, які з них досі друкували угоди протягом двох останніх тижнів липня 2026 року:

ЗапитВиживання виміряно: когорти тикерів США з березня, які продовжували торгуватися наприкінці липня 2026 року
Точний 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

Із 8101 символів, що торгувалися того тижня у 2016, наприкінці липня 2026 року в стрічці залишилися 50.1%, а 4040 — ні. Когорта 2025 дає результат 86.7%. Якщо застосувати скринер, побудований на сьогоднішньому переліку лістингів, і провести його назад на 10 років, він поступово виключатиме дедалі більшу частку ринку.

Зручне припущення полягає в тому, що всі зниклі назви були penny stocks. Але сортування когорти березня 2021 року за рівнями середнього денного доларового обсягу торгів за той місяць показує інше:

ЗапитХто залишив стрічку: тикери з березня 2021 року за денним доларовим обсягом, перевірка наприкінці липня 2026 року
Точний 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 $1M57.5% із 3968 назв. Найактивніша категорія також не була винятком: до кінця липня 2026 року вибули 3.4% із 89 символів, за якими торгували на $1B or more на день у березні 2021 року. Злиття, викуп компанії в приватний статус, банкрутство та вихід з індексу закінчуються в ціновій таблиці однаково: рядки припиняються.

ashare-lake розглядає це як базову проблему. Набір даних про інструменти зберігає делістинговані символи, а не фільтрує їх, залишаючи лише активні. Таблиця delisting_events фіксує, чим завершилася історія кожної вибулої назви, а universe="all_a" у Python API формує історичний зріз, який їх включає. У власній документації проєкту зазначено приблизно дворазову різницю між backtest, що враховує лише компанії, які залишилися в лістингу, та backtest із включенням делістингованих компаній за період із 2016 до 2021 року. Це дзеркальне відображення пастки, описаної в наших нотатках про look-ahead bias у backtesting: сукупності, яка непомітно знає майбутнє.

Дані на конкретний момент часу

load("financial_statement_items", as_of="2018-04-30") повертає останню версію кожного рядка звітності, оприлюднену не пізніше цієї дати, а не показник у пізнішій, перерахованій редакції. Бари містять аргумент adjust: hfq для коригування назад, qfq для нормалізації в межах вікна запиту або сирих цін. Фактор, побудований на показниках, які ринок ще не оприлюднив, нічого не вимірює. Саме це слід перевірити насамперед у будь-якому пайплайні alpha-фактора, згенерованого LLM.

Реєстрація як MCP-сервера

Model Context Protocol використовується агентом для підключення до інструментів. asl mcp працює через stdio, а клієнт запускає процес:

  • claude mcp add ashare-lake -- asl mcp --config /abs/path/to/ashare-lake.toml
  • Будь-який інший MCP-клієнт використовує ті самі два компоненти: asl як команду та mcp --config разом із абсолютним шляхом як аргументи. Шлях має бути абсолютним, оскільки клієнт може запускати процес із будь-якого каталогу.

Доступні шість інструментів, організованих за запитаннями, а не за наборами даних: describe_lake показує, які дані доступні та як їх читати; resolve_symbol зіставляє назву з кодом, зокрема для делістованих назв; query_bars працює з барами; query_fundamentals підтримує аргумент as_of; query_dataset призначений для всіх інших запитів; run_sql виконує один доступний лише для читання DuckDB-запит SELECT у кількох наборах даних. Прапорець --live дає серверу змогу отримувати дані про відповідність символів і нескориговані денні бари безпосередньо з upstream-джерела, не записуючи їх у lake.

Обмеження, які варто знати насамперед

  • Лише A-shares. Без лістингів у Гонконзі, США чи будь-де за межами материкового Китаю.
  • Особистий проєкт. Issues і pull requests опрацьовуються у міру можливостей. У документації прямо зазначено, що гарантії доступності немає: зовнішні сайти змінюються, а IP-адресу можуть заблокувати. У такому разі завантаження даних припиняється, доки хтось не внесе виправлення.
  • Apache 2.0 поширюється на код, але не на дані. Кожне зовнішнє джерело має власні умови. Мейнтейнер не надає права повторно поширювати або перепродавати створені вами файли Parquet. Перед будь-яким комерційним використанням ознайомтеся з умовами джерел.
  • Для джерел, з яких проєкт зчитує дані, не потрібні обліковий запис або токен. У цьому полягає перевага, але водночас і вразливість такого підходу.
  • Підтримка Windows з’явилася у версії 0.3.0, а мінімальна версія Python підвищилася до 3.10 у версії 0.3.1.
Походження цих відомостей про проєкт

Версія 0.5.0, шість дат релізів і мінімальна версія Python взяті з історії релізів проєкту на PyPI та CHANGELOG, переглянутих 4 серпня 2026 року. Каталог наборів даних, поведінка щодо делістингу та даних на конкретний момент часу, прапорці CLI, перелік інструментів MCP, а також формулювання щодо ліцензування і підтримки взяті з документації репозиторію: docs/datasets/catalog.md, docs/reference/cli.md, docs/reference/mcp.md і docs/legal-and-data-sources.md. Програмне забезпечення розвивається швидше, ніж оновлюються публікації, тому перевіряйте документацію для встановленої вами версії. Дві панелі survivorship оцінюють символи US у нашому власному сховищі, а не китайські лістинги, і слугують ілюстрацією механіки, а не вимірюванням ринку A-shares.

Часті запитання

Чи потрібен API key, щоб створити локальне сховище даних A-share?

Для цього рішення — ні. Вихідні джерела, з яких воно читає дані, не потребують реєстрації або токена, а саме сховище працює на вашому комп’ютері. Кожне джерело має власні умови використання, які потрібно врахувати перед будь-яким комерційним застосуванням.

Скільки часу займає завантаження історичних даних в ashare-lake?

Згідно з документацією, повне завантаження історії займає кілька годин реального часу та потребує кількох GB дискового простору. Протягом усього процесу потрібне стабільне підключення до upstream-сервера котирувань. asl init --profile quick охоплює останні три роки за кілька хвилин і водночас містить назви, які згодом були делістинговані.

Чи містить локальне сховище даних A-share делістинговані акції?

Так. Делістинговані символи залишаються в наборі даних інструментів, таблиця delisting_events фіксує, чим завершилася історія кожної назви, а universe="all_a" формує історичний snapshot із їх урахуванням. Наш власний наведений вище аналіз ринку США показує масштаб того, що виключає всесвіт, сформований лише з компаній, які залишилися на ринку.

Чи може AI-агент напряму запитувати дані ashare-lake?

Так. asl mcp надає шість інструментів через Model Context Protocol, зокрема інструмент лише для читання SQL. Тому агент виконує запити до локальних файлів Parquet, а не збирає дані зі сторінок сайтів. Зареєструйте його за допомогою claude mcp add ashare-lake -- asl mcp --config /abs/path/to/ashare-lake.toml.

Чи є ashare-lake заміною для AkShare або Baostock?

Ні. Він працює над ними як додатковий рівень. Ці бібліотеки отримують дані з upstream-джерел, а цей проєкт зберігає, версіонує та узгоджує отримані дані у структурованих файлах Parquet із lineage на рівні рядків і єдиним контрактом для кожного набору даних.


Кожна цифра вище є результатом збереженого запиту з версіонуванням, виконаного на реальних ринкових даних. Розгорніть будь-яку панель, щоб переглянути SQL, або виконайте таку саму перевірку survivorship на власному всесвіті в терміналі Strasmore.

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