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

Подробности изменений
Единый класс 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();

Продвинутые стратегии изъятия средств из портфеля
Две новые стратегии денежного потока для пенсионного планирования и управления целевыми фондами:
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:
Все существующие ноутбуки были обновлены в соответствии с последними изменениями 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