← К списку статей
July 13, 2026
5 мин. чтения

Таргетирование волатильности и торговля на основе GARCH-прогнозов

#volatility
#GARCH
#volatility-targeting
#backtesting
#risk
#crypto
#algorithmic-trading

Первые три части этой серии научили вас прогнозировать волатильность. Мы построили одномерный GARCH(1,1) в Части 1, добавили эффект левериджа и тяжелые хвосты с помощью GJR и инноваций Student-t в Части 2, и смоделировали целую ковариационную матрицу во времени с помощью DCC-GARCH в Части 3. В конце каждой части мы выводили число: ожидаемую волатильность на завтра. И затем, если быть честными, останавливались — как будто получение прогноза и было целью.

Это не так. Прогноз волатильности — не P&L. Никому и никогда не платили за низкий QLIKE-скор. Прогноз становится чего-то стоящим ровно в тот момент, когда он меняет решение, которое вы иначе приняли бы иначе — сколько купить, когда сокращать позицию, сколько капитала выделить. Если ваш прогноз не двигает позицию, его статистическая точность — это частное хобби.

Эта заключительная часть посвящена замыканию этого цикла. Мы берем прогнозы из Частей 1-3 и применяем их в самом чистом возможном решении: таргетирование волатильности — определение размера позиции так, чтобы реализованная волатильность портфеля попадала в постоянный целевой уровень. Затем мы делаем то, что этот блог ценит больше, чем любую отдельную модель: честно оцениваем результат. Мы сравниваем GARCH с простыми, но сильными базовыми моделями (скользящая realized vol, EWMA), используем функции потерь, устойчивые к тому факту, что мы никогда не можем наблюдать истинную волатильность, проводим walk-forward бэктест с издержками и без заглядывания в будущее, и прямо говорим, что таргетирование волатильности дает, а что нет. Спойлер: оно улучшает риск-скорректированную доходность и укрощает просадки гораздо надежнее, чем производит альфу.

Почему таргетирование волатильности — правильный тест

Есть более изощренные способы использовать прогноз волатильности — ценообразование опционов, лимиты VaR, динамическое хеджирование — но таргетирование волатильности изолирует ценность прогноза с наименьшим загрязнением от других ставок. Идея сводится к одному уравнению.

Держите рискованный актив с сигнальным направлением (пока просто "long"). Вместо фиксированной позиции масштабируйте экспозицию обратно пропорционально прогнозной волатильности:

wt=σtargetσ^t(затем ограничивается сверху)w_t = \frac{\sigma_{\text{target}}}{\hat{\sigma}_{t}} \quad \text{(затем ограничивается сверху)}

где σ^t\hat{\sigma}_t — ваш прогноз волатильности на следующий период (сделанный с использованием только данных до tt), а σtarget\sigma_{\text{target}} — годовая волатильность, на которой вы хотите, чтобы работала стратегия — скажем, 15% или 20%. Когда модель прогнозирует спокойный рынок, вы увеличиваете леверидж к 1.0 (или выше); когда она прогнозирует бурю, вы сокращаете позицию. Реализованная волатильность масштабированной позиции, в первом приближении, равна

Vol(wtrt+1)=wtσt+1=σtargetσ^tσt+1σtarget\text{Vol}(w_t r_{t+1}) = w_t \, \sigma_{t+1} = \frac{\sigma_{\text{target}}}{\hat\sigma_t}\, \sigma_{t+1} \approx \sigma_{\text{target}}

всякий раз, когда σ^tσt+1\hat\sigma_t \approx \sigma_{t+1}. Так что вся ценность упражнения покоится на одном: насколько близок ваш прогноз σ^t\hat\sigma_t к фактической волатильности следующего периода σt+1\sigma_{t+1}. Более точный прогноз дает более плоский профиль реализованной волатильности и — как мы увидим — лучший коэффициент Шарпа. Именно поэтому это правильный тест. Прогноз — не украшение; это знаменатель.

Почему это повышает Шарп и контролирует просадки

Здесь работают два эмпирических факта.

Волатильность гораздо более прогнозируема, чем доходность. Направление завтрашней доходности BTC близко к подбрасыванию монеты на дневной частоте; величина же — нет. Волатильность кластеризуется — большие движения следуют за большими движениями — что и является всей причиной существования GARCH (Часть 1 вывела структуру AR(1) в дисперсии, которая кодирует это). R2R^2 на уровне 0.4-0.6 для прогноза дисперсии на один день вперед — обычное дело; то же число для доходностей было бы сигналом уровня Renaissance. Таргетирование волатильности эксплуатирует прогнозируемую величину и остается агностичным к непрогнозируемой.

Коэффициенты Шарпа не постоянны во времени; они падают при всплесках волатильности. Режимы высокой волатильности в крипте — каскады делевериджа, сбои бирж, дни, когда все гэпает на 30% — как правило имеют худшее соотношение доходность/риск, а не лучшее. Механически сокращая экспозицию именно тогда, когда прогнозная волатильность высока, вы недовешиваете периоды, которые вносят наибольший вклад в просадки и наименьший — в накопленную доходность. Moreira и Muir (2017) показали для акций, что портфели с управлением волатильностью — это точное масштабирование 1/σ21/\sigma^2 — повышают коэффициенты Шарпа и дают положительную альфу против неуправляемого фактора. Механизм не магический; это отказ держать постоянную долларовую позицию в предсказуемо турбулентные окна.

Выгода от контроля просадок еще более прямая. Максимальная просадка определяется хвостом распределения доходности позиции. Поскольку wtrt+1w_t r_{t+1} имеет волатильность, зафиксированную около σtarget\sigma_{\text{target}}, тяжелый левый хвост, от которого страдает стратегия с фиксированным номиналом во время взрыва волатильности, сжимается: вы уже входили с малой позицией. Таргетирование волатильности не предсказывает крахи, но систематически недовешивает, когда рынок взбудоражен, а именно тогда и случаются крахи.

Связь с критерием Kelly и дробным сайзингом

Таргетирование волатильности — близкий родственник критерия Kelly. Для одного актива с ожидаемой избыточной доходностью μ\mu и дисперсией σ2\sigma^2 оптимальная для роста (full-Kelly) доля равна

f=μσ2.f^\star = \frac{\mu}{\sigma^2}.

Если предположить, что коэффициент Шарпа μ/σ\mu/\sigma примерно постоянен — сильное предположение, но именно то, которое подразумевается фразой "рынок платит стабильную цену за риск" — тогда μ=Sσ\mu = S\sigma и f=S/σf^\star = S/\sigma, что в точности является таргетированием волатильности с σtarget=S(доля Kelly)\sigma_{\text{target}} = S \cdot (\text{доля Kelly}). Другими словами, таргетирование волатильности — это сайзинг по Kelly в предположении, что ожидаемая доходность масштабируется с волатильностью. Мы разбираем полный и дробный Kelly, и почему никто в здравом уме не торгует полным Kelly, в статье Критерий Kelly и сайзинг стратегии. Практический урок оттуда переносится и сюда: используйте долю от теоретического размера, потому что ошибка оценки в знаменателе (ваш прогноз волатильности) и особенно в числителе (ожидаемая доходность) делает полный сайзинг опасно агрессивным.

Стоит держать в уме еще две связи. Во-первых, таргетирование волатильности сайзит по симметричной дисперсии доходностей, но выплаты в крипте несимметричны — стоимость дня падения на 20% не является зеркалом дня роста на 20%, если учесть леверидж и ликвидацию. Мы разбираем эту асимметрию напрямую в статье Асимметрия убытков и прибыли, а прогноз GJR/EGARCH (Часть 2) уже закладывает часть этого в σ^t\hat\sigma_t, сильнее реагируя на отрицательные шоки. Во-вторых, прогноз волатильности — это точечная оценка; более полное представление о риске прикладывает к ней интервал. Конформное предсказание для трейдинга показывает, как превратить выходы модели в интервалы, свободные от распределения, под которые можно сайзить позицию, что естественно сочетается с темой честной оценки этой статьи.

Конкуренты: кого должен превзойти GARCH

Вот дисциплина, которая отличает реальную оценку от демонстрации. Прежде чем короновать GARCH, нужно дать ему соперников, которые дешевы, очевидны и удивительно трудны для превосхождения. Если ваша изощренная модель GJR-t не может превзойти EWMA из пяти строк, вы узнали что-то ценное и сэкономили себе кучу продакшн-сложности.

Мы сравниваем четыре модели прогноза волатильности следующего периода.

(a) Скользящая реализованная волатильность (rolling standard deviation)

Самый наивный прогноз: завтрашняя волатильность равна выборочному стандартному отклонению последних nn дневных доходностей.

σ^tRV=1n1i=1n(rti+1rˉ)2\hat\sigma_{t}^{\text{RV}} = \sqrt{\frac{1}{n-1}\sum_{i=1}^{n}\bigl(r_{t-i+1}-\bar r\bigr)^2}

У нее один гиперпараметр (окно nn, обычно 20-60 дней) и никакой модели. Ее недостаток в том, что каждое наблюдение в окне получает равный вес, а затем резко исчезает при выходе из окна — эффект "призрака" или "эха", когда один день краха раздувает прогноз ровно на nn дней, а затем исчезает за ночь, независимо от того, действительно ли рынок успокоился.

(b) EWMA / RiskMetrics (λ=0.94\lambda = 0.94)

Экспоненциально взвешенное скользящее среднее устраняет проблему эха, придавая геометрически убывающий вес более старым квадратам доходностей:

σ^t2=λσ^t12+(1λ)rt2\hat\sigma_{t}^{2} = \lambda\,\hat\sigma_{t-1}^{2} + (1-\lambda)\,r_{t}^{2}

Это оценщик RiskMetrics (J.P. Morgan, 1996). При каноническом λ=0.94\lambda = 0.94 для дневных данных эффективная память составляет примерно 1/(1λ)171/(1-\lambda) \approx 17 дней, но затухание плавное — без обрыва. Обратите внимание, чем на самом деле является EWMA: это интегрированный GARCH(1,1) с ω=0\omega = 0 и α+β=1\alpha + \beta = 1, то есть GARCH без возврата к среднему и без долгосрочной дисперсии. У него ноль свободных параметров, если вы принимаете λ=0.94\lambda = 0.94, и это единственная самая жесткая базовая модель во всей этой статье. Значительная доля статей "GARCH превосходит X" тихо не может превзойти EWMA на out-of-sample данных.

import numpy as np
import pandas as pd

def ewma_vol(returns: pd.Series, lam: float = 0.94, sigma0: float | None = None) -> pd.Series:
    """RiskMetrics EWMA conditional volatility (returns in decimal, e.g. 0.03).

    sigma2_t = lam * sigma2_{t-1} + (1 - lam) * r_t^2
    Returns a series aligned to `returns` where value at t uses info up to t.
    """
    r2 = np.square(returns.values)
    var = np.empty_like(r2)
    var[0] = sigma0**2 if sigma0 is not None else r2[0]
    for t in range(1, len(r2)):
        var[t] = lam * var[t - 1] + (1.0 - lam) * r2[t - 1]  # note: r_{t-1}, no look-ahead
    return pd.Series(np.sqrt(var), index=returns.index, name="ewma_vol")

Тонкость, о которую спотыкаются почти все: прогноз для периода tt (пригодный для сайзинга позиции, удерживаемой на протяжении tt) должен строиться из доходностей, наблюдаемых до tt. В рекурсии выше var[t] использует r2[t-1], так что серия — настоящий прогноз на один шаг вперед. Правильно выставить этот индекс — разница между бэктестом и фантазией — подробнее об этом в разделе про walk-forward.

(c) GARCH(1,1) и GJR-t (Части 1-2)

Наши протагонисты. Стандартный GARCH(1,1):

σt2=ω+αϵt12+βσt12,ω>0, α,β0, α+β<1\sigma_t^2 = \omega + \alpha\, \epsilon_{t-1}^2 + \beta\,\sigma_{t-1}^2, \qquad \omega>0,\ \alpha,\beta\ge0,\ \alpha+\beta<1

с долгосрочной дисперсией σˉ2=ω/(1αβ)\bar\sigma^2 = \omega/(1-\alpha-\beta) и прогнозом на один шаг, выпадающим прямо из рекурсии (Часть 1). Расширение GJR-GARCH добавляет термин левериджа, так что отрицательные шоки повышают дисперсию больше, чем положительные:

σt2=ω+(α+γ1[ϵt1<0])ϵt12+βσt12\sigma_t^2 = \omega + (\alpha + \gamma\, \mathbb{1}[\epsilon_{t-1}<0])\,\epsilon_{t-1}^2 + \beta\,\sigma_{t-1}^2

и в паре с инновациями Student-t для обработки тяжелых хвостов крипты это и есть GJR-t из Части 2. Причина, по которой GARCH может превзойти EWMA — возврат к среднему: после шока GARCH тянет прогноз обратно к σˉ2\bar\sigma^2 со скоростью, определяемой α+β\alpha+\beta, тогда как EWMA (будучи интегрированным) никогда не возвращается. Когда волатильность резко возрастает, а затем нормализуется — обычный случай — прогноз GARCH затухает обратно быстрее и точнее. Когда волатильность действительно устойчива (persistent), эти два прогноза почти неразличимы.

(d) HAR-RV на реализованной дисперсии (если есть внутридневные данные)

Если у вас есть внутридневные бары — а на 24/7 криптовалютных рынках они почти всегда есть — вы можете построить гораздо менее шумный прокси волатильности, чем квадраты дневных доходностей: реализованную дисперсию, сумму квадратов внутридневных доходностей за день.

RVt=i=1Mrt,i2(например, M=288 пятиминутных баров)RV_t = \sum_{i=1}^{M} r_{t,i}^2 \qquad (\text{например, } M = 288 \text{ пятиминутных баров})

Гетерогенная авторегрессионная модель Corsi (2009) прогнозирует завтрашнюю реализованную дисперсию по дневным, недельным и месячным средним прошлого RVRV — грубый, но удивительно эффективный способ уловить долгую память с тремя регрессорами:

RVt+1=β0+βdRVt+βwRVt(5)+βmRVt(22)+ut+1RV_{t+1} = \beta_0 + \beta_d\, RV_t + \beta_w\, \overline{RV}_t^{(5)} + \beta_m\, \overline{RV}_t^{(22)} + u_{t+1}

где RVt(5)\overline{RV}_t^{(5)} и RVt(22)\overline{RV}_t^{(22)} — скользящие средние дневного RVRV за 5 и 22 дня. Это обычная регрессия OLS, она эксплуатирует более качественный внутридневной прокси, и часто она оказывается лучшим прогнозистом дневной волатильности из четырех — часто превосходя GARCH именно потому, что RVRV — более чистая цель, чем r2r^2.

import numpy as np
import pandas as pd

def realized_variance(intraday_returns: pd.Series, day_index) -> pd.Series:
    """Daily realized variance = sum of squared intraday (log) returns per day.
    `intraday_returns` indexed by timestamp; `day_index` maps to calendar day.
    """
    return intraday_returns.pow(2).groupby(day_index).sum()

def har_features(rv: pd.Series) -> pd.DataFrame:
    """Build HAR regressors from a daily realized-variance series."""
    df = pd.DataFrame({"rv": rv})
    df["rv_d"] = df["rv"].shift(1)                          # yesterday
    df["rv_w"] = df["rv"].shift(1).rolling(5).mean()        # trailing week
    df["rv_m"] = df["rv"].shift(1).rolling(22).mean()       # trailing month
    df["target"] = df["rv"]                                 # predict today's RV
    return df.dropna()

def fit_har(rv: pd.Series):
    """Fit HAR-RV by OLS. Returns (coef_dict, predict_fn)."""
    df = har_features(rv)
    X = np.column_stack([np.ones(len(df)), df["rv_d"], df["rv_w"], df["rv_m"]])
    y = df["target"].values
    beta, *_ = np.linalg.lstsq(X, y, rcond=None)
    names = ["const", "rv_d", "rv_w", "rv_m"]

    def predict(rv_d, rv_w, rv_m):
        return float(beta @ np.array([1.0, rv_d, rv_w, rv_m]))

    return dict(zip(names, beta)), predict

Замечание про log-HAR: поскольку RVRV имеет правостороннюю асимметрию и строго положителен, многие практики регрессируют logRVt+1\log RV_{t+1} на логарифмические HAR-признаки, что улучшает подгонку и гарантирует положительные прогнозы. Экспоненцируя обратно, следует добавить полудисперсионную коррекцию Йенсена, RV^=exp(y^+12σ^u2)\widehat{RV} = \exp(\hat{y} + \tfrac{1}{2}\hat\sigma_u^2), иначе вы систематически будете недопрогнозировать.

Имея четыре модели прогноза в руках — RV, EWMA, GARCH/GJR-t, HAR — вопрос становится таким: как решить, какая из них лучшая, если мы никогда не можем увидеть то, что все они пытаются предсказать?

Честная оценка прогноза волатильности

Это основной посыл статьи, так что здесь стоит замедлиться.

Вы хотите сравнить прогнозы σ^t2\hat\sigma_t^2 с истинной условной дисперсией σt2\sigma_t^2. Но σt2\sigma_t^2 — это латентная величина — параметр процесса, генерирующего данные, никогда не наблюдаемый напрямую. Все, что у вас есть — одна реализованная доходность в день. Так что каждая оценка волатильности на самом деле является сравнением вашего прогноза с зашумленным прокси истины. Два стандартных прокси:

  • Квадраты доходностей rt2r_t^2. Несмещенный для σt2\sigma_t^2 в модели с нулевым средним (E[rt2Ft1]=σt2\mathbb{E}[r_t^2 \mid \mathcal{F}_{t-1}] = \sigma_t^2), но чрезвычайно шумный: одна дневная доходность — это оценка стандартного отклонения по одному наблюдению. Прокси rt2r_t^2 может быть равен 0 (плоский день), даже когда истинная волатильность высока, или огромным в удачный хвостовой день.
  • Реализованная дисперсия RVtRV_t из внутридневных данных. Гораздо менее шумная — внутридневная выборка усредняет идиосинкратический шум одного наблюдения — именно поэтому HAR-RV работает и почему вам следует использовать RVRV в качестве прокси, если у вас вообще есть внутридневные данные.

Тонкость, которая ловит почти всех: поскольку прокси зашумлен, выбор функции потерь не безобиден. Ранжируйте два прогноза с неправильной функцией потерь, и зашумленный прокси может перевернуть ранжирование, сказав вам, что худший прогноз лучше. Patton (2011) точно вывел, какие функции потерь являются "устойчивыми" в том смысле, что ранжирование прогнозов по ожидаемым потерям на зашумленном прокси дает то же ранжирование, которое вы получили бы на истинной (ненаблюдаемой) дисперсии. Только определенное семейство соответствует этому требованию. На практике важны два представителя.

MSE против QLIKE

Средняя квадратичная ошибка на дисперсии:

LMSE(σ2,h)=(σ2h)2L_{\text{MSE}}(\sigma^2, h) = (\sigma^2 - h)^2

где h=σ^2h = \hat\sigma^2 — прогноз, а σ2\sigma^2 проксируется через r2r^2 или RVRV. MSE устойчив в смысле Паттона (его ранжирование согласовано с прокси), но он симметричен и зависит от масштаба: он одинаково штрафует перепрогноз и недопрогноз одинаковой абсолютной величины и весит ошибки в периоды высокой волатильности гораздо сильнее, чем ошибки в спокойные периоды. Модель, которая идеально попадает в спокойные 95% дней, но проваливает прогнозы дисперсии в три кризисных дня, будет выглядеть ужасно по MSE, даже если ее поведение в кризис — именно то, что вам нужно.

Потеря QLIKE (квазиправдоподобие) — рабочая лошадка:

LQLIKE(σ2,h)=σ2hlogσ2h1L_{\text{QLIKE}}(\sigma^2, h) = \frac{\sigma^2}{h} - \log\frac{\sigma^2}{h} - 1

Это потеря, подразумеваемая гауссовым правдоподобием на дисперсии, она тоже устойчива в смысле Паттона, и у нее есть два свойства, которые делают ее предпочтительным выбором для волатильности. Во-первых, она асимметрична в правильном направлении: она штрафует недопрогноз дисперсии сильнее, чем перепрогноз. Для риск-менеджера или того, кто таргетирует волатильность, это правильная асимметрия: недопрогноз волатильности означает, что вы взяли слишком большой размер позиции ровно перед тем, как это стало важно — это дорогая ошибка. Во-вторых, она (примерно) инвариантна к масштабу: поскольку она зависит от отношения σ2/h\sigma^2/h, ошибка прогноза в 10% стоит примерно одинаково, случается ли она в спокойный день или в кризисный, поэтому оценка не захватывается горсткой наблюдений с высокой дисперсией так, как это происходит с MSE. Эта устойчивость к гетероскедастичности прокси — именно то, что нужно, когда весь смысл в том, что волатильность сильно варьируется.

Обратите внимание, LQLIKE0L_{\text{QLIKE}} \ge 0, с равенством тогда и только тогда, когда h=σ2h = \sigma^2. Меньше — лучше, так же как и с MSE.

import numpy as np

def qlike(proxy: np.ndarray, forecast_var: np.ndarray) -> np.ndarray:
    """Per-observation QLIKE loss. `proxy` is r^2 or RV (a variance proxy),
    `forecast_var` is h = sigma_hat^2. Both strictly positive, same units.
    """
    ratio = proxy / forecast_var
    return ratio - np.log(ratio) - 1.0

def mse_var(proxy: np.ndarray, forecast_var: np.ndarray) -> np.ndarray:
    """Per-observation MSE on the variance scale."""
    return np.square(proxy - forecast_var)

Два операционных предупреждения. Держите прокси и прогноз в идентичных единицах измерения (обе — дневные дисперсии, или обе — годовые), иначе отношение теряет смысл. И никогда не позволяйте forecast_var достичь нуля — ограничьте его снизу небольшим порогом, потому что log0\log 0 отравит все среднее.

Регрессия Mincer-Zarnowitz

Одно число потерь говорит вам, какой прогноз лучше; оно не говорит вам, в чем именно прогноз ошибочен. Регрессия Mincer-Zarnowitz (1969) делает это. Регрессируем прокси на прогноз:

rt2  =  a+bσ^t2+ut.r_t^2 \;=\; a + b\,\hat\sigma_t^2 + u_t.

При оптимальном, несмещенном прогнозе a=0a = 0 и b=1b = 1: в среднем реализованная дисперсия равна прогнозу. Отклонения диагностируют патологию:

  • b<1b < 1 при a>0a > 0: классический признак прогноза, который слишком волатилен — он чрезмерно реагирует, предсказывая крайности, которые не реализуются полностью. Очень часто встречается у моделей, управляемых сырыми квадратами доходностей.
  • b>1b > 1: прогноз недостаточно реагирует, слишком слабо масштабируясь с истинной дисперсией.
  • Низкий R2R^2 регрессии: даже если a,ba,b выглядят нормально в среднем, прогноз плохо отслеживает дисперсию день ото дня. Поскольку прокси настолько шумный, не стоит тревожиться, что MZ R2R^2 против r2r^2 часто составляет всего 0.05-0.20; против RVRV он будет намного выше. R2R^2 против r2r^2 ограничен значительно ниже 1 независимо от того, насколько хорош прогноз, исключительно из-за шума прокси.

Совместный FF-тест H0:(a,b)=(0,1)H_0: (a,b) = (0,1) дает формальную проверку калибровки. На практике используйте MZ как диагностику для понимания прогноза, а QLIKE — для ранжирования прогнозов.

Diebold-Mariano: реально ли различие?

Предположим, средний QLIKE у GARCH равен 0.183, а у EWMA — 0.191. GARCH "выигрывает". Но реален ли этот разрыв в 0.008 или это шум выборки? Тест Diebold-Mariano (1995) отвечает именно на этот вопрос. Определим дифференциал потерь за период

dt=L(proxyt,htA)L(proxyt,htB)d_t = L(\text{proxy}_t, h^A_t) - L(\text{proxy}_t, h^B_t)

для двух прогнозов AA и BB (здесь LL = QLIKE). Нулевая гипотеза — равная предсказательная точность, H0:E[dt]=0H_0: \mathbb{E}[d_t] = 0. Статистика — это среднее дифференциала, стандартизированное его долгосрочной (HAC) стандартной ошибкой, поскольку dtd_t серийно коррелирован:

DM=dˉLRV^(dt)/T  d  N(0,1)\text{DM} = \frac{\bar d}{\sqrt{\widehat{\mathrm{LRV}}(d_t)/T}} \;\xrightarrow{d}\; \mathcal{N}(0,1)

где LRV^\widehat{\mathrm{LRV}} — оценка долгосрочной дисперсии типа Ньюи-Уэста. Статистика DM за пределами ±1.96\pm 1.96 отвергает равную точность на уровне 5%. Важно, что DM — это тест о прогнозах, а не о вложенных моделях, и он учитывает серийную зависимость в серии потерь, которую наивный tt-тест на dtd_t проигнорировал бы.

import numpy as np
from scipy import stats

def diebold_mariano(loss_a: np.ndarray, loss_b: np.ndarray, h: int = 1):
    """Diebold-Mariano test of equal predictive accuracy.
    loss_a, loss_b: per-period losses (e.g. QLIKE) for forecasts A and B.
    h: forecast horizon; Newey-West lag = h - 1 (>=0), plus a small-sample buffer.
    Returns (DM_stat, p_value). Negative DM => A has lower loss (A better).
    """
    d = np.asarray(loss_a) - np.asarray(loss_b)
    T = len(d)
    d_bar = d.mean()

    lag = max(h - 1, 0)
    gamma0 = np.mean((d - d_bar) ** 2)
    lrv = gamma0
    for k in range(1, lag + 1):
        w = 1.0 - k / (lag + 1)
        cov = np.mean((d[k:] - d_bar) * (d[:-k] - d_bar))
        lrv += 2.0 * w * cov

    dm = d_bar / np.sqrt(lrv / T)

    adj = np.sqrt((T + 1 - 2 * h + h * (h - 1) / T) / T)
    dm *= adj
    p = 2.0 * (1.0 - stats.t.cdf(abs(dm), df=T - 1))
    return float(dm), float(p)

Иллюстративный результат в этом комментарии — честный и распространенный исход, и именно поэтому существует этот раздел: GARCH часто показывает немного более низкие средние потери, чем EWMA, и так же часто это преимущество не проходит порог значимости DM. Если вы сообщаете только средний QLIKE, вы убедите себя в наличии преимуществ, которые тест DM бы отклонил. Указывайте статистику DM. Это та же дисциплина, которую мы применяем к доходностям стратегий в статье Честная оценка без устойчивого преимущества — точечная оценка, превосходящая бенчмарк, не является преимуществом, пока вы не исключили, что это шум.

Бэктест: walk-forward стратегия с таргетированием волатильности

Теперь объединим две половины — прогнозист и правило сайзинга — в стратегию и оценим ее единственным способом, который что-то значит: walk-forward, out-of-sample, с издержками.

Стратегия намеренно проста, потому что простота — это то, что позволяет нам приписать результат прогнозу волатильности, а не хитрому сигналу. Long-only BTC с таргетированием волатильности. Каждый день прогнозируем волатильность на следующий день, устанавливаем позицию wt=min(σtarget/σ^t, wmax)w_t = \min(\sigma_{\text{target}}/\hat\sigma_t,\ w_{\max}), держим ночь, повторяем. Вариант long/flat отключает позицию, когда трендовый фильтр отрицателен; вариант с небольшим портфелем сайзит по ковариационной матрице DCC из Части 3 вместо дисперсии одного актива. Мы полностью опишем случай long-only и отметим расширения.

Механика walk-forward и контракт "без заглядывания в будущее"

Самое важное свойство этого бэктеста в том, что каждая величина, используемая для сайзинга позиции на день t+1t+1, вычислима с использованием только данных, доступных на закрытии дня tt. Параметры GARCH переоцениваются на скользящем окне, заканчивающемся в tt; прогноз — это прогноз на один шаг вперед σ^t+1\hat\sigma_{t+1} из этой подгонки; позиция устанавливается на основе этого прогноза; а полученная доходность равна wt+1rt+1w_{t+1} r_{t+1}, где rt+1r_{t+1} — доходность следующего дня, которую модель никогда не видела. Переподгонка GARCH на полной выборке с последующим "прогнозированием" прошлого — самый распространенный способ случайно сфабриковать отличный бэктест. Мы разбираем эту ловушку заглядывания вперед и общую методологию в статье Walk-forward оптимизация.

import numpy as np
import pandas as pd
from arch import arch_model

def walk_forward_voltarget(
    returns: pd.Series,          # daily log returns in decimal (e.g. 0.021)
    proxy_var: pd.Series,        # variance proxy aligned to returns (RV or r^2)
    target_vol_annual: float = 0.20,
    window: int = 750,           # rolling estimation window (days)
    refit_every: int = 5,        # refit GARCH weekly, forecast daily (cost saver)
    w_max: float = 3.0,          # leverage cap
    cost_bps: float = 5.0,       # per-unit-turnover cost in basis points
    ann: int = 365,              # crypto trades 365 days/yr
):
    """Long-only vol-targeted BTC, GARCH(1,1)-t forecasts, strictly walk-forward.
    Returns a DataFrame with position, forecast vol, net returns, and turnover.
    """
    idx = returns.index
    target_daily = target_vol_annual / np.sqrt(ann)

    fcast_vol = pd.Series(index=idx, dtype=float, name="fcast_vol")
    last_res = None

    for i in range(window, len(returns) - 1):
        if (i - window) % refit_every == 0 or last_res is None:
            train = returns.iloc[i - window:i + 1] * 100.0   # scale for the optimizer
            am = arch_model(train, mean="Constant", vol="GARCH",
                            p=1, o=1, q=1, dist="t")           # GJR-t, Part 2
            last_res = am.fit(disp="off")

        f = last_res.forecast(horizon=1, reindex=False)
        var_next = f.variance.values[-1, 0] / (100.0 ** 2)    # unscale
        fcast_vol.iloc[i + 1] = np.sqrt(var_next)

    raw_w = (target_daily / fcast_vol).clip(upper=w_max)
    position = raw_w.shift(0)                                  # w_{i+1} known at close i
    gross_ret = position * returns                            # earned on day i+1

    turnover = position.diff().abs().fillna(0.0)
    cost = turnover * (cost_bps / 1e4)
    net_ret = (gross_ret - cost).dropna()

    out = pd.DataFrame({
        "position": position,
        "fcast_vol": fcast_vol,
        "gross_ret": gross_ret,
        "turnover": turnover,
        "net_ret": net_ret,
    }).dropna()
    return out

def performance_stats(net_ret: pd.Series, ann: int = 365) -> dict:
    """Sharpe, realized vol, max drawdown, CAGR, annual turnover."""
    mu = net_ret.mean() * ann
    sigma = net_ret.std() * np.sqrt(ann)
    sharpe = mu / sigma if sigma > 0 else np.nan
    equity = (1.0 + net_ret).cumprod()
    peak = equity.cummax()
    max_dd = (equity / peak - 1.0).min()
    cagr = equity.iloc[-1] ** (ann / len(net_ret)) - 1.0
    return {
        "sharpe": round(sharpe, 2),
        "realized_vol": round(sigma, 3),
        "max_drawdown": round(max_dd, 3),
        "cagr": round(cagr, 3),
    }

Несколько заметок по реализации, которые важнее, чем кажутся:

  • Масштабирование для оптимизатора. Подгонки arch численно охотнее работают, когда доходности выражены в процентах, отсюда * 100 и соответствующее / 100**2 при обратном масштабировании дисперсии. Забудьте про обратное масштабирование, и ваша целевая волатильность окажется завышена в 10 000 раз.
  • Периодичность переподгонки. Переоценивать параметры GARCH каждый день дорого и почти ничего не дает — параметры стабильны неделя от недели. Переподгонка еженедельно (refit_every=5) при ежедневном прогнозировании (рекурсия обновляет σt2\sigma_t^2 по новым доходностям даже без переподгонки) — стандартный компромисс. Это отражает совет про кэширование из пайплайна копул в статье Копула-модели для совместного риска.
  • Ограничение сверху wmaxw_{\max} — не косметика. Когда прогнозная волатильность обрушивается в режиме мертвого штиля, σtarget/σ^t\sigma_{\text{target}}/\hat\sigma_t может взорваться до 5x, 10x левериджа. Неограниченное таргетирование волатильности с радостью вручит вам катастрофический леверидж ровно перед сменой режима волатильности — именно в тот момент, когда прогноз вот-вот окажется максимально неверным. Ограничьте его (здесь 3x) и признайте, что ограничение будет срабатывать именно в самые спокойные, а задним числом самые опасные периоды.
  • Издержки масштабируются с оборотом, а таргетирование волатильности — это машина по производству оборота. Каждое колебание прогноза меняет размер позиции. На активе с низкой волатильностью и дерганым прогнозом можно взбалтывать книгу ежедневно. Термин cost_bps — не деталь округления; для высокооборотного таргетирования волатильности он может съесть значительную долю улучшения валового Шарпа.

Как выглядит результат (иллюстративно)

Запуск этого на дневных данных BTC за многолетний период, сравнивая четыре модели прогноза в качестве знаменателя сайзинга, обычно дает таблицу следующего вида. Числа ниже иллюстративны — подобраны вручную, чтобы показать типичный паттерн, а не результат реального бэктеста — но порядок и величины репрезентативны для того, что сообщают практики.

Модель для сайзинга Шарп Реализ. вол. Целевая вол. Макс. просадка Годовой оборот
Фиксированный номинал (без таргетирования) 0.71 0.68 -0.78 0.1x
Скользящая RV (60д) 0.94 0.24 0.20 -0.41 12x
EWMA (λ=0.94\lambda=0.94) 1.02 0.21 0.20 -0.35 19x
GARCH(1,1)-t 1.05 0.21 0.20 -0.33 22x
HAR-RV (внутридневной прокси) 1.09 0.20 0.20 -0.31 20x

Два расширения, которые стоит построить

Случай long-only изолирует прогноз, но два расширения достаточно распространены, чтобы показать их явно.

Long/flat с трендовым фильтром. Таргетирование волатильности определяет размер позиции, но не имеет направленного взгляда — оно всегда long. Дешевое, честное улучшение — отключать позицию, когда медленный трендовый фильтр становится отрицательным, так чтобы вы держали long с таргетированием волатильности только в восходящих трендах, а в остальное время сидели вне позиции. Это сохраняет логику сайзинга неизменной и накладывает сверху грубый режимный фильтр; он не претендует на тайминг входов, только на то, чтобы избежать удержания позиции через явные нисходящие тренды.

def apply_trend_gate(position: pd.Series, price: pd.Series, fast: int = 20, slow: int = 100):
    """Zero out the (already vol-targeted) position when the fast SMA is below
    the slow SMA. Both SMAs use only past prices, so no look-ahead is introduced.
    """
    fast_ma = price.rolling(fast).mean().shift(1)   # shift: known at prior close
    slow_ma = price.rolling(slow).mean().shift(1)
    gate = (fast_ma > slow_ma).astype(float)        # 1.0 in uptrend, 0.0 otherwise
    return position * gate.reindex(position.index).fillna(0.0)

Трендовый фильтр снижает оборот на стороне понижения (вы перестаете взбалтывать сокращающуюся позицию на медвежьем рынке), но добавляет собственный режимный риск — он дает ложные срабатывания на болтающихся боковых рынках и запаздывает на разворотах. Помогает ли он — эмпирический вопрос, на который нужно отвечать с той же строгостью walk-forward и DM-теста, что и на само правило сайзинга; трендовый фильтр — это именно тот тип надстройки, которая выглядит отлично in-sample и испаряется out-of-sample.

Портфельное таргетирование волатильности на ковариации DCC. Для книги из нескольких активов скалярный прогноз σ^t\hat\sigma_t становится волатильностью портфеля wΣtw\sqrt{w^\top \Sigma_t w}, где Σt\Sigma_t — изменяющаяся во времени ковариационная матрица из DCC-GARCH Части 3. Вы выбираете базовые веса w0w_0 (равновзвешенные, по рыночной капитализации или наклон средне-дисперсионной оптимизации), вычисляете прогнозную волатильность портфеля под Σt\Sigma_t, и масштабируете весь вектор весов, чтобы попасть в целевую волатильность портфеля.

def portfolio_voltarget_weights(base_w, cov_forecast, target_vol_daily, w_gross_max=3.0):
    """Scale a base weight vector so forecast portfolio vol hits the target.
    base_w:        (n,) base allocation (need not sum to 1).
    cov_forecast:  (n, n) one-step-ahead covariance from DCC-GARCH (daily units).
    """
    base_w = np.asarray(base_w, dtype=float)
    port_var = float(base_w @ cov_forecast @ base_w)
    port_vol = np.sqrt(max(port_var, 1e-12))
    scale = min(target_vol_daily / port_vol, w_gross_max / np.abs(base_w).sum())
    return scale * base_w

Это естественный мост к литературе по построению портфеля: базовые веса w0w_0 могут исходить из средне-дисперсионной теории Markowitz или риск-ориентированного метода вроде HRP/CVaR, а таргетирование волатильности затем ложится сверху как надстройка, масштабирующая совокупный риск до постоянной величины. Матрица DCC важна, потому что корреляции резко возрастают во время крахов (Часть 3) — портфель, который выглядит диверсифицированным на спокойных рынках, может иметь гораздо более высокую прогнозную волатильность, чем подразумевает статическая ковариация, именно тогда, когда это важно, и надстройка в ответ сокращает валовую экспозицию.

Диагностика, которую стоит строить всегда

Никогда не доверяйте одной сводной таблице. Для любого таргетирования волатильности постройте три графика и осмотрите их, прежде чем поверить любому числу Шарпа. Во-первых, реализованная скользящая волатильность стратегии на фоне целевой линии — она должна плотно прилегать к цели; систематический дрейф выше нее означает, что ваш прогноз смещен вниз (дорогое направление). Во-вторых, серия позиции/левериджа — ищите срабатывание ограничения сверху и всплески левериджа непосредственно перед просадками, признак прогноза, застигнутого врасплох сменой режима. В-третьих, диаграмма рассеяния прогноз-против-прокси (картина Mincer-Zarnowitz) — облако с наклоном далеким от 1 говорит о том, что прогноз неправильно масштабирован таким образом, что среднее QLIKE может это скрыть. Эти три графика ловят больше багов и самообмана, чем любая отдельная статистика.

Читайте эту таблицу так, как следует читать любую таблицу бэктеста: смотрите, что устойчиво, а что маргинально. Устойчивые факты бросаются в глаза. Каждый вариант с таргетированием волатильности разгромно превосходит фиксированный номинал по Шарпу и, что более впечатляюще, по просадке и стабильности реализованной волатильности — стратегия с фиксированным номиналом работает при 68% годовой волатильности с просадкой 78%, что просто неинвестируемо. И каждый метод таргетирования дает реализованную волатильность, близкую к целевым 20%, что и есть весь смысл работы этого механизма. Маргинальные факты — это различия между моделями прогноза: HAR немного превосходит GARCH, который немного превосходит EWMA, который немного превосходит скользящую RV, но разрывы малы — десятая доля пункта Шарпа — и, будучи проверенными Diebold-Mariano на прогнозах или бутстрэпом на доходностях, часто не проходили бы порог значимости. Этот малый, хрупкий, зависящий от режима разрыв между изощренной и наивной моделью прогноза — честный заголовок всей этой серии.

Честность о том, что это дает

У этого блога есть целая коллекция статей о бэктестинге без самообмана, так что применим ее к нашему собственному результату, а не будем тихо надеяться, что вы этого не сделаете.

Таргетирование волатильности улучшает риск-скорректированную доходность и просадки. Оно не производит альфу из ничего. Взгляните снова на таблицу. Улучшение Шарпа от таргетирования реально, и оно того стоит — но разложите его, и большая часть окажется результатом отказа держать постоянную позицию в режимах высокой волатильности, что механически избегает худших просадок и стабилизирует траекторию накопления. Стратегия по-прежнему long BTC; у нее нет взгляда на рынок, которого он сам ей не дал бы. Если у BTC отрицательный Шарп на вашей выборке, таргетирование волатильности даст вам менее плохой отрицательный Шарп, а не положительный. Оно переформирует распределение доходности — более тонкие хвосты, более стабильная волатильность, лучшее геометрическое накопление — но сырое направленное преимущество остается тем же, каким является базовый long. Не позволяйте красивой кривой капитала обмануть вас в веру, что вы нашли альфу, когда на самом деле вы нашли риск-менеджмент. Moreira-Muir нашли настоящую альфу в акционных факторах от управления волатильностью, но этот результат касается изменяющегося во времени соотношения риск-доходность фактора, и он не переносится автоматически на один криптоактив на другой выборке.

Преимущество качества прогноза GARCH над EWMA часто мало и зависит от режима. Это неудобный итог Частей 1-3. Вы строили все более изощренные модели — термины левериджа, хвосты Student-t, динамические корреляции — и предельный вклад каждой из них в P&L таргетирования волатильности, по сравнению с наивным EWMA, часто находится в пределах шумовой полосы. Преимущество GARCH (возврат к среднему после шоков) проявляется главным образом в конкретных режимах: резкие всплески, которые затем нормализуются. В затяжных трендах или устойчивых режимах высокой волатильности он едва отличается от EWMA. Это не делает GARCH бесполезным — структура возврата к среднему, интерпретируемые параметры, возможность симулировать траектории вперед и оценивать опционы против прогноза — все это обладает ценностью, которой лишен EWMA — но если ваше единственное применение — сайзинг, запустите тест DM, прежде чем платить за сложность, и знайте, что обнаружение режимов говорит то же самое под другим углом: побеждающая модель зависит от режима.

Шарп бэктеста — это верхняя граница живого Шарпа, и таргетирование волатильности расширяет этот разрыв. Поскольку стратегия высокооборотная и масштабируется левериджем, она необычно чувствительна к трениям, которые наивный бэктест опускает: ваши исполнения хуже, чем закрытие, по которому вы сайзили, издержки фандинга на левериджных перп-позициях начисляются непрерывно, а ограничение левериджа взаимодействует с механикой маржи и ликвидации, которую простое w * return игнорирует. Каждая из этих вещей делает живую торговлю хуже бэктеста. Мы систематически разбираем этот разрыв в статье Паритет бэктеста и живой торговли; для таргетирования волатильности конкретно закладывайте на это бюджет, используя консервативные издержки, реалистичное (низкое) ограничение левериджа и исполняя на следующем баре открытия, а не на закрытии, по которому вы вычислили сигнал.

Отступление о премии за риск волатильности. Все вышесказанное прогнозирует реализованную волатильность. Есть параллельный, торгуемый объект: подразумеваемая волатильность, заложенная в цену опционов, которая в среднем находится выше последующей реализованной волатильности — премия за риск волатильности, компенсация за принятие риска всплеска волатильности. Этот разрыв сам по себе является источником доходности (продажа дисперсии собирает эту премию, покупка хеджирует хвостовой риск), и это действительно другая игра по сравнению с таргетированием волатильности: это ставка на цену волатильности, а не использование прогноза волатильности. Мы не рассматриваем это здесь, но механика начинается с модели ценообразования в статье Ценообразование опционов Black-Scholes, а хороший прогноз реализованной волатильности (Части 1-2) — это именно тот вход, который нужен, чтобы судить, дорогая или дешевая подразумеваемая волатильность. Сравнение вашего прогноза GARCH с подразумеваемой волатильностью опционного рынка — одно из самых честных применений всего, что вы построили в этой серии.

Практические соображения

Набор вещей, которые отличают работающее таргетирование волатильности от хрупкого.

  • Оценивайте на правильном горизонте. Если вы сайзите позицию, удерживаемую один день, прогнозируйте однодневную волатильность. Если вы ребалансируете еженедельно, прогнозируйте (и таргетируйте) недельную волатильность, или агрегируйте дневной прогноз GARCH по горизонту — многошаговый прогноз GARCH возвращается к среднему в сторону σˉ2\bar\sigma^2, что наивное масштабирование "hдневная\sqrt{h}\cdot\text{дневная}" игнорирует. Часть 1 разбирает многошаговое прогнозирование GARCH.
  • Годовое масштабирование на рынках 24/7. Крипта торгуется 365 дней в году без выходных и праздников, так что годовое масштабирование дневной волатильности следует делать через 365\sqrt{365}, а не через 252\sqrt{252}, как в акциях. Ошибиться здесь означает тихо исказить вашу цель примерно на 20%.
  • Знаменателем может быть ковариационная матрица. Для мультиактивной книги замените скалярный σ^t\hat\sigma_t на волатильность портфеля wΣtw\sqrt{w^\top \Sigma_t w} из DCC-GARCH Части 3, и масштабируйте весь вектор весов, чтобы попасть в целевую волатильность портфеля. Это связывает таргетирование волатильности со средне-дисперсионным сайзингом (Markowitz для крипты) и риск-ориентированным распределением (пайплайны HRP и CVaR) — таргетирование волатильности является частным случаем масштабирования до портфельного риск-бюджета для одного актива.
  • Таргетирование волатильности проциклично тонким образом. Когда все запускают одно и то же правило 1/σ1/\sigma, всплеск волатильности вынуждает синхронизированный делеверидж, что толкает цены вниз, что повышает реализованную волатильность, что вынуждает еще больший делеверидж. Эта обратная связь (хорошо задокументированная в "volmageddon" 2018 года и различных каскадах делевериджа в крипте) означает, что правило работает хуже именно тогда, когда многие игроки его используют. Это не повод отказываться от него, но повод ограничить леверидж и не предполагать, что ваши исполнения во время всплеска волатильности будут напоминать исполнения на спокойном рынке.
  • Ограничивайте прогноз снизу и обрезайте его. Нулевой или близкий к нулю прогноз волатильности дает бесконечный леверидж. Всегда ограничивайте σ^t\hat\sigma_t снизу разумным минимумом и ограничивайте позицию сверху, и логируйте, как часто срабатывает каждое из этих ограничений — если ограничение сверху срабатывает большую часть времени, ваша цель слишком агрессивна для этого актива.

Резюме

  • Прогноз волатильности не имеет ценности, пока он не меняет решение. Таргетирование волатильности — сайзинг экспозиции как wt=σtarget/σ^tw_t = \sigma_{\text{target}}/\hat\sigma_t (с ограничением сверху) — самый чистый тест ценности прогноза, потому что качество прогноза напрямую отражается в более плоском профиле реализованной волатильности и более высоком Шарпе.
  • Таргетирование волатильности повышает риск-скорректированную доходность и, в особенности, контролирует просадки, потому что волатильность прогнозируема (она кластеризуется), а направление — нет, и потому что коэффициенты Шарпа падают в режимах высокой волатильности, которые правило автоматически недовешивает. Это сайзинг по Kelly в предположении, что ожидаемая доходность масштабируется с волатильностью.
  • Честно сравнивайте GARCH с сильными базовыми моделями: скользящей реализованной волатильностью, EWMA/RiskMetrics (λ=0.94\lambda=0.94, IGARCH без свободных параметров) и HAR-RV на внутридневном прокси реализованной дисперсии. EWMA и HAR трудно превзойти.
  • Вы не можете наблюдать истинную волатильность, поэтому оценивайте против прокси (r2r^2 или, гораздо лучше, RVRV) с помощью функций потерь, устойчивых к шуму прокси. Предпочитайте QLIKE MSE: он сильнее штрафует недопрогноз (дорогую ошибку) и инвариантен к масштабу, так что не захватывается несколькими днями высокой волатильности. Используйте Mincer-Zarnowitz для диагностики смещения и тест Diebold-Mariano, чтобы решить, реально ли преимущество одного прогноза или это шум.
  • В walk-forward бэктесте с учетом издержек таргетирование волатильности надежно превосходит фиксированный номинал по Шарпу и просадке, а четыре модели прогноза кучкуются близко друг к другу — преимущество GARCH над EWMA мало, зависит от режима и часто статистически незначимо. Указывайте тест DM, а не только среднюю потерю.
  • Будьте честны: таргетирование волатильности — это риск-менеджмент, а не альфа. Оно переформирует распределение доходности той направленной ставки, которая у вас уже была; оно не создает преимущество из ничего. И оно высокооборотное и масштабируется левериджем, так что живые результаты отстают от бэктеста больше обычного.

Источники:

  • Patton, A. J. (2011). Volatility forecast comparison using imperfect volatility proxies. Journal of Econometrics, 160(1), 246-256. DOI
  • Corsi, F. (2009). A simple approximate long-memory model of realized volatility. Journal of Financial Econometrics, 7(2), 174-196. DOI
  • Diebold, F. X., & Mariano, R. S. (1995). Comparing predictive accuracy. Journal of Business & Economic Statistics, 13(3), 253-263. DOI
  • Mincer, J., & Zarnowitz, V. (1969). The evaluation of economic forecasts. In Economic Forecasts and Expectations, NBER.
  • Moreira, A., & Muir, T. (2017). Volatility-managed portfolios. Journal of Finance, 72(4), 1611-1644. DOI
  • J.P. Morgan / Reuters (1996). RiskMetrics Technical Document, 4th ed.
  • Bollerslev, T. (1986). Generalized autoregressive conditional heteroskedasticity. Journal of Econometrics, 31(3), 307-327. DOI
  • Glosten, L. R., Jagannathan, R., & Runkle, D. E. (1993). On the relation between the expected value and the volatility of the nominal excess return on stocks. Journal of Finance, 48(5), 1779-1801. DOI
  • Harvey, D., Leybourne, S., & Newbold, P. (1997). Testing the equality of prediction mean squared errors. International Journal of Forecasting, 13(2), 281-291. DOI
Дисклеймер: Информация в этой статье предоставлена исключительно в образовательных и ознакомительных целях и не является финансовым, инвестиционным или торговым советом. Торговля криптовалютами сопряжена с высоким риском убытков.

MarketMaker.cc Team

Количественные исследования и стратегии

Обсудить в Telegram
Newsletter

Будьте в курсе событий

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

Мы уважаем вашу конфиденциальность. Отписаться можно в любой момент.