Lesson 0008

Upper and Lower Bound Duals

A portfolio weight can press against its ceiling or its floor. The two duals mean opposite economic pressures.

The One-Step Skill

In Lesson 0007, upper slack meant slack for the upper-bound constraint w <= cap. The lower counterpart is the lower-bound constraint w >= floor.

lower bound:  floor <= w
upper bound:  w <= cap

lower slack = w - floor
upper slack = cap - w

If the floor is zero, as in a long-only portfolio, then lower slack is just the weight itself: w - 0 = w.

Read the Two Pressures

Bounds are easier to interpret if you ask which forbidden direction the objective wants to move.

Upper dual

If w = cap and the upper dual is positive, the optimizer wants more of the asset, but the cap blocks it.

Lower dual

If w = floor and the lower dual is positive, the optimizer wants less of the asset, but the floor blocks it.

Loose bound

If a bound has positive slack, that side is not blocking anything locally, so its dual should be zero.

Lesson 0007 Revisited

The tiny QP had this solution:

w     = [0.70, 0.30]
floor = [0.00, 0.00]
cap   = [0.70, 0.80]

So the lower and upper slack arrays are:

lower slack = w - floor = [0.70, 0.30]
upper slack = cap - w   = [0.00, 0.50]

Both lower slacks are positive, so neither lower bound binds. The A upper slack is zero, so the A cap is the active bound.

lower duals: [0.0000, 0.0000]
upper duals: [0.0900, 0.0000]

CVXPY Readout

In the Lesson 0007 code, the constraint order was:

constraints = [
    w >= 0,       # lower bound
    w <= cap,     # upper bound
    cp.sum(w) == 1,
]

That means the lower-bound duals live on constraints[0], and the upper-bound duals live on constraints[1].

lower_slack = w.value
upper_slack = cap - w.value

lower_duals = constraints[0].dual_value
upper_duals = constraints[1].dual_value
Habit: name constraints before reading duals. In real code, constraints[7].dual_value is a bug waiting to happen unless you know exactly what constraint index 7 means.

Three Cases

asset wants more than cap:
  w = cap, upper dual positive, lower dual zero

asset wants less than floor:
  w = floor, lower dual positive, upper dual zero

asset wants an interior weight:
  floor < w < cap, both bound duals zero

For a long-only portfolio, a positive lower-bound dual usually means the optimizer would prefer to short or further reduce that asset, but the model forbids it.

Retrieval Practice

If w = 0.30, floor = 0.00, and cap = 0.80, which bound is active?

If a long-only lower bound binds with positive dual, what does the model want?

In Lesson 0007, where are the lower-bound duals stored?

Primary Source

Use CVXPY's official dual variables guide for where multipliers are stored and the quadratic-program example for the constraint pattern. Keep the bound dual cheat sheet open when reading solver output.