CVXPY ポートフォリオ最適化
次のようなポートフォリオ最適化問題を考えてみましょう。
ポートフォリオ最適化問題
あなたは、以下の3つの資産に投資するポートフォリオを構築しようとしています:
- Stock_A
- Stock_B
- 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$(100%)でなければならない。
- 各資産への投資割合は$0$以上でなければならない(空売りはしない)。
- ポートフォリオの期待リターンは少なくとも9%でなければならない。
目的
上記の制約条件を満たしながら、ポートフォリオのリスク(分散)を最小化する投資割合を求めなさい。
ソースコード
2次計画法(Quadratic Programming, QP)を用いて上記の問題を解きます。
以下は、cvxpy
を用いたポートフォリオ最適化のコード例です:
1 | import cvxpy as cp |
このコードは、cvxpy
を用いて2次計画法を解き、ポートフォリオの最適な投資割合とリスクを求めます。
ソースコード解説
このソースコードは、ポートフォリオ最適化問題を解くために、Pythonの数理最適化ライブラリであるcvxpy
を使用しています。
ソースコードを詳しく説明します。
1. 必要なライブラリのインポート
1 | import cvxpy as cp |
最初に、数理最適化を行うためのcvxpy
ライブラリと、数値計算を行うためのnumpy
ライブラリをインポートします。
2. 投資可能な資産のリスト
1 | assets = ['Stock_A', 'Stock_B', 'Bond_C'] |
ここでは、投資対象となる資産のリストを定義しています。
今回は、3つの資産(Stock_A
, Stock_B
, Bond_C
)に投資します。
3. 予想リターンとリスク(分散)の定義
1 | returns = np.array([0.12, 0.10, 0.06]) |
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 | constraints = [ |
ここでは、最適化問題の制約条件を定義しています。
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 | print("Status:", prob.status) |
最後に、最適化結果を表示します。
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%$以上となり、かつリスク(分散)が最小化されます。
したがって、この結果を基に投資を行うことで、目標リターンを達成しつつ、リスクを最小限に抑えたポートフォリオを構築することができます。