Portfolio Constraints

A constraint is a hard limit on what the finished portfolio may hold. You write per-stock lb and ub, exclude stocks outright, and cap or floor a sector or a mktcap band. Every limit binds: a limit that cannot be met makes the request infeasible rather than quietly bending.

The four linear kinds of limit, and what each one means

Write for the weight of stock . Every optimization already carries the budget row, which says the weights spend the whole portfolio and nothing more:

Your limits add rows to that same statement.

  • A per-stock lb and ub bounds one stock, or every stock at once: .
  • An excluded stock is the ub of zero: . It is a limit rather than a deletion, so the run records that you excluded the stock rather than that you never asked for it.
  • A sector limit bounds the total held in one sector : .
  • A mktcap limit is the same row over a large, mid or small cap band : .

All four are linear in the weights. That single fact is what the whole capability rests on: a linear limit can be added to a convex optimization without changing the kind of problem it is, so the solved portfolio is the best one that obeys your limits rather than an approximation of it.

Two further shapes are available on a sector or mktcap limit. You can bound each stock inside that band, which is a per-stock lb and ub applied to the members rather than to their total. And you can measure the percentages against another band rather than against the whole portfolio, so "IT is at most 35% of the equity sleeve" is expressible. If that sleeve holds 80% of the portfolio, a 35% limit permits 28% of the portfolio.

A minimum effective number of stocks

A fifth limit is not about any one stock or band. It asks the portfolio to be spread across at least stocks in effect:

The left side is the inverse Herfindahl index, the figure every result already reports as effective_n, so the limit and the number you check it against are one definition. Ten stocks at 10% each give 10. One stock at 55% and nine at 5% give about 3.2.

This limit is not linear: it is a cone, . A convex program can still carry it exactly, so the methods that solve one take it inside the program: the mean-variance family (MVO, Min Volatility, Max Quadratic Utility, Black-Litterman, EWMA MVO, HMM Regime MVO, Resampled MVO, Min Semivariance), the tail and drawdown minimizers (Min CVaR, Min CDaR, Min EVaR, Min EDaR, Min MAD, Min GMD, Min FLPM, Min Worst Realization, Min Max Drawdown, Min Average Drawdown, Min Ulcer Index), Maximum Diversification, Distributionally Robust CVaR, Benchmark Tracker, Max Decorrelation, Robust MVO, Kelly and Sparse Markowitz L1.

Every other method refuses it by name and produces no portfolio in that run. The hierarchical and rule-based methods do not solve a program that could hold it. Risk Budgeting solves over a rescaled variable, so the same cone would mean a different rule there. Sparse Index Tracking can select fewer stocks than before it solves.

must be at least 1 and at most the number of stocks in the run. A value the other limits cannot reach, for example 8 when three of ten stocks are excluded, is refused before the run with the largest effective number your limits allow. Like every limit, it holds on the weights the run stores, and a larger is not a claim of lower risk later.

An upper limit on a risk measure

A mandate can cap a risk measure of the portfolio, for example "volatility at most 18% a year" or "CVaR (95%) at most 3% a day". The limit goes into the program the method solves, and the run checks the stored weights against it.

MeasureUnit of the limitChecked against
Volatilityannualvolatility
Semi-deviationannualsemi_deviation
Mean absolute deviationannualmad
CVaR (95%)daily losscvar_95
Worst daydaily lossworst_realization
EVaR (95%)daily lossevar_95
Maximum drawdownfraction, summed returnsmax_drawdown_uncompounded
Average drawdownfraction, summed returnsthe run's record of the limit
Ulcer indexfraction, summed returnsthe run's record of the limit
CDaR (95%)fraction, summed returnscdar_95_uncompounded
EDaR (95%)fraction, summed returnsedar_95_uncompounded

Each limit is computed on this run's own window of daily returns. The annual measures are scaled by the square root of the periods per year, as the results are. The drawdown measures are on summed (uncompounded) returns against a peak that starts at zero, the basis the drawdown minimizers solve on; the compounded drawdown the results show can differ slightly. Each method's record states the figure it reached for every limit, on the limit's own basis. One limit per measure.

A limit is in-sample. It holds on the window the run fits. It does not promise the same volatility or CVaR in the months after the run.

The methods that take a limit are the mean-variance family (MVO, Min Volatility, Max Quadratic Utility, Black-Litterman, EWMA MVO, HMM Regime MVO, Resampled MVO, Min Semivariance), Min CVaR, Min CDaR, Min MAD, Min FLPM, Min Worst Realization, Min Max Drawdown, Min Average Drawdown, Min Ulcer Index, Min EVaR, Min EDaR, Maximum Diversification, Distributionally Robust CVaR, Benchmark Tracker, Max Decorrelation, Robust MVO, Kelly and Sparse Markowitz L1. Min GMD refuses a limit: its program with an EDaR limit did not solve. The hierarchical and rule-based methods refuse it by name too.

A limit tighter than your other limits allow is refused before the run, with the smallest value they do allow. In a rare case the solver reaches the limit only to within its own accuracy; the run then refuses that method by name rather than store weights above the limit.

Limits are solved, never clipped afterwards

There are two ways to build a constrained portfolio, and they do not give the same answer.

The tempting way is to optimize first and fix afterwards: find the unconstrained portfolio, then clip whatever breaches a limit and spread the removed weight over the rest. It is simple and it is wrong.

Take four stocks, each limited to between 10% and 40%. Holding 25% of each satisfies every limit outright, so a correct answer plainly exists. The clip-and-spread approach returns 40%, 10%, 10% and 10%, which sums to 70% rather than 100%. Rescaling that back to 100% then pushes the largest holding above its own 40% ub. Nothing in the result announces this. You receive a portfolio that breaches the limit you set, labelled as though it met it.

So we never do that. There is no clip-and-spread repair step, and no portfolio is labelled as meeting a limit it breaks. Your limits become part of the problem that is solved. A limit that cannot be met therefore makes the problem unsolvable and you are told so, which is the honest outcome and the one you can act on.

One method has a second solve, and it is stated wherever it applies. Hierarchical Risk Parity does not take a sector or mktcap limit itself. A second solve on top of the HRP weights meets it. That second solve is an exact optimization under every limit you set, not a clip, but its result is no longer a pure HRP allocation and can have higher turnover. The run records this, and the HRP page sets out what it costs.

Two ways a method receives your limits

Most methods take your limits as a direct input. They state the portfolio problem as a single optimization, and your rows are handed to it alongside the budget row before anything is solved. Because every limit is linear, adding them does not change the kind of problem it is, and the answer that comes back is the best portfolio that obeys them. Twenty-four of the thirty-one methods work this way, including Mean-Variance, Minimum Volatility, Minimum CVaR, Maximum Diversification and Risk Budgeting.

Two of those twenty-four take your limits one step further out. NCO and Stacking Optimization first build a small number of sub-portfolios, then decide how much money each one gets. Your limits are handed to that second decision, expressed on the final stock weights the blend produces. This is still a direct input, with one consequence worth knowing: the sub-portfolios are fixed before that decision, so a limit the individual stocks could meet can still be out of reach for a blend of them. The run says so and names which limits the blend misses and by how much.

Critical Line Algorithm is a third shape. It takes per-stock lb and ub as a direct input and solves them exactly, because its algorithm advances by tracking which bounds are currently active. That same mechanism is what a sector or mktcap total breaks, which is why it accepts one and not the other.

Where a direct input is not possible

Hierarchical Risk Parity, HERC and HERC2 do not solve a single optimization at all, so there is nothing to hand a limit to. They build a tree that groups similar stocks together, then walk down it, splitting the money between two branches at each step. This third step is called recursive bisection.

What recursive bisection means here

Bisection means splitting something in two. Recursive means doing it again to each half. Starting with the whole portfolio, the tree is cut into two branches and the money is divided between them, usually in inverse proportion to each branch's risk. Each branch is then cut in two and divided again, and so on, until every branch is a single stock and every stock has a weight.

It is a top-down splitting procedure. It is not the bisection method from numerical analysis, which repeatedly halves an interval to hunt for the root of an equation, and nothing here searches from an unconstrained portfolio towards a legal one.

Because the money is committed one split at a time, a limit has to shape each split as the tree is walked, before any stock has a weight.

Suppose a branch holds a fraction of the portfolio and divides into two branches, A and B. Write and for the sums of the lb and the ub of every stock under A, and the same for B. The amount given to A must satisfy:

Each of the four terms is doing work:

  • is what A can absorb on its own.
  • stops you giving A so little that the rest cannot fit under B's ub.
  • stops you giving A so much that B can no longer reach its lb.

This is exact for per-stock lb and ub. An amount given to a branch can be completed into a legal set of weights precisely when it lies between that branch's summed lb and summed ub. The interval above preserves that property for both branches at once, so applying it at every split, down to the individual stocks, guarantees every per-stock lb and ub holds and the weights still sum to one.

Two honest limits of the result. It proves the portfolio obeys your limits; it does not claim to be the lowest-risk portfolio that obeys them. And a sector or mktcap total is not a quantity any branch of the tree forms, so none of the three methods can take one inside the walk. HERC and HERC2 refuse one. Hierarchical Risk Parity meets one by a second solve on top of its weights, set out in the next paragraph. Published research sets out a constrained hierarchical risk parity algorithm that handles box and group constraints together inside the walk, which is a different method from the one used here.

Sector and mktcap limits on Hierarchical Risk Parity

HRP does not take a group rule itself. When the HRP weights with your per-stock lb and ub and your exclusions already meet every sector and mktcap limit, they are used unchanged. Otherwise a second solve on top of those weights finds the closest portfolio that meets every limit, in a chi-square distance that measures how far each split of the HRP tree moved. The result is then no longer an HRP allocation: HRP's split ratios no longer hold, the run records this, and the turnover can be higher. A mandate it cannot meet is refused by name and never relaxed. The HRP page has the measured cost.

When no limit binds, the constrained walk reproduces the unconstrained one to floating-point noise, so any difference you see is attributable to your limits and not to a change of method.

Which constraints each method accepts

Of the 38 methods, 34 accept constraints and 30 accept all three kinds. Hierarchical Risk Parity meets sector and mktcap limits by a second solve on top of its own weights rather than inside its own allocation, and the table marks it. The optimize form shows you this per method before you spend a run, and the PDF and Excel reports record what each method actually did.

A run may deliberately mix methods that take your limits with methods that cannot, because comparing a constrained portfolio against an unconstrained one is sometimes the point. A method that cannot apply your limits produces no portfolio in that run: it is not run without them, and it is not run with them. In Fund Manager Mode the same mix is refused at submission instead, because every method in a fund-manager run must apply every kind of limit the mandate uses.

MethodPer-stock lb and ubExcluded stocksSector and mktcap limits
Mean-Variance (Markowitz)YesYesYes
Black-LittermanYesYesYes
Minimum VolatilityYesYesYes
Max Quadratic UtilityYesYesYes
Minimum CVaRYesYesYes
Minimum CDaRYesYesYes
Minimum SemivarianceYesYesYes
EWMA Mean-VarianceYesYesYes
HMM Regime MVOYesYesYes
Maximum DiversificationYesYesYes
Distributionally Robust CVaRYesYesYes
Benchmark TrackerYesYesYes
Minimum EVaRYesYesYes
Minimum EDaRYesYesYes
Minimum MADYesYesYes
Minimum GMDYesYesYes
Minimum FLPMYesYesYes
Minimum Worst RealizationYesYesYes
Minimum Max DrawdownYesYesYes
Minimum Average DrawdownYesYesYes
Minimum Ulcer IndexYesYesYes
Resampled Mean-VarianceYesYesYes
Maximum DecorrelationYesYesYes
Robust Mean-VarianceYesYesYes
Kelly OptimizationYesYesYes
Sparse Mean-Variance (Reweighted L1)YesYesYes
Sparse Index TrackingYesYesYes
NCOYesYesYes
Stacking OptimizationYesYesYes
Risk BudgetingYesNoYes
Hierarchical Risk ParityYesYesYes, by a second solve
HERCYesYesNo
HERC2YesYesNo
Critical Line AlgorithmYesYesNo
Equal WeightedNoNoNo
Inverse VolatilityNoNoNo
Quintile MomentumNoNoNo
Kalman Pairs TradingNoNoNo

Notes on individual methods

Benchmark Tracker
Under constraints it also stops widening its own tracking-error limit. A desk that writes a tracking-error budget beside a sector limit has stated both as limits, so only the number you asked for is attempted.
Resampled Mean-Variance
Every bootstrap draw carries the constraints, and an average of portfolios that each satisfy them satisfies them too.
Kelly Optimization
This method has a per-stock ub of its own. Yours sits beside it and the tighter of the two applies.
Sparse Mean-Variance (Reweighted L1)
Every reweighted pass carries your rules. A per-stock floor holds that name however expensive the L1 penalty makes it, and the result lists the floored names.
Sparse Index Tracking
The constraints reach the stock selection as well as the weighting. A stock dropped by the selection is held at zero, so an lb on a dropped stock is reported as a conflict rather than quietly ignored.
NCO
Whether your constraints are reachable depends on the date range, because the number of clusters is a property of the window. The same stocks and the same limits were refused over one span and solved over a shorter one.
Stacking Optimization
The blend can miss a limit that the stocks themselves could meet. The run reports that as a limit of the blend and says which limits it misses and by how much.
Risk Budgeting
An excluded stock is the one case this method cannot take: its formulation uses the logarithm of each weight, so a weight of exactly zero is outside its domain. Remove the stock from the run instead. A binding lb or ub also prevents the exact risk contributions this method exists to deliver, so the run reports what it achieved against what you asked for.
Hierarchical Risk Parity
A sector or mktcap total is not a quantity this method ever forms, because a sector cuts across the branches of its tree. HRP does not take a group rule itself. A second solve on top of the HRP weights meets it, so the result is no longer a pure HRP allocation and can have higher turnover. When the HRP weights already meet every group rule, they are used unchanged.
HERC
A sector or mktcap total is not a quantity this method ever forms, because a sector cuts across the branches of its tree. HERC refuses one. The second solve that Hierarchical Risk Parity uses is not applied here: when a group splits a final cluster, that solve moves the members of the cluster by different factors, which breaks the fixed proportions HERC is defined by. HERC also keeps fixed proportions inside each final cluster, so a per-stock lb or ub those proportions cannot carry is refused rather than met by changing the method.
HERC2
As HERC, with equal weights inside each final cluster. Flatter proportions leave more room, so it refuses less often.
Critical Line Algorithm
This method solves per-stock lb and ub exactly: its algorithm advances by tracking which bounds are active. A sector or mktcap total is a different shape of rule and breaks that algorithm, so it is permanently unavailable here rather than pending work.
Equal Weighted
The weights are fixed by the definition of the method. Changing them to meet a limit produces a different strategy rather than a constrained version of this one.
Inverse Volatility
The weights are fixed by each stock's own volatility, for the same reason as Equal Weighted.
Quintile Momentum
This ranks and selects stocks rather than optimizing weights. A limit could mean change the weights, change the stocks selected, or both, and we will not guess which you meant.
Kalman Pairs Trading
Long and short by construction. These constraints are long-only, and an lb over a position that may be negative does not mean what it says. This method is available through the API and is not offered on the website.

Checks that run before a run is spent

Can any portfolio satisfy every limit at once?

Checking each limit on its own is not enough, and the reason is worth understanding. Suppose you set a large cap lb of 60% and an IT ub of 40%, and every large cap stock in your list is an IT stock. Each limit passes its own arithmetic. Together they are impossible, and no per-limit test can see it, because the conflict lives in the overlap between two lists rather than in either limit.

So the check is one linear program carrying every limit at once: the budget row, the effective per-stock lb and ub, and every sector and mktcap row simultaneously. This is exact for limits on the allocation, and it is cheap enough to run as you type.

When it fails, a second program finds the smallest total adjustment that would make your limits hold. The adjustments that come back non-zero name the limits in conflict and the size of each conflict, so you read "your large cap lb and your IT ub miss each other by 12 percentage points" rather than the word infeasible.

What can this list of stocks actually hold?

Before a limit is even infeasible, the more useful question is what your stocks can support. For one sector or mktcap band, holding every other limit fixed, two more linear programs give the answer:

That pair is the reachable range, and the form shows it beside the limit you are writing. The band's own limit is taken out of its own range on purpose: a sector already capped at 20% would otherwise report a maximum of 20%, which is your own limit read back rather than a fact about your stocks.

The same check also reports, for each stock that a limit reaches, the lb and ub that hold after every limit is applied and the limit that set each one. Where several limits reach one stock, the smallest ub and the largest lb hold. It also tells you which of your stocks the run will remove for missing, stale or too short price history, before you submit.

One boundary to keep in mind. These checks cover limits on the allocation and nothing else. A method's own requirement, such as a tracking-error limit, can still refuse a request that sits comfortably inside every reachable range. The checks also read the stocks you selected. A stock removed for short history makes the universe smaller, so the run checks your limits again on the stocks that remain.

Constraints in a backtest

A rolling walk-forward backtest re-optimizes at every rebalance date by default, and your limits are applied at every refit, not only at the start. Feasibility is re-checked at each refit and the outcome is recorded for each. With a coarser re-optimize frequency, a rebalance between refits trades back to the last target fitted under your limits.

Sector and mktcap limits are the exception, and the reason is look-ahead. A sector list carries a date. Applying a list dated 2026 inside a training window that ends in 2016 would let the optimizer pick its 2016 portfolio with knowledge of which companies survived, merged and re-listed. That inflates a backtest and makes it worthless as evidence.

So a sector or mktcap limit whose list is dated after the first rebalance date is excluded from the backtest and the exclusion is recorded, rather than applied quietly with today's data. The decision is taken once, against the first rebalance date, so one set of limits holds across the whole track. Per-stock lb and ub name a stock directly, read no list, carry no date, and are always applied.

The backtest result states which limits it applied and which it excluded, with the date of the list and the reason, on the results page, in the PDF and in the Excel workbook.

What your limits cost

A constrained portfolio differs from the one the same method would build with no limits at all. You can ask the run to measure that difference. The measurement costs a second solve for each method, so it is off unless you ask for it.

Five measures are reported together, and deliberately so. They answer different questions and they rank limits differently, so publishing one of them would present one ranking as the ranking.

  • Active share, half the sum of the absolute weight changes. How much of the book moved.
  • Tracking error between the two portfolios, annualized. How differently the constrained book should behave.
  • Volatility with and without the limits, and the difference. What the limits cost in risk, measured in advance from the same covariance estimate rather than from a realized track.
  • The largest single stock move, because one stock moving twenty points is worth seeing next to an active share that averages it away.
  • Each sector and mktcap total, with and without the limits.

None of these is a forecast, and a larger distance is not a worse set of limits. They describe two portfolios built on the same frozen inputs, and nothing about how either will perform.

The measurement applies to the optimization itself. A rolling backtest does not report it, because it would need a second solve at every rebalance date. The results page, the PDF and the Excel workbook all show it, and a method that cannot supply a measure gives the reason.

Where the sector list comes from

A sector limit needs to know which sector each stock is in, and you supply that list yourself from Sector Lists. The run reads the list, records the revision it read, and stores it with the result. Editing a list changes what your next run means and never what a past run meant. Through the API or an AI assistant, a list can also be sent with the request itself.

A sector limit needs a list that covers every stock in the run. A 25% cap over a list that names 80% of the portfolio would leave the other 20% unbound, so a portfolio could hold far more of that sector than the cap says. The run refuses such a limit and names the stocks the list is missing. Sector names are matched on a standard spelling, so a limit on Financials also binds stocks your list files under BFSI or Banking, and the run reports the match it made.

An mktcap limit needs no list. The bands are built from a market capitalisation snapshot of the stocks in your own run, using absolute thresholds. This is not the SEBI rank-based large, mid and small cap list, which ranks the whole listed universe twice a year and cannot be computed from one portfolio's stocks. The snapshot is point-in-time, so it carries no history and is never applied inside a backtest window. A stock whose market capitalisation is unavailable fails the run rather than escaping the mktcap limit.

References

Why constraints are worth setting

  • Jagannathan, R. and Ma, T. (2003). Risk Reduction in Large Portfolios: Why Imposing the Wrong Constraints Helps. The Journal of Finance, 58(4), 1651-1683. Shows that an upper bound on each weight acts like shrinking the covariance estimate, so constraints can reduce realized risk even when the constraint itself is not what the investor truly believes.
  • Best, M. J. and Grauer, R. R. (1991). On the Sensitivity of Mean-Variance-Efficient Portfolios to Changes in Asset Means: Some Analytical and Computational Results. The Review of Financial Studies, 4(2), 315-342. Quantifies how violently unconstrained mean-variance weights move in response to small changes in estimated returns, which is the instability lb and ub are usually set to control.
  • DeMiguel, V., Garlappi, L., Nogales, F. J. and Uppal, R. (2009). A Generalized Approach to Portfolio Optimization: Improving Performance by Constraining Portfolio Norms. Management Science, 55(5), 798-812. Treats constraints on the size of the weight vector as a single framework and measures the out-of-sample effect.

Why a linear limit fits inside the optimization

  • Boyd, S. and Vandenberghe, L. (2004). Convex Optimization. Cambridge University Press. The standard treatment of why adding linear equalities and inequalities to a convex objective leaves the problem convex, and therefore leaves a global optimum reachable.
  • Rockafellar, R. T. and Uryasev, S. (2000). Optimization of Conditional Value-at-Risk. Journal of Risk, 2(3), 21-41. Shows that minimizing CVaR can be written as a linear program, which is what lets the CVaR and drawdown methods carry your limits as ordinary rows rather than needing special handling.
  • Huangfu, Q. and Hall, J. A. J. (2018). Parallelizing the dual revised simplex method. Mathematical Programming Computation, 10(1), 119-142. The class of algorithm behind the feasibility and reachable range programs described above.

Hierarchical methods and recursive bisection

  • Lopez de Prado, M. (2016). Building Diversified Portfolios that Outperform Out of Sample. The Journal of Portfolio Management, 42(4), 59-69. Introduces hierarchical risk parity and the recursive bisection step described above.
  • Raffinot, T. (2017). Hierarchical Clustering-Based Asset Allocation. The Journal of Portfolio Management, 44(2), 89-99. The clustering-based allocation family that HERC and HERC2 belong to.
  • Pfitzinger, J. and Katzke, N. (2019). A constrained hierarchical risk parity algorithm with cluster-based capital allocation. Stellenbosch University, Department of Economics, Working Paper 14/2019. Sets out hierarchical risk parity weights under box and group constraints together. This is a working paper rather than a peer-reviewed article, and it is cited here as the evidence that sector and mktcap limits on the tree-based methods are not mathematically impossible. The method here is different: Hierarchical Risk Parity meets them by a second solve on top of its own weights, and HERC and HERC2 refuse them.

Availability

Constraints are an Enterprise capability. They can be set on the optimize form, through the REST API, and through a connected AI assistant. All three read the same per-method table shown above, so none of them can offer you a limit a method cannot apply. The table itself is readable on every plan, so you can see what each method does with a limit before you upgrade.

Not investment advice. Past performance is not indicative of future results.