I am trying to find the optimal weights of two indexes (stocks and bonds) to mimic as closely as possible a stocks return. (NOC stock). I am having trouble setting up PuLP to minimize the sum of squared differences.
objective function: (minimize) (sum of weighted stock returns + sum of weighted bond return – stocks return)^2
where the stock and bond weights add to 1 and are both constrained between (0,1)
The issue is my returns are all in daily lists so I need to take the weights and multiple all the returns in the list before I can sum them and then use them in the objective function.
from pulp import * model = LpProblem("Style", LpMinimize) wSPY = LpVariable("SPYw", lowBound=0,upBound=1, cat ='Continuous') #weights of SPY stock index wSHY = LpVariable("SHYw", lowBound=0,upBound=1, cat ='Continuous') #weights of SHY bond index #define Objective Function model += ((sum(wSPY*SPYretls) + sum(wSHY*SHYretls)) - sum(NOCretls))**2 #SPYretls is the SPY stock index returns in a list #SHYretls is the SHY stock index returns in a list #NOCretls is the NOC stock returns in a list #constraints model += wSPY >= 0 model += wSHY >= 0 model += wSHY <= 1 model += wSPY <= 1 model.solve()
Advertisement
Answer
Two things:
You cannot (so far as I’m aware) have a squared-difference objective function in
PuLP
. It can only handly linear programs – so with constraints and objectives which are linear in the decision variables. But I think what you want is to minimise the absolute difference – and that can be done in linear programs, the easiest way is to create an auxillary variable which is constrained to be larger than both the positive difference and the negative difference, i.e.:absDiff = LpVariable("absDiff", lowBound=0, cat ='Continuous')
Then you can add constraints like:
`model += absDiff >= sum_1 - sum_2` `model += absDiff >= sum_2 - sum_1`
- For the lists/sums you can do a sum something like
lpSum([wSPY*i for i in SPYretls])
This is making use of pythons list comprehension.