События и пулы
Yoyo Market (далее — Yoyo) организует прогнозы в двухуровневую иерархию: События содержат один или несколько Пулов, и каждый пул содержит бинарные рынки. На этой странице объясняются обе концепции и их взаимосвязь.
События
Событие — это контейнер верхнего уровня. Оно представляет реальное явление, на которое пользователи могут делать прогнозы — футбольный матч, ценовой таргет криптовалюты, политические выборы и т.д.
Ключевые поля
| Поле | Тип | Описание |
|---|---|---|
id | integer | Уникальный идентификатор. |
name | string | Отображаемое имя (английский). |
name_ru | string | Отображаемое имя (русский). |
tags | string[] | Теги категоризации (например, ["football", "premier-league"]). |
image_url | string | null | Обложка для карточки события. |
versus_images | string[] | Два URL иконок участников (спортивные события). |
versus_names | string[] | Два имени участников (спортивные события). |
has_draw | boolean | Существует ли исход ничьей (спортивные события с трехсторонними рынками). |
status | string | Вычисляемое состояние жизненного цикла — см. ниже. |
is_active | boolean | При false событие скрыто из лент, поиска и прямых ссылок. Создатель все еще мо жет видеть его в "моих событиях". |
is_loop_event | boolean | Пересоздается ли событие по повторяющемуся расписанию (например, циклы цен криптовалют). |
main_pool_id | integer | null | Пул, отображаемый в карточке события в ленте — см. ниже. |
created_at | timestamp | Когда событие было создано. |
closed_at | timestamp | null | Когда событие было закрыто. Null, пока ещё активно. |
Статус события
Статус — это вычисляемое поле, определяемое на основе пулов события:
| Статус | Значение |
|---|---|
"new" | Событие ещё не началось. Все пулы ещё до своего времени live_at. |
"started" | Хотя бы один пул начался, но событие ещё не закрыто. |
"paid" | Событие закрыто и все выплаты произведены (closed_at установлено). |
Циклические события (Loop events)
Циклическое событие — это событие, которое автоматически пересоздается через фиксированный интервал. Используется для повторяющихся криптовалютных прогнозов (например, "Будет ли ETH выше $3,500 через 1 час?").
Поля, специфичные для циклов:
| Поле | Описание |
|---|---|
loop_interval_minutes | Время между пересозданиями циклов (например, 60 для почасовых). |
next_recreate_at | Когда текущий цикл заканчивается и создается новый. |
loop_template_event_id | ID шаблонного события, хранящего конфигурацию. |
Когда цикл закрывается, система рассчитывает все позиции, затем создает свежее событие из шаблона с обновленными параметрами (базовая цена, вероятности, token ID).
Дополнительные поля
fixture_id/fixture_sport— Связь с внешним провайдером спортивных данных (API-Sports) для обновлений счета в реальном времени.polymarket_event_url— URL/slug для получения и синхронизации котировок с Polymarket.pinned_until/pin_order— Управляет закреплением события вверху ленты.
Пулы
Пул — это вопрос внутри события. Каждый пул содержит один или несколько бинарных рынков (исходы YES/NO).
Например, событие футбольного матча может иметь три пула:
- "Победитель матча" (с рынками для Команды A, Ничьей, Команды B)
- "Всего голов больше 2.5"
- "Обе команды забьют"
Ключевые поля
| Поле | Тип | Описание |
|---|---|---|
id | integer | Уникальный идентификатор. |
name | string | Текст вопроса (английский). |
name_ru | string | Текст вопроса (русский). |
rules | string | Описание того, как определяется выигрышный исход. |
won_side | integer | null | Индекс выигрышного рынка после разрешения. Null, пока не разрешен. |
finish_at | timestamp | null | Дедлайн, после которого нельзя размещать ордера. Если null, пул закрывается только вручную. |
live_at | timestamp | null | Когда пул становится активным и открывается торговля. |
margin | integer | Общая маржа для пула (в копейках). |
score | string | null | Текущий счет для живых спортивных событий (например, "2-1"). |
Вычисляемые поля (не хранятся в БД)
sides/sides_ru— Названия рынков, извлеченные из рынков пула.volumes— Объем торгов по каждому рынку.totalPool— Сумма объемов всех рынков.
Концепция main_pool_id
Каждое событие имеет необязательный main_pool_id, указывающий на один из его пулов. Это пул, рынки которого отображаются на карточке события в ленте. Когда пользователь видит событие в списке, показанные вероятности, цены и объемы берутся из этого основного пула.
Если main_pool_id не установлен, фронтенд обычно использует первый пул.
Метаданные пула
Каждый пул может содержать JSON-объект metadata с дополнительной конфигурацией. Это особенно важно для создания событий и цикличес ких событий.
Основные поля метаданных
| Поле | Описание |
|---|---|
market_names | Пользовательские названия для каждого рынка (например, ["Победит ли PSG?", "Закончится ли матч вничью?"]). |
market_names_ru | Русские версии названий рынков. |
market_probabilities | Начальные вероятности (0-1) для каждого рынка, используются вместо объемов. |
market_images | URL изображения для каждого рынка. |
market_yes_names / market_no_names | Пользовательские метки исходов YES/NO для каждого рынка (например, "Выше $100k" / "Ниже $100k"). |
Конфигурация LMSR
| Поле | Описание |
|---|---|
lmsr_b_kopecks | Параметр ликвидности LMSR b для пула в копейках. Определяет, насколько сильно цены двигаются за сделку. Если не задан, используется глобальное значение по умолчанию. |
Синхронизация с Polymarket
| Поле | Описание |
|---|---|
polymarket_token_ids | Массив CLOB token ID Polymarket, сопоставленных с каждым рынком, для синхронизации цен в реальном времени через WebSocket. |
Отслеживание криптоактивов
| Поле | Описание |
|---|---|
asset_symbol | Символ отслеживаемого актива (например, "BTCUSDT"). |
asset_base_price | "Целевая цена", установленная при создании события. |
asset_close_price | Цена актива на момент закрытия цикла. |
Поля цикла
При закрытии цикла система записывает поля next_* в шаблонный пул для настройки предстоящего цикла:
next_asset_base_price— Базовая цена для нового цикла.next_market_probabilities— Начальные вероятности для рынков нового цикла.next_market_names,next_market_names_ru,next_market_images— Структура рынков следующего цикла.next_polymarket_token_ids— Token ID для следующего цикла.
Они считываются воркером пересоздания и применяются к новому пулу.
Связи
Event (1)
├── Pool (1..N)
│ ├── Market (1..N) ← бинарные исходы YES/NO
│ └── metadata ← конфигурация, вероятности, отслеживание активов
└── main_pool_id ────────→ один из вышеуказанных пулов
Событие всегда имеет хотя бы один пул, и каждый пул всегда имеет хотя бы один рынок. Типичная структура для спортивного события с опцией ничьей — один пул с тремя рынками (Команда A побеждает, Ничья, Команда B побеждает).