(訂正 2026/5/10: 著者の理解が誤っており、次を訂正)
$\qquad$ (旧)ドル担保にすることは SOFRが「割る資産」
$\qquad$ (新)ドル担保にすることはTONA$\times$為替が「割る資産」
今回は 通貨スワップの準備として、ドル担保(USD collateral)のTONAカーブを作成するコードを紹介する。
「Pythonで学ぶ債券·金利デリバティブ」(以下 テキスト) 第3章で説明したTONAカーブは円担保(JPY collateral)が暗黙裡に仮定されたCSAベースの割引カーブでもある (テキスト p102) 。以下はこの円担保をドル担保にした場合の、TONA割引カーブ構築法の説明となる。
テキスト p102では「マルチカーブ」という名称のみ紹介し、実装用コードを示していない。グローバルなファイナンスではUSDが標準担保通貨であり、ここで紹介するコードは実務上 必須であろう。
10-1. カバード金利平価
担保通貨が変わるだけで、カーブ構築法は 格段に難しくなる。理論的には、担保通貨を変えることは ニューメレールを変えることに等しい。ニューメレールとは テキスト p.189に記したように、マルチンゲールにするための「割る資産」であるが、ドル担保にすることは TONA$\times$為替が「割る資産」になることを意味している。
つまり TONA(円担保)のニューメレールから、TONA$\times$為替(ドル担保)のニューメレールへの測度変換によって、カーブ構築の数式が説明される。ただ、その導出は長くなるので、回を改め、第11回で説明する。ここでは、難しい理論を無視し、算出する数値例を確認するための計算式のみを示しておく。
ドル担保を前提にすると、国内通貨: $D$ (domestic)はドルであり、外国通貨: $F$ (foreign)は円となる。それぞれのディスカウントファクターを $df^D$ , $df^F$ とする。
FXスポット: $X$ から FXフォワード: $F$ を計算する場合、カバード金利平価 (Covered Interest Rate Parity, CIRP)より、次式が成立する。(この導出は次回を予定)
$$
F = X \cdot \frac{df^F}{df^D} \tag{10-1}
$$
この式は4つの変数で構成され、3つの変数 $X$ , $F$ , $df^D$ は市場で観測可能であり、ドル担保の円ディスカウントファクター $df^F$ は 式の変形で簡単に求めることが出来る。
$$
df^F = \frac{F}{X}\cdot df^D \tag{10-2}
$$
つまり、ドル担保 JPYカーブ $df^F$ は ドル円の為替フォワードとスポットの比にSOFRのディスカウントファクターを掛けて算出できる。(注:為替 X, F は逆数の為替。例えば 1円=0.0064ドル)
ではコードと数値例を見て行く。
10-2. カーブ構築に必要なデータ

$\qquad\qquad\quad$図10-1:SOFR, TONA, クロスカレンシー データ (2026-01-20 )
式(10-2)にしたがい、割引カーブとなるSOFRデータがまず必要である。フォワードFXを計算させるため、TONAカーブのデータと通貨スワップ市場で建値されているクロスカレンシーのベーシスも必要になる。つまり、図10-1 のように 3種類のカーブデータを用意する。
-
2行:sfSwRTリストはSOFRカーブ用のレート(テキスト p91 の図 3.9と比較)-
sfSwRTは sofr swap rate の略 (同様に
tnSwRTはtona swap rate) -
テキストと比べ、市場で標準的に建値されている 2w, 3w 等のノードを入れた
-
このSOFRカーブデータは BGN を使用
(BGNはBloomberg Generic価格の略)。ただし ソース元は何でもよく、例えば、 BlueGamma 等でSOFRカーブは参照可能
-
-
11行:tnSwRTリストは 第9回:Tonar vs 3mTibor テナースワップ のtnDATAリストと同じ -
20行:xcyBSSリストも 市場の標準にしたがい、次の2種類のデータで構成 (xcyBSSは cross currency basisの略で、データは BGN を使用)-
'fxsw'タイプ:FXスワップのデータ-
タプルの中の数字は スポット為替に対して、フォワード為替がどれだけズレるかを表す
- 例えば、ドル円のスポットが158.00円の場合、1週間先のドル円は -9.43銭なので157.9057円 ( =158.00-0.0943 )
-
-
'bss'タイプ:ドル円通貨スワップのベーシス- タプルの中の数字は TONA側に加算される数字
- 例えば、5年のTONAスワップレートは 1.6275% なので、ベーシス
(-36.5bp)加算後は、1.2625% ( =1.6275% - 36.5bp ) - TONA側への加算なので、このベーシスの日数計算は Act/365 であり、SOFRのAct/360 ではない点に注意
(日数計算の異なる金利の足し算は厳禁) - この計算ルールは「第9回:Tonar vs 3mTibor テナースワップ」のベーシスと同じ
- 例えば、5年のTONAスワップレートは 1.6275% なので、ベーシス
- タプルの中の数字は TONA側に加算される数字
-
満期1年までをFXスワップのデータとしている理由は流動性が高いため。一般のWebにも、FXスワップ のデータは開示されている ( Investing.com )。しかし、通貨スワップのベーシスは見つけることが出来なかったため、BGNを使った。
10-3. ドル担保 JPYカーブ構築のコード
では、ドル担保のJPY(TONA)カーブを構築するが、まず 準備として、SOFRとTONAカーブをシングルカーブとして作成しておく。

$\qquad\qquad\qquad\qquad$図10-2:シングルカーブ作成 ( SOFR / TONA )
図10-2 で 新しく登場したコードは次の2点のみ。
-
3行:ql.JointCalendarは複数のカレンダーを合成するコンストラクタ- 3行目では Fedwire決済用カレンダー
calUSfと日本のカレンダーcalJPを合成し、calUJという米国と日本の両方を休日にもつカレンダーオブジェクトを作成
- 3行目では Fedwire決済用カレンダー
-
4行:adD関数 はmyABBRモジュールで新しく定義した短縮形で、calUJ.advance(trdDT, Tp2, DD)に同じ

- カレンダーオブジェクトのadvanceメソッドは多用するので、短縮形を作成
- adD は add dayの略。上図のようにadW, adM, adY 等も作成したが...
(短縮効果はあまりない)
-
その他は以下で既に説明済み
-
6行:makeSofrCurve は テキスト p91 図3.9 -
7行:makeTonaCurve は テキスト p77 図3.1 -
8行:showCvDT は 第8回の( その他 新しく定義した関数等 : showCvDT, isoDT, qlDT ) -
8行:dfDSP, dfNodes は 第8回 の ( 図8-2で使⽤した関数 : dfNodes, dfDSP )
-
(注:この記事のデータフレーム画像は不要な行を削除している)
10-3-1. クロスカレンシー ベーシス カーブ
下図10-3 で出力されたデータフレームのzeroRT列 と DF列が 目標のUSD担保JPYカーブである。まず 出力結果の数値を確認する。
-
図10-3 index14
5年ノードのzeroRT列1.257487%-
図10-2 出力の最後の行 index22 zeroRT列
1.622316%との差は0.36483% -
この差は図10-1の25行目 5年ベーシス
-36.5bp にほぼ等しい
-
-
有料情報端末が算出したディスカウントファクター
(以下 DF)との比較では以下を確認した-
FXスワップ(fxsw)のノードのDFは完全に一致
-
ベーシス(xcyBSS)で満期が短いノードのDFは ほぼ一致
- 満期が長くなると 1e-5桁の値が5前後のズレを示した
('1e-5'という表現はテキスト p230 参照)
- 満期が長くなると 1e-5桁の値が5前後のズレを示した
-
かつて筆者はドル担保のカーブをエクセルで手計算したが、これほどの精度での再現は出来なかった。このカーブ算出は難解で、いまもトラウマになっている。
- このトラウマが理由で 第4回:Hagan-West流 の Tiborカーブ構築 を記した。ただ ドル担保カーブのようなマルチカーブの場合、第4回記事はシングルカーブのため 役不足である

$\qquad\qquad\qquad\qquad$図10-3:USD担保 JPYカーブ
では 図10-3 のコードを概説する。使用したヘルパーは異なるが、テキスト p.77 図3.1の2番セルで説明したQuantLibの基本的なカーブ構築法の 以下の2つのステップは同じである。
-
ステップ1: 各ノード情報をヘルパーオブジェクトに変える-
5行: forループにより、図10-1 で設定したxcyBSSリストからノード情報を取り出す -
ただし、図10-3では 新しい 2つのヘルパーを使用。 これらの詳細は次の10-3-2節で説明する
-
7行: FXスワップ用のFxSwapRateHelper -
11行:通貨ベーシス用のMtMCrossCurrencyBasisSwapRateHelper
-
-
-
ステップ2:PiecewiseLogLinearDiscountでカーブオブジェクトを作成-
15行: forループで作成したcHelperを使い、カーブオブジェクトjBsCvOBJを作成- この行は テキスト 図3.1の15行目とほぼ同じ
-
以上の概説から、2つのヘルパー部分を除き、コード構成は理解できるだろう。
10-3-2. クロスカレンシー カーブ用の2つのヘルパー
図10-3 2,3行目 で設定した変数の説明から始める。これらはヘルパーの引数として与えられるので、当初は意味不明でも読み流してよく、ヘルパーの説明と共に参照しよう。
jpySP:2026年1月20日のドル円 スポット為替(T+2) が 158.1528 円/ドル
base...:base から始まる変数を4つ設定したが、base には 担保通貨USDの意味を持たせた。 反対のワードが othr (othr は other の略)
-
baseIX: USDカーブのインデックスsfIXの別名(sfIXは図10-2の6行目で作成) -
othrIX:JPYカーブのインデックスtnIXの別名(tnIXは図10-2の7行目で作成)- ヘルパーの引数に
sfIXやtnIXを直接指定してもよいが、これら別名を与えて、引数の役割を明確にさせた
- ヘルパーの引数に
-
baseCLLT = True: baseであるドルが担保 (CLLTはcollateralの略) -
baseBSS = False: baseのドル側にベーシスを乗せない- 図10-1のxcyBSSは円側に加算するレート
-
baseRST = True: baseのドル側をリセットさせる (RSTはrestの略)-
標準的な通貨スワップは利払い毎にドル元本をリセット ( MtM / resettable notional、
MtM は mark to market の略) -
リセットに関しては、通貨スワップを説明する記事
(第12回を予定)で数値例を紹介する
-
ではヘルパーの説明に移る。
- 下のヘルパーのスクショはリファレンスマニュアル
(テキスト 1.6節)のものであり、テキスト p.32 下から2行目に記したように、&やconstは無視しよう
( FxSwapRateHelper )
( 図10-3の 7, 8行目の引数との対応関係 )
| fwdPoint | spotFx | tenor | fixingDays | calendar | convention |
|---|---|---|---|---|---|
| sQH(bb/100) | sQH(jpySP) | pD(tt) | Tp2 | calUJ | mFLLW |
| endOfMonth | isFxBaseCurrencyCollateralCurrency | collateralCurve |
|---|---|---|
| EoMf | baseCLLT = True | sfCvHDL |
-
この対応表から、各引数の役割は理解しよう
-
sQH関数: myABBRで新たに定義した短縮形で、テキストのmu.sqHDL関数と同じ-
mu.sqHDL(...) が長いので、myABBRに移し、より短い関数名とした
-
(補足 1) C++を知っていれば、スクショの第1引数の
Handle < Quote > fwdPointから、第1引数はQuote型のハンドルが要求されていることが判るだろう。そのためにsQH関数を使用 -
(補足 2) テキスト p.30 に、著者のブログ "QuantLibソースを読むためのC++基礎" を記したが、現在 Claude Code等が発達し、このブログは見直し中
-
( MtMCrossCurrencyBasisSwapRateHelper )
( 図10-3 12, 13行目の引数との対応関係 )
| basis | tenor | fixingDays | calendar | convention | endOfMonth |
|---|---|---|---|---|---|
| sQH(bb*bps) | pD(tt) | Tp2 | calUJ | mFLLW | EoMf |
| baseCurrencyIndex | quoteCurrencyIndex | collateralCurve |
|---|---|---|
| baseIX = sfIX | othrIX = tnIX | clltCv = sfCvHDL |
| isFxBaseCurrencyCollateralCurrency | isBasisOnFxBaseCurrencyLeg |
|---|---|
| baseCLLT = True | baseBSS = False |
| isFxBaseCurrencyLegResettable | paymentFrequency |
|---|---|
| baseRST = True | frqQ |
- 同様にこの対応表から、各引数の役割を推測しよう
-
bb*bpsはbb÷10000と同じ。(myABBRでbpsを定義)
10-3-3. 式(10-2)の手計算と精度
このセルは最初に示した式(10-2)を使い、ドル担保JPYカーブの1年DFを手計算した。各変数は次の通り。
-
fwd1y:1年FXフォワード = 153.8158 -
sf1yDF:図10-2のSOFR 1年DF = 0.96535756 - 3行目の
jpySP/fwd1y: 式(10-2)と分子分母が逆転している理由は、式(10-2)の為替が逆数為替のため
図10-3 の1年DF=0.99274434 に対し、手計算の0.992577 は 1e-4で2程度 ズレているが、悪くはない。
- 式(10-2)は近似式としては使えるだろう
(ウォールストリートでは最低 1e-6 の一致で正しい計算と見做される)
原稿執筆時点で、ズレの原因は不明。QuantLibのコードを読めば、原因を究明できるだろうが、このテーマは計算が複雑過ぎて トラウマである。
まとめ
-
USD担保 JPYカーブの計算式(10-2)はカバード金利平価から算出
(理論的な導出は第11回を参照) -
USD担保 JPYカーブを構築する場合の必要なデータを 図10-1 に例示
-
2つの新しいヘルパーによる USD担保 JPYカーブ 構築のコード例
(図10-3) -
記事中のコードはテキストのサポートページ より、取得可能。
(今回のコードはq10-xcyCRVjpy.ipynb)


