Kevin Crotty
BUSI 448: Investments
Last time:
Today:
Negative investment weights involve short-selling.
Each position’s weight is:
\[ w_i = \frac{\text{Value of Position}}{\text{Invested Capital}} \]
##### Frontier problem with short-sale constraints
def frontier(means, cov, target):
n = len(means)
Q = matrix(cov, tc="d")
p = matrix(np.zeros(n), (n, 1), tc="d")
# Constraint: short-sales not allowed
G = matrix(-np.identity(n), tc="d")
h = matrix(np.zeros(n), (n, 1), tc="d")
# Fully-invested constraint
A = matrix(np.vstack((np.ones(n), means)), (2, n), tc="d")
b = matrix([1, target], (2, 1), tc="d")
sol = Solver(Q, p, G, h, A, b)
wgts = np.array(sol["x"]).flatten() if sol["status"] == "optimal" else np.array(n * [np.nan])
return wgts
wgts_frontier = [frontier(mns, cov, m) for m in np.linspace(mns.min(), mns.max(),5)]
##### GMV problem with short-sale constraints
n = len(mns)
Q = matrix(cov, tc="d")
p = matrix(np.zeros(n), (n, 1), tc="d")
# Constraint: short-sales not allowed
G = matrix(-np.identity(n), tc="d")
h = matrix(np.zeros(n), (n, 1), tc="d")
# Constraint: fully-invested portfolio
A = matrix(np.ones(n), (1, n), tc="d")
b = matrix([1], (1, 1), tc="d")
sol = Solver(Q, p, G, h, A, b)
wgts_gmv = np.array(sol["x"]).flatten() if sol["status"] == "optimal" else np.array(n * [np.nan])
##### Tangency Portfolio
n = len(mns)
def f(w):
mn = w @ mns
sd = np.sqrt(w @ cov @ w)
return -(mn - r) / sd
# Initial guess (equal-weighted)
w0 = (1/n)*np.ones(n)
# Constraint: fully-invested portfolio
A = np.ones(n)
b = 1
cons = [{"type": "eq", "fun": lambda x: A @ x - b}]
# Short-sale constraint
bnds = [(0, None) for i in range(n)]
# Optimization
wgts_tangency = minimize(f, w0, bounds=bnds, constraints=cons).x
Let’s look at a notebook that constructs frontiers using industry portfolios
BUSI 448