銀行エンジニアリング 40:デジタルツイン(事実を凍結し、仮定は別に置く)
銀行の『これから』を試算するとき、いちばん大事なのは、実績の事実と、模型の仮定を混ぜないことです。MiniBank v20が、実績を凍結して別の模型で試算する仕組みを学びます。
v8以降に実装した台帳・記帳エンジンなどを実際に動かし、正常時と異常時の両方から銀行システムの構造を学ぶ。
Prerequisite: BANKING SYSTEMLEARNING GOALS
このページで学ぶこと
- ベースライン(実績の凍結)と模型の分離
- 入力・モデルの版・シード値で結果を再現する
- 予測は実績ではない、をどう守るか
PLAIN LANGUAGE
まず、ここだけつかむ
銀行の実績を、ある時点で凍結して写し取り、そこに明示した仮定を掛けて、将来の数字を試算します。
同じ入力・同じモデルの版・同じシード値なら、何度でも同じ結果になります。
試算は予測であって実績ではありません。元帳には書き込まず、画面でも別の枠に置きます。
DIFFICULT PARTS, STEP BY STEP
難しいポイントを、順番にほどく
専門用語を覚えることより、「なぜ必要か」「このシステムのどこで使うか」を理解することが目標です。
ベースライン
実績をある時点で凍結した記録です。
あとから実績が動いても、試算の入力を固定するためです。
twin.baselines。入力ハッシュつきで追記専用。
モデルの版
模型の仮定(9つのパラメータ)の版です。
結果の変化が『実績の変化』か『仮定の変更』かを切り分けるためです。
twin.models。別の管理責任者が承認。
シード値
揺らぎ(乱数)の出発点です。
乱数を使っても、同じ条件なら同じ結果を再現するためです。
twin.rand。同じシード値なら同じ列。
Level 1 基礎:模型は、天気予報のようなもの
天気予報は、いまの気圧や気温という『事実』に、大気の動き方という『仮定』を掛けて作ります。予報が外れても、昨日の気温の記録は書き換わりません。
デジタルツインも同じです。銀行の実績(元帳の数字)を、ある時点で凍結して写し取り、そこに『金利が上がったら預金はこれだけ動く』といった仮定を掛けて、将来の数字を試算します。試算は予測であって、実績ではありません。
Level 2 銀行業務:何を凍結し、何を仮定にするか
- 仮定の数字はすべて架空の教育用で、実績から自動で推定した『真実』ではない
- 同じ(ベースライン, シナリオ, モデルの版, シード値)の組み合わせは、1回だけ保存される(冪等)
| 区分 | 内容 | MiniBankでの置き場所 |
|---|---|---|
| 事実(凍結する) | 全 entity の試算表、Treasury の位置と方針、預金の価格、融資の残高と金利と延滞の区分、v18の承認済みのパラメータ | twin.baselines(追記専用) |
| 仮定(明示する) | 預金金利の追随率、預金の感応度、新規貸出の量と感応度、返済の割合など9項目 | twin.models(版管理・別の管理責任者が承認) |
| シナリオ(入力) | 政策金利のショック、期間、一時的な預金流出 | twin.scenarios(追記専用) |
| 結果 | 9段階の因果、月ごとの予測、予測のBS/PL、リスクへの接続 | twin.runs(追記専用) |
Level 3 システム:MiniBankでの実装
- twin.collect が実績を1つの SQL 文で読み、twin.capture が入力ハッシュを付けて保存する。呼ぶ関数はすべて STABLE で同じスナップショットを共有し、時間帯も固定するので、同じ状態は同じハッシュになる
- twin.simulate は純粋な関数。凍結した事実・シナリオ・パラメータ・シード値だけを読み、表も時計も読まない。元帳・商品・契約・上限には一切書かず、Banking の命令(Posting など)を呼ばない
- 揺らぎは twin.rand(シード値から作る擬似乱数)で入れる。同じシード値なら同じ結果、別のシード値なら別の経路になる
- twin.recompute は、保存された入力から結果を作り直して、保存された結果のハッシュと比べる。入力(ベースライン)を書き換えると、入力ハッシュも結果も合わなくなる
- 実績は twin.runs.results の actual、予測は forecast と別のキーに置く。画面も別の枠・別の色・別のラベル(『実績(元帳)』/『予測(模型の出力)』)で描く
異常時:同じ条件なのに、結果が前回と違う
| 段階 | 内容 |
|---|---|
| 症状 | 同じシナリオの累計損益が、前日と違う |
| 確認1 | ベースラインの入力ハッシュ:実績が変わったのか(新しいベースラインか) |
| 確認2 | モデルの版:承認された新しい版に切り替わっていないか |
| 確認3 | シード値:別のシード値では揺らぎの経路が違う。同じ値なら recompute で一致するはず |
Level 4 アーキテクチャ:模型は正本を書き換えない
模型が正本(元帳)を書き換えられると、試算のつもりが実際の帳簿を動かしてしまいます。だから模型の関数は、読むための権限すら持たない純粋な関数にし、実績の読取りは『凍結』の一瞬が中心です(実績との差を見るときだけ、いまの実績をもう一度読みます)。もう一つの守りは、予測と実績を混ぜて表示しないことです。混ぜて見せた瞬間に、予測が事実のように読まれます。
どこを確認すればよいか
- 管理画面『Digital Twin』:ベースライン、シナリオの比較、実行の再計算
- テスト:scripts/banking/v20-twin.test.mjs(同じシード値の再現、元帳の不変、恒等式)
CHECK YOUR UNDERSTANDING
3問で理解チェック
答えを頭の中で考えてから、各項目を開いて確認してください。
Q1模型は元帳に書き込めますか?
いいえ。純粋な関数で、書き込むのは twin の表だけです。
Q2同じ条件で再実行すると?
前の結果がそのまま返ります(冪等)。
Q3ベースラインを書き換えると、何が分かりますか?
入力ハッシュが合わなくなり、再計算も一致しなくなります。
完全に暗記する必要はありません。大切な考え方を説明できそうなら押してください。
SOURCE TRAIL
根拠と関連教材
CURRENT IMPLEMENTATIONは確認したrepository内の実装です。HISTORICAL IMPLEMENTATIONは導入・修正の履歴で、後続migrationによる再定義があり得ます。RELATED LESSONは教材への案内で、実装の一次Sourceではありません。ASSUMPTIONは仮定、UNKNOWNは未確認を表します。
確認基点: d02eae8914f39cbf06bfe422dc39c71886f82b3e / 2026-09-11。稼働環境への適用確認: UNKNOWN。パス実在の自動検査と、記述した技術的事実の確認は別です。
Implementation Status: IMPLEMENTED IN MINIBANK(この教材が扱うコードの範囲)
- RELATED LESSON/docs/be-risk-snapshot-creditスナップショットの考え方(v18)
- CURRENT IMPLEMENTATION
supabase/migrations/20260930160000_v20_twin.sqltwin.collect実績の事実(全 entity の試算表・Treasury・預金価格・融資・v18のパラメータ)を1つの文で読む。呼ぶ関数はすべて STABLE で、時間帯は固定 - CURRENT IMPLEMENTATION
supabase/migrations/20260930160000_v20_twin.sqltwin.captureベースライン(実績の凍結)を追記専用に保存し、入力ハッシュを付ける - CURRENT IMPLEMENTATION
supabase/migrations/20260930160000_v20_twin.sqltwin.simulate凍結した事実・シナリオ・パラメータ・シード値から、9段階の因果と予測のBS/PLを作る純粋な関数(元帳を読まず、書かない) - CURRENT IMPLEMENTATION
supabase/migrations/20260930160000_v20_twin.sqltwin.randシード値から作る、再現できる擬似乱数(同じシード値なら同じ列) - CURRENT IMPLEMENTATION
scripts/banking/v20-twin.test.mjs手計算の1か月・因果・シード値の再現・恒等式・entity と連結・元帳の不変・決裁のDBテスト