roptimizationquadraticquadprog

Constraining norms with inequalities


I have time-series data for N stocks.

sample.data<-replicate(10,rnorm(1000)), where each column shows the returns of different stocks over time.

I am trying to construct a portfolio weight vector to minimize the variance of the returns.

the objective function:

min w^{T}\sum w
s.t. e_{n}^{T}w=1
\left \| w \right \|\leq C

where w is the vector of weights, \sum is the covariance matrix, e_{n}^{T} is a vector of ones, C is a constant. Where the second constraint (\left \| w \right \|) is an inequality constraint.

I used the following code to solve this problem:

library(Rsolnp) 
 gamma<-1  
fn<-function(x) {cov.Rt<-cov(sample.data); return(t(x)%*%cov.Rt%*%x)}   #OBJECTIVE FUNCTION TO MINIMIZE 
eqn<-function(x){one.vec<-matrix(1,ncol=10,nrow=1); return(one.vec%*%x)} #EQUALITY CONSTRAINT
constraints<-1   #EQUALITY CONSTRAINT
ineq<-function(x){one.vec<-matrix(1,ncol=10,nrow=1); #INEQUALITY CONSTRAINT
z1<-one.vec%*%abs(x)
return(z1)  
    }   

uh<-gamma #UPPER BOUND
lb<-0 #LOWER BOUND
x0<-matrix(0,10,1) #STARTING PARAMETER VECTOR (NOT SURE WHAT STARTING VALUES TO PUT HERE)

sol1<-solnp(x0,fun=fn,eqfun=eqn,eqB=constraints, ineqfun=ineq,ineqUB=gamma,ineqLB=lb)

When running this code I get the following error message:

Error in solve.default(cz,tol = 1e-25) : system is computationally singular: reciprocal condition number = 0 In addition: There were 50 warnings (use warnings() to see the first 50)

warnings()
1: In cbind(temp, funv): number of rows of result is not a multiple of vector length

Any ideas what I might be doing wrong? Is there a problem with the starting parameter vector x0?


Solution

  • I changed your code slightly:

    library(Rsolnp)
    set.seed(1)
    sample.data <- matrix(rnorm(10*1000),ncol=10)
    gamma <- 1
    
    #OBJECTIVE FUNCTION TO MINIMIZE 
    fn <- function(x){
      cov.Rt <- cov(sample.data); 
      as.numeric(t(x) %*% cov.Rt %*% x) 
    } 
    #EQUALITY CONSTRAINT
    eqn <- function(x){
      one.vec <- matrix(1, ncol=10, nrow=1)
      as.numeric(one.vec %*% x) 
    } 
    constraints <- 1
    #INEQUALITY CONSTRAINT
    ineq <- function(x){ 
      one.vec <- matrix(1, ncol=10, nrow=1); 
      z1<-one.vec %*% abs(x)
      as.numeric(z1)  
    }   
    
    uh <- gamma #UPPER BOUND
    lb <- 0 #LOWER BOUND
    x0 <- matrix(1, 10, 1) #STARTING PARAMETER VECTOR (NOT SURE WHAT STARTING VALUES TO PUT HERE)
    
    sol1 <- solnp(x0, fun=fn, eqfun=eqn, eqB=constraints)
    

    When we run the above code we get a solution of:

    Iter: 1 fn: 0.09624      Pars:  0.08355 0.08307 0.10154 0.09108 0.11745 0.12076 0.09020 0.09435 0.10884 0.10918
    Iter: 2 fn: 0.09624      Pars:  0.08354 0.08308 0.10153 0.09107 0.11746 0.12078 0.09021 0.09434 0.10883 0.10918
    solnp--> Completed in 2 iterations
    

    But when we add the inequality restriction to the optimization problem, then we run into problems:

    > sol2 <- solnp(x0, fun=fn, eqfun=eqn, eqB=constraints, 
              ineqfun=ineq, ineqUB=gamma, ineqLB=lb)
    
    Iter: 1 fn: 0.09624      Pars:  0.08356 0.08305 0.10153 0.09111 0.11748 0.12078 0.09021 0.09431 0.10881 0.10916
    solnp-->The linearized problem has no feasible
    solnp-->solution.  The problem may not be feasible.
    
    Iter: 2 fn: 272.5459     Pars:  4.44541 4.42066 5.40272 4.84595 6.25082 6.42718 4.80020 5.02004 5.79138 5.81029
    solnp-->The linearized problem has no feasible
    solnp-->solution.  The problem may not be feasible.
    
    Iter: 3 fn: 272.5459     Pars:  4.44547 4.42070 5.40274 4.84596 6.25078 6.42712 4.80023 5.02006 5.79138 5.81023
    Iter: 4 fn: 0.09624      Pars:  0.08357 0.08304 0.10157 0.09106 0.11744 0.12074 0.09021 0.09432 0.10886 0.10918
    Iter: 5 fn: 0.09625      Pars:  0.08354 0.08308 0.10153 0.09107 0.11747 0.12078 0.09021 0.09434 0.10883 0.10919
    Iter: 6 fn: 0.09717      Pars:  0.08394 0.08347 0.10201 0.09150 0.11803 0.12135 0.09064 0.09479 0.10935 0.10971
    Iter: 7 fn: 0.09624      Pars:  0.08353 0.08307 0.10153 0.09106 0.11747 0.12078 0.09020 0.09433 0.10883 0.10919
    Iter: 8 fn: 0.09624      Pars:  0.08353 0.08307 0.10153 0.09106 0.11747 0.12078 0.09020 0.09433 0.10883 0.10919
    solnp--> Solution not reliable....Problem Inverting Hessian.
    Warning message:
    In p0 * vscale[(neq + 2):(nc + np + 1)] :
      longer object length is not a multiple of shorter object length
    

    Let's try to change gamma just a little: gamma <- 1.01

    > sol2 <- solnp(x0, fun=fn, eqfun=eqn, eqB=constraints, 
              ineqfun=ineq, ineqUB=gamma, ineqLB=lb)
    Iter: 1 fn: 0.09624      Pars:  0.08355 0.08307 0.10153 0.09108 0.11745 0.12076 0.09020 0.09435 0.10884 0.10918
    Iter: 2 fn: 0.09624      Pars:  0.08354 0.08308 0.10153 0.09107 0.11746 0.12078 0.09021 0.09434 0.10883 0.10918
    solnp--> Completed in 2 iterations
    

    So your inequality constraint seems to be binding exactly around the equality constraint. Also looking at the two constraints together, it seems a little strange to me. My guess is, that you probably specified your inequality constraint wrong and simply wants something like a shortselling constraint, eg. weights between 0 and 1. This could be archieved following your method by:

    ineq <- function(x){ return(x) }   
    uh <- rep(gamma, 10) #UPPER BOUND
    lb <- rep(0, 10) #LOWER BOUND
    sol3 <- solnp(x0, fun=fn, eqfun=eqn, eqB=constraints, ineqfun=ineq, ineqUB=uh, ineqLB=lb)