Soft turnover constraint for portfolio optimization

525 views
Skip to first unread message

QuantGuySteve

unread,
Mar 28, 2018, 2:02:56 PM3/28/18
to cvxpy

I am using CVXPY and MOSEK to do a simple portfolio optimization. 

I implemented the following dummy code

from cvxpy import *
import numpy as np

np.random.seed(1)
n = 10

Sigma = np.random.randn(n, n) 
Sigma = Sigma.T.dot(Sigma)

orig_weight = [0.15,0.25,0.15,0.05,0.20,0,0.1,0,0.1,0]
w = Variable(n)

mu = np.abs(np.random.randn(n, 1))
ret = mu.T*w

lambda_ = Parameter(sign='positive')
lambda_ = 5

risk = quad_form(w, Sigma)

constraints = [sum_entries(w) == 1, w >= 0, sum_entries(abs(w-orig_weight)) <= 0.750]

prob = Problem(Maximize(ret - lambda_ * risk), constraints)

prob.solve()

print 'Solver Status : ',prob.status

print('Weights opt :', w.value)

I am constraining on being fully invested, long only and to have a turnover of <= 75%. However I would like to use turnover as a "soft" constraint in the sense that the solver will use as little as possible but as much as necessary, currently the solver will almost fully max out turnover. 

I basically want something like this which is convex and doesn't violate the DCP rules

sum_entries(abs(w-orig_weight)) >= 0.05

I would assume this should set a minimum threshold (5% here) and then use as much turnover until it finds a feasible solution. 

Anyone any suggestions how this could be solved or re-written in a convex way or is there a way to relax the turnover constraint so for example if I am running a 100 times rebalance backtest, it won't break if it can't find a feasible solution at e.g. 50% turnover limit but would then relax it to 55%?   

QuantGuySteve

unread,
Apr 2, 2018, 11:59:23 AM4/2/18
to cvxpy

I tried rewriting my objective function to (according to chapter 4.6 from here https://web.stanford.edu/~boyd/papers/pdf/cvx_portfolio.pdf)

prob = Problem(Maximize(lambda_ * ret - risk - penalty * max(sum_entries(abs(w-orig_weight))+0.9,0))  , constraints)

where penalty is e.g. 2 and my constraint object still looks like 

constraints = [sum_entries(w) == 1, w >= 0, sum_entries(abs(w-orig_weight)) <= 0.9]

I have never used soft-constraints and any explanation would be highly appreciated.

Steven Diamond

unread,
Apr 2, 2018, 1:09:55 PM4/2/18
to cvxpy
The point of the soft constraint is to replace the hard constraint. In other words, remove the constraint "sum_entries(abs(w-orig_weight)) <= 0.9"

QuantGuySteve

unread,
Apr 2, 2018, 2:07:12 PM4/2/18
to cvxpy
thanks steve, makes sense. Just to clarify, if I do 


Problem(Maximize(lambda_ * ret - risk - penalty * max_entries(sum_entries(abs(w-orig_weight))+0.9,0)),constraints)

will the solver first try to keep turnover as low as possible up until 90% or how can I use that threshold? Or in other words how would I set it if I want 10% max but are willing to let it go higher to find a feasible solution??

thanks
Reply all
Reply to author
Forward
0 new messages