CVXPY ポートフォリオ最適化

CVXPY ポートフォリオ最適化

次のようなポートフォリオ最適化問題を考えてみましょう。


ポートフォリオ最適化問題

あなたは、以下の3つの資産に投資するポートフォリオを構築しようとしています:

  1. Stock_A
  2. Stock_B
  3. Bond_C

それぞれの資産の予想リターンリスク(分散)は次の通りです:

  • Stock_A: リターン = $12%$、リスク(分散) = $0.04$
  • Stock_B: リターン = $10%$、リスク(分散) = $0.03$
  • Bond_C: リターン = $6%$、リスク(分散) = $0.01$

また、各資産間の共分散は以下のようになっています:

Stock_A Stock_B Bond_C
Stock_A 0.04 0.01 0.00
Stock_B 0.01 0.03 0.01
Bond_C 0.00 0.01 0.01

あなたの目標は、全体のリスクを最小限に抑えつつ、ポートフォリオの期待リターンが少なくとも9%となるように投資割合を決定することです。

制約条件

  1. 各資産への投資割合の合計は$1$(100%)でなければならない。
  2. 各資産への投資割合は$0$以上でなければならない(空売りはしない)。
  3. ポートフォリオの期待リターンは少なくとも9%でなければならない。

目的

上記の制約条件を満たしながら、ポートフォリオのリスク(分散)を最小化する投資割合を求めなさい。

ソースコード

2次計画法(Quadratic Programming, QP)を用いて上記の問題を解きます。

以下は、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
import cvxpy as cp
import numpy as np

# 投資可能な資産のリスト
assets = ['Stock_A', 'Stock_B', 'Bond_C']

# 予想リターンとリスク(分散)
returns = np.array([0.12, 0.10, 0.06])
risks = np.array([0.04, 0.03, 0.01])
covariance = np.array([
[0.04, 0.01, 0.00],
[0.01, 0.03, 0.01],
[0.00, 0.01, 0.01]
])

# 変数の定義
weights = cp.Variable(len(assets))

# リスク(分散)の計算
risk = cp.quad_form(weights, covariance)

# 制約条件の定義
constraints = [
cp.sum(weights) == 1,
weights >= 0,
cp.sum(weights * returns) >= 0.09
]

# 目的関数の定義(リスクの最小化)
prob = cp.Problem(cp.Minimize(risk), constraints)

# 問題の解決
prob.solve()

# 結果の表示
print("Status:", prob.status)
print("Optimal Weights:", weights.value)
print("Total Risk (Variance):", risk.value)

このコードは、cvxpyを用いて2次計画法を解き、ポートフォリオの最適な投資割合リスクを求めます。

ソースコード解説

このソースコードは、ポートフォリオ最適化問題を解くために、Pythonの数理最適化ライブラリであるcvxpyを使用しています。

ソースコードを詳しく説明します。

1. 必要なライブラリのインポート

1
2
import cvxpy as cp
import numpy as np

最初に、数理最適化を行うためのcvxpyライブラリと、数値計算を行うためのnumpyライブラリをインポートします。

2. 投資可能な資産のリスト

1
assets = ['Stock_A', 'Stock_B', 'Bond_C']

ここでは、投資対象となる資産のリストを定義しています。

今回は、3つの資産(Stock_A, Stock_B, Bond_C)に投資します。

3. 予想リターンとリスク(分散)の定義

1
2
3
4
5
6
7
returns = np.array([0.12, 0.10, 0.06])
risks = np.array([0.04, 0.03, 0.01])
covariance = np.array([
[0.04, 0.01, 0.00],
[0.01, 0.03, 0.01],
[0.00, 0.01, 0.01]
])
  • returnsは各資産の予想リターンを表します。
  • risksは各資産のリスク(分散)を表します。
  • covarianceは各資産間の共分散行列を表します。
    共分散行列は、資産間のリスクの相関関係を示します。

4. 変数の定義

1
weights = cp.Variable(len(assets))

ここでは、各資産に対する投資割合を表す変数weightsを定義しています。
weightsは、3つの要素を持つベクトルです(各資産に対する投資割合を示すため)。

5. リスク(分散)の計算

1
risk = cp.quad_form(weights, covariance)

ここでは、ポートフォリオ全体のリスクを計算しています。
cp.quad_formは、二次形式を計算するための関数で、ポートフォリオのリスク(分散)を求めるのに使用されます。

6. 制約条件の定義

1
2
3
4
5
constraints = [
cp.sum(weights) == 1,
weights >= 0,
cp.sum(weights * returns) >= 0.09
]

ここでは、最適化問題の制約条件を定義しています。

  • cp.sum(weights) == 1:各資産の投資割合の合計は$1$(100%)でなければなりません。
  • weights >= 0:各資産の投資割合は$0$以上でなければなりません(空売りはしない)。
  • cp.sum(weights * returns) >= 0.09:ポートフォリオの期待リターンは少なくとも9%でなければなりません。

7. 目的関数の定義(リスクの最小化)

1
prob = cp.Problem(cp.Minimize(risk), constraints)

ここでは、最適化問題を定義しています。
目的関数はポートフォリオのリスク(分散)最小化することです。
また、制約条件もここで設定します。

8. 問題の解決

1
prob.solve()

この行では、定義された最適化問題を解決します。
prob.solve()は、最適化問題を解くための関数です。

9. 結果の表示

1
2
3
print("Status:", prob.status)
print("Optimal Weights:", weights.value)
print("Total Risk (Variance):", risk.value)

最後に、最適化結果を表示します。

  • prob.status:最適化問題の解決ステータス(成功かどうか)を表示します。
  • weights.value:各資産に対する最適な投資割合を表示します。
  • risk.value:最適な投資割合で得られるポートフォリオの総リスク(分散)を表示します。

全体の流れ

このコードは、ポートフォリオ最適化問題を定義し、投資割合を決定することで、リスクを最小化しながら目標リターンを達成するためのものです。

数理最適化ライブラリcvxpyを使用して、制約条件を満たしつつ、ポートフォリオのリスクを最小限に抑える最適な投資割合を計算します。

結果解説

[実行結果]

Status: optimal
Optimal Weights: [0.38461538 0.17307692 0.44230769]
Total Risk (Variance): 0.011634615384615387

上記の実行結果は、ポートフォリオ最適化問題を解いた際に得られた最適な解答を示しています。

以下にそれぞれの項目について説明します。

1. Status: optimal

この「optimal」というステータスは、最適化問題が解決されたことを示しています。

具体的には、全ての制約条件を満たしながら、リスク(分散)を最小限に抑える投資割合が見つかったことを意味します。

2. Optimal Weights: [0.38461538 0.17307692 0.44230769]

これは、各資産に対する最適な投資割合を示しています。
具体的には、以下の通りです:

  • Stock_A: 38.46%
  • Stock_B: 17.31%
  • Bond_C: 44.23%

これらの割合に基づいて投資することで、リスクを最小限に抑えつつ、目標リターン(少なくとも9%)を達成することができます。

3. Total Risk (Variance): 0.011634615384615387

これは、最適な投資割合で得られるポートフォリオの総リスク(分散)を示しています。
具体的には、$0.0116$という値になっています。
この値が小さいほど、ポートフォリオ全体のリスクが低いことを意味します。

結論

この最適化結果から、以下の点が確認できます:

  • 最適な投資割合は、Stock_Aに約$38.46%$、Stock_Bに約$17.31%$、Bond_Cに約$44.23%$です。
  • この投資割合により、ポートフォリオの期待リターンが$9%$以上となり、かつリスク(分散)が最小化されます。

したがって、この結果を基に投資を行うことで、目標リターンを達成しつつ、リスクを最小限に抑えたポートフォリオを構築することができます。