|
|
|
@ -101,8 +101,17 @@ class MVO(object): |
|
|
|
|
retPort = ret@w # T-dimensional array |
|
|
|
|
stdPort = np.std(retPort) |
|
|
|
|
return cov@w/stdPort |
|
|
|
|
@staticmethod |
|
|
|
|
def quadratic_utility(w, ret, gamma): |
|
|
|
|
retPort = ret@w # T-dimensional array |
|
|
|
|
varPort = np.var(retPort) |
|
|
|
|
return np.mean(retPort) - 0.5*gamma*varPort |
|
|
|
|
@staticmethod |
|
|
|
|
def quadratic_utility_grad(w, ret, cov, gamma): |
|
|
|
|
manual_ret = np.mean(ret, axis=0) |
|
|
|
|
return manual_ret - gamma*cov@w |
|
|
|
|
@classmethod |
|
|
|
|
def opt(cls, ret, role="max_sharpe"): |
|
|
|
|
def opt(cls, ret, gamma=0, role="max_sharpe"): |
|
|
|
|
n = ret.shape[1] |
|
|
|
|
init=np.ones(n)/n |
|
|
|
|
if role=="max_sharpe": |
|
|
|
@ -117,6 +126,10 @@ class MVO(object): |
|
|
|
|
cov=np.cov(ret.T) |
|
|
|
|
loss = lambda w: cls.volatility(w, ret) |
|
|
|
|
grad = lambda w: cls.volatility_grad(w, ret, cov) |
|
|
|
|
elif role=="quadratic_utility": |
|
|
|
|
cov=np.cov(ret.T) |
|
|
|
|
loss = lambda w: -cls.quadratic_utility(w, ret, gamma) |
|
|
|
|
grad = lambda w: -cls.quadratic_utility_grad(w, ret, cov, gamma) |
|
|
|
|
else: |
|
|
|
|
return init |
|
|
|
|
bnds = [[0, 0.6] for i in range(n)] |
|
|
|
|