cvxportfolio
cvxportfolio copied to clipboard
Multiprocess error in HelloWorld
When running the HelloWorld example on macOS Catalina with a fresh download from the current repo with versions of the relevant libraries numpy=1.18.1, pandas=1.0.3, cvxpy=1.0.31, and python=3.7.7 on the cell
init_portfolio = pd.Series(index=returns.columns, data=250000.)
init_portfolio.USDOLLAR = 0
results = market_sim.run_multiple_backtest(init_portfolio,
start_time='2013-01-03', end_time='2016-12-31',
policies=[spo_policy, cp.Hold()])
I get the following error
<ipython-input-15-817c8501f3a4> in <module>
4 results = market_sim.run_multiple_backtest(init_portfolio,
5 start_time='2013-01-03', end_time='2016-12-31',
----> 6 policies=[spo_policy, cp.Hold()])
7 results[0].summary()
~/Desktop/cvxportfolio-master/cvxportfolio/simulator.py in run_multiple_backtest(self, initial_portf, start_time, end_time, policies, loglevel, parallel)
150 if parallel:
151 workers = multiprocess.Pool(num_workers)
--> 152 results = workers.map(_run_backtest, policies)
153 workers.close()
154 return results
~/anaconda3/envs/quantopt/lib/python3.7/site-packages/multiprocess/pool.py in map(self, func, iterable, chunksize)
266 in a list that is returned.
267 '''
--> 268 return self._map_async(func, iterable, mapstar, chunksize).get()
269
270 def starmap(self, func, iterable, chunksize=None):
~/anaconda3/envs/quantopt/lib/python3.7/site-packages/multiprocess/pool.py in get(self, timeout)
655 return self._value
656 else:
--> 657 raise self._value
658
659 def _set(self, i, obj):
Exception: Invalid dimensions for arguments.
Any insight into what may be causing this would be much appreciated. Thank you!
Check what happens if you run with parallel=False in run_multiple_backtest(). I know Windows has some RunTime errors. I recall something about "freeze_support" issues. But On Linux boxes it doesn't happen. All of this to determine that what you have might be the dimension problems raised in issue #52.
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
<ipython-input-19-4230c81fade5> in <module>
4 results = market_sim.run_multiple_backtest(init_portfolio,
5 start_time='2013-01-03', end_time='2016-12-31',
----> 6 policies=[spo_policy, cp.Hold()], parallel=False)
7 results[0].summary()
~/Desktop/cvxportfolio-master/cvxportfolio/simulator.py in run_multiple_backtest(self, initial_portf, start_time, end_time, policies, loglevel, parallel)
154 return results
155 else:
--> 156 return list(map(_run_backtest, policies))
157
158 def what_if(self, time, results, alt_policies, parallel=True):
~/Desktop/cvxportfolio-master/cvxportfolio/simulator.py in _run_backtest(policy)
145 def _run_backtest(policy):
146 return self.run_backtest(initial_portf, start_time, end_time,
--> 147 policy, loglevel=loglevel)
148
149 num_workers = min(multiprocess.cpu_count(), len(policies))
~/Desktop/cvxportfolio-master/cvxportfolio/simulator.py in run_backtest(self, initial_portfolio, start_time, end_time, policy, loglevel)
114 start = time.time()
115 try:
--> 116 u = policy.get_trades(h, t)
117 except cvx.SolverError:
118 logging.warning(
~/Desktop/cvxportfolio-master/cvxportfolio/policies.py in get_trades(self, portfolio, t)
264
265 for cost in self.costs:
--> 266 cost_expr, const_expr = cost.weight_expr(t, wplus, z, value)
267 costs.append(cost_expr)
268 constraints += const_expr
~/Desktop/cvxportfolio-master/cvxportfolio/risks.py in weight_expr(self, t, w_plus, z, value)
56
57 def weight_expr(self, t, w_plus, z, value):
---> 58 self.expression = self._estimate(t, w_plus - self.w_bench, z, value)
59 return self.gamma * self.expression, []
60
~/Desktop/cvxportfolio-master/cvxportfolio/risks.py in _estimate(self, t, wplus, z, value)
103 try:
104 self.expression = cvx.quad_form(
--> 105 wplus, values_in_time(self.Sigma, t))
106 except TypeError:
107 self.expression = cvx.quad_form(
~/anaconda3/envs/quantopt/lib/python3.7/site-packages/cvxpy/atoms/quad_form.py in quad_form(x, P)
213 # Check dimensions.
214 if not P.ndim == 2 or P.shape[0] != P.shape[1] or max(x.shape, (1,))[0] != P.shape[0]:
--> 215 raise Exception("Invalid dimensions for arguments.")
216 if x.is_constant():
217 return x.H * P * x
Exception: Invalid dimensions for arguments.
I get this error when I try with the parallel=False.
I also tried to backtest each of the policies individually and cp.Hold() is fine but spo_policy fails with the same error as above.
Use an interactive debugger and set a breakpoint before
self.expression = cvx.quad_form(
--> 105 wplus, values_in_time(self.Sigma, t))
Using the interactive debugger, check the shape of wplus
and whatever values_in_time(self.Sigma, t)
is, and make sure it conforms to the input requirements of cvx.quad_form
. The error message is telling you that the shapes don't conform, and you're going to have to trace backwards why that is the case. The error message lumps all non-conforming shapes into one error message, so you could instead set a breakpoint where the error message is thrown and figure out which condition is being violated.
Problems like these can be avoided by cvxportfolio
being more explicit about the required shapes and dimensions when constructing/initializing objects. Usually these problems are caused by including or not including cash in the dataframes. On the other hand, it isn't difficult to figure out the shape requirements if you use an interactive debugger.
These shape problems have no dependence on the OS one uses, nor does it have anything to do with multiprocessing, it's purely the shapes of the dataframes.
I ran into this as well.
As per my previous comment, we now we know this isn't a multiprocessor issue but the shape/dimension issue (multiprocessor on makes it difficult to debug IMHO).
If you are using the FactorModelSigma or RobustFactorModelSigma, there are some transposes in the that caused these issues. I'm away from my other computer with cvxportfolio at the moment but will offer some suggestions later this week. As Jose mentions, because there is little clarity on the shapes/types of objections expected by cvxportfolio it only adds to the confusion trying to sort this out.
In a side note, I've noticed 0.0.12 has odd behaviours. The DollarNeutral fails for me (e.g., https://github.com/cvxgrp/cvxportfolio/issues/21), passing a dataframe or series to w_bench for a long only run with a benchmark doesn't work, etc.
I really like the potential of this tool but I suspect cvxportfolio needs a much larger overhaul.
The simplest way to correct the shape requirements is to improve the docstrings for all the methods and classes. Right now the docstrings are very sparse, and provide no guidance on the shapes of the input data for constructors of risks, costs, forecasts, etc.