I have a problem trying to find portfolio weights and optimise them while satisfying constraints. I require some help on designing a code that would allow me to simulate multiple arrays of weights while satisfying a range of constraints, please see example below for an explanation:
Problem - simulate various weights while satisfying constraints:
Instruments = ['Fixed Income', 'Equity 1', 'Equity 2', 'Multi-Asset', 'Cash']
Constraints:
At the moment I have code:
import numpy as np:
instruments = ['Fixed Income', 'Equity 1', 'Equity 2', 'Multi-Asset', 'Cash']
weights = np.random.uniform(0.1, 0.4, len(instruments)) # random number generation
weights = weights / weights.sum() # normalise weights
# I have done test runs, and normalised weights always fit the constraints
if weights[-1] > 0.03:
excess = weights[-1] - 0.03
# distribute excess weights equally
weights[:-1] = weights[:-1] + excess / (len(weights) - 1)
and I'm stuck, I also realised that when I distribute the excess weights I have effectively broken my constraint.
Is there anyway to do it? and I have to do it via monte-carlo
Thanks everyone for your help.
Here is one solution:
import numpy as np
N = 1000000
instruments = ['Fixed Income', 'Equity 1', 'Equity 2', 'Multi-Asset', 'Cash']
# each row is set of weights in order of instruments above
weights = np.zeros(shape=(N, len(instruments)))
weights[:, -1] = 0.05
weights[:, 1] = np.random.uniform(0, 0.3, N)
cols = (0, 2, 3)
# fill columns with random numbers
for col in cols[0:-1]:
w_remaining = 1 - np.sum(weights, axis=1)
weights[:, col] = np.random.uniform(0.1, 0.4, N)
# the last column is constrained for normalization
weights[:, cols[-1]] = 1 - np.sum(weights, axis=1)
# select only rows that meet condition:
cond1 = np.all(0.1 <= weights[:, cols], axis=1)
cond2 = np.all(weights[:, cols] <= 0.4, axis=1)
valid_rows = cond1*cond2
weights = weights[valid_rows, :]
# verify sum of weights == 1:
np.testing.assert_allclose(np.sum(weights, axis=1), 1)
This solution is performant, but discards generated examples that don't satisfy the constraints.