テンソル演算を用いた多次元資産集計の定式化
1. モチベーション
本ドキュメントでは、資産配分における多角的なエクスポージャ計算を、条件分岐(if文)を排除した「テンソル演算」のみで完結させる手法を提案します。
テンソルを用いるメリット
-
計算の高速化とロジックの統一:
フロントエンドでの計算は、集計軸の数に関わらず、常に以下の2つの数学的ステップのみで完結します。- 統合グリッドテンソルの生成: \mathcal{G}{i, j_1, \dots, j_k} = \prod{p=1}^{k} G^{(p)}_{i, j_p}
- エクスポージャの縮約計算: E_{j_1, \dots, j_k, m} = \sum_{i=1}^{n} \mathcal{G}{i, j_1, \dots, j_k} \cdot w_i \cdot X{im}
-
フロントエンドでの分岐排除:
「通貨別」や「セクター別」といった条件に応じた処理の出し分けが不要になり、計算エンジンを極めてシンプルに保てます。 -
責任の分離:
バックエンドは「データ(テンソル)」を提供し、フロントエンドは「計算(縮約)」を行うという、役割の純粋化を実現します。
2. 数学的定式化
集計ロジックをアインシュタインの縮約記法を用いて定式化します。
2.1. 各要素の定義
| 記号 | 名称 | 階数 | サイズ | 例・意味 |
|---|---|---|---|---|
| w_i | ウェイトベクトル | 1階 | n | 銘柄 i の保有比率 |
| X_{im} | 指標テンソル | 2階 | n \times m | 銘柄 i の指標 m(デュレーション、スプレッド等) |
| G^{(p)}_{ij_p} | 属性マスタ | 2階 | n \times g_p | 銘柄 i が属性 j_p(USD、ITセクター等)に属するフラグ |
| \mathcal{G}_{i, j_1, \dots, j_k} | 統合グリッドテンソル | k+1 階 | n \times g_1 \times \dots \times g_k | 選択された k 個の属性の全組み合わせ |
- n: 銘柄数 / m: 指標数 / k: 選択された集計軸の数 / g_p: 各集計軸に含まれる項目数
2.2. 統合グリッドテンソルの計算定義
ユーザーが選択した k 個の属性マスタを、共通の「銘柄軸 i」で掛け合わせることで、多次元の集計条件を定義します。
2.3. エクスポージャの計算定義
統合されたグリッド、ウェイト、および指標を掛け合わせ、銘柄軸 i を縮約(合計)します。
結果 E は、選択された属性の組み合わせごとの指標合計値を格納した k+1 階テンソル となります。
3. React実装例 (TensorFlow.js)
3.1. APIレスポンス構造
バックエンドからは、計算済みの属性マスタと指標データが、形状情報と共に提供されます。
{
"indicators": { "data": [...], "shape": [1000, 2] },
"grid_currency": { "data": [...], "shape": [1000, 5] },
"grid_sector": { "data": [...], "shape": [1000, 10] }
}
3.2. フロントエンドでの計算処理
import * as tf from '@tensorflow/tfjs';
// 1. 各グリッドの取得と復元
const w = tf.tensor1d(weights);
const X = tf.tensor2d(indData, [1000, 2]);
const G_curr = tf.tensor2d(currData, [1000, 5]);
const G_sect = tf.tensor2d(sectData, [1000, 10]);
// 2. 統合グリッドの計算(2つの属性を選択した場合:n x g1 x g2)
const G_total = tf.einsum('ig,ih->igh', G_curr, G_sect);
// 3. エクスポージャの計算(g1 x g2 x m)
const exposure = tf.einsum('igh,i,im->ghm', G_total, w, X);
const result = exposure.arraySync(); // 多次元配列としてUIに渡す
3.3. UIへの表示
計算結果は、result[通貨インデックス][セクターインデックス][指標インデックス] としてアクセス可能です。これをテーブルやグラフのデータソースとしてそのまま利用します。