Why Sharpe Ratio Optimization with Integer Futures Positions Fails DCP
Summary
The document presents a portfolio optimization problem involving integer long or short futures positions, transaction costs, expected returns, covariance, position bounds, and a target volatility range. The proposed objective subtracts transaction costs from expected portfolio return and divides that result by portfolio risk. CVXPY reports a DCPError because the objective is a ratio of expressions involving decision variables, including a quadratic risk expression; the shown formulation therefore does not satisfy disciplined convex programming rules.
The post asks how to address the error but contains no resolution or demonstrated alternative. It is useful as an example of the modeling challenge, not as a validated optimization recipe. The formulation also calls a quadratic-form variance term “risk” while constraining it against a target described as standard deviation, so the units and risk definition should be checked. Integer decision variables further limit the applicability of standard convex reformulations, and the document gives no solver results or evidence that the proposed Sharpe maximization is feasible.
Key ideas
- The example maximizes expected return after transaction costs divided by a quadratic risk expression.
- CVXPY rejects the objective because its variable-dependent ratio does not meet DCP rules.
- Futures contract counts are modeled as integer variables that may be positive or negative.
- The formulation should clarify whether its quadratic risk term is variance or standard deviation.
- The post does not provide a working reformulation or empirical optimization results.
Tags
Full text
# Portfolio optimization with Python/CVXPY: DCPError
# Portfolio optimization with Python/CVXPY: DCPError
I'm trying to implement a script for portfolio optimization on a sample universe of 3 future contracts.
I have the following inputs:
- current allocation --> number of contracts currently held for each of the 3 futures
- contracts_size --> the size (in USD) of each of the 3 futures
- ptf_size --> the USD size of my portfolio
- trans_costs_per_contract --> the USD transaction costs per contract traded for each of the 3 futures
- exp_return --> expected return for each of the 3 futures
- covar_matrix --> 3x3 covariance matrix
- ptf_target_vol --> the target standard deviation of the portfolio
- min_contracts / max_contracts --> the min/max number of contracts I want to held for each future
I need to find the number of futures contracts to held (contracts_number) that maximize the after costs sharpe ratio. Since we are dealing with futures, the number of contracts must be integer and can be either positive or negative.
I tried this script:
```
contracts_number = cp.Variable(3, integer=True)
dollar_exposure = cp.multiply(contracts_number, contracts_size)
percent_weights = dollar_exposure / ptf_size
delta_contracts = cp.abs (contracts_number - current_allocation)
perc_trans_costs = (delta_contracts @ trans_costs_per_contract) / ptf_size
ptf_exp_return = (percent_weights @ exp_return) - perc_trans_costs
ptf_risk = cp.quad_form(percent_weights , covar_matrix)
exp_sharpe = ptf_exp_return / ptf_risk
constraints = [min_contracts <= contracts_number, contracts_number <= max_contracts, ptf_risk<= (ptf_target_vol+0.002), ptf_risk>= (ptf_target_vol-0.002)]
prob = cp.Problem(cp.Maximize(exp_sharpe), constraints)
prob.solve(solver="CPLEX", verbose=True, cplex_params={"timelimit": 180})
```
but I get the following error:
```
DCPError: Problem does not follow DCP rules. Specifically:
The objective is not DCP. Its following subexpressions are not:
((var64 @ [61628.06739 84486.713 6960.371795] / Promote(100, (3,))) @ [0.08751445 0.10975094 0.09182673] + -abs(var64 + -[0. 0. 0.]) @ [1.5 1.5 1.5] / 100) / QuadForm(var64 @ [61628.06739 84486.713 6960.371795] / Promote(100, (3,)), [[0.06792497 0.01680063 0.01909388]
[0.01680063 0.10450343 0.02311845]
[0.01909388 0.02311845 0.12322165]])
```
Any idea? ThanksShown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.