2.20 格付け推移行列推定問題
格付け(rating)とは,企業の発行する社債の元本,利息の支払い能力をランク形式で表示したものです.格付け会社は独自の調査結果のもと,A,B,Cや+,-などの記号を用いて対象社債のリスク度合いを示します.格付けは,社債の購入者側からすると購入判断時の評価指標になりますし,発行体となる企業側からすると,資金調達の際の利回り決定の基準となります.
格付け推移行列とは,ある格付け評価を受けている企業が,一定期間後にどのような格付けとなるかについての確率を表す行列のことをいいます.
以下では,この格付け推移行列の推定に関する例題を考えます.
例題
格付けとして,{AAA, AA, A, BBB, BB, B, CCC, CC, C}の9種類があるものとして,格付けに関する1年後の推移行列が以下のように与えられているものとする.
を基に,1ヶ月単位期間の格付け推移行列を推定せよ.
推移確率行列 はマルコフ過程に従うものとします.そのとき,題意より行列は行列と本来一致するはずです.従って,行列を推定するとは,を最小にするようなを求めるということになります.なおは,Frobenius(フロベニウス)ノルムのことで,行列の各成分の二乗和の平方根を表すものとします.
また,格付け推移行列の性質として,行列の各行の和は1で各成分は非負であるものとします.
以上を踏まえると,定式化は以下のようになります.
順序集合 | |
格付けの集合 | |
定数 | |
1年後の格付け推移行列()の各要素 | |
変数 | |
1ヶ月単位の格付け推移行列()の各要素 | |
目的関数(最小化) | |
行列との差のフロベニウスノルムの二乗 | |
制約条件 | |
行列の各行の和は1 | |
行列の各要素条件 |
この問題は目的関数が非線形ですので,非線形計画問題になります.
定式化した結果をC++SIMPLEで記述すると以下のようになります.
なお,行列に関しては,
で表現することにより,演算の回数を節約することができます.
また,局所解に陥ることを回避するため,および収束までの反復回数を軽減するため,行列の初期値として,対角成分に0.9を与え,非対角要素の上限値を0.05としておきます.
// 集合と添字 OrderedSet Rating; // 格付け集合 Element i(set = Rating), j(set = Rating), k(set = Rating); // パラメータ Parameter q0(name = "Q0", index = (i,j)); // 1 年後の格付け推移行列の各要素 // 変数 Variable q(name = "Q", index = (i, j)); // 1 ヶ月単位の格付け推移行列の各要素 // 定式の定義に利用する演算の回数を節約する記法 Expression q2(name = "q2", index=(i, j)); Expression q4(name = "q4", index=(i, j)); Expression q8(name = "q8", index=(i, j)); Expression q12(name = "q12", index=(i, j)); q2[i, j] = sum(q[i, k] * q[k, j], k); q4[i, j] = sum(q2[i, k] * q2[k, j], k); q8[i, j] = sum(q4[i, k] * q4[k, j], k); q12[i, j] = sum(q8[i, k] * q4[k, j], k); Expression diff(name = "diff", index = (i, j)); diff[i, j] = q0[i, j] - q12[i, j]; // 目的関数 Objective diffnrm(name="行列 Q0 と 行列 Q の 12 乗 の差ノルムの二乗", type = minimize); diffnrm = sum(pow(diff[i, j], 2), (i, j)); // 制約条件 sum(q[i, j], j) == 1; // 行列 Q について,各行の和は 1 0 <= q[i, i] <= 1; // 行列 Q の対角要素条件 0 <= q[i, j] <= 0.05, i != j; // 行列 Q の非対角要素条件 // 初期値設定 q[k, k] = 0.9; // 求解 solve(); // 結果出力 diffnrm.val.print(); simple_printf("\n"); simple_printf("Q"); simple_printf(", %s", k); simple_printf("\n"); Element k_tmp; for(k_tmp = Rating.first(); k_tmp < Rating; k_tmp = Rating.next(k_tmp)){ simple_printf("%s", k_tmp); simple_printf(", %7.5f", q[k_tmp, j]); simple_printf("\n"); }
データファイル(csv形式)は以下のようになります.
Q0, AAA, AA, A, BBB, BB, B, CCC, CC, C AAA, 0.9651, 0.0349, 0, 0, 0, 0, 0, 0, 0 AA, 0.0356, 0.9382, 0.0262, 0, 0, 0, 0, 0, 0 A, 0.0014, 0.0433, 0.9364, 0.0186, 0.0003, 0, 0, 0, 0 BBB, 0, 0, 0.0352, 0.9456, 0.0154, 0.0038, 0, 0, 0 BB, 0, 0, 0, 0.1078, 0.872, 0.0049, 0.0153, 0, 0 B, 0, 0, 0, 0, 0.0747, 0.8762, 0.041, 0.0081, 0 CCC, 0, 0, 0, 0, 0, 0.0278, 0.9654, 0.0068, 0 CC, 0, 0, 0, 0, 0, 0, 0.0083, 0.9675, 0.0242 C, 0, 0, 0, 0, 0, 0, 0, 0.0266, 0.9734
このモデルを実行すると以下のような解が得られます.
行列 Q0 と 行列 Q の 12 乗 の差ノルムの二乗 = 2.82001e-005 Q, AAA, AA, A, BBB, BB, B, CCC, CC, C AAA, 0.99697, 0.00303, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000 AA, 0.00310, 0.99459, 0.00231, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000 A, 0.00006, 0.00383, 0.99446, 0.00164, 0.00001, 0.00000, 0.00000, 0.00000, 0.00000 BBB, 0.00000, 0.00000, 0.00307, 0.99523, 0.00137, 0.00032, 0.00000, 0.00000, 0.00000 BB, 0.00000, 0.00000, 0.00000, 0.00976, 0.98852, 0.00039, 0.00133, 0.00000, 0.00000 B, 0.00000, 0.00000, 0.00000, 0.00000, 0.00693, 0.98889, 0.00355, 0.00063, 0.00000 CCC, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00247, 0.99699, 0.00054, 0.00000 CC, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00071, 0.99722, 0.00207 C, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00227, 0.99772
上に戻る