ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

ポートフォリオの最適化 (Black Litterman 法)

この例では、Black Litterman 法を使用して、ポートフォリオの最適化を実行する MATLAB コードから MEX 関数と C のソースコードを生成する方法を説明します。

必要条件

この例には必要条件はありません。

新規フォルダーの作成と関連ファイルのコピー

以下のコードは、現在の作業フォルダー (pwd) 内にフォルダーを作成します。この新規フォルダーには、この例に関連するファイルのみが含められます。現在のフォルダーに影響を与えたくない (またはこのフォルダーにファイルを生成できない) 場合は、作業フォルダーを変更する必要があります。

コマンドの実行: 新規フォルダーの作成と関連ファイルのコピー

coderdemo_setup('coderdemo_portfolio_optimization');

関数 'hlblacklitterman' について

関数 hblblacklitterman.mhblblacklitterman.m は、ポートフォリオに関する財務情報を読み込み、Black Litterman 法を使用してポートフォリオの最適化を実行します。

type hlblacklitterman
function [er, ps, w, pw, lambda, theta] = hlblacklitterman(delta, weq, sigma, tau, P, Q, Omega)%#codegen
% hlblacklitterman
%   This function performs the Black-Litterman blending of the prior
%   and the views into a new posterior estimate of the returns as
%   described in the paper by He and Litterman.
% Inputs
%   delta  - Risk tolerance from the equilibrium portfolio
%   weq    - Weights of the assets in the equilibrium portfolio
%   sigma  - Prior covariance matrix
%   tau    - Coefficiet of uncertainty in the prior estimate of the mean (pi)
%   P      - Pick matrix for the view(s)
%   Q      - Vector of view returns
%   Omega  - Matrix of variance of the views (diagonal)
% Outputs
%   Er     - Posterior estimate of the mean returns
%   w      - Unconstrained weights computed given the Posterior estimates
%            of the mean and covariance of returns.
%   lambda - A measure of the impact of each view on the posterior estimates.
%   theta  - A measure of the share of the prior and sample information in the
%            posterior precision.

% Reverse optimize and back out the equilibrium returns
% This is formula (12) page 6.
pi = weq * sigma * delta;
% We use tau * sigma many places so just compute it once
ts = tau * sigma;
% Compute posterior estimate of the mean
% This is a simplified version of formula (8) on page 4.
er = pi' + ts * P' * inv(P * ts * P' + Omega) * (Q - P * pi');
% We can also do it the long way to illustrate that d1 + d2 = I
d = inv(inv(ts) + P' * inv(Omega) * P);
d1 = d * inv(ts);
d2 = d * P' * inv(Omega) * P;
er2 = d1 * pi' + d2 * pinv(P) * Q;
% Compute posterior estimate of the uncertainty in the mean
% This is a simplified and combined version of formulas (9) and (15)
ps = ts - ts * P' * inv(P * ts * P' + Omega) * P * ts;
posteriorSigma = sigma + ps;
% Compute the share of the posterior precision from prior and views,
% then for each individual view so we can compare it with lambda
theta=zeros(1,2+size(P,1));
theta(1,1) = (trace(inv(ts) * ps) / size(ts,1));
theta(1,2) = (trace(P'*inv(Omega)*P* ps) / size(ts,1));
for i=1:size(P,1)
    theta(1,2+i) = (trace(P(i,:)'*inv(Omega(i,i))*P(i,:)* ps) / size(ts,1));
end
% Compute posterior weights based solely on changed covariance
w = (er' * inv(delta * posteriorSigma))';
% Compute posterior weights based on uncertainty in mean and covariance
pw = (pi * inv(delta * posteriorSigma))';
% Compute lambda value
% We solve for lambda from formula (17) page 7, rather than formula (18)
% just because it is less to type, and we've already computed w*.
lambda = pinv(P)' * (w'*(1+tau) - weq)';
end

% Black-Litterman example code for MatLab (hlblacklitterman.m)
% Copyright (c) Jay Walters, blacklitterman.org, 2008.
%
% Redistribution and use in source and binary forms, 
% with or without modification, are permitted provided 
% that the following conditions are met:
%
% Redistributions of source code must retain the above 
% copyright notice, this list of conditions and the following 
% disclaimer.
% 
% Redistributions in binary form must reproduce the above 
% copyright notice, this list of conditions and the following 
% disclaimer in the documentation and/or other materials 
% provided with the distribution.
%  
% Neither the name of blacklitterman.org nor the names of its
% contributors may be used to endorse or promote products 
% derived from this software without specific prior written
% permission.
%  
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
% CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
% DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
% CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
% SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
% BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
% SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
% WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
% NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
% OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 
% DAMAGE.
%
% This program uses the examples from the paper "The Intuition 
% Behind Black-Litterman Model  Portfolios", by He and Litterman,
% 1999.  You can find a copy of this  paper at the following url.
%     http:%papers.ssrn.com/sol3/papers.cfm?abstract_id=334304
%
% For more details on the Black-Litterman model you can also view
% "The BlackLitterman Model: A Detailed Exploration", by this author
% at the following url.
%     http:%www.blacklitterman.org/Black-Litterman.pdf
%

%#codegen 命令は、当該の MATLAB コードがコード生成用であることを示します。

検定に使用する MEX 関数の生成

'codegen' コマンドを使って MEX 関数を生成します。

codegen hlblacklitterman -args {0, zeros(1, 7), zeros(7,7), 0, zeros(1, 7), 0, 0}

C コードを生成する前に、MATLAB で MEX 関数をテストして、その関数が元の MATLAB コードと機能的に等価であることと実行時エラーが発生しないことを確認しなければなりません。既定の設定では、'codegen' は現在のフォルダーの中に 'hlblacklitterman_mex' という名前の MEX 関数を生成します。これにより、MATLAB コードと MEX 関数をテストして結果を比較することができます。

MEX 関数の実行

生成された MEX 関数の呼び出し

testMex();
View 1
Country        P       mu      w*
Australia	     0	 4.328	 1.524
Canada   	     0	 7.576	 2.095
France   	 -29.5	 9.288	-3.948
Germany  	   100	 11.04	 35.41
Japan    	     0	 4.506	 11.05
UK       	 -70.5	 6.953	-9.462
USA      	     0	 8.069	 58.57
q        	     5
omega/tau	     0.0213
lambda   	     0.317
theta   	     0.0714
pr theta  	     0.929


View 1
Country        P       mu      w*
Australia	     0	 4.328	 1.524
Canada   	     0	 7.576	 2.095
France   	 -29.5	 9.288	-3.948
Germany  	   100	 11.04	 35.41
Japan    	     0	 4.506	 11.05
UK       	 -70.5	 6.953	-9.462
USA      	     0	 8.069	 58.57
q        	     5
omega/tau	     0.0213
lambda   	     0.317
theta   	     0.0714
pr theta  	     0.929

Execution Time - MATLAB function: 0.041607 seconds
Execution Time - MEX function   : 0.008954 seconds

C コードの生成

cfg = coder.config('lib');
codegen -config cfg hlblacklitterman  -args {0, zeros(1, 7), zeros(7,7), 0, zeros(1, 7), 0, 0}

'-config cfg' オプションを指定して 'codegen' を使用し、スタンドアロン C ライブラリを生成します。

生成されたコードの確認

既定の設定では、生成されたライブラリのコードはフォルダー codegen/lib/hbblacklitterman/ に保存されます。

ファイルは、以下のとおりです。

dir codegen/lib/hlblacklitterman/
.                              inv.c                          
..                             inv.h                          
buildInfo.mat                  inv.o                          
codeInfo.mat                   pinv.c                         
hlblacklitterman.a             pinv.h                         
hlblacklitterman.c             pinv.o                         
hlblacklitterman.h             rtGetInf.c                     
hlblacklitterman.o             rtGetInf.h                     
hlblacklitterman_initialize.c  rtGetInf.o                     
hlblacklitterman_initialize.h  rtGetNaN.c                     
hlblacklitterman_initialize.o  rtGetNaN.h                     
hlblacklitterman_ref.rsp       rtGetNaN.o                     
hlblacklitterman_rtw.mk        rt_nonfinite.c                 
hlblacklitterman_terminate.c   rt_nonfinite.h                 
hlblacklitterman_terminate.h   rt_nonfinite.o                 
hlblacklitterman_terminate.o   rtw_proj.tmw                   
hlblacklitterman_types.h       rtwtypes.h                     
interface                      

関数 'hlblacklitterman.c' の C コードの確認

type codegen/lib/hlblacklitterman/hlblacklitterman.c
/*
 * File: hlblacklitterman.c
 *
 * MATLAB Coder version            : 2.7
 * C/C++ source code generated on  : 21-Jul-2014 19:08:57
 */

/* Include Files */
#include "rt_nonfinite.h"
#include "hlblacklitterman.h"
#include "pinv.h"
#include "inv.h"

/* Function Definitions */

/*
 * hlblacklitterman
 *    This function performs the Black-Litterman blending of the prior
 *    and the views into a new posterior estimate of the returns as
 *    described in the paper by He and Litterman.
 *  Inputs
 *    delta  - Risk tolerance from the equilibrium portfolio
 *    weq    - Weights of the assets in the equilibrium portfolio
 *    sigma  - Prior covariance matrix
 *    tau    - Coefficiet of uncertainty in the prior estimate of the mean (pi)
 *    P      - Pick matrix for the view(s)
 *    Q      - Vector of view returns
 *    Omega  - Matrix of variance of the views (diagonal)
 *  Outputs
 *    Er     - Posterior estimate of the mean returns
 *    w      - Unconstrained weights computed given the Posterior estimates
 *             of the mean and covariance of returns.
 *    lambda - A measure of the impact of each view on the posterior estimates.
 *    theta  - A measure of the share of the prior and sample information in the
 *             posterior precision.
 * Arguments    : double delta
 *                const double weq[7]
 *                const double sigma[49]
 *                double tau
 *                const double P[7]
 *                double Q
 *                double Omega
 *                double er[7]
 *                double ps[49]
 *                double w[7]
 *                double pw[7]
 *                double *lambda
 *                double theta[3]
 * Return Type  : void
 */
void hlblacklitterman(double delta, const double weq[7], const double sigma[49],
                      double tau, const double P[7], double Q, double Omega,
                      double er[7], double ps[49], double w[7], double pw[7],
                      double *lambda, double theta[3])
{
  double b_weq[7];
  double pi[7];
  int i0;
  int i1;
  double ts[49];
  double b;
  double b_b;
  double b_ts[7];
  double unusedExpr[7];
  double c_ts[7];
  double d_ts[49];
  int i2;
  double posteriorSigma[49];
  double y[49];
  double x[49];

  /*  Reverse optimize and back out the equilibrium returns */
  /*  This is formula (12) page 6. */
  for (i0 = 0; i0 < 7; i0++) {
    b_weq[i0] = 0.0;
    for (i1 = 0; i1 < 7; i1++) {
      b_weq[i0] += weq[i1] * sigma[i1 + 7 * i0];
    }

    pi[i0] = b_weq[i0] * delta;
  }

  /*  We use tau * sigma many places so just compute it once */
  for (i0 = 0; i0 < 49; i0++) {
    ts[i0] = tau * sigma[i0];
  }

  /*  Compute posterior estimate of the mean */
  /*  This is a simplified version of formula (8) on page 4. */
  b = 0.0;
  for (i0 = 0; i0 < 7; i0++) {
    b_weq[i0] = 0.0;
    for (i1 = 0; i1 < 7; i1++) {
      b_weq[i0] += P[i1] * ts[i1 + 7 * i0];
    }

    b += b_weq[i0] * P[i0];
  }

  b_b = inv(b + Omega);
  b = 0.0;
  for (i0 = 0; i0 < 7; i0++) {
    b += P[i0] * pi[i0];
    b_ts[i0] = 0.0;
    for (i1 = 0; i1 < 7; i1++) {
      b_ts[i0] += ts[i0 + 7 * i1] * P[i1];
    }
  }

  b = Q - b;
  for (i0 = 0; i0 < 7; i0++) {
    er[i0] = pi[i0] + b_ts[i0] * b_b * b;
  }

  /*  We can also do it the long way to illustrate that d1 + d2 = I */
  pinv(P, unusedExpr);

  /*  Compute posterior estimate of the uncertainty in the mean */
  /*  This is a simplified and combined version of formulas (9) and (15) */
  b = 0.0;
  for (i0 = 0; i0 < 7; i0++) {
    b_weq[i0] = 0.0;
    for (i1 = 0; i1 < 7; i1++) {
      b_weq[i0] += P[i1] * ts[i1 + 7 * i0];
    }

    b += b_weq[i0] * P[i0];
    c_ts[i0] = 0.0;
    for (i1 = 0; i1 < 7; i1++) {
      c_ts[i0] += ts[i0 + 7 * i1] * P[i1];
    }
  }

  b_b = inv(b + Omega);
  for (i0 = 0; i0 < 7; i0++) {
    b_ts[i0] = c_ts[i0] * b_b;
    for (i1 = 0; i1 < 7; i1++) {
      d_ts[i0 + 7 * i1] = b_ts[i0] * P[i1];
    }
  }

  for (i0 = 0; i0 < 7; i0++) {
    for (i1 = 0; i1 < 7; i1++) {
      b = 0.0;
      for (i2 = 0; i2 < 7; i2++) {
        b += d_ts[i0 + 7 * i2] * ts[i2 + 7 * i1];
      }

      ps[i0 + 7 * i1] = ts[i0 + 7 * i1] - b;
    }
  }

  for (i0 = 0; i0 < 49; i0++) {
    posteriorSigma[i0] = sigma[i0] + ps[i0];
  }

  /*  Compute the share of the posterior precision from prior and views, */
  /*  then for each individual view so we can compare it with lambda */
  invNxN(ts, y);
  b = 0.0;
  for (i0 = 0; i0 < 7; i0++) {
    for (i1 = 0; i1 < 7; i1++) {
      x[i0 + 7 * i1] = 0.0;
      for (i2 = 0; i2 < 7; i2++) {
        x[i0 + 7 * i1] += y[i0 + 7 * i2] * ps[i2 + 7 * i1];
      }
    }

    b += x[i0 + 7 * i0];
  }

  theta[0] = b / 7.0;
  b_b = inv(Omega);
  b = 0.0;
  for (i0 = 0; i0 < 7; i0++) {
    for (i1 = 0; i1 < 7; i1++) {
      d_ts[i0 + 7 * i1] = P[i0] * b_b * P[i1];
    }

    for (i1 = 0; i1 < 7; i1++) {
      y[i0 + 7 * i1] = 0.0;
      for (i2 = 0; i2 < 7; i2++) {
        y[i0 + 7 * i1] += d_ts[i0 + 7 * i2] * ps[i2 + 7 * i1];
      }
    }

    b += y[i0 + 7 * i0];
  }

  theta[1] = b / 7.0;
  b_b = inv(Omega);
  b = 0.0;
  for (i0 = 0; i0 < 7; i0++) {
    for (i1 = 0; i1 < 7; i1++) {
      d_ts[i0 + 7 * i1] = P[i0] * b_b * P[i1];
    }

    for (i1 = 0; i1 < 7; i1++) {
      y[i0 + 7 * i1] = 0.0;
      for (i2 = 0; i2 < 7; i2++) {
        y[i0 + 7 * i1] += d_ts[i0 + 7 * i2] * ps[i2 + 7 * i1];
      }
    }

    b += y[i0 + 7 * i0];
  }

  theta[2] = b / 7.0;

  /*  Compute posterior weights based solely on changed covariance */
  for (i0 = 0; i0 < 49; i0++) {
    y[i0] = delta * posteriorSigma[i0];
  }

  invNxN(y, x);
  for (i0 = 0; i0 < 7; i0++) {
    b_weq[i0] = 0.0;
    for (i1 = 0; i1 < 7; i1++) {
      b_weq[i0] += er[i1] * x[i1 + 7 * i0];
    }

    w[i0] = b_weq[i0];
  }

  /*  Compute posterior weights based on uncertainty in mean and covariance */
  for (i0 = 0; i0 < 49; i0++) {
    posteriorSigma[i0] *= delta;
  }

  invNxN(posteriorSigma, y);
  for (i0 = 0; i0 < 7; i0++) {
    b_weq[i0] = 0.0;
    for (i1 = 0; i1 < 7; i1++) {
      b_weq[i0] += pi[i1] * y[i1 + 7 * i0];
    }

    pw[i0] = b_weq[i0];
  }

  /*  Compute lambda value */
  /*  We solve for lambda from formula (17) page 7, rather than formula (18) */
  /*  just because it is less to type, and we've already computed w*. */
  pinv(P, b_weq);
  *lambda = 0.0;
  for (i0 = 0; i0 < 7; i0++) {
    *lambda += b_weq[i0] * (w[i0] * (1.0 + tau) - weq[i0]);
  }

  /*  Black-Litterman example code for MatLab (hlblacklitterman.m) */
  /*  Copyright (c) Jay Walters, blacklitterman.org, 2008. */
  /*  */
  /*  Redistribution and use in source and binary forms,  */
  /*  with or without modification, are permitted provided  */
  /*  that the following conditions are met: */
  /*  */
  /*  Redistributions of source code must retain the above  */
  /*  copyright notice, this list of conditions and the following  */
  /*  disclaimer. */
  /*   */
  /*  Redistributions in binary form must reproduce the above  */
  /*  copyright notice, this list of conditions and the following  */
  /*  disclaimer in the documentation and/or other materials  */
  /*  provided with the distribution. */
  /*    */
  /*  Neither the name of blacklitterman.org nor the names of its */
  /*  contributors may be used to endorse or promote products  */
  /*  derived from this software without specific prior written */
  /*  permission. */
  /*    */
  /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND  */
  /*  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,  */
  /*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  */
  /*  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  */
  /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR  */
  /*  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  */
  /*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,  */
  /*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR  */
  /*  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  */
  /*  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  */
  /*  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING  */
  /*  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  */
  /*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH  */
  /*  DAMAGE. */
  /*  */
  /*  This program uses the examples from the paper "The Intuition  */
  /*  Behind Black-Litterman Model  Portfolios", by He and Litterman, */
  /*  1999.  You can find a copy of this  paper at the following url. */
  /*      http:%papers.ssrn.com/sol3/papers.cfm?abstract_id=334304 */
  /*  */
  /*  For more details on the Black-Litterman model you can also view */
  /*  "The BlackLitterman Model: A Detailed Exploration", by this author */
  /*  at the following url. */
  /*      http:%www.blacklitterman.org/Black-Litterman.pdf */
  /*  */
}

/*
 * File trailer for hlblacklitterman.c
 *
 * [EOF]
 */

クリーンアップ

ファイルを削除して元のフォルダーに戻ります。

コマンドの実行: クリーンアップ

cleanup
この情報は役に立ちましたか?