The source files can be found in examples/.

Profile: desk, monthly

The second profile is a professional desk rebalancing monthly. The trade-offs invert the retail profile: rebalancing infrequently means each decision can afford real compute and real analysis, and turnover matters far less. The edge here comes from a view and from exploring the whole risk/return trade-off rather than from cost control.

The reasoning, following the strategy decision framework:

  • Compute is abundant, decisions are rare — a monthly cadence justifies a richer prior and a full frontier sweep.
  • The desk has a view — it encodes a house thesis with an EntropyPoolingPrior rather than taking the sample moments at face value.
  • Explore, then choose — instead of one objective, it traces the efficient frontier and selects the risk-adjusted (tangency) book.
  • Budget is substantial — an exact DiscreteAllocation is affordable.
When to reach for this

This is the template for a research-driven, lower-frequency book: invest the compute in a better prior and a frontier sweep, pick a point deliberately, and allocate exactly. Turnover and fee control matter less when you trade rarely.

using PortfolioOptimisers, CSV, TimeSeries, DataFrames, PrettyTables, Clarabel, HiGHS,      StatsPlots, GraphRecipesresfmt = (v, i, j) -> begin    return if j == 1        v    else        isa(v, AbstractFloat) ? "$(round(v*100, digits=3)) %" : v    endend;

1. Data and the house view

The desk's thesis: healthcare will outperform energy. It encodes that as an entropy-pooling view, reweighting the empirical scenarios so the prior reflects the conviction (see Entropy Pooling).

X = TimeArray(CSV.File(joinpath(@__DIR__, "..", "SP500.csv.gz")); timestamp = :Date)[(end - 252):end]rd = prices_to_returns(X)prices = vec(values(X)[end, :])sets = UniverseSets(;                    dict = Dict("nx" => rd.nx, "energy" => ["CVX", "XOM", "RRC"],                                "healthcare" => ["JNJ", "LLY", "MRK", "PFE", "UNH"]))view_prior = EntropyPoolingPrior(; sets = sets,                                 mu_views = LinearConstraintEstimator(;                                                                      val = ["healthcare >= energy"]))pr = prior(view_prior, rd)slv = Solver(; name = :clarabel, solver = Clarabel.Optimizer,             settings = Dict("verbose" => false),             check_sol = (; allow_local = true, allow_almost = true))rf = 4.2 / 100 / 252
0.0001666666666666667

2. The efficient frontier

With compute to spare, the desk traces the whole frontier on the view-tilted prior — minimum-risk books across a sweep of return targets — rather than committing to a single objective up front.

frontier = optimise(MeanRisk(; obj = MinimumRisk(),                             opt = JuMPOptimiser(; pe = pr, slv = slv,                                                 ret = ArithmeticReturn(;                                                                        settings = JuMPReturnsSettings(;                                                                                                       lb = Frontier(;                                                                                                                     N = 15))))))plot_efficient_frontier(frontier.w, pr; rt = frontier.ret)
Example block output

3. Choosing the book

From the frontier, the desk takes the risk-adjusted optimum — the MaximumRatio (tangency) portfolio on the same view-tilted prior.

desk = optimise(MeanRisk(; obj = MaximumRatio(; rf = rf),                         opt = JuMPOptimiser(; pe = pr, slv = slv)))pretty_table(DataFrame("Asset" => rd.nx, "Tangency weight" => desk.w);             formatters = [resfmt],             title = "Desk monthly — risk-adjusted optimum on the view prior")
Desk monthly — risk-adjusted optimum on the view prior
┌────────┬─────────────────┐
│  Asset  Tangency weight │
│ String          Float64 │
├────────┼─────────────────┤
│   AAPL │           0.0 % │
│    AMD │           0.0 % │
│    BAC │           0.0 % │
│    BBY │           0.0 % │
│    CVX │           0.0 % │
│     GE │           0.0 % │
│     HD │           0.0 % │
│    JNJ │           0.0 % │
│    JPM │           0.0 % │
│     KO │           0.0 % │
│    LLY │         0.002 % │
│    MRK │        76.988 % │
│   MSFT │           0.0 % │
│    PEP │           0.0 % │
│    PFE │           0.0 % │
│     PG │           0.0 % │
│    RRC │           0.0 % │
│    UNH │           0.0 % │
│    WMT │           0.0 % │
│    XOM │        23.008 % │
└────────┴─────────────────┘

4. Exact finite allocation

On a $500,000 book the rounding is small but the desk wants the provably-best whole-share book, so it uses DiscreteAllocation with a MIP solver (HiGHS).

mip_slv = Solver(; name = :highs, solver = HiGHS.Optimizer,                 settings = Dict("log_to_console" => false))alloc = optimise(DiscreteAllocation(; slv = mip_slv),                 FiniteAllocationInput(; w = desk.w, prices = prices, cash = 500_000.0))invested = sum(alloc.shares .* prices)pretty_table(DataFrame("Asset" => rd.nx, "Target" => desk.w,                       "Shares" => round.(Int, alloc.shares), "Realised" => alloc.w);             formatters = [resfmt],             title = "\$500,000 allocated — invested \```math(round(Int, invested)), cash left \```(round(alloc.cash, digits = 2))")
$500,000 allocated — invested ```math(round(Int, invested)), cash left ```(round(alloc.cash, digits = 2))
┌────────┬──────────┬────────┬──────────┐
│  Asset    Target  Shares  Realised │
│ String   Float64   Int64   Float64 │
├────────┼──────────┼────────┼──────────┤
│   AAPL │    0.0 % │      0 │    0.0 % │
│    AMD │    0.0 % │      0 │    0.0 % │
│    BAC │    0.0 % │      0 │    0.0 % │
│    BBY │    0.0 % │      0 │    0.0 % │
│    CVX │    0.0 % │      0 │    0.0 % │
│     GE │    0.0 % │      0 │    0.0 % │
│     HD │    0.0 % │      0 │    0.0 % │
│    JNJ │    0.0 % │      0 │    0.0 % │
│    JPM │    0.0 % │      0 │    0.0 % │
│     KO │    0.0 % │      1 │  0.013 % │
│    LLY │  0.002 % │      0 │    0.0 % │
│    MRK │ 76.988 % │   3512 │ 76.972 % │
│   MSFT │    0.0 % │      0 │    0.0 % │
│    PEP │    0.0 % │      0 │    0.0 % │
│    PFE │    0.0 % │      0 │    0.0 % │
│     PG │    0.0 % │      0 │    0.0 % │
│    RRC │    0.0 % │      1 │  0.005 % │
│    UNH │    0.0 % │      0 │    0.0 % │
│    WMT │    0.0 % │      0 │    0.0 % │
│    XOM │ 23.008 % │   1079 │ 23.011 % │
└────────┴──────────┴────────┴──────────┘

5. The book

plot_stacked_bar_composition([desk], rd; xticks = (1:1, ["Desk monthly"]))
Example block output

This page was generated using Literate.jl.