Releases: mbk-dev/okama
v2.2.2
Adds new analytics — ex-post tracking error for Portfolio and an RMS/std
method switch for tracking error across Index, AssetList, and Portfolio,
plus inflation-adjusted and price-only drawdown views — and fixes the
maintain_balance goals of find_the_largest_withdrawals_size() together with
duplicated efficient-frontier points under a thread backend.
Added
Portfolio.tracking_error(benchmark, rolling_window, method)— ex-post
tracking error of a portfolio against a benchmark (#61). The benchmark may be
a string ticker or an asset-like object (Asset,Portfolio); the method
delegates toAssetList.methodparameter forAssetList.tracking_errorand the underlying
helpers.Index.tracking_error:"rms"(default, legacy uncentered
root-mean-square) or"std"(centered sample standard deviation with
Bessel's correction).AssetList.real_drawdownsandPortfolio.real_drawdowns— drawdowns of the
inflation-adjusted wealth index, exposing purchasing-power losses hidden by
nominal growth (requiresinflation=True) (#51).AssetList.price_drawdownsandPortfolio.price_drawdowns— drawdowns based
on close prices not adjusted for dividends, which can differ markedly from the
total-returndrawdownsfor high-dividend assets (#44).
Fixed
PortfolioDCF.find_the_largest_withdrawals_size()raised
ValueError: target_survival_period must be less than Monte Carlo simulation period
for themaintain_balance_pvandmaintain_balance_fvgoals on any Monte
Carlo period ≤ 27, even though those goals never usetarget_survival_period
and the caller never passed it (#90). The parameter is now validated only for
thesurvival_periodgoal.EfficientFrontier.ef_pointsproduced duplicated right-part points under a
thread-based joblib backend, because the right-part worker both appended its
row to the shared list and returned it (#86). The worker now only returns the
row, matching the left-part worker.Frame.kstest_series(used bykstest_for_all_distributionsand the
distribution-fit properties ofAssetList/Portfolio) raised
TypeError: ndtr() takes from 1 to 2 positional arguments but 3 were given
with scipy 1.18.0 on Python ≥ 3.12, which routes the named-distribution
kstest(..., "norm", args=...)call through thendtrufunc. The
Kolmogorov–Smirnov test now passes a frozen-distribution CDF, which is
numerically equivalent and compatible with scipy 1.17 and 1.18.
Docs
- Clarified that
tracking_errorvalues are decimal fractions, not percentages. PortfolioDCF.find_the_largest_withdrawals_size()docstring now notes that
IndexationStrategy/PercentageStrategysubclasses (e.g.
CutWithdrawalsIfDrawdown,VanguardDynamicSpending) are supported.
v2.2.1
Fixes the multi-period Efficient Frontier around single-asset corner points — the right part of the frontier now always terminates at the corner asset (no dominated "hook", no silently missing right part, pairwise frontiers reach the asset dots) — and removes pandas 3 deprecation warnings.
Fixed
EfficientFrontier.ef_pointsdrew a dominated hook near the max-CAGR corner (#84): SLSQP started exactly at the optimal vertex of the bounds fails spuriously, and the fallback start converged to an interior local maximum.EfficientFrontier._maximize_risk()now keeps the better of the optimizer result and the 100% single-asset portfolio whenever the target CAGR equals an asset's own CAGR, so the right part of the frontier ends exactly at the corner asset with monotonically increasing risk.- The right part of
EfficientFrontier.ef_pointscould silently disappear together with its corner point when the right CAGR span was much narrower than the left one (the point-count formula produced an empty target range). - Pairwise efficient frontiers (
EfficientFrontier.plot_pair_ef()) stopped short of the asset point when the best rebalanced mix beat the asset by less than 1% of CAGR (#87). An asset is now considered to be the global max-CAGR point only when both its CAGR and its risk match it, and a narrow-but-real right CAGR span is drawn instead of being treated as degenerate. EfficientFrontier.plot_pair_ef()ignored the parent'srebalancing_strategy, always computing pair frontiers with the default yearly rebalancing.Pandas4Warningon pandas 3 (#85): dropped the deprecatedcopykeyword insymbols_in_namespace()andIndex.rolling_fn()(slated for removal in pandas 4.0).
Changed
- The
EfficientFrontier.ef_pointstarget grid now samples every asset's CAGR lying inside the range (previously only the minimum-variance asset's), so the frontier polyline passes exactly through single-asset points on the boundary. The number of rows inef_points/mdp_pointscan therefore slightly exceedn_points.
Docs
- README refreshed: fixed broken images on PyPI, added a hero image, an MCP server section and a uv install option.
v2.2.0
Makes Monte Carlo cash-flow simulations dramatically faster (vectorized wealth
and cash-flow engines, a Brent-based withdrawal solver — three to four orders
of magnitude per simulation), adds money-weighted IRR (MWRR) for portfolio
cash flows — both on historical data and across Monte Carlo forecast paths —
makes the Monte Carlo return draw cached and reproducible, and fixes three
cash-flow calculation bugs.
Added
Portfolio.dcf.irr()(PortfolioDCF.irr) — nominal annualized money-weighted
internal rate of return (IRR/MWRR) of the portfolio cash flow over the full
historical period, honoring the configuredCashFlowstrategy
(IndexationStrategy,PercentageStrategy,VanguardDynamicSpending,
CutWithdrawalsIfDrawdown,TimeSeriesStrategy). With no intermediate cash
flows it equalsPortfolio.get_cagr()for the period.Portfolio.dcf.monte_carlo_irr()(PortfolioDCF.monte_carlo_irr) — the
distribution (pandas.Series) of per-path money-weighted IRRs across Monte
Carlo forecast paths, the forward-looking counterpart ofPortfolioDCF.irr.irr_of_cashflow_matrix()inokama.portfolios.dcf_calculations— a
vectorized Newton solver (analytic derivative,scipy.optimize.brentq
fallback) computing IRR for an(n_periods, n_series)cash-flow matrix in one
pass; shared by bothPortfolioDCF.irrandPortfolioDCF.monte_carlo_irr.seedparameter for reproducible Monte Carlo draws:MonteCarlo.seedand the
newseedargument ofPortfolioDCF.set_mc_parameters().
Changed
- The Monte Carlo return draw (
MonteCarlo.monte_carlo_returns_ts) is now
generated once and cached — shared byPortfolioDCF.monte_carlo_wealth,
monte_carlo_cash_flow,monte_carlo_survival_period,monte_carlo_irrand
the CAGR-distribution methods — so all of them see one consistent scenario set
(previously each access regenerated fresh randomness). The cache is invalidated
when any Monte Carlo parameter changes (distribution,
distribution_parameters,period,mc_number,seed). As a consequence,
unseeded results ofPortfolioDCF.find_the_largest_withdrawals_size()and of
the CAGR-distribution methods shift versus 2.1.1: the bisection in
find_the_largest_withdrawals_sizenow evaluates every candidate against the
same scenario set (removing the sampling noise that previously broke its
monotonicity). Useset_mc_parameters(..., seed=...)for reproducible runs. Portfolio.dcf.find_the_largest_withdrawals_size()is faster: the bisection
search is replaced with Brent's method (scipy.optimize.brentq) on a signed
goal residual, and both ends ofwithdrawals_rangeare checked first so the
solver exits after 1–2 Monte Carlo simulations when the solution lies outside
the range. The public signature, theResultshape and the stopping rule
(error_rel < tolerance_rel) are unchanged;iter_maxnow caps objective
evaluations (Monte Carlo simulations), including the two range-end checks, so
the history of intermediate attempts inResult.solutionsdiffers from the
former bisection midpoints.iter_maxvalues below 1 are now rejected with a
ValueError.- Monte Carlo wealth simulation is vectorized:
Portfolio.dcf.monte_carlo_wealth()
and everything built on it (monte_carlo_survival_period(),
plot_forecast_monte_carlo(),
find_the_largest_withdrawals_size()) now computes all
random paths in one pass (get_wealth_indexes_fv_with_cashflow_mcin
okama.portfolios.dcf_calculations) instead of a per-path pandasapply.
Results are unchanged (pinned by an equivalence-test grid across strategies,
frequencies and extra cash flows); measured speedup of one full simulation is
three to four orders of magnitude (×1400 for yearly and ×6800 for monthly
withdrawal frequencies on 1,000 paths × 30 years). The negative-balance
masking and the survival-date scan are vectorized as well. - Monte Carlo cash-flow simulation is vectorized as well:
Portfolio.dcf.monte_carlo_cash_flow()builds its cache with the new
get_cash_flow_fv_mc(one pass for all paths, sharing a core with the
wealth engine), andPortfolio.dcf.monte_carlo_irr()now consumes the
sharedmonte_carlo_wealth/monte_carlo_cash_flowcaches instead of two
per-path computations (measured end-to-end speedup ofmonte_carlo_irr():
×488 on 1,000 paths × 30 years).
Fixed
PortfolioDCF.monte_carlo_cash_flow()withremove_if_wealth_index_negative=True
previously masked a cash-flow draw against a wealth-index draw generated from
different randomness; with the shared cached draw the depletion mask is now
consistent per path.- In periodic-frequency simulations, the first month of a period containing
extra cash flows (time_series) skipped its return in
get_wealth_indexes_fv_with_cashflow(and additionally skipped the cash
flow inget_cash_flow_fvbalance tracking). The recursion is now uniform
for every month; wealth indexes and cash flow series with extra cash flows
atyear/half-year/quarterfrequencies change accordingly (#81). VanguardDynamicSpendingfloor_ceilinglimits never bound in wealth-index
calculations (wealth_index,monte_carlo_wealthand everything built on
them): the previous withdrawal was always reported as 0. Wealth indexes for
VDS strategies withfloor_ceilingchange accordingly and are now
consistent withcash_flow_ts(#82).VanguardDynamicSpending.__init__bypassed the validating setters for
floor_ceiling,min_max_annual_withdrawalsandadjust_min_max, so
out-of-contract limits (e.g. a non-negative floor ormin > max) were
silently accepted at construction. The constructor now routes through the
public setters, and both limit setters acceptNone(meaning "limit
disabled") so the documented defaults remain valid (#83).
Security
- Dependency floor
idna >= 3.15to close CVE-2026-45409.
Docs
- New "IRR — money-weighted return" section in the
04 investment portfolios with DCF
notebook demonstratingPortfolio.dcf.irr()and
Portfolio.dcf.monte_carlo_irr(). - The
find_the_largest_withdrawals_size()docstring example now shows a real,
seeded solver run (range-end checks followed by Brent steps).
v2.1.1
Adds systematic (grid-based) enumeration of portfolio weights on the efficient frontier as a deterministic alternative to Monte-Carlo sampling, and enriches the frontier sampling outputs with per-asset weight columns.
Added
EfficientFrontier.get_grid_portfolios()(multi-period, rebalanced) andEfficientFrontierSingle.get_grid_portfolios()(single-period) enumerate all portfolios whose weights lie on a fixed percentage grid (step, default0.10), respecting per-assetbounds. This complements the randomget_monte_carlo()with a reproducible, exhaustive sampling of the feasible region.Float.get_grid_weights()helper inokama.common.helpers— a reusable generator of all weight vectors summing to 1.0 on a given grid step, honoring per-asset bounds. Thestepis validated to lie in[0.01, 1.0]and to divide 1.0 evenly.- Per-asset weight columns in the outputs of
EfficientFrontier.get_monte_carlo()andEfficientFrontier.get_grid_portfolios()(multi-period), matching the column layout already produced byEfficientFrontierSingle.get_monte_carlo().
Tooling
- Pinned
sphinx < 9for the docs build: the Sphinx 9.x autodoc rewrite raisesValueError: The truth value of a DataFrame is ambiguouson pandas DataFrame class attributes (e.g. inokama.common.make_asset_list). - Bumped the pre-commit
ruffhook tov0.15.14to match the poetry/CI ruff version, so it stops re-applying fixes the project ruff already suppresses via# noqa: UP0xxcomments.
Full Changelog: v2.1.0...v2.1.1
v2.1.0
okama 2.1.0
Feature release that switches get_cagr and get_cumulative_return to an expanding-window definition, makes the okama API endpoint configurable via environment variables, and ships a batch of correctness fixes across the helpers, frontier, DCF, macro, and plotting layers.
Changed
AssetList.get_cumulative_return()andPortfolio.get_cumulative_return()now return an expanding cumulative return series instead of a single end-of-period scalar. Notebook 03 investment portfolios.ipynb updated accordingly.AssetList.get_cagr()andPortfolio.get_cagr()now compute CAGR on an expanding window, consistent withget_cumulative_return().
Added
- Configurable API base URL and request timeout via environment variables (
OKAMA_API_URL,OKAMA_API_TIMEOUT) inokama.settingsandokama.api.api_methods.
Fixed
Frame.get_semideviation()(inokama.common.helpers) now uses the sample mean of returns instead of the population mean, restoring the standard semideviation definition; propagated throughAssetListandPortfolioconsumers.AssetList.recovery_periodsis robust to alast_datethat is not on a month start.EfficientFrontier/EfficientFrontierReb(single- and multi-period variants) now raiseRuntimeErroron failed SLSQP optimisation instead of silently returning invalid weights.AssetList.plot_assets()/Portfolio.plot_assets()autoscale no longer passes the invalidaxis="year"argument.Inflation.cumulative_inflation(inokama.macro) uses.iloc[-1]instead of positional[-1], fixing a pandas FutureWarning / lookup bug.PortfolioDCFdiscount-rate attribute renamed from the misspelledmonlthly_discount_ratetomonthly_discount_rate(okama.portfolios.dcf,okama.portfolios.dcf_calculations).- Helpers producing NaN rows now use
np.nanindict.fromkeys(...)so resulting DataFrames keep float dtype (okama.common.helpers, consumed byAssetListandPortfolio).
Removed
- Dead
Portfolio._clear_cf_cachemethod.
Tooling
- Enabled ruff
UP(pyupgrade) rules and applied auto-fixes acrossokama.common.helpers,okama.common.helpers.rebalancing,okama.portfolios.dcf, and notebook 11 rebalancing portfolio.ipynb. - Aligned declared supported Python versions with the
pyproject.tomlminimum;AGENTS.mdnow mandates a TDD workflow for production code changes. .gitignoreexcludes.env.
Full Changelog: v2.0.1...v2.1.0
Okama 2.0.1
Okama 2.0.1 is a maintenance-focused release that improves compatibility with pandas 3.x and Python 3.14, refines PortfolioDCF cash flow calculations, and makes several plotting and sharing APIs easier to integrate.
New features
pandas 3.x and Python 3.14 compatibility
- okama now supports
pandas3.x and Python 3.14. - Compatibility updates were applied across
Asset,AssetList,Portfolio,PortfolioDCF,MacroABC,Rebalance, and related helpers to keep timestamp conversion, grouping, and resampling behavior working with the new pandas aliases.
Plotting and integration improvements
PortfolioDCF.plot_forecast_monte_carlo(),MonteCarlo.plot_qq(), andMonteCarlo.plot_hist_fit()now return matplotlibAxesobjects, which simplifies embedding okama charts into custom figures.Portfolio.plot_assets()andEfficientFrontier.plot_assets()now accept extramatplotlib.pyplot.scatter()keyword arguments for custom styling.Portfolio.okamaio_linknow serializes the fullRebalanceconfiguration, includingRebalance.period,Rebalance.abs_deviation, andRebalance.rel_deviation.
Performance and analytics improvements
EfficientFrontieradds caching for intermediate calculations to speed up repeated optimization runs.AssetList.get_monthly_geometric_mean_return()andPortfolio.get_monthly_geometric_mean_return()add direct monthly geometric mean return calculations.Asset.first_dateandAsset.last_dateare now used more consistently byListMaker, which improves control over downloaded history ranges.
Bugs fixed
PortfolioDCF.wealth_index()andPortfolioDCF.cash_flow_ts()no longer apply reverse discounting in present-value mode.PortfolioDCF.find_the_largest_withdrawals_size()was fixed for Monte Carlo period validation and now works correctly withVanguardDynamicSpendingandCutWithdrawalsIfDrawdown.PortfolioDCF.plot_forecast_monte_carlo()no longer mutatesPortfolioDCF.cashflow_parameterswhile plotting.MonteCarlodistribution fitting and plotting fixes improve float dtype handling and restore compatibility in QQ/histogram workflows.pandascompatibility fixes also cover deprecatedDataFrame.applymap(),pd.concat(..., copy=...), and updatedpd.Grouperfrequency aliases.
Developer experience
- Linting and formatting migrated from
flake8+blacktoruff check, including GitHub workflows, pre-commit configuration, andAGENTS.mdinstructions for contributors. - Added
.pre-commit-config.yamlwith ruff hooks and a top-levelrequirements.txtmirroring runtime dependencies frompyproject.toml. - Added
CHANGELOG.mdfollowing the Keep a Changelog format and Semantic Versioning. - README now shows GitHub and pepy.tech download badges and an updated project roadmap.
Documentation and examples
Updated documentation and notebooks reflect the current API changes:
- 04 investment portfolios with DCF.ipynb
- 10 forecasting.ipynb
- 11 rebalancing portfolio.ipynb
- Read the Docs navigation and API pages were refreshed for
okama.search()andokama.symbols_in_namespace().
Okama 2.0.0
Unified Efficient Frontier with multi-period optimization and advanced withdrawal strategies for retirement planning.
- Merged
EfficientFrontierandEfficientFrontierRebinto a singleEfficientFrontierclass - Significantly faster Efficient Frontier calculations with caching, parallel computations, and objective function optimization
- New advanced withdrawal strategies: Vanguard Dynamic Spending (VDS) and CutWithdrawalsIfDrawdown (CWD)
Major Changes
Unified EfficientFrontier class with multi-period optimization
EfficientFrontier and EfficientFrontierReb have been merged into a single EfficientFrontier class. Every Efficient Frontier is now computed with rebalancing (multi-period) by default. Optimization of rebalanced portfolios now supports weight constraints (bounds), allowing users to set minimum and maximum allocation limits for each asset.
The calculation speed has been significantly improved through:
- Caching of intermediate results
- Parallel computations
- Objective function optimization
- Fast vectorized methods in
Rebalanceclass
WARNING:
The legacy single-period class has been renamed to EfficientFrontierSingle. If you were using the old EfficientFrontier (single-period), switch to EfficientFrontierSingle.
import matplotlib.pyplot as plt
# New unified EfficientFrontier (multi-period with rebalancing)
ls = ["SPY.US", "GLD.US"]
curr = "USD"
y = ok.EfficientFrontier(
assets=ls,
first_date="2004-12",
last_date="2020-10",
ccy=curr,
rebalancing_strategy=ok.Rebalance(period="year"), # set rebalancing period to one year
ticker_names=True, # use tickers in DataFrame column names (can be set to False to show full assets names instead tickers)
n_points=40, # number of points in the Efficient Frontier
)
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")
# Plot the assets
y.plot_assets(kind="cagr")
# Set axis labels
ax.set_xlabel("Risk (Standard Deviation)")
ax.set_ylabel("CAGR")
ax.legend();
Advanced Withdrawal Strategies
Two new cash flow strategies for retirement planning and endowment fund management:
Vanguard Dynamic Spending (VDS)
Implementation of the Vanguard Dynamic Spending rule that adjusts withdrawals based on portfolio performance with floor and ceiling guardrails.
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 = vdsCutWithdrawalsIfDrawdown (CWD)
Risk-based withdrawal strategy that reduces the withdrawal amount when portfolio drawdown exceeds defined thresholds.
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 = cwdDetailed explanation of new withdrawal strategies is at 04 investment portfolios with DCF.ipynb.
New Classes and Methods
first_date & last_date parameters in Asset
first_date&last_dateparameters are available in theAssetclass. Using these parameters could significantly improve the speed of downloading historical data.
Cash flow strategies
IndexationStrategy,PercentageStrategy,TimeSeriesStrategy— base cash flow management classesVanguardDynamicSpending— dynamic spending rule with floor/ceiling guardrails and min/max annual withdrawal adjustmentsCutWithdrawalsIfDrawdown— drawdown-based withdrawal reduction strategy with configurable threshold/reduction pairs
EfficientFrontier improvements
EfficientFrontier.plot_transition_map()— visualization of asset allocation across the Efficient FrontierEfficientFrontier.plot_cml()— Capital Market Line plottingEfficientFrontier.get_most_diversified_portfolio()— Most Diversified Portfolio (MDP) optimization based on diversification ratioEfficientFrontier.get_monte_carlo()generates random portfolios with Monte Carlo simulation respectingboundsEfficientFrontier.plot_assets()now accepts**kwargsfor matplotlibscatter()
AssetList
AssetList.get_monthly_geometric_mean_return()— new method for geometric mean return calculation
MonteCarlo
MonteCarlo.plot_forecast_monte_carlo()now returns matplotlibAxesobjectMonteCarlo.get_parameters_for_distribution()— distribution fitting with parameters for normal, lognormal, and Student's t distributionsMonteCarlo.kstest()andMonteCarlo.kstest_for_all_distributions()— Kolmogorov-Smirnov goodness-of-fit testsMonteCarlo.plot_hist_fit()— histogram with fitted distribution overlayMonteCarlo.plot_qq()— QQ-plot for visual distribution fit assessment
Portfolio architecture
- New
MonteCarloclass for advanced Monte Carlo simulations and statistical distribution analysis (moved fromPortfolio) - New
PortfolioDCFclass for discounted cash flow analysis, portfolio survival analysis, and withdrawal strategy testing - New
Rebalancehelper class encapsulating rebalancing logic withwealth_ts_efandreturn_ror_ts_efmethods for fast optimization
Documentation and Examples
New and updated Jupyter Notebook examples in the /examples directory:
- 04 investment portfolios with DCF.ipynb — many new examples for
PortfolioDCF,VanguardDynamicSpending, andCutWithdrawalsIfDrawdownstrategies - 07 efficient frontier multi-period.ipynb — significantly reworked with examples for the unified
EfficientFrontierclass and multi-period optimization - 10 forecasting.ipynb — updated Monte Carlo forecasting examples including
MonteCarlodistribution fitting methods - 11 rebalancing portfolio.ipynb — several new examples
All existing notebooks have been refreshed to reflect the latest API changes in okama 2.0.0.
Bug Fixes
- Fixed
AssetList.annual_return_tsandPortfolio.annual_return_tsannual arithmetic mean return compounding calculation - Fixed
PortfolioDCF.wealth_index(discounting="pv")calculation - Fixed
PortfolioDCF.cashflow_parametersbeing modified afterplot_forecast_monte_carlo() - Fixed
PortfolioDCF.find_the_largest_withdrawals_sizenot preserving original CashFlow parameters - Fixed
PortfolioDCFcash flow adjustments in first and last year for partial periods - Fixed
Portfolio.mean_returncalculation to useror.mean()formula - Fixed
MonteCarlo._get_params_for_lognormalparameter calculation - Fixed
MonteCarlo.kstest()fitting to lognormal distribution to use gross returns - Fixed Pandas
FutureWarningforconcatwith empty DataFrame inRebalanceclass - Fixed
MonteCarlo.mc_numbersetter parameter name - Fixed
PortfolioDCF._target_cagr_range_leftcalculation
Other Changes
- Python 3.10 is no longer supported
- API connection switched to HTTPS with SSL verification
- Updated all Jupyter Notebook examples in
/examplesdirectory - Significant increase in test coverage for DCF, Monte Carlo, and cash flow strategy modules
Full Changelog: v1.5.0...v2.0.0
Okama 1.5.0
Rebalancing bands - new rebalancing strategies for investment portfolios.
- Calendar-based rebalancing
- Rebalancing bands (threshold-based)
Mean-variance optimization with rebalancing-strategy-adjusted Efficient Frontier and asset weight bounds.
New features
Rebalance - new class to define rebalancing strategies
Rebalancing strategies are now defined in both Portfolio and EfficientFrontierReb with Rebalance class.
rs = ok.Rebalance(period="year", abs_deviation=0.10, rel_deviation=0.30)
pf = ok.Portfolio(['SPY.US', 'AGG.US'], rebalancing_strategy=rs)WARNING:
The previous Portfolio class initialization method is now deprecated.
ok.Portfolio(rebalancing_period="year") will not work anymore.
However, as the default rebalancing strategy is monthly calendar-based. The simple definition without rebalancing strategy is still working:
ok.Portfolio(['SPY.US', 'AGG.US'], weights=[.6, .4])Rebalance class
- New
Rebalanceclass has 3 parameters: period, abs_deviation, rel_deviation Rebalance.wealth_ts()calculates wealth index time series of rebalanced portfolio (optionally with assets wealth time series)Rebalance.assets_weights_ts()calculates assets weights monthly time series for rebalanced portfolioRebalance.return_ror_ts()returns monthly rate of return time series of rebalanced portfolio
New methods and properties in Portfolio class
- new property
rebalancing_strategyto configure rebalancing period, absolute and relative deviations - new property
rebalancing_eventsreturns time series of rebalancing events and type of rebalancing
Changes in PortoflioDCF class
PortfolioDCF.monte_carlo_wealth_pvcalculates discounted random wealth indexes with cash flowsPortfolioDCF.monte_carlo_wealth_fvcalculates not discounted (nominal) random wealth indexes with cash flowsPortfolioDCF.find_the_largest_withdrawals_size()now uses bisection method to find the largest withdrawals size.PortfolioDCF.find_the_largest_withdrawals_size()has 3 possible goals: 'maintain_balance_pv', 'maintain_balance_fv' and 'survival_period'PortfolioDCF.find_the_largest_withdrawals_size()new attributewithdrawals_rangedefines the possible range for withdrawals to speed up the calculationsPortfolioDCF.find_the_largest_withdrawals_size()hasiter_maxattribute to limit the intermediate steps when searching for resolutionPortfolioDCF.find_the_largest_withdrawals_size()returnsResultclass. If the solutions is not found it is still possible to see the intermediate steps
New methods and properties in EfficienFrontierReb class
EfficienFrontierReb class now uses rebalancing_strategy parameter for initialization (the same as Portfolio).
It supports bounds to define the weight limitations for the assets.
- new
rebalancing_strategyparameter to define the rebalancing strategy - new
boundsparameter defines the bounds for the assets weights - new
EfficienFrontierReb.plot_pair_ef()method plots the Efficient Frontier of every pair of assets
Changes in EfficientFrontier class
EfficientFrontier.get_monte_carlomethod generates random rebalanced portfolios with Monte Carlo simulation according toboundslimitations.
New Jupyter Notebook with examples for Rebalancing strategies
New Jupyter Notebook with examples of investment portfolios with different rebalancing strategies:
10 rebalancing portfolio.ipynb
Okama 1.4.4
New examples for investment portfolios with cash flow in 04 investment portfolios with DCF.ipynb.
Several bugs in Portfolio and PortfolioDCF are fixed.
Fixed:
Portfolio.dcf.initial_investment_pvmust return None if cash flow parameters are not defined- add
use_discounted_valuesparameterto helpers.Frame.get_wealth_indexes_with_cashflow - use
self.use_discounted_values = Falseinplot_forecast_monte_carlofor any value of backtest parameter - clean up Portfolio dat cache if symbol changed
Okama 1.4.3
Okama 1.4.3 is dedicated to Cash Flow strategies and Monte Carlos simulations.
New features
3 new classes to set up Cash Flow strategies
Cash flow parameters for investment portfolios are now configured in the corresponding classes.
IndexationStrategyfor strategies with regular indexed withdrawals / contributionsPercentageStrategyfor strategies weith regualr fixed percentage withdrawals / contributionsTimeSeriesStrategyfor strategies with user-defined withdrawals and contributions. Withdrawals, contributions, as well as their dates, are defined in the dictionary.
All 3 classes are inhereted from parent class CashFlow.
Portfolio class does not have cash flow parameters (initial_amount, cashflow, discount_rate) anymore.
New class to set up Monte Carlo simulation parameters
MonteCarlos class has several properties:
distribution- the type of a distribution to generate random rate of returnperiod- forecast period in years for portfolio wealth index time seriesnumber- number of random wealth indexes to generate with Monte Carlo simulation
All Monte Carlos properties are linked to PortfolioDCF instance and can be accessed by Portfolio().dcf.mc construction. For example the type of random distribution is available through Portfolio().dcf.mc.disctribution.
New methods and properties in PortfolioDCF
PortfolioDCF has a new parameter use_discounted_values (default is False). Id defines whether to use discounted values in backtesting wealth indexes (initial investments, withdrawal or contribution size). discount_rate parameter is shifted from Portfolio to PortfolioDCF.
find_the_largest_withdrawals_size- find the largest withdrawals size for Monte Carlo simulation according to Cashflow Strategy. This method works withIndexationStrategyandPercentageStrategyinitial_investment_fvproperty to calculate the future value (FV) of the initial investments at the end of forecast period.initial_investment_pvproperty to calculate the discounted value (PV) of the initial investments at the historical first datewealth_index_with_assetsworks as the same property ofPortfoliobut considers cash flow (contributions and withdrawals)set_mc_parametersmethod is a shortcut to add Monte Carlo simulation parameters
Changes in methods and properties in PortfolioDCF
monte_carlo_survival_period,survival_date_histandsurvival_period_histmethods have now new parameterthreshold. The threshold defines the percentage of the initial investments when the portfolio balance considered voidedplot_forecast_monte_carlonumber of parameters is reduced to:backtestandfigsize

