【MILP】Mixed-Integer Quadratic Programming portfolio optimzation

Problem

The classical Markowitz problem is as follows:
max ⁡ x r T x − λ x T Q x \max_x r^Tx-\lambda x^TQx xmaxrTxλxTQx
The quadprog solver addresses this quadratic programming problem. Some cardinality constraints would be added. x x x is the vector of asset allocation fractions, with 0 ≤ x ( i ) ≤ 1 0\leq x(i)\leq 1 0x(i)1 for each i i i. The indicator variables v v v such that v ( i ) = 0 v(i)=0 v(i)=0 when x ( i ) = 0 x(i)=0 x(i)=0, and v ( i ) = 1 v(i)=1 v(i)=1 when x ( i ) > 0 x(i)>0 x(i)>0. To get variables that satisfy this restriction, set the v v v vectror to be a binary variable, and impose the linear constraints.
v ( i ) f min ⁡ ≤ x ( i ) ≤ v ( i ) f max ⁡ v(i)f_{\min}\leq x(i)\leq v(i)f_{\max} v(i)fminx(i)v(i)fmax
and
m ≤ ∑ v ( i ) ≤ M m\leq \sum v(i)\leq M mv(i)M

Objective and Successive linear Approximations

The objective function is
min ⁡ x λ x T Q x − r T x \min_x\lambda x^TQx-r^Tx xminλxTQxrTx
However, the intlinprog MILP solver requires a linear objective function. There is a standard technique to reformulate this problem into one with linear objective and nonlinear constraints. Introduce a slack variable z z z to represent the quadratic term.
min ⁡ x , z λ z − r T x { x T Q x − z ≤ 0 z ≥ 0 \min_{x, z} \lambda z-r^Tx\\ \begin{cases} x^TQx-z\leq 0\\ z\geq 0 \end{cases} x,zminλzrTx{ xTQxz0z0
To solve MILP approximations iteratively, we could approximate the nonlinear constraint locally near the current point
x T Q x − z = x 0 T Q x 0 + 2 x 0 T Q δ − z + O ( ∣ δ ∣ 2 ) x^TQx-z=x_0^TQx_0+2x_0^TQ\delta-z+O(|\delta|^2) xTQxz=x0TQx0+2x0TQδz+O(δ2)
Replacing δ \delta δ by x − x 0 x-x_0 xx0
x T Q x − z = − x 0 T Q x 0 + 2 x 0 T Q x − z + O ( ∣ x − x 0 ∣ 2 ) x^TQx-z = -x_0^TQx_0+2x_0^TQx-z+O(|x-x_0|^2) xTQxz=x0TQx0+2x0TQxz+O(xx02)
For each intermediate solution x k x_k xk you introduce a new linear constraint in x x x and z z z as the linear part of the expression above:
− x k T Q x k + 2 x k T Q x − z ≤ 0 -x_k^TQx_k+2x_k^TQx-z\leq 0 xkTQxk+2xkTQxz0

Code

%% integer programming
clc;
clear all;
close all;

%%
load port5;
r = mean_return;
Q = Correlation .* (stdDev_return * stdDev_return');
N = length(r);
% indexes
xvars = 1:N;
vvars = N+1:2*N;
zvar = 2*N+1;

lb = zeros(2*N+1, 1);
ub = ones(2*N+1, 1);
ub(zvar) = Inf;

% set the number of assets in the solution to between 100 and 150.
M = 150;
m = 100;
A = zeros(1, 2*N+1);
A(vvars) = 1; % A*x represents the sum of v(i)
A = [A; -A];
b = zeros(2, 1);
b(1) = M;
b(2) = -m;

% set the minimal nonzero fraction of assets to be 0.05 and the maximal to
% be 0.20
fmin = 0.001;
fmax = 0.05;

% inequalities fmin(i)*v(i)<=x(i)<= fmax(i)*v(i)
Atemp = eye(N);
Amax = horzcat(Atemp, -Atemp*fmax, zeros(N, 1));
A = [A; Amax];
b = [b; zeros(N, 1)];
Amin = horzcat(-Atemp, Atemp*fmin, zeros(N, 1));
A = [A; Amin];
b = [b; zeros(N, 1)];

% constraint sum(x_i)=1
Aeq = zeros(1, 2*N+1);
Aeq(xvars) = 1;
beq = 1;

% risk-aversion coefficient lambda
lambda = 100;

% objective function
f = [-r; zeros(N, 1); lambda];

%% solve
ops = optimoptions(@intlinprog, 'Display', 'off');
[xLinInt, fval, exitFlag, output] = intlinprog(f, vvars, A, b, Aeq, beq, lb, ub, ops);

%% stopping condition
thediff = 1e-4;
iter = 1;
assets = xLinInt(xvars); 
trueVar = assets'*Q*assets;
zslack = xLinInt(zvar);

cvx code

%% MLIP
n = 10;
k_high = 8;
k_low = 2;
fmax = 0.30;
fmin = 0.05;
mu = abs(randn(n, 1));
Sigma = randn(n, n)/10;
Sigma = Sigma'*Sigma;

cvx_solver mosek
cvx_begin
    variable w(n);
    variable bi(n) binary;
    ret = mu'*w;
    risk = quad_form(w, Sigma);
    maximize(ret-risk);
    subject to 
        ones(1, n)*w==1;
        w>=0;
        w<=bi;
        % k_high>=nnz(w)>=k_low;
        % norm(w, Inf)<=fmax;
        fmin*bi<=w;
        fmax*bi>=w;
        sum(bi)>=k_low;
        sum(bi)<=k_high;
cvx_end

w=value(w);

Reference

Mathlab MILP

猜你喜欢

转载自blog.csdn.net/qq_18822147/article/details/114586747