# \[ANN\] PortfolioOptimisers.jl: Ape together strong

**URL:** <https://discourse.julialang.org/t/ann-portfoliooptimisers-jl-ape-together-strong/133099>\
**Category:** Package Announcements\
**Tags:** plotting, jump, optimization, clustering, portfolioanalytics\
**Created:** [October 13, 2025, 12:22am UTC](https://discourse.julialang.org/t/ann-portfoliooptimisers-jl-ape-together-strong/133099 "2025-10-13T00:22:45Z")\
**Posts on this page:** 1\
**Showing post:** 6

<div class="post-metadata">

**Author:** ![dcelisgarza](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dcelisgarza/32/215951_2.png) [@dcelisgarza](https://discourse.julialang.org/u/dcelisgarza)\
**Post date:** [April 14, 2026, 4:25pm UTC](https://discourse.julialang.org/t/ann-portfoliooptimisers-jl-ape-together-strong/133099/6 "2026-04-14T16:25:05Z")

</div>

# PortfolioOptimisers.jl v0.19.0

## Highlights

- [Quick start guide](https://dcelisgarza.github.io/PortfolioOptimisers.jl/stable/user_guide/01_Basic_Optimisation#1.-Computing-returns).
- The entire [API](https://dcelisgarza.github.io/PortfolioOptimisers.jl/stable/api/00_API#Features) has been documented by clankers.

## New features

### Breaking

- Added benchmark prices. They can be specified per asset (as a matrix), or as an index (as a vector). This enables optimising on excess returns which is a form of tracking. It’s compatible with every optimiser, cross validation, and prediction. Breaking because I had to add a flag to all optimisation estimation structs even though it didn’t break existing code or APIs.
- Improved the consistency of various moment estimators which internally compute the variance. They also used to contain expected returns estimators, but we now use the ones inside the variance estimator because the expected returns estimator was computing the mean used to compute the variance.
- `expend_train -> expand_train` keyword in `WalkForwardEstimator` subtypes to make it consistent with `reduce_test`.

### Non-breaking

- `SubsetResampling` optimiser. This takes random, unique, samples of the asset universe and optimises each one in turn. The final weights are the (optionally weighted) average weights of each asset in each optimisation. If an asset wasn’t sampled for a given optimisation, its weight is taken to be zero. It interpolates between the equal weighted portfolio and the pure internal optimiser. It’s quite cool, i like this optimiser a lot because it adds noise that reduces overfitting for mid assets, but buries shit ones and lets great ones shine through. It’s like a targeted yet stochastic combination of the `L_n` penalty families.
- `LogRiskBudgeting` what used to be the normal risk budgeting algorithm can now accept an orthant vector, which means risk budgeting portfolios can now take on negative weights. But they have to be specified _a priori_. Limited to asset risk budgeting, factor risk budgeting already allows for negative asset weights. It might be possible to generalise but i haven’t thought it through.
- `MixedIntegerRiskBudgeting` explores all orthants to get a low risk portfolion that meets the risk budget threshold. It’s very expensive because there are `2^N` sign combinations, where `N` is the number of assets. You don’t have to specify the orthant vector, it is obtained on the fly. It also doesn’t guarantee the lowest risk portfolio simply because the MIP optimiser might give up depending on your settings. Limited to asset risk budgeting, factor risk budgeting already allows for negative asset weights. It might be possible to generalise but i haven’t thought it through.
- Windowed variants of all moment estimators. They simply wrap one of the already provided estimators. You can provide a `window` which can be an integer to take the last `window` number of entries, or a vector to index those specific indices. The moments will be computed based on that window rather than the entire history. They also support weighted estimators by currying the outer weights inward with the right indexing.

## Docs

- Added a quick start guide.
- I’ve added more docstring examples and defined some of the necessary interfaces one would need to implement to add custom behaviour.
- I caved and unleashed the clankers on the API docs. I only asked for API documentation of function signatures, variable, type and function explanations. Almost 18k lines later here we are. It seems to have done a fairly good job, but one does not simply read 18k lines and find all issues at once. But at least, the APIs are now documented so people can actually use the entire library without looking at the code. I will methodically go over the new docs to improve their quality.

## Bug fixes

- Fixed a bug in risk budgeting optimisers where constraints were being correctly built from the wrong variable, which meant unnecessary coupling between systems that also needlessly made certain constraint combinations impossible to define.

## Future plans

- Improve the documentation.
  - The clanker-made docs are competent, but not to the standard I’d like.
  - They’re missing interface definitions, sources, language standardisation, nicer mathematical notation, not all methods are documented (mainly internal ones).
  - Split the API docs into public and private.
  - More examples and entries to the user guide.

- Plots, this is a sore point for me.
  - I have had trouble with Makie.jl due to its less than stellar support for dendrograms.
  - Plots has the problem that I have to load GraphRecipes.jl and StatsPlots.jl to load the extension, which is less than ideal.
  - I’d like to have interactive plots with mouse-over labels but that would lock me into Plotly
  - The API of my plotting functions sucks and I haven’t figured out a way to make it better. Recipes seem fragile but I’ll maybe ask a clanker to figure it out for me.
  - Need plots for prediction results, not just optimisation results.

- Cross sectional factor prior.
- Copula based synthetic returns. Needs vine copulas, I’ve not found any Julia implementation.
- Remove python dependencies. Needs bootstrapping and bin width computation functions, but I’ve found no suitable Julia library that does either of these.
- Pipelines.
- Online statistical methods maybe? Though I’m not sure how to make most of the current ones can be updated. I’m inclined to let it ride as it is, it may not be worth it. Unless someone else wants to give it a stab and open a PR.

---

_[View the full topic](https://discourse.julialang.org/t/ann-portfoliooptimisers-jl-ape-together-strong/133099)._
