Second-Order Cone Programming (SOCP) Example Using CVXPY

Second-Order Cone Programming (SOCP) Example Using CVXPY

Problem: Portfolio Optimization with Transaction Costs

In portfolio optimization, we aim to allocate a given budget across various assets to maximize returns while controlling for risk.

In this example, we will add transaction costs (e.g., costs incurred when buying and selling assets) to the optimization problem.
This problem is naturally modeled as a Second-Order Cone Programming (SOCP) problem.

Problem Setup:

  • Variables:

    • $( x_i )$: The amount invested in asset $( i )$.
    • $( r_i )$: The expected return for asset $( i )$.
    • $( \Sigma )$: The covariance matrix representing the risk between the assets.
  • Objective:
    Maximize the expected return while controlling for risk (measured as portfolio variance) and including transaction costs.

  • Formulation:
    $$
    \text{Maximize} \quad r^T x - \gamma \cdot \sqrt{x^T \Sigma x} - \lambda \cdot \sum_i |x_i - x_i^0|
    $$
    where:

    • $( r^T x )$ is the expected return,
    • $( \gamma )$ is the risk aversion parameter,
    • $( \sqrt{x^T \Sigma x} )$ is the portfolio variance (risk),
    • $( \lambda )$ is the transaction cost parameter,
    • $( |x_i - x_i^0| )$ is the absolute change in position (transaction cost), where $( x_i^0 )$ represents the initial positions.
  • Constraints:

    1. Total investment must equal the available budget.
    2. The portfolio must stay within certain bounds for each asset.

SOCP Formulation:

We can represent this optimization problem using SOCP constraints by rewriting the risk term $( \sqrt{x^T \Sigma x} )$ as a second-order cone constraint.

Code Implementation Using CVXPY

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import cvxpy as cp
import numpy as np

# Data for the problem
n = 5 # Number of assets
np.random.seed(0)

# Expected returns for each asset
r = np.random.rand(n)

# Covariance matrix (symmetric positive semidefinite)
Sigma = np.random.randn(n, n)
Sigma = Sigma.T @ Sigma # Make the covariance matrix positive semi-definite

# Initial positions (already held assets)
x0 = np.random.rand(n)

# Parameters
gamma = 0.1 # Risk aversion parameter
lambda_ = 0.05 # Transaction cost parameter
budget = 1 # Total budget

# Decision variable: investment in each asset
x = cp.Variable(n)

# Objective: maximize expected return - risk - transaction costs
# Risk term: sqrt(x.T * Sigma * x) is modeled as second-order cone
risk = cp.quad_form(x, Sigma) # Quadratic form for risk (x.T @ Sigma @ x)
transaction_costs = cp.norm1(x - x0) # l1 norm for transaction costs

# Maximize expected return minus risk and transaction costs
objective = cp.Maximize(r.T @ x - gamma * cp.norm(risk, 2) - lambda_ * transaction_costs)

# Constraints
constraints = [
cp.sum(x) == budget, # Total investment must equal budget
x >= 0, # No short-selling (no negative positions)
x <= 1 # No asset can take more than 100% of the budget
]

# Define and solve the problem
problem = cp.Problem(objective, constraints)
problem.solve()

# Results
print("Status:", problem.status)
print("Optimal Portfolio:", x.value)
print("Optimal Value:", problem.value)

Explanation of the Code:

  1. Data:

    • r: A vector of expected returns for each asset.
    • Sigma: The covariance matrix representing the risk between assets.
    • x0: The initial asset positions before the optimization.
  2. Objective:

    • The objective is to maximize the expected return, minus the risk (modeled as a second-order cone) and transaction costs (modeled as the $( l_1 )$-norm of the change in positions).
    • cp.quad_form(x, Sigma) represents the quadratic risk term, $( x^T \Sigma x )$.
    • The $( l_1 )$-norm of x - x0 captures the absolute transaction costs.
  3. Constraints:

    • The sum of the asset allocations must equal the available budget.
    • We enforce non-negative asset allocations (no short-selling) and limit the allocation to a maximum of $100$% per asset.
  4. SOCP Structure:

    • The risk term involves a second-order cone constraint because of the quadratic term $( \sqrt{x^T \Sigma x} )$, which $CVXPY$ automatically handles as an SOCP.

Output Example:

1
2
3
4
Status: optimal
Optimal Portfolio: [4.39530365e-01 3.32443990e-01 5.68332295e-10 2.28025644e-01
1.65363907e-10]
Optimal Value: 0.49075615889954766

In this output:

  • The Optimal Portfolio gives the asset allocation that maximizes the return while minimizing risk and transaction costs.
  • The Optimal Value represents the objective value at the solution.

Conclusion:

This example demonstrates how to solve a portfolio optimization problem with transaction costs using Second-Order Cone Programming (SOCP) in $CVXPY$.

SOCP allows us to model the risk term (which involves a quadratic form) as a second-order cone, and $CVXPY$ simplifies the solution process.

This approach is particularly useful for finance problems where risk and transaction costs need to be balanced.