Benchmark Tracking Example
In [9]:
Copied!
import numpy as np
import pandas as pd
import cvxpy as cp
import numpy as np
import pandas as pd
import cvxpy as cp
In [10]:
Copied!
cov = pd.read_excel("Homework4.xlsx", "One hundred stocks", skiprows=2,header=None).iloc[:, 1:]
cov.shape
cov = pd.read_excel("Homework4.xlsx", "One hundred stocks", skiprows=2,header=None).iloc[:, 1:]
cov.shape
Out[10]:
(100, 100)
Stocks with Highest Volatilities¶
Find the fully-invested long-only portfolio with minimum tracking error that can be formed by picking the ten stocks with highest volatilities.
In [11]:
Copied!
top_10_candidates = np.argsort(np.diag(cov))[-10:]
top_10_candidates = np.argsort(np.diag(cov))[-10:]
In [12]:
Copied!
import time
n = 100
x = cp.Variable(n)
xB = np.ones(1) * (1/100)
obj = cp.Minimize(cp.quad_form(x - xB, cov))
# fully invested, long-only
constraints = [cp.sum(x) == 1, x >= 0]
# constraints on non-candidates
constraints += [
x[i] == 0 for i in range(100) if i not in top_10_candidates
]
prob = cp.Problem(obj, constraints)
# solve the problem
stime = time.time()
prob.solve()
print('Tracking Error = ', (x-xB).value.T@cov@(x - xB).value)
print('Elapsed time = ', time.time()-stime)
import time
n = 100
x = cp.Variable(n)
xB = np.ones(1) * (1/100)
obj = cp.Minimize(cp.quad_form(x - xB, cov))
# fully invested, long-only
constraints = [cp.sum(x) == 1, x >= 0]
# constraints on non-candidates
constraints += [
x[i] == 0 for i in range(100) if i not in top_10_candidates
]
prob = cp.Problem(obj, constraints)
# solve the problem
stime = time.time()
prob.solve()
print('Tracking Error = ', (x-xB).value.T@cov@(x - xB).value)
print('Elapsed time = ', time.time()-stime)
Tracking Error = 12.217633027416225 Elapsed time = 0.0390017032623291
Clustering Representatives¶
Use the "stock clustering" Lagrangian relaxation routine SGalgo () to select ten stocks.
Use the ten selected stocks to construct a long-only fully-invested portfolio that minimizes tracking error.
In [13]:
Copied!
from Cluster import *
sigma = np.diag(cov) ** .5
rho = cov / np.outer(sigma, sigma)
RHO = np.round(100 * rho).values
K = 10
from Cluster import *
sigma = np.diag(cov) ** .5
rho = cov / np.outer(sigma, sigma)
RHO = np.round(100 * rho).values
K = 10
In [14]:
Copied!
u, besty, bestx, bestsol = SGalgo(RHO, K, verbose=False)
u, besty, bestx, bestsol = SGalgo(RHO, K, verbose=False)
Iteration 16: Best Lagrangian = 8327.000000000002, Best solution = 8327.0 Optimal value found = 8327.0
In [15]:
Copied!
top_10_candidates = np.where(besty == 1)[0]
top_10_candidates = np.where(besty == 1)[0]
In [16]:
Copied!
import time
n = 100
x = cp.Variable(n)
xB = np.ones(1) * (1/100)
obj = cp.Minimize(cp.quad_form(x - xB, cov))
# fully invested, long-only
constraints = [cp.sum(x)==1, x>=0]
# constraints on non-candidates
constraints += [
x[i] == 0 for i in range(100) if i not in top_10_candidates
]
prob = cp.Problem(obj,constraints)
# solve the problem
stime = time.time()
prob.solve()
print('Tracking Error = ',(x-xB).value.T@cov@(x - xB).value)
print('Elapsed time = ',time.time()-stime)
import time
n = 100
x = cp.Variable(n)
xB = np.ones(1) * (1/100)
obj = cp.Minimize(cp.quad_form(x - xB, cov))
# fully invested, long-only
constraints = [cp.sum(x)==1, x>=0]
# constraints on non-candidates
constraints += [
x[i] == 0 for i in range(100) if i not in top_10_candidates
]
prob = cp.Problem(obj,constraints)
# solve the problem
stime = time.time()
prob.solve()
print('Tracking Error = ',(x-xB).value.T@cov@(x - xB).value)
print('Elapsed time = ',time.time()-stime)
Tracking Error = 1.3681569489997978 Elapsed time = 0.039000749588012695
Forward Selection¶
In [19]:
Copied!
cnt = 0
n = 100
xB = np.ones(1) * (1/n)
selected = []
stime = time.time()
while cnt < 10:
# select stocks
opt_val = float('inf')
opt_cand = -1
for cand in range(100):
if cand not in selected:
x = cp.Variable(n)
obj = cp.Minimize(cp.quad_form(x - xB, cov))
constraints = [cp.sum(x)==1, x>=0]
constraints += [
x[i] == 0 for i in range(n) if i not in selected + [cand]
]
prob = cp.Problem(obj,constraints)
prob.solve(solver=cp.GUROBI)
val = (x-xB).value.T@cov@(x - xB).value
if val < opt_val:
opt_val = val
opt_cand = cand
cnt += 1
print('Candidate', cnt, ' selected', opt_cand, ' current opt val =', opt_val)
selected.append(opt_cand)
print('Elapsed time = ',time.time()-stime)
cnt = 0
n = 100
xB = np.ones(1) * (1/n)
selected = []
stime = time.time()
while cnt < 10:
# select stocks
opt_val = float('inf')
opt_cand = -1
for cand in range(100):
if cand not in selected:
x = cp.Variable(n)
obj = cp.Minimize(cp.quad_form(x - xB, cov))
constraints = [cp.sum(x)==1, x>=0]
constraints += [
x[i] == 0 for i in range(n) if i not in selected + [cand]
]
prob = cp.Problem(obj,constraints)
prob.solve(solver=cp.GUROBI)
val = (x-xB).value.T@cov@(x - xB).value
if val < opt_val:
opt_val = val
opt_cand = cand
cnt += 1
print('Candidate', cnt, ' selected', opt_cand, ' current opt val =', opt_val)
selected.append(opt_cand)
print('Elapsed time = ',time.time()-stime)
Candidate 1 selected 58 current opt val = 25.06025199999999 Candidate 2 selected 19 current opt val = 13.981154079967688 Candidate 3 selected 74 current opt val = 10.056245266247643 Candidate 4 selected 20 current opt val = 7.501332971539565 Candidate 5 selected 33 current opt val = 5.607685890084806 Candidate 6 selected 13 current opt val = 4.207905032566866 Candidate 7 selected 23 current opt val = 3.171827645670608 Candidate 8 selected 59 current opt val = 2.334426022439366 Candidate 9 selected 39 current opt val = 1.6210198227940362 Candidate 10 selected 52 current opt val = 1.1324072817031632 Elapsed time = 49.03603935241699