059_NonconvexPortfolio.mw

取引コストの非凸ポートフォリオ最適化

イントロダクション

投資には、資本の長期的な成長と低リスクという相反する2つの目的があります。

1952 年に発表されたマルコビッツモデルは、これらの2つの目的のバランスを取る為の2次計画法最適化モデルです。
決定変数は各資産に投資された金額です。

目的は、以下の項目を条件として総リターンの変化を最小にすることです。

(1) ポートフォリオから予想された成長は少なくとも何らかの目標レベルです。

(2) 資本額いじょうの投資を行わない。

マルコビッツモデルの元の形のままでは取引コストを仮定しません、そして、結果は二次計画法で容易に解決されています。
研究者は、凸状な(線形的な)取引コストや他の直線的な規制を加えることによって、マルコビッツモデルの頻繁な凸状一般化を研究しました。

このワークシートでは、投資家が資産購買の非凸取引コストを支払うと仮定します。(これらのコストは投資された量の凹形の区分的線形関数によって計算されます。)
ブローカーが手数料率の大口割引を提供する時にこの原価構造は慣例になっています。

これらの条件から、マルコビッツモデルは局所的最適化アルゴリズムを使用することで
簡単に解くことの出来ない、非凸最適化問題になります。

> restart:
with( LinearAlgebra ):
with( plots ):
with( Optimization );
with( GlobalOptimization );

Warning, the name changecoords has been redefined

[ImportMPS, Interactive, LPSolve, LSSolve, Maximize, Minimize, NLPSolve, QPSolve]

Warning, the name Interactive has been rebound

[GlobalSolve, Interactive]

マルコビッツモデルのオリジナル式

比較の基礎として、初めに、取引コストなしでオリジナルのマルコビッツモデルを定式化して、事例では二次計画法を使用して解きます。

                                                       

X = x[1] .. x[n] を購入した総額として、b を持っているの資本の総額、R を期間における資産リターンの乱数ベクトル、r を R の期待値、g を望む最低成長(ドル)、Q を R の共分散行列とします。

目的関数は、sum(x[i]*R[i], i = 1 .. n) となり、x^t*Q*x とイコールと表せます。

例えば、n=3 とした場合、以下の二次計画問題を解きます。

最小化:  x^t*Q*t

条件: x[1]+x[2]+x[3] <= b

    g <= x[1]*r[1]+x[2]*r[2]+x[3]*r[3]

    x[1], x[2], x[3] は正

ここで、以下のデータがあると仮定します。

> n := 3:
X := <x,y,z>:
b := 10000; # can invest up to $10,000
g := 1000;  # expected return of at least $1,000, or 10%
r := <.05, -.04, .15>;
Q := <<.08, -.20, .05> | <-.20, .03, -.15> | <.05, -.15, .45>>;

b := 10000

g := 1000

r := Vector[column]([[0.5e-1], [-0.4e-1], [.15]])

Q := Matrix([[0.8e-1, -.20, 0.5e-1], [-.20, 0.3e-1, -.15], [0.5e-1, -.15, .45]])

目的関数 x^t*Q*t

> objective := expand( Transpose(X).Q.X );  

objective := 0.8e-1*x^2-.40*x*y+.10*x*z+0.3e-1*y^2-.30*y*z+.45*z^2

制約条件:

> budget := add( X[i], i=1..n ) <= b;
growth := add( X[i]*r[i], i=1..n ) >= g;

budget := x+y+z <= 10000

growth := 1000 <= 0.5e-1*x-0.4e-1*y+.15*z

目的関数は x で二次で、 y と z、制約条件は線形です。問題を解決する為、二次計画法を使用します。Maple には QPSolve が用意されており、これを使用して二次計画問題を解きます。

> originalSol := QPSolve( objective, {budget, growth}, assume=nonnegative );

originalSol := [15211014.666268, [x = 3606.70457946722581, z = 5659.98204130499836, y = 733.313379227775954]]

資産 y の期待収益はマイナス成長 (-4%) ですが、その共分散と他の2つの資産は多様化利益を提供できるほど十分負です。

すなわち、総リターンの変化を減少させることで、このモデルにおける最適配分は上向きでになります。

したがって、このモデルの下における最適の配分は積極的です。

モデルに取引コストの追加

ブローカーによって設定された関数 t とそれらの投資予算から出されるコストについて、x ドル投資した際に支払うコミッション t(x) ついて考えます。

3つの資産問題の予算制限は以下になります。

> nonconvexBudget := add( X[i], i=1..n ) + add( t(X[i]), i=1..n ) <= b;

nonconvexBudget := x+y+z+t(x)+t(y)+t(z) <= 10000

簡潔にする為、まず、コミッションレートは仕入高の一定の割合となり、t(x) = c*x と 0 < c < 1 の時、例えば、c=0.03 とすると、予算制限は以下になります。

> t_const := z-> .03*z:
linearBudget := eval( nonconvexBudget, { t=t_const });

linearBudget := 1.03*x+1.03*y+1.03*z <= 10000

初めに、線形なコスト関数を解きます。予想されるように、1000ドルの成長目標を達成する為に最も高い収益、変化の資産を比較的多く投資する為、購買力が減少するので最小分散は増加します。

> QPSolve( objective, {linearBudget, growth}, assume=nonnegative );

[15595820.629613, [x = 3468.23664794274192, z = 5664.25376972768390, y = 576.247446407243388]]

次に、ブローカーがコミッションの大口割引を提供すると仮定し、コミッションが凹面で与えられるように仕入高において区分線形関数を与えるようにします。
この原価構造は実際に一般的な方法です。


以下では、私たちは凹形の区分的線形取引コスト関数を定義しプロットします。

> maxRate := .30: minRate:=.02:
n := 2:
c := [seq( minRate + (maxRate - minRate)*(n-i)/n, i=0..n)]:
breakpoints := [0, 3000, 6000, infinity]:
t_lin := [seq( c[i+1]*(x-breakpoints[i+1])+add( c[j]*(breakpoints[j+1]-breakpoints[j]),j=1..i), i=0..n)]:
t_piecewise := unapply( piecewise( op(ListTools:-Flatten( [seq([x>=breakpoints[i] and x<breakpoints[i+1], t_lin[i]], i=1..n+1 ) ]))), x):
Transaction_cost(x) = t_piecewise(x);
plot( t_piecewise(x), x=0..10000, title="Transaction Cost vs. Purchase Amount" );

Transaction_cost(x) = PIECEWISE([.3000000000*x, 0 <= x and x < 3000], [.1600000000*x+420.0000000, 3000 <= x and x < 6000], [0.2e-1*x+1260.000000, 6000 <= x and x < infinity])

[Plot]

以下では、私たちがゼロ取引コスト(赤い表面)と区分線形取引コスト(青い表面)を問題に適用した際の予算制限をプロットします。

赤い面によって表示されている領域(4面体)は凸状ですが、青い面によって表示されている領域は非凸であるのに注意してください。
非凸は最適化問題とグローバル最適化のテクニックより適切な1つを選び出すのに挑戦します。

> pwBudget := eval( nonconvexBudget, { t = t_piecewise } ):
implicitplot3d( [lhs(budget)=10000, lhs(pwBudget)=10000],
                x=0..10000, y=0..10000, z=0..10000, style=patchnogrid,
               axes=normal, transparency=.4, color=[red, blue],
               orientation=[-30,70],
               title="Budget Constraints with Zero Costs (red) and Nonconvex Costs (blue)");

[Plot]

非凸モデルの解

オリジナルの問題のゼロコストの解を確認します。

> originalSol;

[15211014.666268, [x = 3606.70457946722581, z = 5659.98204130499836, y = 733.313379227775954]]

初めに Maple に組み込まれている局所的な最適解を求めるコマンドを使用し、初期ポイントをゼロコスト問題の最適解として、非凸問題を解いてみます。
このデータでは、制限が方々で微分不可であり、ほとんどの局所ソルバーが全ての入力の一次導関数のに制限を仮定する為、局所ソルバーでは解を見つけることができません。

> NLPSolve( objective, {growth, pwBudget}, assume=nonnegative, initialpoint=originalSol[2] );

Error, (in Optimization:-NLPSolve) no improved point could be found

従って、GlobalOptimization Toolbox のソルバーを指定します。

> pwSol := GlobalSolve( objective, {growth, pwBudget}, x=0..10000, y=0..10000, z=0..10000 );

pwSol := [17699316.4260216318, [x = 2021.89781021897852, z = 5992.70072992700716, y = 0.]]

以下に、可能な領域を境として最適の配分(緑色)の位置を示すダイヤグラムを表します。
予算制限(青)と成長阻害要因(灰色)を表す面を示します。

> opt := eval( [x,y,z], pwSol[2] ):
p1 := plots[implicitplot3d]( [lhs(pwBudget)=10000, rhs(growth)=1000],
                x=0..8500, y=0..8500, z=0..8500,
               axes=normal, transparency=.0, style=patchnogrid, color=[blue,grey],
               orientation=[-30,70],
               title="Optimal Allocation under a Nonconvex Transaction Cost Function"):
p2 := plottools[sphere](opt, 200, color=green, style=patchnogrid):
plots[display]( [p1, p2] );

[Plot]