株式のポートフォリオ最適化 with MATLAB


## 目次
&emsp;[はじめに](#はじめに)
 
&emsp;[1. 事前情報](#1-事前情報)
 
&emsp;&emsp;[1.1 基本知識と基本理論を少しだけ](#1-1-基本知識と基本理論を少しだけ)
 
&emsp;&emsp;&emsp;[リターン (収益率)](#リターン-収益率-)
 
&emsp;&emsp;&emsp;[期待リターンとリスク](#期待リターンとリスク)
 
&emsp;&emsp;&emsp;[ポートフォリオのボラティリティ](#ポートフォリオのボラティリティ)
 
&emsp;&emsp;[1.2 株式のリターンデータ](#1-2-株式のリターンデータ)
 
&emsp;[2. 実践](#2-実践)
 
&emsp;&emsp;[2.1 資産の収益率 – リスク分布図を描く](#2-1-資産の収益率-リスク分布図を描く)
 
&emsp;&emsp;[2.2 現在のポートフォリオと資産の効率的フロンティアを描く](#2-2-現在のポートフォリオと資産の効率的フロンティアを描く)
 
&emsp;&emsp;&emsp;[効率的フロンティア](#効率的フロンティア)
 
&emsp;&emsp;[2.3 目標期待リターンを達成するポートフォリオを計算](#2-3-目標期待リターンを達成するポートフォリオを計算)
 
&emsp;&emsp;[2.4 シャープレシオ最大化するポートフォリオを計算](#2-4-シャープレシオ最大化するポートフォリオを計算)
 
&emsp;&emsp;&emsp;[ポートフォリオの確認](#ポートフォリオの確認)
 
&emsp;&emsp;&emsp;[シャープレシオの比較](#シャープレシオの比較)
 
<a name="endToc"></a>

# はじめに

NISA も世の中に浸透してきて、個人投資家として儲けたい！と思っている方も多いのでは？と思います。そんな方に朗報です。MATLAB を使えば簡単にポートフォリオ最適化を行えます。今回は皆さんの金融ライフをよりよくするために株式 (金融資産) のポートフォリオ最適化を行います。


ポートフォリオ最適化とは一般に、限られた資産でリスクを減らしてリターンを大きくする、もしくはシャープレシオを最大にするポートフォリオを持つことです。

# 1. 事前情報
## 1.1 基本知識と基本理論を少しだけ
### リターン (収益率)

金融資産 $X$ の時刻 $t$ における価格 $X_t$ とするとリターン $R$ とは

 $$ R=\frac{X_{t+1} -X_t }{X_t } $$ 

で与えられます。もしくは、金融工学でよく用いられるのは対数リターン

 $$ R=\log \frac{X_{t+1} }{X_t } $$ 

です。対数リターンを用いると変度の大きさや相対的な比較が容易になるため便利です。今回の計算では1つ目の定義を用います。

### 期待リターンとリスク

 $R$ は確率変数で 、

 $$ {\mathrm{E}}[R]=\mu ,~~{\mathrm{V}}[R]=\sigma^2 $$ 

をそれぞれ期待リターン (収益率) とボラティリティと言います。ボラティリティの平方根 ( $\sigma \ge 0$ ) がリスクです。

### ポートフォリオのボラティリティ

確率変数 $R_p =R_1 ,R_2 ,\ldots, R_n$ (様々な株式のリターン) の和 (ポートフォリオ) の分散は以下の様に示されるのは常識だと思いますが念のため ...

 $$ {\mathrm{V}}[R_1 +R_2 +\cdots +R_n ]=\sum_i {\mathrm{V}}[R_i ]+\sum_{i,j} 2\cdot {\mathrm{C}\mathrm{o}\mathrm{v}}(R_i ,R_j ) $$ 

第一項は正なので、第二項の共分散を負にすればこのポートフォリオのボラティリティを下げることが出来ます。これが "**卵は1つのかごに盛るな**" と言われる所以です。またリターンの動きに負の相関があるものをポートフォリオに持つと良いと言われる理由でもあります。


## 1.2 株式のリターンデータ

今回用いるデータは、次の MATLAB の例題に有るリターンのデータです：


[Construct a PortfolioCVaR Object and Determine Efficient Portfolios](https://www.mathworks.com/help/finance/portfolio.estimatefrontier.html#:~:text=Create%20a%20Portfolio%20Object%20and%20Determine%20Efficient%20Portfolios)

```matlab
load CAPMuniverse
Data = Data(:,1:12); % 時系列のリターンデータ R_t
assetList = Assets(1:12)'; % 株式の名前
AssetCovar = cov(Data,"omitrows"); % 分散共分散行列
head(array2table(Data,VariableNames=assetList))
```

```matlabTextOutput
      AAPL         AMZN         CSCO         DELL         EBAY       GOOG       HPQ          IBM         INTC         MSFT         ORCL         YHOO   
    _________    _________    _________    _________    _________    ____    _________    _________    _________    _________    _________    _________

     0.088805       0.1742     0.008775    -0.002353      0.12829    NaN       0.03244     0.075368      0.05698    -0.001627     0.054078     0.097784
    -0.084331     -0.08324     -0.05608     -0.08353    -0.093805    NaN     -0.075613    -0.033966    -0.046667    -0.033802      -0.0883    -0.067368
     0.014634     -0.14877    -0.003039     0.070984     0.066875    NaN     -0.006356      0.03516     0.008199     0.010567    -0.052837    -0.073363
    -0.086538    -0.060072    -0.016619    -0.038847    -0.012302    NaN     -0.063688    -0.017241     -0.05824    -0.033477    -0.058824     -0.10307
     0.047368     0.061013       0.0587    -0.037708    -0.000964    NaN      0.028416    -0.004386      0.04127     0.013091     0.076771      0.10609
    -0.017588    -0.005319     0.037215    -0.044598     0.055659    NaN      0.069221     0.039648     0.045732     0.007268      0.11976     0.070743
    -0.051151    -0.035265    -0.030143    -0.029912    -0.021511    NaN      -0.02251     0.008475     0.045948    -0.025657    -0.029201    -0.088703
    -0.059946     -0.04779    -0.025258    -0.023359    -0.063295    NaN      0.035096     0.004202     0.017393     -0.03255    -0.060069     -0.10021
```

アメリカの IT 銘柄が目白押しですね。


分散共分散行列を計算し、各資産の期待リターンとボラティリティの推定値を求めます

```matlab
prsk = sqrt(diag(AssetCovar)); % 各資産のボラティリティの推定値
pret = mean(Data,"omitmissing")'; % 各資産の期待リターンの推定値
varName = ["Initial Weight","New Weight","Buy (Long)","Sell (Short)"];
initPort=1/length(pret)*ones(length(pret),1); % 初期のポートフォリオ (全資産均等)
```

# 2. 実践
## 2.1 資産の収益率 – リスク分布図を描く

これは scatter プロットで一発です:

```matlab
scatter(prsk,pret,"filled"); % Scatter plot
text(prsk+0.0005,pret,assetList,FontSize=16); % 資産名
```

![figure_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473841/0e47b077-1c4a-8f6d-6af9-941eeca5a1eb.png)


## 2.2 現在のポートフォリオと資産の効率的フロンティアを描く

ポートフォリオオブジェクトを作成します。今回は簡単のため無リスク資産 (国債) を持つことは考えない制約を与えます。


plotFrontier 関数で効率的フロンティアを描きます。

```matlab
p = Portfolio(AssetList=assetList,InitPort=initPort);
p = estimateAssetMoments(p,Data,Missingdata=true);
p = setDefaultConstraints(p);
plotFrontier(p);
```

![figure_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473841/fb95fc75-3623-3dbd-8aba-b496bce9841e.png)


### 効率的フロンティア

効率的フロンティアとは、分散投資を実施したときに実現するポートフォリオの中で、あるリスクの水準で最大のリターンを獲得できるポートフォリオの集合のことです。この直線上以外のポートフォリオは効率的でない (もったいない) ポートフォリオです。


## 2.3 目標期待リターンを達成するポートフォリオを計算

この関数を実行すると、新しい Weight のみならず何を売って、何を買うまで分かります。

```matlab
targetRet = 2.5e-3; % 日利の目標期待リターン
[pwgt,pbuy,psell] = estimateFrontierByReturn(p,targetRet);
ptbl = table(initPort,pwgt,pbuy,psell,RowNames=assetList,VariableNames=varName);
% 結果を表示
disp(ptbl);
```

```matlabTextOutput
            Initial Weight    New Weight    Buy (Long)    Sell (Short)
            ______________    __________    __________    ____________

    AAPL       0.083333        0.099231      0.015898              0  
    AMZN       0.083333               0             0       0.083333  
    CSCO       0.083333               0             0       0.083333  
    DELL       0.083333               0             0       0.083333  
    EBAY       0.083333               0             0       0.083333  
    GOOG       0.083333         0.55927       0.47594              0  
    HPQ        0.083333        0.010431             0       0.072902  
    IBM        0.083333         0.25203       0.16869              0  
    INTC       0.083333               0             0       0.083333  
    MSFT       0.083333        0.079042             0      0.0042918  
    ORCL       0.083333               0             0       0.083333  
    YHOO       0.083333               0             0       0.083333  
```


## 2.4 シャープレシオ最大化するポートフォリオを計算

Sharpe Ratio 最大化するポートフォリオも簡単に計算できます:

```matlab
[swgt,sbuy,ssell] = estimateMaxSharpeRatio(p); % シャープレシオ最大化
srtbl = table(initPort,swgt,sbuy,ssell,RowNames=assetList,VariableNames=varName);
% 結果を表示
disp(srtbl);
```

```matlabTextOutput
            Initial Weight    New Weight    Buy (Long)    Sell (Short)
            ______________    __________    __________    ____________

    AAPL       0.083333         0.043936           0        0.039398  
    AMZN       0.083333       2.2643e-10           0        0.083333  
    CSCO       0.083333       3.6746e-11           0        0.083333  
    DELL       0.083333       9.1694e-11           0        0.083333  
    EBAY       0.083333       3.1209e-10           0        0.083333  
    GOOG       0.083333          0.95606     0.87273               0  
    HPQ        0.083333       1.5488e-10           0        0.083333  
    IBM        0.083333       3.9311e-11           0        0.083333  
    INTC       0.083333       2.5121e-10           0        0.083333  
    MSFT       0.083333       4.6462e-11           0        0.083333  
    ORCL       0.083333       4.3367e-11           0        0.083333  
    YHOO       0.083333       2.2901e-12           0        0.083333  
```

### ポートフォリオの確認
効率的フロンティアの上の方に位置しているのが分かります：
```matlab
p = setInitPort(p,swgt);  % ポートフォリオの設定
[~,~,h]= plotFrontier(p); % 効率的フロンティア描画
h(1).MarkerFaceColor = "r";
```

![figure_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473841/b4d9bb55-5231-37ae-6612-ab761525445d.png)


### シャープレシオの比較
```matlab
estimatePortSharpeRatio(p,initPort) % 初期のシャープレシオ
```

```matlabTextOutput
ans = 0.0295
```

```matlab
estimatePortSharpeRatio(p,swgt)     % ポートフォリオ最適化後
```

```matlabTextOutput
ans = 0.1240
```
シャープレシオが改善していますね！