Bootstrapクラステンプレートは、まさに生成されているイールドカーブ(自分自身this_curve)を使ってインスタント化されます。Bootstrapインスタンスは、このカーブ(this_curve)の内部変数、内部メソッドにアクセスできるようにするため、PiecewiseYieldCurveクラスのフレンドとして宣言されています。同様のfriend宣言は、BootstrapErrorクラスでも行われています。このクラスはBootstrapのアルゴリズムの中で使われますが、これについては後で説明します。最後に、Bootstrapクラスのインスタンスと、イールドカーブ目標精度の要求水準、さらにhelper(原商品のレートを扱うクラス)をメンバー変数として保持します。ここから実装を見ていきましょう。コンストラクターの実装に驚きは無いと思います。ベースクラスに必要な引数を渡し、それ以外の引数は自分のメンバー変数に格納しています。最後にメンバーとして保持しているBootstrapクラスのインスタンスに自分自身の情報を渡し、あらかじめ行っておくべき計算をさせています。この事については後で説明します。)メソッドの実装は、あいまいさを残さないよう、注意が必要です。)メソッドなのか推定させるのは酷です。)を明示的に呼び出すようにしています。)メソッドは、実際の計算をBootstrapのインスタンスに委託しています。)メソッドの中味は、なぜこのメソッドがOverrideされないといけなかったかが、一目でわかります。)が呼び出されています。このやり方は、他のインスペクターとなるメソッドにも当てはまります。ForwardRateStructureから派生していたとしても、オーバーライドする必要はありません。)から呼び出されるからで、関数のOverride(書き換え)はこの関数のみで十分です。ここでBootstrapHelperクラスのテンプレートを説明する必要があります。このクラスのインターフェースは下記Listing3.9に記述の通りです。traitsのところで説明した通り、我々はBootstrapHelper<YieldTermStructure>のようなかたちでインスタンスを生成し、カーブの中で使いたいと考えます。便宜上、Libraryはこのクラスに対し(長ったらしいクラス名を簡略化する為)RateHelperという別名を提供しています。このクラスのインスタンス(あえて言えば、この派生クラスのインスタンス)は、イールドカーブ上のひとつのNode(Pillar)におけるBootstrapアルゴリズムの補助を行います。あるNodeにおける入力データは原商品の市場レートになります。この情報は、常に変動するため(情報そのものではなく)“Quote”インスタンスに対する、“Handle”のかたちで渡されます。イールドカーブ構築の為の原商品としては、インターバンク預金金利、スワップなどがあり、それぞれ固有の方法で市場金利が呈示されています。従って、それぞれの商品毎に(RateHelperの)派生クラスを用意しなければなりません。BootstrapHelperのすべての派生クラスに共通のメソッドは、ベースクラスで実装されています。BootstrapHelperクラスは、ObserverとObservableの2つのベースクラスから派生しています。従ってその両方の機能を持っており、(Observerとして)市場データのクラスに自らを登録し(データの変更があれば通知を受ける)、(Observableとして)自らに登録されたイールドカーブ(インスタンス)に対し、データの変更があれば通知し、再Bootstrapを促します。コンストラクターは、Handle<Quote>(市場データを保持しているQuoteクラスのHandle)を引数として取り、それをメンバー変数に保持すると同時に、(Observerである)自らを(Observableである)Quoteインスタンスに登録します。3種類のメソッドが用意されており、いずれも原商品の価格(利回り)を取扱います。)メソッドは、市場データを保持しているインスタンスのHandleを返します。)の間違いと思われる)、Bootstrap後(あるいはその最中)のイールドカーブを使って計算された(原商品の)レートを返します。)で計算されたレートの誤差をプラスマイナスの表示付きで返します。2種類のメソッドがBootstrapのアルゴリズムの構築の為に用意されています。)メソッドは、helperインスタンスを、生成するイールドカーブにリンクさせます。)メソッドは、イールドカーブのNodeの中で一番最後の日付を返します。その日付は、イールドカーブからその各Nodeの原商品の金利をBootstrap計算する上で、一番最後のデータポイントとなります。(この一番最後の日付は、必ずしも原商品の中で一番期間が長いものに対応するとは限りません。Swapであるなら、イールドカーブは、そのスワップの最終期日からさらに何年か先まで(変動金利のインデックスとなっているスワップの期間の最終日まで)伸ばしておく必要があります。)メソッドは、Quoteのインスタンスから送られてきた(市場レートが変化したという)通知を、さらにhelperのObserverインスタンスへ転送するものです。3.9には含まれていないので、別途QuantLibのソースコードで確認して下さい。)QuantLibではRateHelperクラスから派生するいくつかの具体的なHelperクラスを用意しています。簡潔にするために、実際のコードを載せず、身振り手振りでの説明で済ませることをお許し下さい。)となっているが間違いと思われる)を実装しています。Rateを予想します。Valueを計算します。Multi-Curveの方法でデリバティブズの値洗いを行う場合は、BootstrapしたカーブをForwardingカーブとして使い、別のカーブをDiscountingカーブとして使うこともできます。興味があるなら、Multi-Curveに関するより詳細な説明は、下記の文献を参照して下さい。2013.これで、やっとBootstrapのプログラムコードの中味を詳しく見ることができます。3.10にIterativeBootstrapクラスのインターフェースを示します。このクラスはQuantLibライブラリで提供されており、デフォールトで使われているBootstrapの方法です。}}便利なように、curveインスタンスからtraitsタイプとinterpolatorタイプを抜き出し、typedefを使って型名を作っています。)メソッドは、特に興味をそそるようなものではありません。コンストラクターは、メンバーとして持つTermStructureインスタンスへのポインターをNullに初期化しているだけです。3.10に含まれていないので、ソースコードで実際に確認して下さい)。)メソッドで実装されています。Libraryにあるソースコードを読んで下さい(訳注:但し100行以上あります)。配列がそれに該当)に、(Bootstrappingしようとしている)今のTermStructureのインスタンスをセットします。)の中で、計算の都度行っています。理由は、同じhelperインスタンスを他のイールドカーブでも使えるようにする為です。(注:当然ながら、マルチスレッドの動作環境では、競合が起こるため、同じhelperの集合を他のカーブに渡すのは安全ではありません。次に、各データの配列を初期化します。配列の最初のNodeの日付と(カーブ上の)値は、引き渡されたtraitsインスタンスから取ってきます。dateに該当します。最初のNode(カーブ上の)値は、Bootstrapされるカーブの種類によって変わってきます。ディスカウントカーブでは、1になり、ゼロ金利カーブやフォワード金利カーブにおいては、ゼロとかダミーの値を入れておきます(このダミー値はいずれにしてもBootstrapのプロセスの中で書き換えられていきます)。日付配列の残りの要素は、各helperインスタンスの持つ最終期日を順次代入していきます。ここで、1次元Solverのインスタンスを生成します。Loopアルゴリズムになっています。ネストの内側のループ計算(ここでは正規のBootstrapと呼んでおきましょう)は各NodeのBootstrapを順番に行っており、外側のループ計算は、それを何回かやり直す為のものです。Splineのように)Non-localなInterpolationの方法(訳注:高次のSpline関数の係数を求めるため、線で繋ぐ2点のNodeだけでなく、すべてのNodeポイントのデータを使って連立方程式を立て、その解を計算する方法)の場合、あるNodeの値をBootstrapで計算すると、カーブ全体がその影響を受けるため、すでにBootstrap済のNodeの値を(誤差が一定の許容範囲に収まるまで)再Bootstrapする必要があるからです。述べた通り、内側のForループは、カーブの期間の最も短いNodeから始め、順番に期間の長いNodeへ進んでいきます。(iteration==0)の部分)、InterpolationはNodeを1つずつ進んで行きます(訳注:この部分は、QuantLibの原コードを見ると、すこし違ったコーディングがされていますが、趣旨は同じです)。それが最後まで終わると、一応すべてのNodeのデータが得られます。2回目以降のIterationは、そのデータ全部を使って(すなわち、それを初期値として一次の連立方程式の解を求めるアルゴリズムを走らせ、)各Nodeポイントにおける市場レートを導出します。traitsから取ってくる事も可能ですし、カーブを線形補外して一旦guessとして使う事も可能です。2回目以降の再帰計算では手前で行った計算結果を新たなguessとして使います。各Nodeの最大値と最小値も、既に計算された各Nodeの値を使って、Traitsクラスから提供されます。ゼロ金利カーブやフォワード金利カーブのBootstrapを行うTraitsでは、最小値を0で設定しており、マイナス金利を発生させないようにしています。ディスカウントカーブのTraitsでは、カーブの中で増加部分が発生しないようにして(各Nodeの最大値を一つ前のNodeの値に設定することによって)、同じくマイナス金利を発生させないようにしています。(訳注:2010年代に入り、Sfr、Euroや円金利でマイナス金利が常態化してきており、この制約は見直す必要あります。QuantLibライブラリを見ると、マクロ変数としてQL_NEGATIVE_RATESを定義しており、マイナス金利を許容する場合は、上記のチェックをはずすようになっています)連立方程式の解を出すアルゴリズムの為に必要な最後の要素は、解が0になる関数です(訳注:最小値問題)。それは、BootstrapErrorクラステンプレートで提供されています(下記Listing3.11参照)。)メソッドを、関数オブジェクトインターフェースにより取り込んでいます。このクラスのコンストラクターは、引数として、生成されるイールドカーブのポインター、各Nodeに対応するhelper、およびNodeのインデックス番号を取り、それらをメンバー変数に代入しています。)メソッドは、このクラスのインスタンスを生成して関数として使えるようにしています。error(値の誤差)を返します。};これで、すべての準備は整いました。ループでは、BootstrapErrorクラスのインスタンスが生成され、それがsolverインスタンスに渡されます。solverは、そのNodeの値を誤差ゼロで返します。quote(Bootstrap後で再計算された市場レート)が、市場レートと許容範囲の誤差内で一致しているという事です。(原)イールドカーブのデータは、(Bootstrapにより返されたデータにより)更新され、またloopによる再計算が開始されます。すべてのNodeのBootstrapが終われば、外側のLoopが、再計算が必要かチェックを行います。interpolationであれば、そこで終わりです。interpolationであれば、誤差のチェックを行い、それが一定値以下になるまで再びLoopでの再計算が行われます。以上で、Bootstrapアルゴリズムの説明を終了します。これ以上、読者の忍耐力を試すつもりはありませんので、このExampleによる説明もここで終わります。PiecewiseYieldCurveクラスのサンプルコードはQuantLibの提供するサンプル例の“Swap-valuation”で使われていますので、参考にして下さい。>(C++に精通の読者は)PiecewiseYieldCurveクラスの宣言を見て、「ちょっと待てよ」とおっしゃるかもしれません。friendクラスとして宣言すると、encapsulationを壊す可能性があり、クラス間の整合性を厳密にとっていく必要が出てきます。Bootstrapクラスはカーブのデータに対し、書込みを行う必要があります。仮にfriendクラスとして宣言せずに、カーブデータに対するアクセス権を与えるとしたら、それには3つの方法があります。ひとつめは、(カーブのデータを)Bootstrapインスタンスに渡してしまう方法です。これは2つのクラスのデータ整合性を取るために同様に厳格なプログラミングが必要になります(また、カーブクラスの内部変数を変更しようとすれば、Bootstrapクラスのプログラム内容の変更も必要になります)。2番目は、カーブクラスの持つ内部変数データをpublicなインターフェースで解放する方法です。これはencapsulationを壊す、より大きなリスクをもたらします(Bootstrapの過程でカーブデータを書き換える必要がある事を思い出して下さい)。最後に、カーブのデータを別のクラスに持たせて、Privateな継承でアクセスをコントロールする方法です。Release1.0の段階では、Friendの宣言が最初の2つの選択肢より優れ、プログラムもシンプルになると考えていました。3番目のオプションがおそらくベストだと思いますが、今後のReleaseで導入を検討していきたいと思います。プログラム例:イールドカーブにz-スプレッドを追加:このセクションのプログラム例は(前のセクションよりもかなり簡単ですが)、あるイールドカーブにスプレッドを加え、別のイールドカーブを生成する方法を説明します。ここでは、すでにあるリスクフリーのイールドカーブを、修正してクレジットカーブを生成してみます。リスク相当部分をz-spread、即ちゼロ金利カーブに加えられる固定スプレッドとして表現します。Pattern)を使っています。当初のオブジェクトに対し、いくつかの動作を加える一方、残りの動作は当初のインスタンスに任せるという形で、当初のオブジェクトを包み込む技法です。};上記Listing3.12では、ZeroSpreadedTermStructureクラスの実装を示しています。述べた通り、ゼロ金利のイールドカーブをベースに構築されています。)メソッドをここで実装しています。当然の事ながら、コンストラクターは、修正元となるゼロ金利カーブ(のHandle)と、そこに足される固定スプレッド(のHandle)を引数としてとっています。データソースを変更できるようにする為、いずれの引数もHandleとして取り込まれています。引数は、メンバー変数に格納され、かつ(それらをObservableとして)ここで生成されるイールドカーブをObserverとして登録します。)メソッドが、Observableクラスから飛んできたデータ更新の通知を処理します。このクラスのコンストラクターでは、ベースクラスのコンストラクターを明示的に呼び出していない点に注意して下さい。3.1での説明を思い出して欲しいのですが、これは即ち、ここで生成されるイールドカーブのインスタンスは、ベースクラスとなるTermStructureクラスの仕組みの中で使われるデータを一切持たないという事です。Dateの計算についても、自分自身でそれを用意する必要があります。Patternでは、それを(自身で用意するのではなく)、包含されるオブジェクトのメソッドに委譲されます。Freeのカーブが持つそれぞれ対応するメソッドに委譲しています。最後に、このクラス独自の動作(メソッド)、即ち固定スプレッドを加えるという動作を、実装しています。)メソッドの中で行われています。Free金利(当然ながら連続複利利率で表示されたもの)を、ベースとなるゼロ金利カーブから取得し、それに固定スプレッドを加え、その結果の値を新たなゼロ金利として返します。curveを生成してくれます。<ライセンス表示>QuantLibのソースコードを使う場合は、ライセンス表示とDisclaimerの表示が義務付けられているので、添付します。