# Linear Programming in Python using PuLP – Part 3: Optimizing Investment Portfolios with Multi-Objective Optimization

In the previous article, we introduced the concepts of linear programming and multi-objective optimization and showed how to solve a problem using the Pulp library in Python. In this follow-up article, we will apply these concepts to a finance domain problem. We will demonstrate how to use linear programming to find the optimal investment portfolio and balance multiple objectives, such as maximizing returns and minimizing risk.

Investment portfolios are an important tool for managing risk and maximizing returns. However, finding the optimal portfolio can be a complex task, especially when multiple objectives are involved. In this article, we will show how linear programming can be used to find the optimal portfolio that balances multiple objectives and provides the best possible returns while minimizing risk.

We will start by defining the problem and the variables, constraints, and objectives that need to be considered. Then, we will demonstrate how to use the Pulp library in Python to solve the problem and find the optimal investment portfolio. We will conclude by discussing the results and the implications of the solution for investors. Whether you’re an experienced investor or just starting out, this article will provide valuable insights into the world of linear programming and multi-objective optimization.

### Defining the Problem

In this article, we will consider a problem of finding the optimal investment portfolio that balances multiple objectives, such as maximizing returns and minimizing risk. The problem can be formulated as follows:

• Objective 1: Maximize the expected return on investment
• Objective 2: Minimize the risk of the portfolio
• Constraint 1: The portfolio must be fully invested (i.e., the sum of the investment amounts for all assets must equal 1)
• Constraint 2: The investment in each asset must be non-negative

Given the above objectives and constraints, we will use linear programming and the Pulp library in Python to find the optimal investment portfolio that balances the trade-off between maximizing returns and minimizing risk.

## Problem Formulation

In this problem, we are trying to find the optimal investment portfolio that balances the trade-off between maximizing returns and minimizing risk. The problem can be formulated mathematically as follows:

Let `x_i` be the fraction of the investment portfolio invested in asset `i`, where `i = 1, 2, ..., n` and `n` is the number of assets in the portfolio.

The expected return on investment for each asset `i` is given by `r_i`, and the risk of the portfolio is given by the standard deviation `s`.

The problem can be formulated as the following linear programming problem:

Where `σ_i` is the standard deviation of asset `i`.

### How To: Solve the Problem

Here are the steps that we need to follow to solve the problem.

#### Code: Solving the Problem

In this section, we will use the Pulp library in Python to solve the optimization problem we defined in the previous section. We will follow the steps outlined in the previous section to define variables, add constraints, define objectives, and solve the problem.

Here’s the code to solve the problem:

``````from pulp import *

# Define the number of assets in the portfolio
n = 4

# Define the expected return and standard deviation for each asset
returns = [0.1, 0.2, 0.15, 0.3]
deviations = [0.15, 0.2, 0.1, 0.3]

# Create two new LpProblem objects, one for maximizing the return and one for minimizing the risk
return_problem = LpProblem("Maximize Return", LpMaximize)
risk_problem = LpProblem("Minimize Risk", LpMinimize)

# Define variables using the LpVariable class, one for each asset in the portfolio
x = [LpVariable(f"x{i}", 0, 1) for i in range(n)]

# Add constraints to both problems, ensuring that the portfolio is fully invested and the investment in each asset is non-negative
return_problem += sum(x) == 1
risk_problem += sum(x) == 1

for i in range(n):
return_problem += x[i] >= 0
risk_problem += x[i] >= 0

# Define the objectives for both problems, maximizing the expected return and minimizing the risk
return_problem += sum([x[i] * returns[i] for i in range(n)])
risk_problem += sum([x[i] * deviations[i] for i in range(n)])

# Solve both problems using the solve method of the LpProblem class
return_problem.solve()
risk_problem.solve()

# Print the results, including the fraction of the portfolio invested in each asset and the expected return and standard deviation of the portfolio
print("--- Results ---")
print("Maximize Return:")
for i in range(n):
print(f"Asset {i}: {x[i].value()}")
print(f"Expected Return: {value(return_problem.objective)}")

print("Minimize Risk:")
for i in range(n):
print(f"Asset {i}: {x[i].value()}")
print(f"Standard Deviation: {value(risk_problem.objective)}")
``````

In the above code, we first defined the number of assets in the portfolio and the expected return and standard deviation for each asset. Then, we created two `LpProblem` objects, one for maximizing the return and one for minimizing the risk. We defined variables using the `LpVariable` class and added constraints to both problems to ensure that the portfolio is fully invested and the investment in each asset is non-negative. Finally, we defined the objectives for both problems, maximizing the expected return and minimizing the risk, and solved both problems using the `solve` method of the `LpProblem` class. The results, including the fraction of the portfolio invested in each asset and the expected return and standard deviation of the portfolio, were printed at the end.

#### Understanding the Code

The code to solve the optimization problem uses the Pulp library in Python, which provides an easy-to-use interface for defining and solving linear programming problems.

In the code, we first imported the Pulp library using the following line:

``````from pulp import *
``````

Next, we defined the number of assets in the portfolio and the expected return and standard deviation for each asset:

``````# Define the number of assets in the portfolio
n = 4

# Define the expected return and standard deviation for each asset
returns = [0.1, 0.2, 0.15, 0.3]
deviations = [0.15, 0.2, 0.1, 0.3]
``````

Then, we created two `LpProblem` objects, one for maximizing the return and one for minimizing the risk:

``````# Create two new LpProblem objects, one for maximizing the return and one for minimizing the risk
return_problem = LpProblem("Maximize Return", LpMaximize)
risk_problem = LpProblem("Minimize Risk", LpMinimize)
``````

The `LpProblem` class is the main class in the Pulp library and is used to define a linear programming problem. The first argument to the `LpProblem` class is a name for the problem, and the second argument is the optimization direction, either `LpMaximize` for maximizing the objective function or `LpMinimize` for minimizing the objective function.

Next, we defined variables using the `LpVariable` class, one for each asset in the portfolio:

``````# Define variables using the LpVariable class, one for each asset in the portfolio
x = [LpVariable(f"x{i}", 0, 1) for i in range(n)]
``````

The `LpVariable` class is used to define variables in a linear programming problem. The first argument to the `LpVariable` class is a name for the variable, and the second and third arguments are the lower and upper bounds for the variable, respectively. In this case, we defined `x_i` as a variable between 0 and 1, representing the fraction of the portfolio invested in asset `i`.

Next, we added constraints to both problems, ensuring that the portfolio is fully invested and the investment in each asset is non-negative:

``````# Add constraints to both problems, ensuring that the portfolio is fully invested and the investment in each asset is non-negative
return_problem += sum(x) == 1
risk_problem += sum(x) == 1

for i in range(n):
return_problem += x[i] >= 0
risk_problem += x[i] >= 0
``````

The `+=` operator is used to add constraints to the `LpProblem` objects. The first constraint ensures that the sum of the investments in all assets is equal to 1, representing a fully invested portfolio. The second set of constraints ensures that the investment in each asset is non-negative.

Next, we defined the objectives for both problems, maximizing the expected return and minimizing the risk:

``````# Define the objectives for both problems, maximizing the expected return and minimizing the risk
return_problem += sum([x[i] * returns[i] for i in range (n)])
risk_problem += sum([x[i] * deviations[i] for i in range(n)])

``````

The objectives for both problems were defined using the `+=` operator and the `sum` function. The first objective maximizes the expected return, which is the sum of the products of the fraction of the portfolio invested in each asset and the expected return of that asset. The second objective minimizes the risk, which is the sum of the products of the fraction of the portfolio invested in each asset and the standard deviation of that asset.

Finally, we solved both problems using the `solve` method of the `LpProblem` class:

``````# Solve both problems using the solve method of the LpProblem class
return_problem.solve()
risk_problem.solve()
``````

The `solve` method solves the linear programming problem and returns the optimal solution.

At the end, we printed the results, including the fraction of the portfolio invested in each asset and the expected return and standard deviation of the portfolio:

``````# Print the results, including the fraction of the portfolio invested in each asset and the expected return and standard deviation of the portfolio
print("--- Results ---")
print("Maximize Return:")
for i in range(n):
print(f"Asset {i}: {x[i].value()}")
print(f"Expected Return: {value(return_problem.objective)}")

print("Minimize Risk:")
for i in range(n):
print(f"Asset {i}: {x[i].value()}")
print(f"Standard Deviation: {value(risk_problem.objective)}")
``````

In this section, we used the Pulp library in Python to solve a linear programming problem to find the optimal investment portfolio that balances the trade-off between maximizing returns and minimizing risk. The code defines variables, adds constraints, defines objectives, and solves the problem to find the optimal solution.

This series of articles has covered different optimization problems and the use of the Pulp library in Python to solve them. To conclude this series, we will solve an optimization problem related to logistics with more than 10 variables and 4 objectives and several constraints. This will provide an opportunity to demonstrate the versatility of the Pulp library and its ability to solve complex optimization problems. Stay tuned!

## One response to “Linear Programming in Python using PuLP – Part 3: Optimizing Investment Portfolios with Multi-Objective Optimization”

1. […] the previous article we saw an advanced problem for linear programming related to finance […]

Other posts