Самостоятельный quant-workbench для A-shares: разбор
Как устроена самостоятельная quant-workbench для A-shares: скрининг, мониторинг, бэктесты и обзор рынка на вашем компьютере. Четыре проверки перед запуском.
Self-hosted квантовая рабочая среда для A-shares — это одна веб-страница, которая скринирует рынок, отслеживает список бумаг, запускает бэктесты и готовит обзор после закрытия рынка на компьютере под вашим контролем, а не в терминале брокера. Один из проектов под лицензией MIT, tickflow-stock-panel, объединяет все эти функции за одним портом. К августу 2026 года он собрал около 2 800 звёзд на GitHub. Список функций прочитать легко. Но именно нижележащий слой определяет, продолжит ли всё это работать в следующем квартале.
Из чего состоит самостоятельный quant-workbench для рынка A-share
Архитектура достаточно компактна, чтобы держать её в голове. Согласно коду и документации в коммите от августа 2026 года, она включает:
- Веб-страницу на React и TypeScript.
- Сервис на Python и FastAPI со планировщиком, который обновляет данные по таймеру.
- Локальное хранилище: файлы Parquet на диске, которые запрашиваются через DuckDB, а вычисления выполняются в Polars.
- Движок бэктестинга vectorbt, использующий эти файлы.
- SDK поставщика, который получает все котировки, отображаемые на панели.
Обратите внимание, чего здесь нет. Ни один компонент этого стека не подключается к бирже. Панель выполняет расчёты, а поставщик передаёт данные. Термин «self-hosted» описывает место запуска кода и ничего не говорит о происхождении чисел. Владение исходными барами — задача расположенного ниже слоя, локального озера рыночных данных A-share. Именно этот слой позволяет заменить все компоненты над ним.
Что включает бесплатный уровень доступа к источнику данных
Доступ панели определяется одной переменной окружения. Если оставить ключ поставщика пустым, проект работает в режиме None, как он назван в документации: получает дневные исторические бары через бесплатный endpoint, а данные за текущую сессию поступают через один–два часа после закрытия. Если указать ключ, доступ расширяется в соответствии с платным уровнем. Для работы с данными на конец дня это пригодный бесплатный уровень. Для внутридневной работы он устанавливает жёсткое ограничение. Эти условия поставщик может подтвердить при любом продлении.
Сопровождающий проекта прямо описывает эту схему:
Этот проект предназначен только для обучения и количественных исследований и не является инвестиционной рекомендацией. Результаты бэктестов не гарантируют будущую доходность.
Это личный проект с открытым исходным кодом, основанный на источнике данных TickFlow, а не официальный проект TickFlow.
README, shy3130/tickflow-stock-panel, просмотрено 13 августа 2026 года
Иными словами, проект предназначен для обучения и количественных исследований, «не является инвестиционной рекомендацией», а результаты бэктестов не отражают будущую доходность. Это «личный проект с открытым исходным кодом, а не официальный продукт TickFlow». В этом и состоит главный вывод для подобных проектов. Решение Zero-ops снимает с вас операционную работу. Но зависимость остаётся прежней: вы арендуете данные у компании, которая никогда не соглашалась поддерживать эту панель. В README также указано, что проект предназначен только для обучения и исследований, а файл лицензии содержит лицензию MIT.
Почему следует фиксировать SHA коммита, а не номер версии
SHA коммита — это 40-значный идентификатор, который git присваивает каждому сохранённому изменению. Он навсегда обозначает одно конкретное состояние кода.
По состоянию на 13 августа 2026 года на странице GitHub Releases этого репозитория ничего не было. При этом в нём есть 31 тег версии — от v0.1.31 до v0.1.88, — с пропусками в нумерации и без сопроводительных примечаний. Самый новый тег указывал на коммит от 31 июля 2026 года, тогда как ветка по умолчанию уже содержала изменения от 6 августа 2026 года. Тег, отстающий от ветки и не содержащий примечаний, не позволяет понять, какой именно код вы получаете.
Поэтому запишите SHA. На 6 августа 2026 года вершиной ветки по умолчанию был ecfddb451e97f6fc9a7e43ac33e4ef0e69933b33. Переключитесь на этот коммит и укажите его рядом с любым выводом, который сделаете по результатам бэктестов. Через шесть недель фраза «я запустил последнюю версию» уже ничего не означает.
Документированный запуск состоит из двух команд: скопируйте файл примера окружения в .env, затем выполните docker compose up --build — эта команда запускает панель на порту 3018. Это инструкции мейнтейнера для данного коммита, а не проверенный сценарий запуска: сборка загружает образы и требует доступа к сети, который на этой странице не проверялся. Для разработки (./dev.sh или .\dev.ps1 в Windows) нужны Python версии 3.11 или новее, Node версии 20 или новее, а также менеджеры пакетов uv и pnpm.
Что отправляет функция LLM-стратегии и куда
Генерация стратегий, комментарии по отдельным акциям и подготовка обзора — необязательные функции. Оставьте AI_API_KEY пустым, и весь этот интерфейс останется скрытым. Если заполнить его, нужно также указать AI_PROVIDER (совместимый с OpenAI endpoint или Ollama), AI_BASE_URL, AI_MODEL и AI_DAILY_TOKEN_BUDGET. Последний параметр прекращает вызовы после исчерпания дневного лимита токенов.
Важно, куда направляется запрос. Ваш prompt и контекст, который панель к нему добавляет, покидают ваш компьютер и отправляются на настроенный endpoint. Если указать базовый URL размещённого API, запрос уйдёт соответствующей компании. Если указать runtime в собственной сети, данные останутся внутри неё. Самостоятельное размещение панели не означает самостоятельное размещение модели. Ключи хранятся в открытом виде в файле .env в корне проекта. Их также можно изменить на странице настроек, защищённой паролем панели длиной не менее шести символов. В нашей заметке о альфа-факторах, сгенерированных LLM объясняется, почему стратегии, написанные машиной, часто дают сбой.
Учитывает ли бэктестер торговые издержки?
В описании бэктестера указаны режим T+1, комиссии, проскальзывание и стоп-лоссы. Но наличие этих переключателей не означает, что они включены. Бэктест, в котором сделки исполняются по опубликованной цене закрытия, а издержки равны нулю, предполагает бесплатную торговлю. Это неверно. Базисный пункт — одна сотая процента. На панели ниже показан средний разрыв между лучшей ценой спроса и лучшей ценой предложения в базисных пунктах для шести американских листингов за один час в середине торговой сессии 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Самый узкий спред на панели был у SPY: в среднем 0.29 б. п. за этот час. Самый широкий спред был у F: 6.98 б. п. Пересечь этот разрыв приходится дважды: при входе и при выходе из позиции. Поэтому круговая сделка обходится примерно вдвое дороже указанной величины — ещё до учёта комиссий.
Время исполнения не менее важно, чем выбор инструмента. На следующей панели показано, насколько менялась цена одного из этих листингов в течение отдельной минуты. Значения усреднены по получасовым интервалам за тот же день.
Точный 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Панель начинается с 08:00, до открытия регулярной сессии. В этот период средний минутный диапазон составлял 0 б. п.: фактически торговались только те минуты, в которых цена оставалась на одном уровне. Последний интервал, 16:30, приходится на время после закрытия и показал в среднем 4.2 б. п. Бэктест выбирает одну точку из каждого такого диапазона и считает её ценой исполнения. Важно смотреть на кривую, а не только на крайние значения: одно и то же допущение в одни часы оказывается благоприятным, а в другие — завышает издержки. Для акций класса A действуют дополнительные ограничения. Режим T+1 не позволяет продать акции, купленные сегодня, до следующей торговой сессии. Дневные лимиты изменения цены могут полностью исключить рассчитанный выход из позиции. В нашем разборе воспроизводимого бэктеста показано, какие параметры должен фиксировать обоснованный бэктест. В материале о смещении с опережением данных разобран другой способ, которым внешне безупречная кривая доходности может оказаться ошибочной.
С поправкой или без неё: вопрос происхождения данных
Корпоративные действия — одна из причин, по которым скринер может незаметно вводить в заблуждение. Если компания проводит дробление акций в соотношении ten-to-one, в этот день на графике появляется падение на 90%, хотя инвесторы не теряют ни цента. В панели ниже перечислены twelve крупнейших форвардных дроблений акций на биржах США в период с 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В результате самого крупного дробления одна акция превращается в 10000 акций с даты вступления решения в силу Feb 10, 2026. Такие коэффициенты не сводятся к привычному дроблению four-for-one: корпоративный feed передаёт весь диапазон значений в одном столбце. Даже самое небольшое из twelve дроблений превращает одну акцию в 20 акций. Этого достаточно, чтобы график без поправки выглядел как обвал. Скринер импульса, который использует исходные цены, отметит каждую такую акцию как рухнувшую. Китайские feeds сталкиваются с той же проблемой, используя собственную терминологию и передавая для каждого ряда три варианта: без поправки, с поправкой вперёд и с поправкой назад. Проверьте, какой именно вариант загрузила ваша панель. В материале История цен с поправкой на дробление пошагово разобраны расчёты.
Что проверить перед самостоятельным размещением подобных сервисов
- Происхождение данных. Кто поставляет данные, на каких условиях лицензии и позволяет ли бесплатный тариф использовать их так, как вы планируете.
- Хранение ключей. Где на диске сохраняются API-ключи, кто имеет доступ к странице настроек и доступна ли машина за пределами вашей сети.
- Расчёт затрат. Учитывает ли бэктестер комиссии, проскальзывание и правила самого рынка, а также какие значения используются в этих полях, если вы их не меняете.
- Путь обновления. Точный commit, который вы развернули, должен быть записан рядом с результатами, чтобы через несколько месяцев их можно было воспроизвести.
Часто задаваемые вопросы
Можно ли бесплатно запустить собственный quant-workbench для акций класса A?
Код распространяется по лицензии MIT и бесплатен. Данные — отдельный вопрос: если поле с ключом поставщика оставить пустым, проект использует бесплатные исторические дневные бары, а данные за текущую сессию поступают через один-два часа после закрытия рынка. Более быстрые или детализированные данные доступны только на платных тарифах поставщика.
Что здесь на самом деле означает self-hosted?
Веб-страница, планировщик, сохранённые файлы и бэктестер работают на вашем собственном компьютере или сервере. Аккаунт на чужой платформе не нужен. Это не означает, что данные принадлежат вам. Дополнительные функции AI также работают удалённо, если только вы не подключите модель в собственной сети.
Передаёт ли функция LLM мои данные третьей стороне?
Да, если она включена, данные отправляются на настроенный вами endpoint, совместимый с OpenAI. По умолчанию функция отключена: если поле с AI-ключом оставить пустым, с компьютера ничего не отправляется.
Почему следует фиксировать commit SHA, а не тег версии?
По состоянию на 13 августа 2026 года в этом репозитории не было опубликованных релизов и примечаний к релизам. При этом его новейший тег указывал на более старый код, чем ветка по умолчанию. В такой ситуации «Latest» означает состояние ветки на день клонирования, тогда как commit SHA однозначно фиксирует код. Такой же принцип применяется к материалам по алгоритмической торговле с открытым исходным кодом в целом: фиксируйте именно ту версию, которую запускали.
Примечания по проверке
Все приведённые выше сведения об архитектуре и конфигурации взяты из публичного репозитория 13 августа 2026 года, на коммите ecfddb451e97f6fc9a7e43ac33e4ef0e69933b33, который являлся вершиной ветки по умолчанию и был датирован 6 августа 2026 года. На странице Releases ничего не было опубликовано. В списке тегов находился 31 тег версии — от v0.1.31 до v0.1.88; новейший указывал на коммит от 31 июля 2026 года. Цитируемые строки принадлежат разработчику. Они взяты из README без пересказа. Команда запуска контейнера также процитирована из README и здесь не выполнялась.
Рыночные панели показывают бумаги, торгующиеся в США. Для них указаны фиксированные даты в прошлом, чтобы значения не менялись. Они нужны для демонстрации двух проверок, применимых к любому рынку: издержек исполнения и корректировки с учётом корпоративных действий. Эти панели не предназначены для описания китайского рынка.
Каждая панель сопровождается SQL-запросом, на основе которого она построена. Запрос можно развернуть ниже. Чтобы выполнить такую же проверку spread по собственному списку бумаг до подключения одной из них к скринеру, сформулируйте запрос на обычном английском языке в терминале Strasmore.