def optimize_with_mosek(self, predicted, today): """ 使用Mosek来优化构建组合。在测试中Mosek比scipy的单纯形法快约18倍,如果可能请尽量使用Mosek。 但是Mosek是一个商业软件,因此你需要一份授权。如果没有授权的话请使用scipy或optlang。 """ from mosek.fusion import Expr, Model, ObjectiveSense, Domain, SolutionError index_weight = self.index_weights.loc[today].fillna(0) index_weight = index_weight / index_weight.sum() stocks = list(predicted.index) with Model("portfolio") as M: x = M.variable("x", len(stocks), Domain.inRange(0, self.constraint_config['stocks'])) # 权重总和等于一 M.constraint("sum", Expr.sum(x), Domain.equalsTo(1.0)) # 控制风格暴露 for factor_name, limit in self.constraint_config['factors'].items( ): factor_data = self.factor_data[factor_name].loc[today] factor_data = factor_data.fillna(factor_data.mean()) index_exposure = (index_weight * factor_data).sum() stocks_exposure = factor_data.loc[stocks].values M.constraint( factor_name, Expr.dot(stocks_exposure.tolist(), x), Domain.inRange(index_exposure - limit, index_exposure + limit)) # 控制行业暴露 for industry_name, limit in self.constraint_config[ 'industries'].items(): industry_data = self.industry_data[industry_name].loc[ today].fillna(0) index_exposure = (index_weight * industry_data).sum() stocks_exposure = industry_data.loc[stocks].values M.constraint( industry_name, Expr.dot(stocks_exposure.tolist(), x), Domain.inRange(index_exposure - limit, index_exposure + limit)) # 最大化期望收益率 M.objective("MaxRtn", ObjectiveSense.Maximize, Expr.dot(predicted.tolist(), x)) M.solve() weights = pd.Series(list(x.level()), index=stocks) # try: # weights = pd.Series(list(x.level()), index=stocks) # except SolutionError: # raise RuntimeError("Mosek fail to find a feasible solution @ {}".format(str(today))) return weights[weights > 0]
def solve_sdp_program(W): assert W.ndim == 2 assert W.shape[0] == W.shape[1] W = W.copy() n = W.shape[0] W = expand_matrix(W) with Model('gw_max_3_cut') as M: W = Matrix.dense(W / 3.) J = Matrix.ones(3*n, 3*n) # variable Y = M.variable('Y', Domain.inPSDCone(3*n)) # objective function M.objective(ObjectiveSense.Maximize, Expr.dot(W, Expr.sub(J, Y))) # constraints for i in range(3*n): M.constraint(f'c_{i}{i}', Y.index(i, i), Domain.equalsTo(1.)) for i in range(n): M.constraint(f'c_{i}^01', Y.index(i*3, i*3+1), Domain.equalsTo(-1/2.)) M.constraint(f'c_{i}^02', Y.index(i*3, i*3+2), Domain.equalsTo(-1/2.)) M.constraint(f'c_{i}^12', Y.index(i*3+1, i*3+2), Domain.equalsTo(-1/2.)) for j in range(i+1, n): for a, b in product(range(3), repeat=2): M.constraint(f'c_{i}{j}^{a}{b}-0', Y.index(i*3 + a, j*3 + b), Domain.greaterThan(-1/2.)) M.constraint(f'c_{i}{j}^{a}{b}-1', Expr.sub(Y.index(i*3 + a, j*3 + b), Y.index(i*3 + (a + 1) % 3, j*3 + (b + 1) % 3)), Domain.equalsTo(0.)) M.constraint(f'c_{i}{j}^{a}{b}-2', Expr.sub(Y.index(i*3 + a, j*3 + b), Y.index(i*3 + (a + 2) % 3, j*3 + (b + 2) % 3)), Domain.equalsTo(0.)) # solution M.solve() Y_opt = Y.level() return np.reshape(Y_opt, (3*n,3*n))
def Markowitz(mu, covar, alpha, L=1.0): # defineerime kasutatava mudeli kasutades keskväärtusi model = mosek_model.build_model('meanVariance') # toome sisse n mitte-negatiivset kaalu weights = mosek_model.weights(model, "weights", n=covar.shape[1]) # leiame kaaludele vastavad finantsvõimendused lev = mosek_math.l1_norm(model, "leverage", weights) # nõuame, et oleks täidetud tingimus omega_1 + ... + omega_n = 1 mosek_bound.equal(model, Expr.sum(weights), 1.0) # nõuame, et oleks täidetud tingimus |omega_1| + ... + |omega_n| <= L mosek_bound.upper(model, lev, L) v = Expr.dot(mu.values, weights) # arvutame variatsiooni var = mosek_math.variance(model, "variance", weights, alpha*covar.values) # maksimeerime sihifunktsiooni mosek_model.maximise(model, Expr.sub(v, var)) # arvutame lõpuks kaalud ja tagastame need weights = pd.Series(data=np.array(weights.level()), index=stocks.keys()) return weights
def solve(x0, risk_alphas, loadings, srisk, cost_per_trade=DEFAULT_COST, max_risk=0.01): N = len(x0) # don't hold no risk data (likely dead) lim = np.where(srisk.isnull(), 0.0, 1.0) loadings = loadings.fillna(0) srisk = srisk.fillna(0) risk_alphas = risk_alphas.fillna(0) with Model() as m: w = m.variable(N, Domain.inRange(-lim, lim)) longs = m.variable(N, Domain.greaterThan(0)) shorts = m.variable(N, Domain.greaterThan(0)) gross = m.variable(N, Domain.greaterThan(0)) m.constraint( "leverage_consistent", Expr.sub(gross, Expr.add(longs, shorts)), Domain.equalsTo(0), ) m.constraint("net_consistent", Expr.sub(w, Expr.sub(longs, shorts)), Domain.equalsTo(0.0)) m.constraint("leverage_long", Expr.sum(longs), Domain.lessThan(1.0)) m.constraint("leverage_short", Expr.sum(shorts), Domain.lessThan(1.0)) buys = m.variable(N, Domain.greaterThan(0)) sells = m.variable(N, Domain.greaterThan(0)) gross_trade = Expr.add(buys, sells) net_trade = Expr.sub(buys, sells) total_gross_trade = Expr.sum(gross_trade) m.constraint( "net_trade", Expr.sub(w, net_trade), Domain.equalsTo(np.asarray(x0)), # cannot handle series ) # add risk constraint vol = m.variable(1, Domain.lessThan(max_risk)) stacked = Expr.vstack(vol.asExpr(), Expr.mulElm(w, srisk.values)) stacked = Expr.vstack(stacked, Expr.mul(loadings.values.T, w)) m.constraint("vol-cons", stacked, Domain.inQCone()) alphas = risk_alphas.dot(np.vstack([loadings.T, np.diag(srisk)])) gain = Expr.dot(alphas, net_trade) loss = Expr.mul(cost_per_trade, total_gross_trade) m.objective(ObjectiveSense.Maximize, Expr.sub(gain, loss)) m.solve() result = pd.Series(w.level(), srisk.index) return result
def _solve_cvxopt_mosek(self): from mosek.fusion import Model, Domain, ObjectiveSense, Expr n, r = self.A with Model('L1 lp formulation') as model: model.variable('x', r, Domain.greaterThan(0.0)) model.objective('l1 norm', ObjectiveSense.Minimize, Expr.dot()) raise NotImplementedError
def solve_sdp_program(A): assert A.ndim == 2 assert A.shape[0] == A.shape[1] A = A.copy() n = A.shape[0] with Model('theta_1') as M: A = Matrix.dense(A) # variable X = M.variable('X', Domain.inPSDCone(n)) # objective function M.objective(ObjectiveSense.Maximize, Expr.sum(Expr.dot(Matrix.ones(n, n), X))) # constraints M.constraint(f'c1', Expr.sum(Expr.dot(X, A)), Domain.equalsTo(0.)) M.constraint(f'c2', Expr.sum(Expr.dot(X, Matrix.eye(n))), Domain.equalsTo(1.)) # solution M.solve() sol = X.level() return sum(sol)
def markowitz(exp_ret, covariance_mat, aversion): # define model model = mModel.build_model("mean_var") # set of n weights (unconstrained) weights = mModel.weights(model, "weights", n=len(exp_ret)) mBound.equal(model, Expr.sum(weights), 1.0) # standard deviation induced by covariance matrix var = mMath.variance(model, "var", weights, covariance_mat) mModel.maximise(model=model, expr=Expr.sub(Expr.dot(exp_ret, weights), Expr.mul(aversion, var))) return np.array(weights.level())
def markowitz_riskobjective(exp_ret, covariance_mat, bound): # define model model = mModel.build_model("mean_var") # set of n weights (unconstrained) weights = mModel.weights(model, "weights", n=len(exp_ret)) # standard deviation induced by covariance matrix stdev = mMath.stdev(model, "std", weights, covariance_mat) # impose a bound on this standard deviation mBound.upper(model, stdev, bound) mModel.maximise(model=model, expr=Expr.dot(exp_ret, weights)) return np.array(weights.level())
def markowitz(exp_ret, covariance_mat, aversion): # define model with Model("mean var") as model: # set of n weights (unconstrained) weights = model.variable("weights", len(exp_ret), Domain.inRange(-np.infty, +np.infty)) model.constraint(Expr.sum(weights), Domain.equalsTo(1.0)) # standard deviation induced by covariance matrix var = __variance(model, "var", weights, covariance_mat) model.objective(ObjectiveSense.Maximize, Expr.sub(Expr.dot(exp_ret, weights), Expr.mul(aversion, var))) model.solve() #mModel.maximise(model=model, expr=Expr.sub(Expr.dot(exp_ret, weights), Expr.mul(aversion, var))) return np.array(weights.level())
def markowitz(exp_ret, covariance_mat, aversion): # define model with Model("mean var") as model: # set of n weights (unconstrained) weights = model.variable("weights", len(exp_ret), Domain.inRange(-np.infty, +np.infty)) model.constraint(Expr.sum(weights), Domain.equalsTo(1.0)) # standard deviation induced by covariance matrix var = __variance(model, "var", weights, covariance_mat) model.objective( ObjectiveSense.Maximize, Expr.sub(Expr.dot(exp_ret, weights), Expr.mul(aversion, var))) model.solve() #mModel.maximise(model=model, expr=Expr.sub(Expr.dot(exp_ret, weights), Expr.mul(aversion, var))) return np.array(weights.level())
def markowitz_riskobjective(exp_ret, covariance_mat, bound): # define model with Model("mean var") as model: # set of n weights (unconstrained) weights = model.variable("weights", len(exp_ret), Domain.inRange(0.0, 1.0)) # standard deviation induced by covariance matrix stdev = __stdev(model, "std", weights, covariance_mat) # impose a bound on this standard deviation #mBound.upper(model, stdev, bound) model.constraint(stdev, Domain.lessThan(bound)) #mModel.maximise(model=model, expr=Expr.dot(exp_ret, weights)) model.objective(ObjectiveSense.Maximize, Expr.dot(exp_ret, weights)) # solve the problem model.solve() return np.array(weights.level())
def solve_sdp_program(W): assert W.ndim == 2 assert W.shape[0] == W.shape[1] W = W.copy() n = W.shape[0] with Model('gw_max_cut') as M: W = Matrix.dense(W / 4.) J = Matrix.ones(n, n) # variable Y = M.variable('Y', Domain.inPSDCone(n)) # objective function M.objective(ObjectiveSense.Maximize, Expr.dot(W, Expr.sub(J, Y))) # constraints for i in range(n): M.constraint(f'c_{i}', Y.index(i, i), Domain.equalsTo(1.)) # solve M.solve() # solution Y_opt = Y.level() return np.reshape(Y_opt, (n, n))
def solve_sdp_program(W, k): assert W.ndim == 2 assert W.shape[0] == W.shape[1] W = W.copy() n = W.shape[0] with Model('fj_max_k_cut') as M: W = Matrix.dense((k - 1) / (2 * k) * W) J = Matrix.ones(n, n) # variable Y = M.variable('Y', Domain.inPSDCone(n)) # objective function M.objective(ObjectiveSense.Maximize, Expr.dot(W, Expr.sub(J, Y))) # constraints for i in range(n): M.constraint(f'c_{i}', Y.index(i, i), Domain.equalsTo(1.)) for j in range(i + 1, n): M.constraint(f'c_{i},{j}', Y.index(i, j), Domain.greaterThan(-1 / (k - 1))) # solution M.solve() Y_opt = Y.level() return np.reshape(Y_opt, (n, n))
import json import numpy as np from mosek.fusion import Model, Domain, Expr, ObjectiveSense A = np.array([[-1., 3.], [4., -1.]]) b = np.array([4., 6.]) c = np.array([1., 1.]) with Model('ex1') as M: # variable x x = M.variable('x', 2, Domain.greaterThan(0.)) # constraints M.constraint('c1', Expr.dot(A[0, :], x), Domain.lessThan(b[0])) M.constraint('c2', Expr.dot(A[1, :], x), Domain.lessThan(b[1])) # objective function M.objective('obj', ObjectiveSense.Maximize, Expr.dot(c, x)) # solve M.solve() # solution sol = x.level() # report to json with open('ex1_output.json', 'w') as f: json.dump({ 'solution': {f'x[{i+1}]': xi for i, xi in enumerate(sol)}, 'cost': np.dot(sol, c), }, f)
import json import numpy as np from mosek.fusion import Model, Domain, Expr, ObjectiveSense A = np.array([[-1., 3.], [4., -1.]]) b = np.array([4., 6.]) c = np.array([1., 1.]) with Model('ex2') as M: # variable y y = M.variable('y', 2, Domain.greaterThan(0.)) # constraints M.constraint('c1', Expr.dot(A.T[0, :], y), Domain.greaterThan(c[0])) M.constraint('c2', Expr.dot(A.T[1, :], y), Domain.greaterThan(c[1])) # objective function M.objective('obj', ObjectiveSense.Minimize, Expr.dot(b, y)) # solve M.solve() # solution sol = y.level() # report to json with open('ex2_output.json', 'w') as f: json.dump( { 'solution': {f'y[{i+1}]': yi for i, yi in enumerate(sol)}, 'cost': np.dot(b, sol), }, f)
def Build_Co_Model(self): r = len(self.roads) mu, sigma = self.mu, self.sigma m, n, r = self.m, self.n, len(self.roads) f, h = self.f, self.h M, N = m + n + r, 2 * m + 2 * n + r A = self.__Construct_A_Matrix() A_Mat = Matrix.dense(A) b = self.__Construct_b_vector() # ---- build Mosek Model COModel = Model() # -- Decision Variable Z = COModel.variable('Z', m, Domain.inRange(0.0, 1.0)) I = COModel.variable('I', m, Domain.greaterThan(0.0)) Alpha = COModel.variable('Alpha', M, Domain.unbounded()) # M by 1 vector Beta = COModel.variable('Beta', M, Domain.unbounded()) # M by 1 vector Theta = COModel.variable('Theta', N, Domain.unbounded()) # N by 1 vector # M1_matrix related decision variables ''' [tau, xi^T, phi^T M1 = xi, eta, psi^t phi, psi, w ] ''' # no-need speedup variables Psi = COModel.variable('Psi', [N, n], Domain.unbounded()) Xi = COModel.variable('Xi', n, Domain.unbounded()) # n by 1 vector Phi = COModel.variable('Phi', N, Domain.unbounded()) # N by 1 vector # has the potential to speedup Tau, Eta, W = self.__Declare_SpeedUp_Vars(COModel) # M2 matrix decision variables ''' [a, b^T, c^T M2 = b, e, d^t c, d, f ] ''' a_M2 = COModel.variable('a_M2', 1, Domain.greaterThan(0.0)) b_M2 = COModel.variable('b_M2', n, Domain.greaterThan(0.0)) c_M2 = COModel.variable('c_M2', N, Domain.greaterThan(0.0)) e_M2 = COModel.variable('e_M2', [n, n], Domain.greaterThan(0.0)) d_M2 = COModel.variable('d_M2', [N, n], Domain.greaterThan(0.0)) f_M2 = COModel.variable('f_M2', [N, N], Domain.greaterThan(0.0)) # -- Objective Function obj_1 = Expr.dot(f, Z) obj_2 = Expr.dot(h, I) obj_3 = Expr.dot(b, Alpha) obj_4 = Expr.dot(b, Beta) obj_5 = Expr.dot([1], Expr.add(Tau, a_M2)) obj_6 = Expr.dot([2 * mean for mean in mu], Expr.add(Xi, b_M2)) obj_7 = Expr.dot(sigma, Expr.add(Eta, e_M2)) COModel.objective( ObjectiveSense.Minimize, Expr.add([obj_1, obj_2, obj_3, obj_4, obj_5, obj_6, obj_7])) # Constraint 1 _expr = Expr.sub(Expr.mul(A_Mat.transpose(), Alpha), Theta) _expr = Expr.sub(_expr, Expr.mul(2, Expr.add(Phi, c_M2))) _expr_rhs = Expr.vstack(Expr.constTerm([0.0] * n), Expr.mul(-1, I), Expr.constTerm([0.0] * M)) COModel.constraint('constr1', Expr.sub(_expr, _expr_rhs), Domain.equalsTo(0.0)) del _expr, _expr_rhs # Constraint 2 _first_term = Expr.add([ Expr.mul(Beta.index(row), np.outer(A[row], A[row]).tolist()) for row in range(M) ]) _second_term = Expr.add([ Expr.mul(Theta.index(k), Matrix.sparse(N, N, [k], [k], [1])) for k in range(N) ]) _third_term = Expr.add(W, f_M2) _expr = Expr.sub(Expr.add(_first_term, _second_term), _third_term) COModel.constraint('constr2', _expr, Domain.equalsTo(0.0)) del _expr, _first_term, _second_term, _third_term # Constraint 3 _expr = Expr.mul(-2, Expr.add(Psi, d_M2)) _expr_rhs = Matrix.sparse([[Matrix.eye(n)], [Matrix.sparse(N - n, n)]]) COModel.constraint('constr3', Expr.sub(_expr, _expr_rhs), Domain.equalsTo(0)) del _expr, _expr_rhs # Constraint 4: I <= M*Z COModel.constraint('constr4', Expr.sub(Expr.mul(20000.0, Z), I), Domain.greaterThan(0.0)) # Constraint 5: M1 is SDP COModel.constraint( 'constr5', Expr.vstack(Expr.hstack(Tau, Xi.transpose(), Phi.transpose()), Expr.hstack(Xi, Eta, Psi.transpose()), Expr.hstack(Phi, Psi, W)), Domain.inPSDCone(1 + n + N)) return COModel