【QuantLib-Python】金利スワップの評価と検証

# 0. はじめに

## 0-1. この記事を読めば

- わかる
    - TIBORスワップの商品性
    - そもそもTIBORとは
    - TIBORスワップの評価（手計算）
    - TIBORスワップの評価（QuantLib-Python）
    - **QuantLib-Pythonによる評価の検証**
- わからない（書ききれなかったこと）
    - スワップの歴史
    - 中央清算機関での清算の詳細
    - ヘッジ会計など

## 0-2. 誰のための記事か

マーケット部門の従事者で1~2年目の方を読者として想定している．マルチンゲール・アプローチについて知っていると詳細な議論が終えるようになっている．マルチンゲール・アプローチの参考文献としては[村上](https://www.kindaikagaku.co.jp/book_list/detail/9784764904804/  "外部サイトへ")が挙げられる．

## 0-3. 金利スワップとは

スワップについては以下のような説明がある[^1]．
[^1]: スワップ取引のすべて pp.40-42

> 「スワップ取引」とは，将来のキャッシュ・フローを交換する取引である．2当事者間の相対取引（OTC：Over The Counter）であり，お互いに取引相手の信用リスクを負うが，合意にさえ至ればどのようなキャッシュ・フローもスワップ取引の対象となりうる．

さらに金利スワップについても説明が続く．

>同種通貨のキャッシュ・フローの交換取引が金利スワップである．（中略）最も典型的な金利スワップは固定金利（fixed rate）と変動金利（floating rate）を交換するスワップである．

以下では金利スワップを考えていく．固定金利を受ける（resp. 払う）側をレシーバー（resp. ペイヤー）といい，このポジションを組むことを金利スワップをレシーブ（resp. ペイ）するという．

```mermaid
graph LR
    R[レシーバー]
    P[ペイヤー]
    P -->|固定金利| R
    R -.->|変動金利| P
```

## 0-4. QuantLib-Pythonとは

QuantLib-PythonとはQuantLibというC++で書かれた「金融商品の時価評価ライブラリ」をPythonから呼び出すためのラッパーである．QuantLibではスワップやオプションといった金融商品の時価を計算することができ，それを手軽にPythonから呼び出せるQuantLib-Python（以下これを単にQuantLibと呼ぶ）は大変便利なものである．詳細は[公式HP](https://www.quantlib.org/  "外部サイトへ")へ．

## 0-5. 前提条件

- 計算環境
    - Windows 11
    - Python 3.12
    - pandas 2-2-2
    - QuantLib 1.33
- 数理ファイナンスの知識
    - 割引キャッシュ・フロー法による現在価値の考え方
    - （マルチンゲール・アプローチの考え方）

# 1. TIBORスワップ

## 1-1. 商品性

TIBORスワップは金利スワップの1つで，変動金利としてTIBOR（[1-2. TIBOR](#1-2-tibor)）を参照するものを指す．以下，これを単にスワップと呼ぶ．

TIBORスワップはCCPを通じて信用リスクを乗せないフェアなプライシングがされていると解釈できる[^2]．
 [^2]: フィナンシャルエンジニアリング p.304
 > 現在はほとんどの標準化されたデリバティブについては中央清算機関（CCP）を通じて清算されることが義務づけられている．これは，そのようなデリバティブが取引所で取引される先物と同じように扱われることを意味する．
 
これについては[^3]にも記載がある．
[^3]: スワップ取引のすべて pp.54-55
> 「スワップレートは観察可能である」とよくいわれるが，このことの意味は，スワップが十分な流動性をもって市場で取引されているため，情報ベンダーが情報端末で提供する以下のような画面で容易に市場の気配値を得ることができるという意味である．

| X年X月X日 | 円/円スワップレート（ABC銀行）|
| :--- | :---: |
| | offer - bid |
| 1年 | 0.12 - 0.08 |
| 2年 | 0.17 - 0.13 |
| 3年 | 0.25 - 0.21 |
| 4年 | 0.37 - 0.33 |
| 5年 | 0.52 - 0.48 |
| 6年 | 0.70 - 0.66 |
| 7年 | 0.88 - 0.84 |
| 8年 | 0.90 - 0.86 |
| 9年 | 1.14 - 1.10 |
| 10年 | 1.36 - 1.32 |

ここでTIBORスワップの具体例を挙げる[^4]．TIBORスワップはこのような条件で取引される．
[^4]: スワップ取引のすべて p.44

| | 日本円TIBORスワップ |
| :---: | :--- |
| 通貨 | 日本円 |
| 想定元本 | 13億円 |
| 期間 | 2024年10月15日～2026年10月15日 |
| 支払日 | 2025年4月15日を第1回とし，以降毎年期限までの4月15日と10月15日 <BR> Modified Following Business Day Convention |
| 営業日 | 東京 |
| 金利 | 固定金利 2.00%（Actual/365 (Fixed)，半年後払い） <br> 変動金利 6ヶ月TIBOR（Actual/365 (Fixed)，半年後払い） |
| TIBOR | 金利計算期間の初日の2東京営業日前に発表される6ヶ月日本円TIBOR |

## 1-2. TIBOR

変動金利として参照する**TIBOR**（東京銀行間取引金利，Tokyo InterBank Offered Rate）について基本的な事項をまとめる．TIBORについては[^5]に説明がある．
[^5]: スワップ取引のすべて p.39
> TIBORは短期金融市場の1つであるインターバンク市場の取引の実勢を反映する円の金利指標で，現在ではわが国の金融機関が実際の国内ローンに利用している金利形態である．

TIBORの数理モデルについてまとめる．

一般に金利には**スポット・イールド**と**フォワード・イールド**があり，TIBORについてそれぞれを$Y(t,t+\Delta)$と$Y(t,T,T+\Delta)$で表す．ただし前者は観測時点$t$における足許（**スポット**）時点$t$から時点$t+\Delta$までの間にかかる金利（年率）を，後者は観測時点$t$における将来（**フォワード**）時点$T$から時点$T+\Delta$までの間にかかる金利（年率）を指す．定義から
```math
\begin{align*}
    Y(t,t+\Delta) = Y(t,t,t+\Delta)
\end{align*}
```
となっている．LIBORは商慣習として連続複利ではなく（半年）単利で計算されるため，満期が$T$時点の割引債の$t$時点で観測した価格$P(t,T)$を用いて
```math
\begin{align*}
    Y(t,t+\Delta) & = \frac{1}{\Delta} \frac{1 - P(t,t+\Delta)}{P(t,t+\Delta)}, \\
    Y(t,T,T+\Delta) & = \frac{1}{\Delta} \frac{P(t,T) - P(t,T+\Delta)}{P(t,T+\Delta)}
\end{align*}
```
と表される．

:::note warn
割引債の価格からTIBORを導いている，すなわちTIBORを割引金利として用いていることに注意されたい．いわゆるフォワードと割引で同じカーブを用いることがTIBORスワップの評価の肝である．
:::

## 1-3. フェア・レート

相対で取引するスワップでは需給によってスワップ・レートが変わってくる．しかし**無裁定な市場を仮定した**ときの，レシーバーとペイヤーが公平な固定金利の水準を考えることができ，これを**フェア・レート**と言う．このレートを導出することを**スワップを評価する**という．

ここでは具体的に以下の条件で金利スワップをレシーブしたとする．

| | レシーバー |
| :---: | :---: |
| 想定元本 | 1（単位円） |
| 受払日 | 半年ごとにN年間
| 固定金利 | S |
| 変動金利 | $Y(T,T+\text{半年})$ |

（イメージ図）t=0時点では受け渡しは発生しない．（→の先が×になっている）

```mermaid
sequenceDiagram
    actor R as レシーバー
    actor P as ペイヤー
    R --x P: t=0
    P -x R: 
    loop N年後まで毎半期
        R -->> P: TIBOR
        P ->> R: スワップレート S
    end
```

このとき実際のスワップレート$S$とは別に**理論的に導出されるフェア・レート**$R$は
```math
\begin{align*}
    R = \frac{2 \times (1-P(0,N))}{P(0,\text{半年})+P(0,\text{1年})+\cdots+P(0,N)}
\end{align*}
```
と表される．

:::note info
フェア・レートは足許の割引カーブから計算できる．
:::

需給によってフェア・レート$R$とマーケットのスワップ・レート$S$の大小関係は決まってくる．

以下，導出を2つの形で述べるが適宜省略されたい．どちらも上式の評価式が導出される．

<details close>
<summary>マルチンゲール・アプローチによる導出</summary>

固定（変動）金利のキャッシュ・フローをまとめて固定（変動）レグと呼ぶことにする．取引が成立している事実から当事者間の期待利得は等しいといえる．すなわち**取引時点に限れば固定レグと変動レグの現在価値は等しく**なっている．その時の$R$を求めるため，まずは固定レグの将来$t$時点の現在価値を計算していく．

固定レグは一定の金額を定期的に支払うキャッシュ・フローという意味でAnnuityの一例である．その現在価値$PV_{\mathrm{固}}(t)$は半年ごとに受け取る$R/2$を割り引いて
```math
\begin{align*}
    PV_{\mathrm{固}}(t) & = \left(\frac{R}{2}, \frac{R}{2}, \ldots , \frac{R}{2}\right) \cdot \underset{=:\mathrm{Annuity}(t)}{\underline{{}^t\! \left(P(t,\lfloor t \rfloor), P(t,\lfloor t \rfloor+\text{半年}), \ldots, P(t,N)\right)}} \\
    & = \left(\frac{R}{2}, \frac{R}{2}, \ldots , \frac{R}{2}\right) \cdot \mathrm{Annuity}(t) \\
    & = \frac{R}{2} \times \mathrm{sum}(\mathrm{Annuity}(t))
\end{align*}
```
と計算できる．ただし$\lfloor t \rfloor$は半年単位で見た$t$の次の時点を表す．（例：$t$が9ヶ月後なら$\lfloor t \rfloor$は1年後．）実務上は$\mathrm{Annuity}(t)$をあらかじめ計算しておくことも多い．

一方で変動レグの現在価値$PV_{\mathrm{変}}$を計算することは難しい．それは将来の利払日$(T+\text{半年})$-時点において支払う金利$Y(T,T+\Delta)$が$T$-時点にならないと確定せず，したがって**ペイオフも同様に不確定である**ことによる．

しかし**無裁定という仮定**を用いれば変動レグの現在価値はマルチンゲール・アプローチから計算できる．このとき将来$T$時点のスポットLIBOR$L(T,T+\Delta)$はあたかも足許$t$時点のフォワードLIBOR$L(t,T,T+\Delta)$であるかのように計算される，

:::note info
【仮定】市場は無裁定である．
:::

変動レグの現在価値はスポットTIBORを用いて

```math
\begin{align*}
    PV_{\mathrm{変}}(t)
    = \left(
        \frac{Y(\lfloor t \rfloor-\text{半年}, \lfloor t \rfloor)}{2}, 
        \ldots, 
        \frac{Y(N-\text{半年}, N)}{2}\right)
        \cdot \mathrm{Annuity}(t)
\end{align*}
```
と表される．この右辺を計算していく．

ここである測度（具体的にはフォワード・メジャー）が存在して，すべての年限の割引債の価格がその測度のもとでマルチンゲールとなるのであった（**マルチンゲール・アプローチ**）．


$\lfloor t \rfloor$-時点のペイオフのみを考えた時，その現在価値は

```math
\begin{align*}
    E\left[\frac{Y(\lfloor t \rfloor-\text{半年}, \lfloor t \rfloor)}{2}\times P(t,\lfloor t \rfloor) \middle | \mathcal{F}_t \right]
\end{align*}
```
である．これを以下のように計算していく．
```math
\begin{align*}
    & E\left[\frac{Y(\lfloor t \rfloor-\text{半年}, \lfloor t \rfloor)}{2}\times P(t,\lfloor t \rfloor) \middle | \mathcal{F}_t \right] \\
    & = E\left[\frac{1}{\text{半年}} \frac{P(\lfloor t \rfloor-\text{半年},\lfloor t \rfloor-\text{半年}) - P(\lfloor t \rfloor-\text{半年},\lfloor t \rfloor)}{P(\lfloor t \rfloor-\text{半年},\lfloor t \rfloor)}\times P(t,\lfloor t \rfloor) \middle | \mathcal{F}_t \right] \\
    & = 2 \times  (P(t,\lfloor t \rfloor-\text{半年}) - P(t,\lfloor t \rfloor))
\end{align*}
```

それぞれを$ 0 \le (\lfloor t \rfloor-\text{半年}) < N $について和を取って

```math
\begin{align*}
    & PV_{\mathrm{変}}(t) \\
    & = 2\times \{(P(t,\lfloor t \rfloor-\text{半年}) - P(t,\lfloor t \rfloor)) + (P(t,\lfloor t \rfloor) - P(t,\lfloor t \rfloor + \text{半年})) \\
    & \quad \ + \cdots +  (P(t,N-\text{半年}) - P(t,N))\} \\
    & = 2 \times (P(t,\lfloor t \rfloor-\text{半年}) - P(t,N))
\end{align*}
```

を得る．取組時点($t$=0)の現在価値が固定レグと変動レグで等しいことから
```math
\begin{align*}
    \frac{R}{2} \times \mathrm{sum}(\mathrm{Annuity}(0)) = PV_{\text{固}}(0) = PV_{\text{変}}(0) = P(0,0) - P(0,N)
\end{align*}
```
を解いて
```math
\begin{align*}
    R & = \frac{2 \times (P(0,0) - P(0,N))}{\mathrm{sum}(\mathrm{Annuity}(0))} \\
    & = \frac{2 \times (1-P(0,N))}{P(0,\text{半年})+P(0,\text{1年})+\cdots+P(0,N)}
\end{align*}
```
が導かれる．

</details>

<details close>
<summary>複製ポートフォリオによる導出</summary>

無裁定スワップレートが上で与えられるとしたとき，それをもとにした固定レグの現在価値は$1-P(0,N)$となる．これを元手に変動レグの支払いを複製できる．

| 時点 | 受取 | 支払 | 受取-支払 |
|:-:|:-:|:-:|:-:|
| 0 | $1-P(0,N)$ | 1 **TIBORに投資** - P(0,N) **割引債に投資** | 0 |
| 1/2 | $1+Y(0,1/2)/2$ **元本償還+利息** | 1 **TIBORに再投資** | $Y(0,1/2)/2$ |
| 1 | $1+Y(1/2,1)/2$ **元本償還+利息** | 1 **TIBORに再投資** | $Y(1/2,1)/2$ |
| … | … | … | … |
| T+半年 | $1+Y(T,T+1/2)/2$ **元本償還+利息** | 1 **TIBORに再投資** | $Y(T,T+1/2)/2$|
| … | … | … | … |
| N | $1+Y(N-1/2,N)/2$ **元本償還+利息** | 1 **割引債償還** | $Y(N-1/2,N)/2$ |


</details>

# 2. QuantLib-Pythonを用いた評価

## 2-1. 商品

[1-1. 商品性](#1-1-商品性)で例として挙げた商品を考える（再掲）．

| | 日本円TIBORスワップ |
| :---: | :--- |
| 通貨 | 日本円 |
| 想定元本 | 13億円 |
| 期間 | 2024年10月15日～2026年10月15日 |
| 支払日 | 2025年4月15日を第1回とし，以降毎年期限までの4月15日と10月15日 <BR> Modified Following Business Day Convention |
| 営業日 | 東京 |
| 金利 | 固定金利 2.00%（Actual/365 (Fixed)，半年後払い） <br> 変動金利 6ヶ月TIBOR（Actual/365 (Fixed)，半年後払い） |
| TIBOR | 金利計算期間の初日の2東京営業日前に発表される6ヶ月日本円TIBOR |

## 2-2. フェア・レート

プロット用のpandas含めてライブラリをインポートする．
```Python
import QuantLib as ql

import pandas as pd
```

評価日を設定し，時間計算の条件を決める．

```Python
today = ql.Date(15,10,2024)
ql.Settings.instance().evaluationDate = today

tenor = ql.Period(ql.Semiannual)                # 利払間隔
calendar = ql.Japan()                           # 祝休日
business_day_convention = ql.ModifiedFollowing  # 営業日調整
day_count = ql.Actual365Fixed()                 # 日数計算法
rule = ql.DateGeneration.Backward               # 日付生成のルール
end_of_month = False                            # 月末日ロール

settle_days_spot_next = ql.Period('2D')         # スワップのラグ
```

ゼロ・イールドから割引カーブを引く．ql.Periodクラスは掛け算ができるので楽をする．

```Python
zero_yields = [
    (today,           0.010), # today
    (today + tenor,   0.015), # 半年
    (today + 2*tenor, 0.018), # 1年
    (today + 3*tenor, 0.019), # 1年半
    (today + 4*tenor, 0.020)  # 2年
]
dates, zero_rates = zip(*zero_yields)
zero_curve = ql.ZeroCurve(dates, zero_rates, day_count) # ゼロ・カーブ生成

discount_curve = ql.DiscountCurve(
    dates,
    [zero_curve.discount(date) for date in dates],
    day_count,
    calendar
    )                                                   # 割引カーブ生成

display(
    pd.DataFrame([(d, discount_curve.discount(d)) for d in dates]
                 , columns=['date', 'df']
                 ).round(3)
    )

discount_curve.enableExtrapolation() # グリッド外を補間
```

`display`の結果はこのようになる．

| date | df |
| ---: | ---: |
| October 15th, 2024 | 1.000 |
|   April 15th, 2025 | 0.993 |
| October 15th, 2025 | 0.982 |
|   April 15th, 2026 | 0.972 |
| October 15th, 2026 | 0.961 |


[1-3. フェア・レート](#1-3-フェアレート)で求めた価格式を用いればフェア・レートは次のように計算できる．

```math
\begin{align*}
    R = \frac{2 \times (1-0.961)}{0.993+0.982+0.972+0.961} = 2.0070\ \%
\end{align*}
```

実際に計算したのが以下である．複雑に見えるが上の計算と照らし合わせて理解されたい．

```Python
annuity = [discount_curve.nodes()[_][1]
           for _ in range(1, len(discount_curve.nodes()))
           ]
fair_rate = (
    2 * (1-discount_curve.nodes()[-1][1]) /
    sum(annuity)
)

print(f'フェア・レートは{fair_rate:.4%}') # フェア・レートは2.0070%
```

次にQuantLIbのvannilaSwapクラスを用いてフェア・レートを計算する．

まずTIBORのフォワードカーブを引く．[1-3. フェア・レート](#1-3-フェアレート)で述べたようにフォワードと割引で同じカーブを用いる．また2営業日前のフィキシング・レートを設定しておく．これがなければ最初の受払におけるTIBORの参照ができない．ここでは**適当に**固定レート合わせて2%とする．

:::note info
正しいフィキシングの計算方法は[3. QuantLib-Pythonによるプライシングの検証](#3-quantlib-pythonによるプライシングの検証)を参照．
:::

```Python
discount_curve_handle = ql.YieldTermStructureHandle(discount_curve)
tibor = ql.Tibor(tenor, discount_curve_handle)
tibor.clearFixings()
tibor.addFixing(calendar.advance(today, - settle_days_spot_next), 0.02)
```

スワップの設定を決めていく．ここで[2-1. 商品](#2-1-商品)の設定を反映する．

```Python
type = ql.VanillaSwap.Receiver
nominal = 1300000000

schedule = ql.Schedule(today,           # 開始日
                       today + 4*tenor, # 終了日
                       tenor,
                       calendar,
                       business_day_convention,
                       business_day_convention,
                       rule,
                       end_of_month
                       )
print(schedule.dates())
# Date(15,4,2025), Date(15,10,2025), Date(15,4,2026), Date(15,10,2026))

fixed_schedule = float_schedule = schedule

fixed_rate = 2 # %単位
spread = 0

swap = ql.VanillaSwap(type, nominal,
                      fixed_schedule, fixed_rate/100, day_count, 
                      float_schedule, tibor, spread, tibor.dayCounter()
                      )
```

スワップの情報が想定通りであるか確認する．

```Python
assert swap.type()                          == type
assert swap.nominal()                       == nominal
assert [d for d in swap.fixedSchedule()]    == list(schedule.dates())
assert swap.fixedDayCount()                 == day_count
assert swap.fixedRate()                     == fixed_rate/100
assert [d for d in swap.floatingSchedule()] == list(schedule.dates())
assert swap.spread()                        == spread
assert swap.floatingDayCount()              == tibor.dayCounter()

assert swap.startDate()                     == schedule.startDate()  # 2024年10月15日
assert swap.maturityDate()                  == schedule.endDate()    # 2026年10月15日
```

価格付けエンジンを定め，フェア・レートを算出し価格式での導出と比較する．誤差は5%程であり，ある程度大きいと判断できる．

```Python
engine = ql.DiscountingSwapEngine(discount_curve_handle)
swap.setPricingEngine(engine)

print(f'フェアレートは{swap.fairRate():.4%}')     # フェア・レートは2.1322%
print(f'差分は{fair_rate - swap.fairRate():.4%}') # 差分は-0.1253% (-12.53bp)
```

# 3. QuantLib-Pythonによるプライシングの検証

誤差が大きいためキャッシュ・フローとNPVを確認する．キャッシュ・フローに違和感はなく，NPVについても最初の割引カーブに沿って計算されていることがわかる．

```Python
df_fixed_cf = pd.DataFrame([(cf.date(), cf.amount())for cf in swap.fixedLeg()],
                            columns=['date', 'fixed_cf']
                           )
df_float_cf = pd.DataFrame([(cf.date(), cf.amount())for cf in swap.floatingLeg()],
                            columns=['date', 'float_cf']
                           )

display(
    pd.merge(df_fixed_cf, df_float_Cf, on = 'date').round(-3)
)

assert (swap.floatingLegNPV() ==
        -1 * df_float_cf['float_cf'].dot(pd.Series(annuity)))
```

`display`の結果はこのようになる．

| date | fixed_cf | float_cf |
| ---: | ---: | ---: |
|   April 15th, 2025 | 12964000.0 | 12964000.0 |
| October 15th, 2025 | 13036000.0 | 13749000.0 |
|   April 15th, 2026 | 12964000.0 | 13688000.0 |
| October 15th, 2026 | 13036000.0 | 15071000.0 |

スケジュールは毎半年の15日に立っているためどうやらフィキシング周りで誤差が出ていると考えられる．実際，フィキシング日を確認すると

```Python
display(
    pd.DataFrame([{
        'fixingDate':     cf.fixingDate().ISO(),
        'accrualStart':   cf.accrualStartDate().ISO(),
        'accrualEnd':     cf.accrualEndDate().ISO(),
        'paymentDate':    cf.date().ISO(),
        'fixing/forward': cf.indexFixing(),
        'rate':           cf.rate(),
        'amount':         cf.amount()
    } for cf in map(ql.as_floating_rate_coupon, swap.leg(1))]).round({'amount':-3})
)
```
フィキシング日が2営業日前にずれている．

| fixingDate | accrualStart | accrualEnd | paymentDate | fixing/forward | rate | amount |
| :--- | ---: | ---: | ---: | ---: | ---: | ---: |
| 2024-10-10 | 2024-10-15 | 2025-04-15 | 2025-04-15 | 0.020000 | **0.020000** | 12964000.0  |
| 2025-04-11 | 2025-04-15 | 2025-10-15 | 2025-10-15 | 0.021094 | 0.021094 | 13749000.0 |
| 2025-10-10 | 2025-10-15 | 2026-04-15 | 2026-04-15 | 0.021116 | 0.021116 | 13688000.0 |
| 2026-04-13 | 2026-04-15 | 2026-10-15 | 2026-10-15 | 0.023122 | 0.023122 | 15071000.0 |

ここから[1-3. フェア・レート](#1-3-フェアレート)で求めた価格式とQuantLibによる実装の違いは

1. 最初のフィキシング・レートが2%である
1. 決済日（settlement days）が2日後

という点であることが原因と考えられるため，これらを修正していく．そのために条件を満たすIborIndexクラスを作成していく．また先ほどのtiborをiborに変更したスワップを作成する．その他の引数は同じものを用いている．

```Python
ibor = ql.IborIndex('Ibor',
                    tenor,
                    0,                     # 決済日との日数の差
                    ql.JPYCurrency(),      # 通貨
                    calendar,
                    ql.Unadjusted,         # 営業日調整
                    end_of_month,
                    day_count,
                    discount_curve_handle
                    )

swap_ibor = ql.VanillaSwap(type, nominal,
                      fixed_schedule, fixed_rate/100, day_count, 
                      float_schedule, ibor, spread, day_count
                      )
```

決済日とフィキシング日とのずれを0としている点に注意されたい．フィキシングの詳細を見ると，
```Python
display(
    pd.DataFrame([{
        'fixingDate':     cf.fixingDate().ISO(),
        'accrualStart':   cf.accrualStartDate().ISO(),
        'accrualEnd':     cf.accrualEndDate().ISO(),
        'paymentDate':    cf.date().ISO(),
        'fixing/forward': cf.indexFixing(),
        'rate':           cf.rate(),
        'amount':         cf.amount()
    } for cf in map(ql.as_floating_rate_coupon, swap_ibor.leg(1))]).round({'amount':-3})
)
```

フィキシング日と決済日のずれがなくなっていることがわかる．

| fixingDate | accrualStart | accrualEnd | paymentDate | fixing/forward | rate | amount |
| :--- | ---: | ---: | ---: | ---: | ---: | ---: |
| 2024-10-15 | 2024-10-15 | 2025-04-15 | 2025-04-15 | 0.015056 | **0.015056** | 9760000.0  |
| 2025-04-15 | 2025-04-15 | 2025-10-15 | 2025-10-15 | 0.021094 | 0.021094 | 13749000.0 |
| 2025-10-15 | 2025-10-15 | 2026-04-15 | 2026-04-15 | 0.021116 | 0.021116 | 13688000.0 |
| 2026-04-15 | 2026-04-15 | 2026-10-15 | 2026-10-15 | 0.023122 | 0.023122 | 15071000.0 |

この新しいスワップについてフェア・レートを計算すると，

```Python
swap_ibor.setPricingEngine(engine)

print(f'フェアレートは{swap_ibor.fairRate():.4%}')     # フェア・レートは2.0070%
print(f'差分は{fair_rate - swap_ibor.fairRate():.4%}') # 差分は-0.0000%
```
のように差分が0になった．

したがって最初のフェア・レートとのずれはフィキシング日とレートの違いによるものでることがわかった．

# おまけ

## プライス

スワップのプライスについては以下で求まる．

```Python
print(f'フェア・レートは{swap.NPV():.3e}') # レシーバー側のプライスは-3.359e+06
```

# -1. おわりに

本記事は社内勉強会の資料を加筆・修正したものである．初学者の助けとなれば幸いである．

また本記事を執筆するにあたって以下の文献を参考にした．

[杉本浩一, 福島良治, 若林公子 著 (2023年)『スワップ取引のすべて 第6版』 金融財政事情研究会
](https://store.kinzai.jp/public/item/book/B/14347/ "出版社へ")

[ジョン ハル 著ほか (2016年)『フィナンシャルエンジニアリング : デリバティブ取引とリスク管理の総体系 第9版』 金融財政事情研究会](https://store.kinzai.jp/public/item/book/B/12176/  "出版社へ")

[木島正明 著 (1999年)『期間構造モデルと金利デリバティブ (シリーズ<現代金融工学> ; 3)』 朝倉書店](https://www.asakura.co.jp/detail.php?book_code=27503  "出版社へ")

[服部孝洋 著 (2023年) 『日本国債入門』 金融財政事情研究会](https://store.kinzai.jp/public/item/book/B/14386/  "出版社へ")

[村上秀記 著 (2015年) 『マルチンゲールアプローチ入門 』 近代科学社](https://www.kindaikagaku.co.jp/book_list/detail/9784764904804/  "出版社へ")