0

I have a simple optimization problem in python which I need to re-run quite often (more than 10,000 times).

Most of the calculation can be done with numpy and the n-dimensional arrays quite efficient, however, when it comes to the optimization I am lost, since I have to switch to scipy.optimize.minimize.

Is there a method to run the optimization at once?

Currently I am looping through each line - see code below:

#%% imports
import numpy as np
from scipy import optimize
import time

#%% functions
def square(x, a, cov):
    return (x-a).dot(cov).dot(x-a)

def minimization(args):
    f, x, a, cov, beta, bnds = args
    con_beta = {'type': 'eq', 'fun': lambda x, beta: np.sum(x*beta) - 1, 'jac': lambda x, beta: beta, 'args': (beta, ) }
    res = optimize.minimize(f, x, bounds=bnds, method='SLSQP', args=(a, cov), constraints = con_beta)
    return res.x

#%% initialize data
numberOfRuns = 260 * 100
numberOfAssets = 4
corr = np.ones((numberOfAssets,numberOfAssets))*0.8 + np.eye(numberOfAssets)*0.2
cov = (np.eye(numberOfAssets)*0.15).dot(corr).dot(np.eye(numberOfAssets)*0.15)
mu = np.zeros(numberOfAssets)
cov_n = np.zeros((numberOfRuns, numberOfAssets, numberOfAssets))
bm_n = np.zeros((numberOfRuns, numberOfAssets))
guess_n = np.ones((numberOfRuns, numberOfAssets))/(numberOfAssets-1)
bm_n[:,0] = 1
guess_n[:,0] = 0

bnds = [(0, None) for _ in range(numberOfAssets)]
bnds[0] = (0,0)

for i in range(numberOfRuns):
    cov_n[i,:,:] = np.cov(np.random.multivariate_normal(mu, cov/260, 260).T)*260
beta_n = cov_n[:,0,:]/cov_n[:,0,0][:,np.newaxis]

#%% Run 1
tic = time.time()
for i in range(numberOfRuns):
    res = minimization((square, guess_n[i,:], bm_n[i,:], cov_n[i,:,:], beta_n[i,:], bnds))
toc= time.time()
tictoc1 = toc - tic
print(tictoc1) #21.678 seconds

#%% Run 2
tic = time.time()
args = [(square, guess_n[i,:], bm_n[i,:], cov_n[i,:,:], bnds) for i in range(numberOfRuns)]
p = Pool(4)
res = p.map(minimization, args)
toc = time.time()
tictoc2 = toc - tic
print(toc - tic) #~11 seconds

#%% The End

Is there a more elegant and efficient way instead of looping through??

PS: I have tried to use "Pool", however this "just" halfes the time - still the same problem with the loop.

  • have a look at the [multiprocessing](https://docs.python.org/2/library/multiprocessing.html) and [threading](https://docs.python.org/2/library/threading.html#module-threading) libraries – DrBwts Sep 04 '19 at 18:02
  • Constrained optimization is often slow because it requires rather complicated algorithms. An elegant solution is to get rid of the constraints and use a simpler and faster solver. The equality constraint requires that `sum(x*beta) == 1`. This is equivalent to saying `sum(x[1:]*beta[1:]) == 1 - x[0]*beta[0]`. Instead of optimizing *N* parameters you can optimize *N*-1 parameters and have the *N*th implicitly defined. This version does no longer need the equality constraint. – MB-F Sep 05 '19 at 08:30

0 Answers0