Otimização Matemática na elaboração de Portfólios: Um exemplo prático com programação linear
A criação de portfólios considerados ótimos é fundamental no mercado financeiro para investidores que desejam maximizar seus retornos ao mesmo tempo em que minimizam os riscos.
Nesse contexto, a otimização matemática, especialmente com o uso de técnicas como a programação linear, fornece as ferramentas necessárias para alcançar esse objetivo.
Neste artigo, vou explorar com vocês um exemplo hipotético de alocação de ativos utilizando programação linear, com o objetivo de construir um portfólio otimizado.
O que é otimização Matemática?
Otimização matemática é o processo de encontrar a melhor solução para um problema dado conjunto de restrições. No contexto de porfólios de investimentos, o objetivo é maximizar o retorno esperado ou minimizar o risco, considerando restrições como limites de alocação em certos ativos, requisitos de liquidez, ou preferências de risco.
Programação Linear: A base para Portfólios Ótimos
A programação linear é uma técnica de otimização em que tanto a função objetivo quanto as restrições são lineares. Uma das aplicações mais comuns na gestão de portfólios é o modelo de Markowitz, que busca minimizar o risco (medido pela variância dos retornos) para um determinado nível de retorno esperado. No entanto, para simplificar e ilustrar o conceito, utilizaremos um exemplo básico de programação linear para maximizar o retorno de um portfólio, sujeito a restrições de alocação.
Exemplo prático: Maximização do retorno com programação linear
Suponha que temos um porfólio composto por três ativos financeiros: A, B e C. Queremos determinar a proporção do capital a ser investido em cada ativo para maximizar o retorno esperado, dado que:
Vamos definir as variáveis de decisão:
A função objetivo que desejamos maximizar é o retorno total esperado:
Recomendados pelo LinkedIn
Maximizar Z = 0.05*xA+0.07*xB+0.04*xC
Sujeito às seguintes restrições:
Resolvendo o Problema com Python
Usaremos a biblioteca `PuLP` em Python para resolver o problema de otimização linear:
import pulp
# Definindo o problema
prob = pulp.LpProblem("Maximizar_Retorno", pulp.LpMaximize)
# Variáveis de decisão
x_A = pulp.LpVariable('x_A', lowBound=0, upBound=1)
x_B = pulp.LpVariable('x_B', lowBound=0, upBound=1)
x_C = pulp.LpVariable('x_C', lowBound=0, upBound=1)
# Função objetivo
prob += 0.05 * x_A + 0.07 * x_B + 0.04 * x_C, "Retorno_esperado"
# Restrições
prob += x_A <= 0.7, "Restricao_A_max_70%"
prob += x_B <= 0.7, "Restricao_B_max_70%"
prob += x_C <= 0.7, "Restricao_C_max_70%"
prob += x_A >= 0.1, "Restricao_A_min_10%"
prob += x_B >= 0.1, "Restricao_B_min_10%"
prob += x_C >= 0.1, "Restricao_C_min_10%"
prob += x_A + x_B >= 0.6, "Restricao_AB_min_60%"
prob += x_A + x_B + x_C == 1, "Restricao_Total"
# Resolvendo o problema
prob.solve()
# Resultados
print(f"Status: {pulp.LpStatus[prob.status]}")
print(f"Proporção investida em A: {x_A.varValue * 100:.2f}%")
print(f"Proporção investida em B: {x_B.varValue * 100:.2f}%")
print(f"Proporção investida em C: {x_C.varValue * 100:.2f}%")
print(f"Retorno esperado do portfólio: {pulp.value(prob.objective) * 100:.2f}%")
Com isso temos o seguinte resultado:
Status: Optimal Proporção investida em A: 20.00%
Proporção investida em B: 70.00%
Proporção investida em C: 10.00%
Retorno esperado do portfólio: 6.30%
Essa solução nos diz o seguinte:
Retorno esperado do portfólio: 6.30%: Este é o retorno máximo possível dentro das restrições impostas, representando um bom equilíbrio entre o retorno e adivesificação.
Agora, vamos escrever o gráfico para exibir as soluções:
import numpy as np
import matplotlib.pyplot as plt
# Criando os valores para x (proporção investida em A) e y (proporção investida em B)
x = np.linspace(0, 1, 400)
y1 = 0.7 # Restrição de A, B, C <= 70%
y2 = 0.6 - x # Restrição de A + B >= 60%
y3 = (x + 0.1) # Restrição de B >= 10%
y3[y3 > 1] = np.nan # Limitar B a valores <= 1
# Área de solução viável
plt.figure(figsize=(10, 8))
plt.fill_between(x, 0, np.minimum(np.minimum(y1, y2), y3), where=(y2 >= 0) & (y3 >= 0), color='gray', alpha=0.3)
# Linhas de restrição
plt.plot(x, [y1]*len(x), color='b', label='A, B, C <= 70%')
plt.plot(x, y2, color='g', label='A + B >= 60%')
plt.plot(x, y3, color='r', label='B >= 10%')
# Curvas de nível para a função objetivo
X, Y = np.meshgrid(x, x)
Z = 0.05 * X + 0.07 * Y + 0.04 * (1 - X - Y)
plt.contour(X, Y, Z, 50, alpha=0.5, cmap='jet')
# Eixos e limites
plt.xlim(0, 1)
plt.ylim(0, 1)
plt.xlabel('Proporção investida em A')
plt.ylabel('Proporção investida em B')
# Mostrar gráfico
plt.legend()
plt.title('Região Viável e Função Objetivo para o Portfólio Ótimo')
plt.show()
O resultado deste código pode ser visto a seguir:
Na figura, as áreas coloridas representam as regiões onde cada restrição é satisfeita. A interseção dessas áreas define a região viável, dentro da qual o portfólio ótimo se encontra. As curvas diagonais representam as linhas de contorno da função objetivo, que indicam o retorno esperado. O ponto onde essas curvas tocam a fronteira da região viável é a solução ótima encontrada.
Conclusão
A otimização matemática, quando aplicada à construção de porfólios, permite uma alocação eficiente de recursos, alinhada às metas de retorno e controle de risco dos investidores. Adicionando restrições que promovam a diversificação, como vimos neste exemplo, é possível evitar a concentração de capital em um único ativo, criando portfólios que não apenas maximizam o retorno, mas também atendem a requisitos especfíficos de diversificação.