3
$\begingroup$

The minimizing problem is the following : $$ \underset{w}{\operatorname{argmin}} \sum_{i=1}^{n}\left[w_{i}\times (\frac{Vw}{\sigma})_{i} - b_{i}\right]^{2}$$ with $V$ a $n\times n$ matrix (covariance matrix) which depends on the vector $w$ of size $n$, $\sigma$ is a scalar which is equal to $\sigma = \sqrt{w^\top Vw}$.

For $i=1,\ldots,n$, the quantity $w_{i}\times\left(\frac{Vw}{\sigma}\right)_{i}$ has a meaning in finance and I want the vector to be as close as possible to the target vector $b$. That's why I am minimizing this function.

I have a function that uses scipy.minimize to solve this problem and it returns the optimal weights $\tilde{w}=(w_{i})$ of a portfolio of 500+ stocks. However, some of these weights are very low and I would like the weights $w_{j}$ that are under a certain thresold $\rm thr$ to be set to 0.

One way to have this would be to run my function, then manually set such weights to 0 with if conditions, and finally rescale the weights so the sum equals one. The problem with this method is that the final vector $w$ will not be the optimal vector $\tilde{w}$ anymore.

Do you know any way to minimize a function while having such conditions ?

$\endgroup$
9
  • $\begingroup$ what is the function you are minimizing? can you write down your model? $\endgroup$ Jun 19, 2020 at 12:57
  • $\begingroup$ Welcome to OR.SE! Please take a look at these questions and answers, and see whether they answer your question: or.stackexchange.com/questions/76/… and or.stackexchange.com/questions/33/… $\endgroup$ Jun 19, 2020 at 13:05
  • $\begingroup$ Thank you @LarrySnyder610 ! I checked your links, unfortunately I don't think my problem can be solved with the answers. $\endgroup$
    – FredNgu
    Jun 19, 2020 at 13:10
  • $\begingroup$ OK -- in that case, it would be good if you can put your problem statement into your question rather than in the comments. Hopefully someone will have a good answer for you. Thanks! $\endgroup$ Jun 19, 2020 at 13:11
  • 2
    $\begingroup$ The $w_i$ are semicontinuous variables or.stackexchange.com/questions/1512/… . Any MIQP solver should be able to handle this, whether handled directly as semicontinuous variables, or handled by binary variables Believe me when I say you are not the first person in the history of portfolio optimization who has done this. $\endgroup$ Jun 19, 2020 at 13:17

1 Answer 1

1
$\begingroup$

with optimization engines like CPLEX you can model this if with logical constraints:

For instance, (x<=2) implies (y>=3) can be written in OPL, which is one of CPLEX APIs

(x<=2) => (y>=3);

Now for your portfolio example if you start with the standard Markowitz example

you may easily add if constraints or logical constraints:

{string} Investments = ...;
float Return[Investments] = ...;
float Covariance[Investments][Investments] = ...;
float Wealth = ...;
float Rho = ...;  // Variance Penalty (increasing rho from 0.001 to 1.0 
                  //                   produces a distribution of funds 
                  //                   with smaller and smaller variability).

/******************************************************************************
 * MODEL DECLARATIONS
 ******************************************************************************/

range float FloatRange = 0.0..Wealth;

dvar float  Allocation[Investments] in FloatRange;  // Investment Level


/******************************************************************************
 * MODEL
 ******************************************************************************/

// Minimal Investment
float minimalInvestment=0.01;
// max nb assets
float nbAssetsMax=5;


dexpr float Objective =
  (sum(i in Investments) Return[i]*Allocation[i])
    - (Rho/2)*(sum(i,j in Investments) Covariance[i][j]*Allocation[i]*Allocation[j]);

maximize Objective;

subject to {
  // sum of allocations equals amount to be invested
  allocate: (sum (i in Investments) (Allocation[i])) == Wealth;
  
  sum(i in Investments) (Allocation[i]>=minimalInvestment)<=nbAssetsMax;
  
  forall(i in Investments) (Allocation[i]>=minimalInvestment) || (Allocation[i]==0);
  
  
  
}

tuple AllocationSolutionT{ 
    string Investments; 
    float value; 
};
{AllocationSolutionT} AllocationSolution = {<i0,Allocation[i0]> | i0 in Investments};


float TotalReturn = sum(i in Investments) Return[i]*Allocation[i];
float TotalVariance = sum(i,j in Investments) Covariance[i][j]*Allocation[i]*Allocation[j];

execute DISPLAY {
  writeln("Total Expected Return: ", TotalReturn);
  writeln("Total Variance       : ", TotalVariance);
}

in particular

forall(i in Investments) (Allocation[i]>=minimalInvestment) || (Allocation[i]==0);

makes sure that an allocation is either 0 or more than a minimum level

NB:

I gave an example in OPL but that 's the same in C, python, java ...

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.