Strasmore Research
Навчання Matt ConnorВід Matt Connor

Self-hosted quant-воркбенч для A-share: пояснення

Як self-hosted quant-воркбенч для A-share сканує ринок і запускає backtests на вашій машині. Що визначає його роботу та які чотири речі перевірити спочатку.

Self-hosted quant-workbench для A-shares — це одна вебсторінка, яка сканує ринок, відстежує список інструментів, запускає backtests і готує огляд після завершення торгів. Усе працює на машині під вашим контролем, а не в терміналі брокера. Один із таких проєктів, tickflow-stock-panel, поширюється за ліцензією MIT і об’єднує всі ці функції через один порт. Станом на серпень 2026 року він зібрав приблизно 2 800 зірок на GitHub. Список функцій прочитати нескладно. Але саме нижній програмний шар визначає, чи працюватиме все це наступного кварталу.

З чого складається self-hosted quant-воркбенч для A-share

Архітектура достатньо компактна, щоб утримувати її в голові. За кодом і документацією станом на коміт у серпні 2026 року вона має такий вигляд:

  • Вебсторінка на React і TypeScript.
  • Сервіс на Python і FastAPI із планувальником, який оновлює дані за таймером.
  • Локальне сховище: файли Parquet на диску, які запитуються через DuckDB, а обчислення виконуються в Polars.
  • Рушій backtesting — vectorbt, підключений до цих файлів.
  • SDK постачальника даних, який завантажує всі ціни, що відображаються на панелі.

Зверніть увагу, чого в цій структурі немає. Жоден її компонент не підключається до біржі. Панель виконує обчислення, а постачальник даних їх забезпечує. Термін «self-hosted» описує місце запуску коду й нічого не говорить про джерело числових даних. Володіння сирими барами — завдання рівня нижче, локального сховища ринкових даних A-share, і саме воно дає змогу замінювати всі компоненти над ним.

Що охоплює безкоштовний рівень джерела даних

Одна змінна середовища визначає, які дані бачить панель. Якщо залишити ключ постачальника порожнім, проєкт працює в режимі, який у документації названо None mode: він отримує історичні денні бари з безкоштовного endpoint, а дані поточної сесії стають доступними через одну-дві години після закриття торгів. Якщо вказати ключ, доступ розширюється відповідно до платного рівня. Для роботи з даними на кінець дня це придатний безкоштовний рівень. Для будь-яких внутрішньоденних даних він є жорстким обмеженням. Умови постачальник може змінити під час будь-якого продовження доступу.

Супроводжувач прямо описує цю модель:

Цей проєкт призначений лише для навчання та кількісних досліджень і не є інвестиційною рекомендацією. Результати backtest не гарантують майбутньої дохідності.
Це особистий open-source проєкт на базі джерела даних TickFlow, а не офіційний проєкт TickFlow.
README, shy3130/tickflow-stock-panel, переглянуто 13 серпня 2026 року

Іншими словами, проєкт призначений для навчання та кількісних досліджень, «не є інвестиційною рекомендацією», результати backtest не гарантують майбутньої дохідності, а сам проєкт є «особистим open-source проєктом, а не офіційним продуктом TickFlow». Це головний висновок для всього цього класу рішень. Zero-ops прибирає операційну роботу з вашого боку. Але залежність залишається: ви орендуєте дані в компанії, яка ніколи не брала на себе зобов’язань щодо підтримки цієї панелі. README також обмежує використання навчанням і дослідженнями, тоді як файл ліцензії містить ліцензію MIT.

Навіщо фіксувати SHA коміту, а не номер версії

SHA коміту — це 40-символьний ідентифікатор, який git присвоює кожній збереженій зміні. Він назавжди визначає один конкретний стан коду.

Станом на 13 серпня 2026 року на сторінці GitHub Releases цього репозиторію не було жодного запису. Водночас у ньому є 31 тег версії — від v0.1.31 до v0.1.88, — із пропусками в нумерації та без супровідних приміток. Найновіший тег указував на коміт від 31 липня 2026 року, тоді як default branch уже містила зміни від 6 серпня 2026 року. Тег, який відстає від гілки й не має приміток, не дає змоги зрозуміти, який саме код ви отримуєте.

Тому запишіть SHA. Станом на 6 серпня 2026 року head default branch мав значення ecfddb451e97f6fc9a7e43ac33e4ef0e69933b33. Перевірте цей коміт і зафіксуйте його поруч із будь-яким висновком, зробленим за результатами backtests. Через шість тижнів фраза «я запускав останню версію» вже нічого не означає.

Задокументований початок роботи складається із двох рядків: скопіюйте приклад файлу середовища до .env, а потім запустіть docker compose up --build. Ця команда запускає панель на порту 3018. Це інструкції мейнтейнера для цього коміту, а не перевірений сценарій запуску: під час збирання завантажуються images, і потрібен доступ до мережі, який на цій сторінці не перевірявся. Для розробки потрібні Python 3.11 або новіша версія, Node 20 або новіша версія, а також менеджери пакетів uv і pnpm. У Windows використовуйте ./dev.sh або .\dev.ps1.

Що надсилає функція стратегії на основі LLM і куди

Генерація стратегій, коментарі щодо окремих акцій і підготовка огляду є необов’язковими. Залиште AI_API_KEY порожнім — і весь цей інтерфейс залишиться неактивним. Заповнивши його, ви також задасте AI_PROVIDER (сумісний з OpenAI endpoint або Ollama), AI_BASE_URL, AI_MODEL і AI_DAILY_TOKEN_BUDGET. Останній параметр припиняє виклики після вичерпання денного ліміту токенів.

Важливо, куди саме спрямовується запит. Ваш prompt і контекст, який панель додає до нього, залишають ваш комп’ютер і надходять на налаштований endpoint. Якщо вказати базову URL-адресу hosted API, запит надійде відповідній компанії. Якщо вказати runtime у власній мережі, дані залишаться у вашій інфраструктурі. Самостійне розгортання панелі не означає самостійного розгортання моделі. Ключі зберігаються у відкритому тексті у файлі .env у кореневій папці проєкту. Їх також можна редагувати на сторінці налаштувань, захищеній паролем dashboard довжиною щонайменше шість символів. У нашій нотатці про альфа-фактори, згенеровані LLM пояснюється, де стратегії, написані моделлю, зазвичай дають збій.

Чи моделює backtester торгові витрати?

Backtester заявляє про підтримку розрахунків T+1, комісій, прослизання та stop-loss. Але наявність цих налаштувань не означає, що їх застосовано. Backtest, у якому угоди виконуються за надрукованою ціною закриття, а витрати дорівнюють нулю, фактично передбачає безкоштовну торгівлю. Це не відповідає дійсності. Базисний пункт становить одну соту відсотка. Панель нижче показує середній розрив між найкращою ціною bid і найкращою ціною offer у базисних пунктах для шести лістингів у США протягом однієї години в середині торгової сесії 17 червня 2026 року.

ЗапитВартість перетину спреду: середній котирувальний спред, шість лістингів у США, середина дня, 17 червня 2026 року
Точний SQL-код для кожного числа
SELECT
    ticker                                                                       AS symbol,
    round(avg(toFloat64(ask_price) - toFloat64(bid_price))
          / avg((toFloat64(ask_price) + toFloat64(bid_price)) / 2) * 10000, 2)   AS spread_bps
FROM global_markets.cache_stocks_quotes
WHERE ticker IN ('SPY', 'AAPL', 'MSFT', 'NVDA', 'KO', 'F')
  AND sip_timestamp >= toDateTime('2026-06-17 15:00:00', 'UTC')
  AND sip_timestamp <  toDateTime('2026-06-17 16:00:00', 'UTC')
  AND bid_price > 0
  AND ask_price > bid_price
GROUP BY ticker
ORDER BY spread_bps
Run this yourself

Найвужчий spread у панелі, SPY, у середньому становив 0.29 bps протягом цієї години. Найширший, F, становив 6.98 bps. Цей розрив потрібно подолати двічі: під час входу та виходу з позиції. Тому вартість round trip становить приблизно подвійну показану величину ще до врахування комісій.

Час має не менше значення, ніж вибір активу. Наступна панель бере один із цих лістингів і вимірює, яку відстань проходила його ціна протягом однієї хвилини. Показники усереднено за півгодинними інтервалами протягом того самого дня.

ЗапитЯк далеко рухається ціна протягом однієї хвилини: KO, за часом Нью-Йорка, 17 червня 2026 року
Точний SQL-код для кожного числа
SELECT
    formatDateTime(
        toStartOfInterval(toTimeZone(window_start, 'America/New_York'), INTERVAL 30 MINUTE),
        '%H:%i')                                                                 AS et_time,
    round(avg((toFloat64(high) - toFloat64(low)) / toFloat64(close)) * 10000, 1)  AS range_bps
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'KO'
  AND window_start >= toDateTime('2026-06-17 12:00:00', 'UTC')
  AND window_start <  toDateTime('2026-06-17 21:00:00', 'UTC')
  AND volume > 0
  AND close > 0
GROUP BY et_time
ORDER BY et_time
Run this yourself

Панель починається з 08:00, до відкриття регулярної сесії. У цей час середній рух за хвилину становив 0 bps: хвилини, у яких відбувалися угоди, проходили за однією ціною. Останній інтервал, 16:30, припадає на час після закриття сесії та в середньому становив 4.2 bps. Backtest обирає одну точку з кожного такого діапазону й вважає її ціною виконання. Оцінюйте криву, а не лише крайні точки: те саме припущення в одні години є сприятливим, а в інші — надмірно жорстким. Для акцій класу A діють додаткові обмеження: правило T+1 не дає продати придбані сьогодні акції до наступної сесії, а денні ліміти зміни ціни можуть повністю унеможливити змодельований вихід. У нашому розборі відтворюваного backtest показано, які параметри має фіксувати обґрунтована модель, а матеріал про look-ahead bias пояснює інший спосіб, у який може виникнути оманливо гладка крива.

Скориговані чи нескориговані дані: питання походження

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

ЗапитДванадцять найбільших форвардних дроблень акцій у лістингах США, з 1 січня до 13 серпня 2026 року
Точний SQL-код для кожного числа
SELECT
    ticker                                                            AS symbol,
    formatDateTime(execution_date, '%b %e, %Y')                       AS effective_on,
    round(any(toFloat64(split_to)) / any(toFloat64(split_from)), 2)   AS shares_after_per_share
FROM global_markets.stocks_splits
WHERE execution_date >= toDate('2026-01-01')
  AND execution_date <= toDate('2026-08-13')
  AND split_from > 0
  AND split_to > split_from
  AND ticker NOT IN ('SPCX')
GROUP BY ticker, execution_date
ORDER BY shares_after_per_share DESC, execution_date DESC
LIMIT 12
Run this yourself

У найбільшому випадку одна акція перетворюється на 10000, починаючи з Feb 10, 2026. Такі коефіцієнти — не звичайний спліт чотири до одного; стрічка даних про корпоративні дії містить увесь діапазон значень в одному стовпці. Навіть найменший із дванадцяти сплітів перетворює одну акцію на 20 акцій. Цього достатньо, щоб нескоригований графік виглядав як обвал. Momentum-скринер, який використовує необроблені ціни, позначає кожну з них як акцію, що зазнала краху. Китайські стрічки даних мають ту саму проблему, але використовують власну термінологію й надають для кожного ряду три варіанти: нескоригований, скоригований уперед і скоригований назад. Перевірте, який саме варіант завантажила ваша панель. У матеріалі Історія цін із поправкою на спліти наведено розрахунки.

Що перевірити перед самостійним розгортанням подібних систем

  • Походження даних. Який постачальник їх надає, за якою ліцензією та чи дозволяє безкоштовний тариф використовувати дані у вашому сценарії.
  • Робота з ключами. Де API-ключі зберігаються на диску, хто має доступ до сторінки налаштувань і чи доступна машина за межами вашої мережі.
  • Моделювання витрат. Чи враховує backtester комісії, прослизання та правила самого ринку, а також які значення використовуються для цих параметрів, якщо їх не змінювати.
  • Оновлення системи. Точний commit, який ви розгорнули, слід записати поруч із результатами, щоб відтворити їх через кілька місяців.

Поширені запитання

Чи безкоштовно запускати власний A-share quant workbench?

Код поширюється за ліцензією MIT і є безкоштовним. Дані — окреме питання: якщо поле vendor key залишити порожнім, цей проєкт використовує безкоштовні історичні денні бари. Дані за поточну сесію надходять через one-to-two hours after the close. Усе, що потребує більшої швидкості або глибини, доступне через платні тарифи постачальника.

Що тут насправді означає self-hosted?

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

Чи надсилає функція LLM мої дані третій стороні?

Так, якщо її ввімкнено — на будь-який OpenAI-сумісний endpoint, який ви налаштуєте. За замовчуванням функція вимкнена: якщо AI key залишити порожнім, із комп’ютера нічого не передається.

Навіщо фіксувати commit SHA, а не version tag?

Станом на 13 серпня 2026 року в цьому репозиторії не було опублікованих релізів і release notes, а найновіший tag вказував на старіший код, ніж default branch. Тоді «Latest» означає стан гілки на день, коли ви її клонували, тоді як commit SHA є точним посиланням. Та сама дисципліна застосовується до матеріалів про open-source quant trading загалом: фіксуйте саме те, що запускали.

Примітки щодо перевірки

Усі наведені вище відомості про архітектуру та конфігурацію взято з публічного репозиторію 13 серпня 2026 року, на commit ecfddb451e97f6fc9a7e43ac33e4ef0e69933b33, який був головою default branch і датувався 6 серпня 2026 року. На сторінці Releases нічого не було; список tag містив 31 version tag — від v0.1.31 до v0.1.88. Найновіший tag вказував на commit від 31 липня 2026 року. Наведені цитати належать самому мейнтейнеру. Їх скопійовано з README, а не переказано. Команду запуску контейнера також процитовано з README; тут її не виконували.

Ринкові панелі містять дані щодо лістингів у США. Їх прив’язано до фіксованих дат у минулому, щоб цифри не змінювалися. Вони демонструють дві перевірки, актуальні для будь-якого ринку: витрати на виконання та коригування через corporate actions. Ці панелі не призначені для опису китайського ринку.


Кожна панель містить SQL-запит, за яким її побудовано. Запит можна розгорнути нижче. Щоб виконати таку саму перевірку spread для власного списку компаній перед додаванням однієї з них до screener, сформулюйте запит звичайною англійською мовою в терміналі Strasmore.

#open-source#backtesting#screening#a-shares#self-hosted