CRP — сервисный контур для онлайн-прогнозирования краткосрочного движения цены BTC на основе свечных данных и инженерных признаков.
Проект решает прикладную задачу: собирать рыночные данные в реальном времени, формировать вектор признаков фиксированного формата и получать ML-сигнал в устойчивом сервисном режиме с сохранением полной истории входов/выходов в базе данных.
Ключевая модельная идея в текущей реализации:
- используются две отдельные модели:
up— модель роста;down— модель падения.
- итоговый сигнал собирается из их совместного ответа вместе с confidence.
Поток данных в системе:
ingestorрегулярно запрашивает последнюю свечу Binance для заданного инструмента и интервала.- Свеча сохраняется в PostgreSQL с upsert-логикой.
feature-workerберет окно последних свечей, вычисляет инженерные признаки и добавляет внешние факторы.- Полученный feature vector отправляется в
model-server. model-serverделегирует инференс вml-predictor.ml-predictorпрогоняет вектор через две модели (up/down) и возвращает:prediction,confidence,- отдельные
signal/confidenceпо каждой модели.
feature-workerсохраняет результат в таблицуpredictions.
Binance API
|
v
ingestor (Go) ---> PostgreSQL (candles, predictions)
^
|
feature-worker (Go) -- features --> model-server (Go) --> ml-predictor (FastAPI)
|
v
serialized ML models
- Источник: Binance REST API (
/api/v3/klines). - Назначение: обновление таблиц
candles_5m|30m|1h. - Режим: отдельный worker на каждый активный интервал из
runtime.active_intervals. - Модель хранения: уникальность по
symbol + open_timeвнутри каждой интервальной таблицы.
- Вычисляет признаки по историческому окну (
window). - Запускает отдельный цикл обработки на каждый активный интервал.
- Добавляет внешние признаки (fear/greed, funding, ETF-блок).
- Отправляет feature vector в модельный API.
- Сохраняет прогнозы в
predictions_5m|30m|1h.
- Легковесный API-шлюз между Go-контуром и Python-инференсом.
- Держит единый контракт
/predictи/healthдля остальной системы. - Читает метаданные моделей из общего конфига.
- Загружает пару моделей на старте.
- Поддерживает сериализацию
joblibиpickle(включая auto-режим определения). - Формирует итоговый ответ по двум сигналам.
- Централизованное хранилище:
- рыночные свечи,
- результаты предсказаний,
- confidence-метрики.
config/models.json — единый источник правды для модельного слоя.
В нем описываются:
- runtime-параметры пайплайна (
runtime.symbol,runtime.active_intervals, совместимо сruntime.interval); - логические имена моделей (
name); - фактические пути до файлов (
path); - формат сериализации (
format):joblib,pickle/pkl,auto.
runtime.active_intervals поддерживает 5m, 30m, 1h и используется как единый источник для:
- запуска отдельных ingestion-воркеров по интервалам;
- запуска отдельных циклов
feature-workerпо интервалам; - выбора таблиц в БД (
candles_5m|30m|1h,predictions_5m|30m|1h); - отображения данных по interval в Grafana.
Это позволяет менять таймфрейм и модельные файлы без изменений в коде сервисов.
config/features.json задает:
- торговый инструмент;
- размер исторического окна;
- список вычисляемых признаков;
- параметры блока внешних признаков.
Хранит OHLCV-срезы рынка в отдельных таблицах:
candles_5m,candles_30m,candles_1h,symbol,open_time,close_time,open,high,low,close,volume,- служебные временные поля и индексы.
Для объединенного чтения (например, Grafana) создается view candles_all.
Хранит историю модельного решения в отдельных таблицах:
predictions_5m,predictions_30m,predictions_1h,- агрегированный
signalиconfidence, - отдельные значения для
up/down, - timestamp создания записи.
Для объединенного чтения создается view predictions_all.
Эта структура позволяет:
- анализировать поведение каждой модели отдельно;
- сравнивать согласованные и конфликтующие ответы;
- строить пост-оценку качества сигналов на истории.
В проекте используется комбинация:
- базовых ценовых и объемных признаков,
- техиндикаторных и статистических преобразований,
- поведенческих и волатильностных признаков,
- внешних макро/настроенческих факторов.
Примеры инженерных признаков:
volume_profile_imbalance,normalized_atr,efficiency_ratio,volume_zscore,price_acceleration,bb_width_pct,rsi_momentum_div,return_skewness_24h,price_momentum,volatility_ratio,close_position,hl_range_pct.
Проект объединяет три слоя в одном репозитории:
- online inference контур (Go + FastAPI + PostgreSQL),
- infra-описание (compose, docker, конфиги),
- offline модельный контур (
model_engineeringс ноутбуками и датасетами).
За счет этого в одном месте сосуществуют:
- подготовка и эволюция моделей,
- сервисная эксплуатация,
- хранение фактической истории решений.
- Часть внешних признаков в
internal/features/external.goреализована как заглушки (funding_rate, ETF-блок). - Качество финального сигнала зависит от согласованности двух независимых моделей и стабильности входного feature vector.
- Контур ориентирован на предсказание внутри фиксированного таймфрейма и текущего набора признаков.
- Go (основной сервисный контур),
- Python + FastAPI (инференс),
- NumPy / scikit-learn / XGBoost (модельные артефакты),
- PostgreSQL (история данных и предсказаний),
- Prometheus (сбор метрик),
- Grafana (визуализация),
- Nginx (reverse proxy + basic auth),
- Docker Compose (оркестрация сервисов).
В feature-worker поднят endpoint /metrics (по умолчанию :9102), который экспортирует:
crp_prediction_results_total{symbol,interval,result="win|loss"}— счётчик исходов;crp_prediction_winrate_ratio{symbol,interval}— текущий winrate в диапазоне[0..1];crp_prediction_last_result{symbol,interval}— последний исход (1/0);crp_predictions_stored_totalиcrp_predictions_signal_total— поток предсказаний.
Prometheus скрапит feature-worker:9102, а Grafana использует datasource CRP Prometheus (uid=crp-prometheus).
Дашборд CRP Prediction Quality использует гибридный подход:
- история результатов и winrate — из PostgreSQL (включая восстановление результата по связке
predictions_all + candles_all); - live winrate — из Prometheus.
- Публично проброшен только порт
80сервисаnginx. - Все остальные сервисы (PostgreSQL, Grafana, Prometheus, Go/Python API) работают только во внутренней docker-сети.
- Перед запуском задайте секреты в
.env:POSTGRES_PASSWORD=...GRAFANA_ADMIN_PASSWORD=...
- Для
nginxвключенbasic authчерез файл:/root/crp-secrets/nginx/.htpasswd
- HTTPS-терминация выполняется на
nginx(порт443),80используется только для редиректа на HTTPS. - TLS-сертификаты подключаются из:
/root/crp-secrets/nginx/certs/grafana.crt/root/crp-secrets/nginx/certs/grafana.key
Пример создания htpasswd (если файла еще нет):
mkdir -p /root/crp-secrets/nginx
printf "ops_admin:$(openssl passwd -apr1 'CHANGE_ME_PASSWORD')\n" > /root/crp-secrets/nginx/.htpasswd
chmod 644 /root/crp-secrets/nginx/.htpasswd