Заказать токеномику
База знаний Кейсы Заказать токеномику

Симуляции в токеномике: от Монте-Карло до агентного моделирования

Методы симуляции токеномики: анализ чувствительности, сценарный анализ, Монте-Карло, агентное моделирование. Код на Python, графики, сравнение подходов.

Зачем симулировать токеномику

Табличная модель токеномики — это один сценарий: «при таких-то параметрах будет такой-то результат». Но параметры всегда неточны. Сколько пользователей придёт — 5 000 или 50 000? Какой процент застейкает? Когда инвесторы начнут продавать?

Симуляция отвечает не на вопрос «что будет», а на вопрос «что может быть и с какой вероятностью». Вместо одного прогноза — распределение исходов. Вместо «цена будет $0.50» — «в 90% сценариев цена остаётся выше $0.30».

В этой статье — четыре уровня симуляций, от простых к сложным. Каждый следующий уровень добавляет точность, но и требует больше данных и кода.

Уровень 1: Анализ чувствительности

Самый простой метод. Берём табличную модель и меняем один параметр, фиксируя остальные. Смотрим, как результат зависит от этого параметра.

Когда применять

  • На ранней стадии проектирования — чтобы понять, какие параметры критичны
  • При подборе параметров bonding curve, эмиссии, вестинга
  • Для ответа на вопрос «что сломается первым»

Пример: чувствительность стейкинга к APR

Протокол с эмиссией 800 токенов/день. Вопрос: при каком проценте стейкинга APR становится ниже 5% (порог, при котором крупные стейкеры уходят)?

Результат: при стейкинге выше ~58% APR падает ниже 5%. Это критический порог — если модель предполагает 60% стейкинга, система работает на грани.

Процент стейкингаAPRСтатус
20%14.6%Безопасно
40%7.3%Приемлемо
58%5.0%Порог
60%4.9%Ниже порога
80%3.7%Критично
Код симуляции (Python)
import numpy as np
import matplotlib.pyplot as plt

total_supply = 10_000_000
daily_rewards = 800

staking_pcts = np.linspace(0.1, 0.9, 50)  # от 10% до 90% стейкинга
aprs = (daily_rewards * 365) / (total_supply * staking_pcts)

fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(staking_pcts * 100, aprs * 100, linewidth=2.5, color='#2563eb')
ax.axhline(y=5, color='#dc2626', linestyle='--', label='Порог 5% APR')
ax.fill_between(staking_pcts * 100, aprs * 100, 5,
                where=(aprs * 100 < 5), alpha=0.15, color='#dc2626')
ax.set_xlabel('Процент стейкинга (%)')
ax.set_ylabel('APR (%)')
ax.set_title('Чувствительность APR к проценту стейкинга')
ax.legend()
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Ограничение метода
Анализ чувствительности меняет один параметр за раз. В реальности параметры взаимосвязаны: рост числа пользователей увеличивает и стейкинг, и давление на продажу. Для учёта взаимосвязей нужен следующий уровень — сценарный анализ.

Уровень 2: Сценарный анализ

Фиксируем набор параметров для каждого сценария. Стандартный подход — три сценария:

ПараметрПессимистичныйБазовыйОптимистичный
Пользователи (мес 12)5 00020 00080 000
Процент стейкинга30%50%70%
Отток15%/мес8%/мес3%/мес
Давление на продажу (инвесторы)80% после клиффа50%20%

Что показывает

В пессимистичном сценарии давление на продажу составляет 1.6M токенов/мес (80% от 2M разлока), а свободный float растёт быстрее (мало стейкеров). Это двойной удар по цене.

В оптимистичном — продаётся лишь 400K/мес, а 70% стейкается. Давление на продажу в 4 раза ниже.

МетрикаПессимистичныйБазовыйОптимистичный
Давление на продажу1.6M/мес1.0M/мес0.4M/мес
Свободный float (мес 12)23.8M17.0M10.2M
Соотношение sell / float6.7%5.9%3.9%
Код симуляции (Python)
import numpy as np
import matplotlib.pyplot as plt

months = np.arange(1, 25)

scenarios = {
    'Пессимистичный': {
        'users_final': 5_000,
        'stake_pct': 0.30,
        'sell_pressure': 0.80,
        'color': '#dc2626'
    },
    'Базовый': {
        'users_final': 20_000,
        'stake_pct': 0.50,
        'sell_pressure': 0.50,
        'color': '#2563eb'
    },
    'Оптимистичный': {
        'users_final': 80_000,
        'stake_pct': 0.70,
        'sell_pressure': 0.20,
        'color': '#16a34a'
    }
}

total_supply = 100_000_000
initial_circulating = 10_000_000  # TGE
monthly_unlock = 2_000_000        # вестинг инвесторов

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

for name, s in scenarios.items():
    circulating = np.zeros(len(months))
    net_sell = np.zeros(len(months))

    for i, m in enumerate(months):
        unlocked = min(initial_circulating + monthly_unlock * m, total_supply)
        staked = unlocked * s['stake_pct']
        free_float = unlocked - staked
        sell_tokens = monthly_unlock * s['sell_pressure']

        circulating[i] = free_float
        net_sell[i] = sell_tokens

    axes[0].plot(months, circulating / 1e6, label=name,
                 color=s['color'], linewidth=2)
    axes[1].plot(months, net_sell / 1e6, label=name,
                 color=s['color'], linewidth=2)

axes[0].set_title('Свободный float (млн токенов)')
axes[0].set_xlabel('Месяц')
axes[0].legend()
axes[0].grid(True, alpha=0.3)

axes[1].set_title('Давление на продажу (млн токенов/мес)')
axes[1].set_xlabel('Месяц')
axes[1].legend()
axes[1].grid(True, alpha=0.3)

plt.tight_layout()
plt.show()
Проблема сценарного анализа
Три сценария — это три точки. Какова вероятность каждого? Что между ними? Сценарный анализ не отвечает на эти вопросы. Для этого нужен Монте-Карло.

Уровень 3: Монте-Карло

Метод Монте-Карло — это тысячи случайных сценариев. Вместо фиксированных параметров задаём распределения: «пользователей будет от 5 000 до 80 000, наиболее вероятно ~20 000». Модель запускается 1 000–10 000 раз с разными случайными значениями.

Результат — не точка и не три точки, а полное распределение исходов с перцентилями и доверительными интервалами.

Как работает

  1. Определяем входные параметры и их распределения
  2. На каждой итерации сэмплируем значения из распределений
  3. Прогоняем модель, записываем результат
  4. Повторяем 1 000–10 000 раз
  5. Анализируем распределение результатов

Выбор распределений

ПараметрРаспределениеПочему
Число пользователейЛогнормальноеРост может быть взрывным, но не отрицательным
Процент стейкингаБетаОграничен от 0 до 1, можно задать моду
Давление на продажуБетаАналогично — доля от 0 до 1
Время до продажиЭкспоненциальноеБольшинство продаёт быстро, единицы ждут долго
Цена токенаЛогнормальноеМультипликативная динамика, не бывает отрицательной

Пример: устойчивость казначейства

Протокол поднял $5M на TGE. Команда тратит деньги, но зарабатывает комиссию с пользователей. Вопрос: хватит ли казначейства на 36 месяцев?

Модель состоит из четырёх параметров. Каждый сэмплируется из распределения, потому что точное значение неизвестно заранее:

ПараметрРаспределениеДиапазонПочему именно такой
Ежемесячный burn rateЛогнормальное (медиана $150K, σ=0.3)$90K – $250KЗарплаты, инфраструктура, маркетинг. Логнормальное — потому что расходы не бывают отрицательными, но могут неожиданно вырасти
Рост пользователейНормальное (μ=8%, σ=4%)0% – 16%/месОрганический рост с высокой неопределённостью. Может быть близок к нулю
Доход на пользователяРавномерное ($2 – $8/мес)$2 – $8Комиссии протокола. Диапазон на основе аналогов (DeFi: $3–$5, GameFi: $1–$2)
Начальные пользователиЛогнормальное (медиана 2000, σ=0.5)800 – 5 000Зависит от успеха маркетинговой кампании на TGE

Зависимости внутри модели:

  • Доход = пользователи × доход_на_пользователя (больше пользователей → больше дохода)
  • Burn rate растёт на 2%/мес (инфляция зарплат, рост команды)
  • Баланс казначейства = предыдущий баланс + доход − расходы
  • Если баланс падает до 0 — протокол не может оплачивать операции

Результат 2 000 прогонов:

МетрикаЗначение
Медиана (P50) баланса на месяц 24~$3.2M
5-й перцентиль (P5) на месяц 24~$0.4M
95-й перцентиль (P95) на месяц 24~$8.1M
Доля прогонов с обнулением к месяцу 36~12%

Ключевой вывод: в 12% прогонов казначейство обнуляется до месяца 36. Это значит, что при текущих параметрах протокол имеет ~88% шансов дожить до трёх лет без дополнительного фандрейзинга. Если порог приемлемого риска — 5%, нужно либо снижать burn rate, либо увеличивать начальное казначейство до ~$7M.

Код симуляции (Python)
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)
n_simulations = 2000
n_months = 36
initial_treasury = 5_000_000  # $5M

results = np.zeros((n_simulations, n_months))

for sim in range(n_simulations):
    treasury = initial_treasury

    # Сэмплируем параметры для этого прогона
    monthly_burn = np.random.lognormal(mean=np.log(150_000), sigma=0.3)
    user_growth = np.random.normal(0.08, 0.04)  # 8% ± 4% рост/мес
    revenue_per_user = np.random.uniform(2, 8)   # $/user/мес
    initial_users = np.random.lognormal(mean=np.log(2000), sigma=0.5)

    users = initial_users

    for month in range(n_months):
        users *= (1 + max(user_growth + np.random.normal(0, 0.02), -0.1))
        revenue = users * revenue_per_user
        burn = monthly_burn * (1 + 0.02 * month)  # расходы растут 2%/мес

        treasury = treasury + revenue - burn
        results[sim, month] = max(treasury, 0)

# === Визуализация ===
fig, axes = plt.subplots(1, 2, figsize=(14, 5))

months = np.arange(1, n_months + 1)
p5 = np.percentile(results, 5, axis=0)
p25 = np.percentile(results, 25, axis=0)
p50 = np.percentile(results, 50, axis=0)
p75 = np.percentile(results, 75, axis=0)
p95 = np.percentile(results, 95, axis=0)

axes[0].fill_between(months, p5/1e6, p95/1e6, alpha=0.1, color='#2563eb')
axes[0].fill_between(months, p25/1e6, p75/1e6, alpha=0.2, color='#2563eb')
axes[0].plot(months, p50/1e6, color='#2563eb', linewidth=2, label='Медиана')
axes[0].plot(months, p5/1e6, color='#dc2626', linewidth=1,
             linestyle='--', label='5-й перцентиль')
axes[0].axhline(y=0, color='black', linewidth=0.5)
axes[0].set_xlabel('Месяц')
axes[0].set_ylabel('Казначейство ($M)')
axes[0].set_title('Монте-Карло: баланс казначейства')
axes[0].legend()
axes[0].grid(True, alpha=0.3)

bankrupt_by_month = np.zeros(n_months)
for month in range(n_months):
    bankrupt_by_month[month] = np.mean(results[:, month] == 0) * 100

axes[1].bar(months, bankrupt_by_month, color='#dc2626', alpha=0.7)
axes[1].set_xlabel('Месяц')
axes[1].set_ylabel('% прогонов с пустым казначейством')
axes[1].set_title('Кумулятивная вероятность банкротства')
axes[1].grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

Как читать результаты

МетрикаЧто показываетПример
Медиана (P50)Наиболее вероятный исходКазначейство = $3.2M через 24 мес
5-й перцентиль (P5)Худший реалистичный сценарийКазначейство = $0.4M через 24 мес
95-й перцентиль (P95)Лучший реалистичный сценарийКазначейство = $8.1M через 24 мес
Вероятность событияШанс конкретного исхода12% прогонов: казначейство = 0 к месяцу 36
VaR (Value at Risk)Максимальная потеря с заданной вероятностьюС вероятностью 95% потери не превысят $4.6M
Правило 5-го перцентиля
Проектируйте токеномику так, чтобы система оставалась работоспособной в 5-м перцентиле (худших 5% прогонов). Если при P5 казначейство обнуляется на месяц 18, а runway должен быть 24 — модель нужно пересматривать.

Типичные ошибки

  • Коррелированные параметры сэмплируются независимо. Если растёт число пользователей — растёт и нагрузка на казначейство. Используйте копулы или совместные распределения
  • Слишком широкие распределения. «Пользователей от 100 до 10 000 000» — не информативно. Сужайте диапазоны на основе аналогов
  • Мало итераций. 100 прогонов не дадут стабильных перцентилей. Минимум 1 000, лучше 5 000
  • Игнорирование хвостов. Средний результат неинтересен — важны экстремальные сценарии

Уровень 4: Агентное моделирование

Монте-Карло варьирует параметры, но модель внутри каждого прогона остаётся детерминированной: формулы считают от начала до конца. Агентное моделирование (ABM) добавляет ещё один слой — поведение отдельных участников.

В ABM каждый пользователь — отдельный агент со своим балансом, стратегией и правилами принятия решений. На каждом шаге агенты реагируют на текущее состояние системы, и их действия меняют это состояние для всех остальных.

Это позволяет моделировать эмерджентные эффекты: каскадные выходы из стейкинга, атаки на governance, bank-run на пулы ликвидности — всё то, что невозможно выразить формулой.

Подробный разбор с кодом, примером стейкинга и банк-рана — в отдельной статье: Агентное моделирование в токеномике.

Сравнение методов

Анализ чувствительностиСценарныйМонте-КарлоABM
СложностьНизкаяНизкаяСредняяВысокая
Число исходовN точек3–51 000+1 000+
Взаимосвязи параметровНетВручнуюЧерез распределенияЧерез поведение
Эмерджентные эффектыНетНетНетДа
ИнструментыGoogle SheetsGoogle SheetsPython / RPython (cadCAD, radCAD)
Когда применятьРанний этапПрезентация инвесторамСтресс-тест моделиСложные механизмы

Что использовать на каком этапе

  • Анализ чувствительности — определите, какие параметры критичны. Это занимает час в таблице
  • Сценарный анализ — покажите 3 сценария инвесторам и команде. Общий язык для принятия решений
  • Монте-Карло — проверьте устойчивость: «в каком проценте прогонов всё ломается?». Нужен Python
  • Агентное моделирование — если в системе есть участники с конкурирующими стратегиями и обратная связь между действиями

Комбинирование методов

На практике методы не исключают друг друга. Типичный порядок для проекта:

  1. Таблица — allocation, вестинг, базовая unit-экономика
  2. Анализ чувствительности — находим параметры, к которым модель наиболее чувствительна
  3. Монте-Карло — 2 000 прогонов по ключевым параметрам, получаем перцентили
  4. ABM — для критических механизмов (стейкинг, AMM, governance) строим агентную модель и запускаем 100+ прогонов

Каждый шаг информирует следующий: анализ чувствительности показывает, что варьировать в Монте-Карло. Монте-Карло показывает, где нужна ABM.

Robust₉₅ = P(система работает | P5 сценарий) > 0.95
Цель: система остаётся работоспособной в 95% прогонов при 5-м перцентиле входных параметров

Практические рекомендации

Когда хватит таблицы

  • Allocation и вестинг — фиксированные графики, нечего симулировать
  • Unit-экономика на ранней стадии — пока нет данных для распределений
  • Презентация концепции инвесторам — нужна простота, не перцентили

Когда нужен Монте-Карло

  • Проектирование казначейства — ключевой вопрос «хватит ли денег»
  • Подбор параметров эмиссии — при каких значениях инфляция выходит из-под контроля
  • Оценка runway — срок жизни проекта при разных сценариях роста

Когда нужна ABM

  • Стейкинг с неравномерным распределением (киты)
  • AMM и пулы ликвидности
  • Governance с голосованием
  • Любая система с обратной связью между участниками

Подробнее: Агентное моделирование в токеномике

Нужна симуляция для вашего проекта?

Стресс-тестируем токеномику: от Монте-Карло до агентного моделирования. Находим слабые места до запуска.

Обсудить проект →

Связанные материалы