ТЗ: Токен-аналитика (CoinGecko + AI) в модуле aiAnalytics
Метаданные
| Параметр | Значение |
|---|---|
| Дата создания | 2026-07-12 |
| Дата последнего изменения | 2026-07-12 |
| Статус апрува | ✅ Одобрено |
| Дата апрува | 2026-07-12 |
1. Назначение
Модуль aiAnalytics сегодня умеет две вещи: обзор рынка (GET /ai-analytics/market/outlook) и разбор пула ликвидности (POST /ai-analytics/pool/analytics). Токенов в нём нет.
Задача — достроить ветку токенов, чтобы фронт мог показать страницу каталога токенов, карточку конкретного токена со всей информацией, которую отдаёт CoinGecko, поиск, новости — и по запросу получить AI-аналитику (summary) по токену.
Backend-only. Референс поведения — /Users/vovilonn/Documents/work/defilab/zenfi (apps/backend/src/markets/).
2. Функциональные требования
2.1. Пользовательские сценарии
- Пользователь открывает страницу аналитики → видит список токенов с ценой, изменением за 1ч/24ч/7д/30д, капитализацией, объёмом и мини-графиком; листает страницы; сортирует по капитализации, объёму или изменению цены.
- Пользователь вводит запрос в поиск → видит подходящие токены и переходит в любой из них.
- Пользователь открывает карточку токена → видит подробные рыночные метрики, описание проекта, ссылку на сайт и whitepaper, соцсети, репозитории, категории, ATH/ATL, supply, метрики сообщества и разработки.
- Пользователь смотрит график цены за выбранный период (1д…365д).
- Пользователь читает новости, релевантные токену.
- Пользователь нажимает «AI-аналитика» → получает structured-summary: вердикт, ключевые наблюдения, риски, сценарии и готовый Markdown для рендера.
2.2. Бизнес-логика
Эндпоинты
Все — @UseGuards(JwtAuthGuard) + @ApiBearerAuth(), @ApiTags('AI Analytics'). Каждый ответ несёт провенанс данных: cached, stale, fetchedAt.
| Метод | Путь | Источник | TTL |
|---|---|---|---|
GET | /ai-analytics/tokens | CoinGecko /coins/markets | 60 c |
GET | /ai-analytics/tokens/search | CoinGecko /search | 300 c |
GET | /ai-analytics/tokens/trending | CoinGecko /search/trending | 300 c |
GET | /ai-analytics/tokens/:id | CoinGecko /coins/{id} | 300 c |
GET | /ai-analytics/tokens/:id/chart | CoinGecko /coins/{id}/market_chart | 300 c |
GET | /ai-analytics/tokens/:id/news | CryptoCompare (общий фид) | 600 c |
GET | /ai-analytics/market/global | CoinGecko /global + alternative.me | 60 c |
POST | /ai-analytics/tokens/:id/analytics | LLM | 3600 c |
/search и /trending объявляются до /:id, иначе Nest сматчит их как id.
Ключевые правила
- Исходящий запрос списка фиксирован сервером:
price_change_percentage=1h,24h,7d,30d— константа, клиентом не управляется. Без неё CoinGecko вообще не возвращает поля 1ч/7д/30д. - Валюта только USD. Поля DTO названы
*Usd,/coins/{id}валюту не принимает. ПараметрvsCurrencyв контракт не выносится. - Сортировка по изменению цены — в памяти. CoinGecko умеет
orderтолько по капитализации, объёму и id. Приsort=change24h(и аналогах) сервис берёт один кешированный пул топ-250 по капитализации, сортирует и пагинирует в памяти. Ограничение документируется: ранжирование идёт только внутри топ-250. - Новости — общий фид + матчинг в памяти. Пер-токенного фильтра у CryptoCompare нет:
categoriesвалидируется по его собственному фиксированному справочнику, и для длинного хвоста токенов категории не существует. Токен матчится поcategories→tags→titleэлемента ленты. Ноль совпадений → общая лента с флагомmatchedBySymbol: false. - Правило детерминизма. Каждое число, которое видит пользователь, считается в коде и передаётся модели дословно. Модель пишет только прозу.
- Фолбэки не кешируются. Ни AI-фолбэк, ни пустая лента новостей не попадают в кеш — следующий запрос повторит попытку.
- Постоянная ошибка апстрима не подменяется stale-данными. Право на stale имеет только ретраибельная корзина (429/5xx/сеть).
AI-аналитика
Модель получает: цену и изменения 1ч/24ч/7д/30д/1г, капитализацию и ранг, FDV, объём 24ч, отношение объёма к капитализации, supply (circulating/total/max), ATH/ATL и расстояние до них, RSI(14), волатильность 7д, тренд, категории, описание проекта, метрики разработки и сообщества, sentiment-голоса, Fear&Greed, доминацию BTC, до 5 заголовков новостей.
Ответ (строгий JSON, валидируется и нормализуется в коде):
{
"verdict": "bullish|bearish|neutral",
"summary": "2–3 предложения",
"highlights": ["3–5 ключевых наблюдений"],
"risks": ["2–4 риска"],
"scenarios": [{ "trigger": "…", "direction": "up|down|sideways", "range": "3–6%", "note": "…" }],
"disclaimer": "… Не является финансовой рекомендацией."
}
Markdown рендерится в коде из этого же JSON, вторым вызовом LLM не ходим: один вызов модели, ноль расхождений между analysis и markdown.
2.3. UI/UX требования
Не применимо (backend-only). Ответ AI-эндпоинта содержит и машинные поля, и готовый Markdown для прямого рендера.