Новые релизы okama

Okama 2.0.0

Вот и дождались юбилейного релиза :grinning_face_with_smiling_eyes:

В этот раз изменений накопилось много… Основные темы релиза такие:

  • EfficientFrontier и EfficientFrontierReb объединены в единый класс EfficientFrontier
  • Существенно ускорены расчёты Границы эффективности благодаря кэшированию, параллельным вычислениям и оптимизации целевой функции
  • Добавлены новые продвинутые стратегии изъятия средств: Vanguard Dynamic Spending (VDS) и CutWithdrawalsIfDrawdown (CWD). О них будет отдельная статья.

image

Подробности изменений

Единый класс EfficientFrontier с многопериодной оптимизацией

EfficientFrontier и EfficientFrontierReb были объединены в единый класс EfficientFrontier. Теперь любая Граница эффективости по умолчанию рассчитывается с ребалансировкой (многопериодный подход). Оптимизация ребалансируемых портфелей теперь поддерживает ограничения на веса (bounds), позволяя пользователям задавать минимальные и максимальные пределы распределения для каждого актива.

Скорость расчётов была значительно увеличена благодаря:

  • кэшированию промежуточных результатов
  • параллельным вычислениям
  • оптимизации целевой функции
  • быстрым векторизованным методам в классе Rebalance

ПРЕДУПРЕЖДЕНИЕ:
Устаревший класс с классической оптимизацией Марковица (без ребалансировки) был переименован в EfficientFrontierSingle. Если вы использовали старый EfficientFrontier (однопериодный), перейдите на EfficientFrontierSingle.

import matplotlib.pyplot as plt

y = ok.EfficientFrontier(
    assets="SPY.US", "GLD.US"],
    first_date="2004-12",
    last_date="2020-10",
    ccy="USD",
    rebalancing_strategy=ok.Rebalance(period="year"),  # календарная ребалансировка раз в год
    ticker_names=True,  # использовать наименование ценных бумаг вместо тикеров
    n_points=40,  # количество точек на Границе эффективности (детализация графика)
)
fig, ax = plt.subplots(figsize=(12, 10))

# Plot the Efficient Frontier
ax.plot(df_reb_year.Risk, df_reb_year.CAGR, label="Annually rebalanced")
ax.plot(df_not_reb.Risk, df_not_reb.CAGR, label="Not rebalanced")

# Отрисовка точек активов
y.plot_assets(kind="cagr")

ax.set_xlabel("Risk (Standard Deviation)")
ax.set_ylabel("CAGR")
ax.legend();

image

Продвинутые стратегии изъятия средств из портфеля

Две новые стратегии денежного потока для пенсионного планирования и управления целевыми фондами:

Vanguard Dynamic Spending (VDS)

Реализация правила Vanguard Dynamic Spending, которое корректирует изъятия средств в зависимости от результатов портфеля с использованием нижних и верхних ограничителей.

pf = ok.Portfolio(['SPY.US', 'BND.US'], weights=[.6, .4], first_date='2010-01', last_date='2024-10', ccy='USD', inflation=True)
vds = ok.VanguardDynamicSpending(
    parent=pf,
    initial_investment=1_000_000,
    frequency="year",
    percentage=-0.05,
    floor_ceiling=(-0.05, 0.10),  # -5% floor / +10% ceiling
)
pf.dcf.cashflow_parameters = vds

CutWithdrawalsIfDrawdown (CWD)

Стратегия изъятия средств, основанная на риске, которая уменьшает сумму изъятия, когда просадка портфеля превышает заданные пороги.

cwd = ok.CutWithdrawalsIfDrawdown(
    parent=pf,
    initial_investment=1_000_000,
    frequency="year",
    amount=-60_000,
    indexation="inflation",
    crash_threshold_reduction=[(.10, .25), (.20, .50), (.35, 1)],
)
pf.dcf.cashflow_parameters = cwd

Подробное описание новых стратегий изъятия средств приведено в 04 investment portfolios with DCF.ipynb.

Новые классы и методы

Параметры first_date и last_date в Asset

  • Параметры first_date и last_date доступны в классе Asset. Использование этих параметров может значительно ускорить загрузку исторических данных.

Улучшения в классе EfficientFrontier

  • EfficientFrontier.plot_transition_map() — визуализация границы переходов
  • EfficientFrontier.plot_cml() — построение линии рынка капитала
  • EfficientFrontier.get_most_diversified_portfolio() — оптимизация Most Diversified Portfolio (MDP) на основе коэффициента диверсификации
  • EfficientFrontier.get_monte_carlo() генерирует случайные портфели с помощью моделирования Монте-Карло с учётом ограничения по весам (bounds)
  • EfficientFrontier.plot_assets() теперь принимает **kwargs для matplotlib scatter()

AssetList

  • AssetList.get_monthly_geometric_mean_return() — новый метод для расчёта геометрической средней доходности за месяц

MonteCarlo

  • MonteCarlo.plot_forecast_monte_carlo() теперь возвращает объект matplotlib Axes
  • MonteCarlo.get_parameters_for_distribution() — подбор распределения с параметрами для нормального, логнормального распределений и распределения Стьюдента
  • MonteCarlo.kstest() и MonteCarlo.kstest_for_all_distributions() — тесты согласия Колмогорова — Смирнова
  • MonteCarlo.plot_hist_fit() — гистограмма с наложением подобранного распределения
  • MonteCarlo.plot_qq() — QQ-график для визуальной оценки качества подгонки распределения

Архитектура портфеля

  • Новый класс MonteCarlo для продвинутого моделирования Монте-Карло и статистического анализа распределений (перенесён из Portfolio)
  • Новый класс PortfolioDCF для анализа дисконтированных денежных потоков, анализа выживаемости портфеля и тестирования стратегий изъятия средств
  • Новый вспомогательный класс Rebalance, инкапсулирующий логику ребалансировки, с методами wealth_ts_ef и return_ror_ts_ef для быстрой оптимизации

Документация и примеры

Новые и обновлённые примеры Jupyter Notebook в каталоге /examples:

  • 04 investment portfolios with DCF.ipynb — множество новых примеров для PortfolioDCF, VanguardDynamicSpending и стратегии CutWithdrawalsIfDrawdown
  • 07 efficient frontier multi-period.ipynb — существенно переработан, добавлены примеры для единого класса EfficientFrontier и многопериодной оптимизации
  • 10 forecasting.ipynb — обновлённые примеры прогнозирования методом Монте-Карло, включая методы подгонки распределений MonteCarlo
  • 11 rebalancing portfolio.ipynb — несколько новых примеров

Все существующие ноутбуки были обновлены в соответствии с последними изменениями API в okama 2.0.0.

Исправления ошибок

  • Исправлен расчёт капитализации годовой средней арифметической доходности в AssetList.annual_return_ts и Portfolio.annual_return_ts
  • Исправлен расчёт PortfolioDCF.wealth_index(discounting="pv")
  • Исправлена проблема, при которой PortfolioDCF.cashflow_parameters изменялся после plot_forecast_monte_carlo()
  • Исправлено поведение PortfolioDCF.find_the_largest_withdrawals_size, из-за которого не сохранялись исходные параметры CashFlow
  • Исправлены корректировки денежного потока PortfolioDCF в первом и последнем году для неполных периодов
  • Исправлен расчёт Portfolio.mean_return, теперь используется формула ror.mean()
  • Исправлен расчёт параметров MonteCarlo._get_params_for_lognormal
  • Исправлена подгонка логнормального распределения в MonteCarlo.kstest(), теперь используются валовые доходности
  • Исправлен FutureWarning Pandas для concat с пустым DataFrame в классе Rebalance
  • Исправлено имя параметра сеттера MonteCarlo.mc_number
  • Исправлен расчёт PortfolioDCF._target_cagr_range_left

Прочие изменения

  • Python 3.10 больше не поддерживается
  • Подключение к API переведено на HTTPS с проверкой SSL
  • Обновлены все примеры Jupyter Notebook в каталоге /examples
  • Существенно увеличено покрытие тестами для модулей DCF, Monte Carlo и стратегий денежного потока

Полный список изменений: v1.5.0…v2.0.0