Strasmore Research
Deep Dives · Matt ConnorBy Matt Connor ·

Коли рівні ваги кращі за оптимізацію

Рівновагове зважування перевершує оптимізований розмір позицій за короткої вибірки. Python-симуляція показує момент переваги та її зникнення зі зростанням вибірки.

Рівновагове зважування перевершує оптимізований розмір позицій, коли вибірка надто мала для надійної оцінки очікуваної дохідності. А короткі вибірки — це радше норма, ніж виняток. Оптимізатор виконує коректні математичні розрахунки на основі параметра, який ніхто не вміє добре вимірювати. Портфель 1/N із рівними вагами взагалі нічого не оцінює. Саме тому він зберігає стійкість, коли оцінки виявляються неточними.

Чи справді рівновагове зважування перевершує оптимізацію?

За однієї конкретної умови — так. Розглянемо ці терміни по черзі. Рівновагове зважування, яке позначають як 1/N, рівномірно розподіляє капітал між N позиціями й не потребує жодного прогнозу. Mean-variance optimization визначає ваги з найкращою очікуваною дохідністю на одиницю оціненої дисперсії. Критерій Kelly визначає ваги, що максимізують довгострокове складне зростання. Для некорельованих активів його результат зводиться до ваги, пропорційної очікуваній надлишковій дохідності кожного активу, поділеній на його дисперсію. У нашому посібнику щодо визначення розміру позиції за критерієм Kelly цю формулу розглянуто докладно.

Обом оптимізаторам потрібен один і той самий вхідний параметр: очікувана дохідність кожного активу. Саме цю величину вибірка оцінює найгірше. Волатильність можна оцінити за коротким періодом із прийнятною точністю. Середнє значення — ні, і розрив між цими двома оцінками достатньо великий, щоб його можна було побачити в будь-якій історії цін. На панелі нижче наведено шість широко утримуваних акцій. Для кожної окремо розраховано показники за кожен календарний рік із 2015 до 2024 року та показано різницю між найвищою і найнижчою річними оцінками. Для кожної назви це зроблено двічі: для середньої денній дохідності в річному вираженні та для річної волатильності.

ЗапитДесятирічні річні оцінки: середнє значення змінюється значно сильніше, ніж волатильність
Точний SQL-код для кожного числа
WITH prices AS
(
    SELECT
        ticker,
        date,
        toFloat64(max(close)) AS c
    FROM global_markets.stocks_daily_aggs
    WHERE ticker IN ('AAPL', 'MSFT', 'NVDA', 'SPY', 'KO', 'JNJ')
      AND date >= '2015-01-01'
      AND date <  '2025-01-01'
    GROUP BY ticker, date
),
rets AS
(
    SELECT
        ticker,
        date,
        c / lagInFrame(c, 1) OVER (PARTITION BY ticker ORDER BY date ASC ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) - 1 AS ret
    FROM prices
),
yearly AS
(
    SELECT
        ticker,
        toYear(date)                     AS yr,
        avg(ret) * 252 * 100             AS mean_pct,
        stddevPop(ret) * sqrt(252) * 100 AS vol_pct
    FROM rets
    WHERE isFinite(ret)
    GROUP BY ticker, yr
    HAVING count() >= 200
)
SELECT
    ticker,
    round(max(mean_pct) - min(mean_pct), 1) AS mean_estimate_range_pct,
    round(max(vol_pct) - min(vol_pct), 1)   AS vol_estimate_range_pct
FROM yearly
GROUP BY ticker
ORDER BY mean_estimate_range_pct DESC
Run this yourself

Для NVDA оцінка середньої річної дохідності за ці десять років змінювалася в діапазоні 184.7 процентного пункту. Для порівняння, діапазон оцінки волатильності цього самого активу за ті самі роки становив 28.6 пунктів. Навіть найстабільніша назва на панелі, KO, демонструвала зміну оцінки середньої річної дохідності в межах 23.9 пунктів. Будь-яка схема, яка передає оптимізатору середню дохідність минулого року як очікувану дохідність поточного року, використовує число з настільки значною похибкою.

Яка довжина вибірки потрібна для оцінювання очікуваної дохідності?

Стандартна похибка оціненої середньої дохідності дорівнює волатильності активу, поділеній на квадратний корінь із тривалості вибірки в роках. Йдеться саме про роки, а не про кількість спостережень: якщо збирати дані за ті самі дванадцять місяців щогодини замість щодня, це нічого не змінить. Якщо підставити у формулу актив із волатильністю 20%, то один рік історії дає стандартну похибку 20 процентних пунктів на рік. Чотири роки зменшують її вдвічі — до 10. Щоб знизити похибку до одного пункту — такої точності хотілося б досягти перед ранжуванням двох активів, чиї справжні середні дохідності відрізняються на два пункти, — потрібно чотири століття даних.

Для волатильності ситуація інша. Її точність підвищується разом із кількістю спостережень, а не календарною тривалістю періоду, тому кілька місяців щоденних даних уже дають оцінку з похибкою в межах кількох пунктів. На графіку нижче двадцять років щоденних дохідностей одного index fund розподілено на неперекривні блоки фіксованої довжини. Для кожного блоку розраховано обидві оцінки та показано, наскільки вони відрізняються від блоку до блоку.

ЗапитНаскільки розсіюються оцінки середнього значення та волатильності залежно від довжини вибірки
Точний SQL-код для кожного числа
WITH prices AS
(
    SELECT
        date,
        toFloat64(max(close)) AS c
    FROM global_markets.stocks_daily_aggs
    WHERE ticker = 'SPY'
      AND date >= '2005-01-01'
      AND date <  '2025-01-01'
    GROUP BY date
),
rets AS
(
    SELECT
        date,
        c / lagInFrame(c, 1) OVER (ORDER BY date ASC ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) - 1 AS ret
    FROM prices
),
numbered AS
(
    SELECT
        ret,
        row_number() OVER (ORDER BY date ASC) AS i
    FROM rets
    WHERE isFinite(ret)
),
sweep AS
(
    SELECT
        arrayJoin([21, 63, 126, 252, 504]) AS n,
        i,
        ret
    FROM numbered
),
blocks AS
(
    SELECT
        n,
        intDiv(i - 1, n)                 AS blk,
        avg(ret) * 252 * 100             AS mean_pct,
        stddevPop(ret) * sqrt(252) * 100 AS vol_pct
    FROM sweep
    GROUP BY n, blk
    HAVING count() = n
)
SELECT
    concat(toString(n), ' sessions') AS sample_length,
    round(stddevPop(mean_pct), 1)    AS mean_estimate_spread_pct,
    round(stddevPop(vol_pct), 1)     AS vol_estimate_spread_pct,
    count()                          AS window_count
FROM blocks
GROUP BY n
ORDER BY n ASC
Run this yourself

У блоках тривалістю 21 sessions оцінка середньої дохідності розкидана в діапазоні 53.7 процентних пунктів, тоді як для оцінки волатильності, розрахованої на тих самих блоках, цей показник становить 10.9 пунктів. Якщо збільшити тривалість блоку до 504 sessions, розкид оцінки середньої дохідності скорочується до 10.6 пунктів. Він зменшується пропорційно квадратному кореню: кожне дворазове скорочення похибки потребує вчетверо більшого обсягу даних.

Симуляція з фіксованим seed, яку можна запустити самостійно

Це ще не доводить, що похибка оцінювання достатньо велика, щоб віддати перевагу підходу 1/N. Наведена нижче процедура це показує. Для неї потрібна лише інсталяція Python: файли даних, завантаження та сторонні пакети не потрібні. Процедура самостійно генерує доходності на основі вибраних вами параметрів. Тому справжня відповідь відома, і обидва підходи можна порівняти з нею.

  1. Імпортуйте два модулі — import random і import statistics — а також from math import log. У наступному рядку задайте seed за допомогою random.seed(20260816).
  2. Визначте п’ять активів зі справжньою очікуваною річною доходністю 5, 6, 7, 8 і 9 відсотків. Для кожного задайте справжню річну волатильність на рівні 20 відсотків. Доходності мають бути некорельованими. Перейдіть до денного кроку за допомогою mu_d = mu_a / 252 і sd_d = sd_a / (252 ** 0.5).
  3. Виберіть довжину вибірки T із діапазону [60, 125, 250, 500, 1000, 2500, 5000].
  4. Згенеруйте T денних доходностей для кожного активу за допомогою random.gauss(mu_d, sd_d). Ця вибірка є всією історією, доступною менеджеру.
  5. Оцініть середню доходність кожного активу за допомогою statistics.mean, а волатильність — за допомогою statistics.stdev. Оптимізатор використовує лише ці дві оцінки.
  6. Побудуйте портфель із рівними вагами, присвоївши кожному з п’яти активів вагу 0,2. Цей портфель не використовує жодної з оцінок.
  7. Побудуйте оптимізований портфель. Для цього задайте сиру вагу кожного активу як mu_hat / (sd_hat ** 2), а потім поділіть кожну вагу на суму абсолютних значень сирих ваг. Так обидва портфелі матимуть однаковий валовий рівень експозиції.
  8. Згенеруйте нову позавибіркову траєкторію з 2520 денних доходностей для кожного активу на основі справжніх параметрів. Жоден із портфелів не використовував цю траєкторію під час побудови.
  9. Оцініть обидва портфелі на цій траєкторії за середнім значенням log(1 + r), де r — це зважена сума доходностей п’яти активів за день.
  10. Повторіть кроки 4–9 для 2000 незалежних випробувань на кожному значенні T. Зафіксуйте частку випробувань, у яких портфель із рівними вагами показав кращий результат, ніж оптимізовані ваги.

Читайте результати діапазону від короткого T до довгого T. На короткому кінці портфель із рівними вагами перемагає у значній більшості випробувань. У міру збільшення T ця частка стабільно знижується, а на довгому кінці більшість випробувань виграють оптимізовані ваги. Десь посередині результати перетинаються. Точка перетину залежить від seed і різниці між справжніми середніми доходностями. Напрямок не змінюється: більший обсяг даних грає на користь оптимізатора, а менший — на користь 1/N. Щоб повторити експеримент, змініть ціле число всередині random.seed(20260816) і знову запустіть діапазон.

Як оптимізатор підсилює помилкову оцінку середньої дохідності

Подивімося, де саме оцінки входять у вагу. Оцінена середня дохідність міститься в чисельнику, а оцінена дисперсія — у знаменнику. Якщо подвоїти оцінку середньої дохідності, вага подвоїться. Якщо зменшити оцінку дисперсії на чверть, вага зросте на третину. У сприятливій вибірці обидві помилки діють в одному напрямку: низка хороших результатів підвищує виміряну середню дохідність і часто одночасно знижує виміряну дисперсію за той самий період. Оптимізатор сприймає цей актив як найкращий у групі й відповідно збільшує його вагу. За межами вибірки він знову стає звичайним активом цієї групи. Стратегія рівновагового розподілу не враховувала сприятливу вибірку.

Моделювання показує м’якшу версію цієї проблеми. П’ять некорельованих активів утворюють діагональну коваріаційну матрицю, яку не потрібно обертати. Реальні портфелі корельовані, а вибіркова коваріаційна матриця, побудована на кількості спостережень, лише трохи більшій за кількість активів, є близькою до виродженої. Її обертання перетворює невеликі помилки у вхідних даних на дуже великі ваги. Саме так оптимізатор може сформувати позицію в одному активі обсягом у кілька разів більшим за капітал, компенсовану короткою позицією в його близькому заміннику. У нашій нотатці про ризик концентрації в портфелі розглянуто, як така вага впливає на просадку.

Вхідні дані також не залишаються незмінними. На графіку нижче показано ковзну однорічну середню денну дохідність, перераховану в річному вимірі та розраховану щомісяця, для широкого індексного фонду й великої компанії сектору споживчих товарів першої необхідності.

ЗапитКовзна середня дохідність за один рік — показник, який отримав би оптимізатор
Точний SQL-код для кожного числа
WITH prices AS
(
    SELECT
        ticker,
        date,
        toFloat64(max(close)) AS c
    FROM global_markets.stocks_daily_aggs
    WHERE ticker IN ('SPY', 'KO')
      AND date >= '2015-10-01'
      AND date <  '2025-01-01'
    GROUP BY ticker, date
),
rets AS
(
    SELECT
        ticker,
        date,
        c / lagInFrame(c, 1) OVER (PARTITION BY ticker ORDER BY date ASC ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) - 1 AS ret
    FROM prices
),
trailing AS
(
    SELECT
        ticker,
        date,
        avg(ret) OVER (PARTITION BY ticker ORDER BY date ASC ROWS BETWEEN 251 PRECEDING AND CURRENT ROW) * 252 * 100 AS trailing_mean_pct,
        row_number() OVER (PARTITION BY ticker ORDER BY date ASC) AS i
    FROM rets
    WHERE isFinite(ret)
)
SELECT
    toString(toStartOfMonth(date))                     AS month,
    round(avgIf(trailing_mean_pct, ticker = 'SPY'), 1) AS spy_trailing_mean_pct,
    round(avgIf(trailing_mean_pct, ticker = 'KO'), 1)  AS ko_trailing_mean_pct
FROM trailing
WHERE i >= 252
  AND date >= '2017-01-01'
GROUP BY month
ORDER BY month ASC
Run this yourself

Кожна точка на цих двох лініях — це значення, яке певний оптимізатор міг би використати як очікувану дохідність на відповідну дату. Перше місячне значення для SPY становить 17.7%, а останнє — 25.8%; між ними є 96 значень. KO починає той самий період зі значення -0.4%. Стратегія зважування, яка щомісяця використовує цей ряд, успадковує кожне його коливання.

Чи виправляють проблему half Kelly і shrinkage?

Вони її пом’якшують. На практиці застосовують чотири підходи, і кожен із них відмовляється від частини теоретичного оптимуму, щоб зменшити чутливість до оцінки.

  • Half Kelly удвічі зменшує кожну вагу. Крива зростання Kelly пласка поблизу піку та круто знижується нижче нього. Тому позиція в половину від оптимальної відмовляється від невеликої частини теоретичного темпу зростання, але значно сильніше обмежує збитки від завищеної оцінки переваги. Таргетування волатильності ґрунтується на тій самій ідеї щодо знаменника: розмір позиції визначається за єдиним показником, який може надати коротка вибірка.
  • Shrinkage наближає кожне оцінене середнє до крос-секційного середнього всіх оцінок. Ступінь такого наближення зростає зі скороченням вибірки. У граничному випадку очікувана дохідність усіх активів стає однаковою. За однакової волатильності оптимізатор самостійно повертає однакові ваги. Портфель із рівними вагами — це портфель із повним shrinkage.
  • Обмеження, тобто заборона коротких позицій і ліміт на одну позицію, визначають, наскільки одна вдала оцінка може збільшити вагу окремого активу. Це контроль збитків, а не покращення самої оцінки.
  • Повна відмова від очікуваної дохідності залишає підходи мінімальної дисперсії та risk parity, які використовують лише коваріацію. Саме цей показник вибірка справді може надати.

Жоден із чотирьох підходів не створює інформацію, якої немає у вибірці. Вони лише змінюють, наскільки значна частина портфеля залежить від інформації, якої у вас може не бути.

Коли оптимізація виправдовує себе

Перехід відбувається в обох напрямках. Щойно T стає достатньо великим порівняно з різницею між справжніми середніми значеннями, оптимізований розподіл випереджає рівнозважений і надалі зберігає перевагу. Що більша ця різниця, то раніше це відбувається. Оптимізація також є правильним інструментом, коли вхідні дані надає сам ринок: коваріації та hedge ratios оцінюються набагато точніше, ніж очікувані доходності.

Рівнозважений підхід також має свою ціну. Він ігнорує інформацію, якою ви справді володієте, а в невеликому наборі активів може створювати таку саму концентрацію, як і будь-який оптимізатор. Використовуйте його як базовий орієнтир, який кожен варіант розподілу має перевершити на даних, недоступних під час визначення ваг. Підбір ваг і оцінювання їх на одній і тій самій вибірці — це look-ahead bias у backtesting під іншою назвою, і такий підхід щоразу створює надмірно сприятливе враження про оптимізатор. Щоб отримати чесний діапазон навколо виміряної переваги, а не одну точкову оцінку, стандартним інструментом є бутстреповані довірчі інтервали.

FAQ

Чи справді equal weight перевершує mean variance optimization?

На коротких вибірках часто так. Оптимізатору потрібна оцінка очікуваної дохідності кожного активу. Стандартна помилка цієї оцінки приблизно дорівнює волатильності активу, поділеній на квадратний корінь із тривалості вибірки в роках. Поки ця помилка перевищує реальні відмінності між активами, оптимізатор сортує шум. У equal weight немає оцінки, у якій можна помилитися.

Скільки спостережень потрібно для оцінки очікуваної дохідності?

Більше, ніж має майже будь-хто. Для активу з волатильністю 20 відсотків один рік денних даних дає стандартну помилку близько 20 відсоткових пунктів на рік. Щоб удвічі зменшити цю помилку, потрібен у чотири рази довший календарний період. Додавання внутрішньоденних спостережень у межах того самого року не допомагає. Натомість волатильність можна оцінювати за кількома місяцями даних.

Чи є half Kelly просто меншою ставкою?

Це менша ставка на сприятливіших умовах. Крива зростання Kelly пласка поблизу піку. Тому зменшення ставки вдвічі коштує невеликої частки теоретичного темпу зростання, водночас приблизно вдвічі зменшуючи волатильність траєкторії та скорочуючи втрати від завищеної оцінки переваги.

Що таке портфель 1/N?

Це портфель, у якому однакова частка капіталу вкладається в кожну з N позицій, а ребалансування здійснюється за встановленим графіком. Для нього не потрібні прогноз дохідності чи оцінка коваріації. Саме тому він є стандартним бенчмарком для кожної схеми зважування, якій такі оцінки потрібні.

Як побудовано панелі

Усі три панелі використовують денні ціни закриття й розраховують прості дохідності від одного закриття до наступного. Дублікати зводяться до однієї ціни закриття для кожного тикера та дати. Середні значення переводяться в річний вимір множенням середньої денної дохідності на 252 торгові сесії. Волатильність переводиться в річний вимір множенням денної стандартної відхильності на квадратний корінь із 252. Річна панель включає календарний рік лише за наявності щонайменше 200 сесій. Панель блоків використовує неперекривні блоки та відкидає останній неповний блок для кожної довжини. Її стовпець із кількістю вікон показує, скільки блоків сформовано для кожної довжини. Дивіденди ніде не враховуються, тому це дохідності за ціною, а рівень будь-якого середнього значення для dividend-paying активів занижений. Мета панелей — показати розкид оцінок, а не їхній рівень.


Під кожною панеллю наведено точний SQL-запит, а для симуляції — її seed. Щоб виконати таку саму перевірку стабільності оцінок для власного списку назв, сформулюйте запит простою англійською мовою в терміналі Strasmore.

#quant#position sizing#portfolio construction#estimation error#kelly