Instrumentsは、それ自体ですでに基本概念です。Classとして構成し、そこから様々な種類の金融商品の派生クラスを定義していくでしょう。)で価格が返ってくるような仕組みにしておけば、様々な商品のポートフォリオの総額を計算する場合、上記のような簡単なコードで記述できるという事)このように関数を定義すれば、具体的な商品のタイプを気にする必要ありません。)のメソッドにどのような引数を渡せばよいのか解らないし、さらにどのようなメソッドを呼び出すのかも解りません。Classが持つべき)インターフェースについてよく考えてみる必要があります。金融市場では、-非常に単純な商品から非常に複雑な商品に至る-広範な商品が取引されており、ある特定の商品(例えば株式オプション)のクラスに特有のメソッドが、他の商品(例えば金利スワップ)では意味をなさないという事は十分起こり得ます。従ってInstrumentsベースクラスで定義すべき、すべての金融商品に共通のメソッドの数は極めて限られました。我々は、その共通するメソッドを、現在価値を返すメソッド(場合によっては推定誤差の値も含めて)と、その金融商品が満期を過ぎているかどうかを返すメソッドだけにしました。templatesのような技術を使っても)、ベースクラスでは特定できない為、そのメソッドは引数を取らない形で宣言しています。従って、メソッドに必要な入力項目は、金融商品ごとに、保存されなければなりません。その結果、Instrumentクラスのインターフェースは下記Listing2.1のようになっています。};プログラミングの慣行に従って、当初、各メソッドはすべて純粋仮想関数にしました。Lifeが指摘したように)必ずそうしなければならないというものではありません。ベースクラスで具体的に定義・実装した方が良いようなプログラムの動作があるかもしれません。本当にそうなのか調べるために、一般的な金融商品に期待される共通の動作が何であるのか、またそれを実行させる為のプログラムで共通するところはあるのか、よく分析してみる必要がありました。その結果、QuantLibの開発過程のなかで、2つの必要事項が見つかり、開発期間中に実装の方法を変更しました。ここでは、それらの現時点での実装内容を説明します。ひとつは、特定の金融商品について、価格計算の方法が複数存在し(例えば、解析解で価格計算をする方法と、数値解でそれを行う方法)、その実装を継承の仕組みを使わずにできないだろうかということです。Patternを使えばいいのではと思われるかもしれません。本チャプターのSection2.2で、その実装方法を説明します。ひとつは、金融商品の価格は、市場データに依存しているという事実からくるものです。市場データは、本質的に時間の経過によって変化するものです。従って、その商品の価格も時間の経過によって変化していきます。金融商品の価格変化は、市場データを提供するソースが複数存在しうるという点からも発生します。我々は、ひとつの金融商品が複数のデータソースとリンクできるようにする必要があると考えました。その場合、価格計算のメソッドを呼び出した時は、その都度、最新データを使って金融商品の価格を再計算させるような仕組みが必要と考えました。複数のデータソースを任意に選択できるような仕組みも必要と考えました。データソースを変更した場合は、その金融商品にとっては、市場データのアップデートと同じ取扱い(都度価格の再計算を行う)とすべきとも考えました。効率性の低下も関心事でした。多くの金融商品をひとまとめにして、定期的に時価を確認して、ポートフォリオの全体の価値を適宜モニターするとします。その際、単純な仕組みでは、時価の変更が無かった商品についても、すべて価格の再計算を行ってしまう可能性がありました。従って、Instrumentクラスのメソッドの中に、時価を一時保管する仕組みを取り入れました。時価の再計算は、市場データの更新があった場合のみ行い、それ以外の場合は、一時保管されている値を使うような仕組みです。実装どの金融商品についても共通な、価格を一時保管したり、再計算したりする仕組みを司るプログラムコードは、2種類のデザインパターンを使って書かれています。文献を参照)入力データに変更があった場合、InstrumentクラスはObserverパターンを使って、その変更の通知を受ける仕組みにしています。Four(4人組)」の(有名な)本を読まない理由にしないでください。ここではどのようにそれが使われているか解説します。(金融商品と市場データとの関係から)明らかなように、InstrumentクラスはObserverの役割を持ち、(Instrumentが価格計算で使う)市場データはObservableの役割をもっています。入力データ(訳注:市場データ)が更新された場合、それを(ObserverであるInstrumentに)通知されるような仕組みを構築する為には、Observerが、その入力データを保管しているオブジェクト(Observable)への‘参照’を保持しておく必要があります。Pointer(訳注:メモリーリークを防ぐため、ポインターの指し示すメモリー領域の管理を自動的に行ってくれるポインター)が必要になると気づかれるでしょう。ポインターの仕組みだけでは、我々が必要としているメカニズムにとって十分ではありません。説明した通り、入力データの変更は、市場価格が動く以外に、データソースの変更からも発生します。(訳注:例えば、同じ銘柄の株が複数の取引所で取引されている場合、データソースは一本だけではない)(Smart)ポインターを1つしか持たない場合、それが参照するオブジェクトの直近のデータのみにしかアクセスできません。我々が必要とするのは、ポインターを保持するポインターです。この仕組みは、QuantLibの中では、Handleという名前のクラス・テンプレートを使って実装されました。ここで議論となっている点と関連する部分で言えば、ある特定のHandleの複数のコピーは、ひとつのオブジェクトに対するリンクを共有しているという点です。仮に、ポインターが別のオブジェクトを指すようになった場合、Handleのすべてのコピーにそれが通知され、それらのHandleを保持しているオブジェクト(訳注:Instruments)に対し、新しいポイント先(のデータ)を通知する仕組みになっています。Handleは、そこが指し示しているオブジェクト(訳注:市場データを保持するオブジェクト)から、それを監視するすべてのObserver(訳注:市場データをモニターしているInstruments)に対し、データ変更の通知を転送する仕組みを持っています。市場データの役割を持ち、Handleクラスの中で保持できる、様々な種類のObservableクラスを実装しました。その中で、最も基本的なクラスがQuoteクラスで、市場価格を一個だけ保持する機能を持っています。金融商品の価格計算に必要な市場データ(Observable)は、その他にも、もっと複雑な構造を持つイールドカーブやボラティリティのTermStructureクラスなどがあります。(それらのクラスも、最終的には一個しかデータを持たないQuoteクラスのインスタンスに行きつきます。イールドカーブオブジェクトはBootstrappingを行うため、預金金利やスワップレートを保持するQuoteクラスのインスタンスを必要とします)Instrumentベースクラスが持つもう1つの課題は、具体的な価格計算のアルゴリズムは派生クラスで実装するとして、ベースクラスにおいて価格の再計算を行った後の値を一旦保持しておくメカニズムを、どのように抽象化するか、という事です。QuantLibの初期の頃のバージョンでは、この仕組みをInstrumentクラスそのものに、含めていました。その後のバージョンで設計を変更し、その仕組みを抜き出して別のクラスに持たせることとしまた。そのクラスはLazyObjectという名前で呼ばれており、ライブラリの中で、他の用途にも使われています。};プログラムコードは極めて単純です。calculated_は、価格の計算結果が“直近のものかどうか”のフラッグを保持します。)メソッドは、(ベースクラスである)Observerのメソッドを実装したものであり、Observableクラスから(入力データが更新されたという)通知が届いた場合に、メンバー変数calculated_をfalseにセットし、すでにある価格計算結果を、古いものとして扱います。Methodパターンを使って実装されています。その仮想関数は、ベースクラスのメソッドの中で呼び出されます。)の実装の中で)特定すればよいだけで、計算結果の一時保存について考える必要がありません。派生クラスの実装部分は、ベースクラスのメソッドの中に(コンパイルの際に)組み込まれます。計算結果の一時保存のロジックは単純です。フラッグがfalseにセットされている)、派生クラスにおいて価格の再計算を行い、calculated_フラッグを再びtrueに戻します。現在保存されているデータが最新分であれば何もしません。ロジックは簡単でも、実装はそれほど単純ではありません。)メソッドを呼び出す場合が想定されるからです(例えばLazyObjectがイールドTermStructureで、Bootstrappingを行うような場合)。)が再び呼びだされ、無限ループに陥ってしまいます。)が実行される前に)このフラッグをtrueにセットする事により、そういった事が防げます。)の実行時に)エラーにより例外処理に飛ぶ場合は、その前に、このフラッグをfalseに戻しておく必要があります。その後、さらに再例外処理に飛び、インストールされているエラー処理Handlerにプロセスが移動します。LazyObjectには、さらにいくつかのメソッドが用意されており、ユーザーに再計算を行わせないようにしたり、逆に強制したりできるようになっています。これについてはここでは説明しません。InstrumentクラスはLazyObjectから派生しています。)に、派生クラスで機能を追加している)しています。Methodパターンに従って、派生クラスに、そのInstrumentに固有な計算アルゴリズムの実装を委任できるようにしています。(訳注:このクラスの段階でperformCalculations()を実装しておらず、さらに派生するクラスでの実装を前提にしている。)このクラスは、価格計算結果を一時保存するメンバー変数、NPV_を持っています。派生クラスではそこで必要なメンバー変数を追加で宣言する事ができます。(注:Instrumentクラスでは、ここでは書いていませんが、その他にerrorEstimate_変数が定義されており、NPV_に関する論点がそのまま適用できます)。)を呼び出して、その商品の期限が到来しているかどうかをチェックしています。)を呼び出し、NPV_を適切な値にセットします。デフォールトの設定はNPV_を0に設定しますが、派生クラスで別の適切な値とする事も可能です。その後calculated_フラッグをtrueに設定します。)に一定の作業を必ずさせる必要があります。NPV_に計算結果を、(メンバー変数に)書き込む事です。(その他派生クラスに特有のメンバー変数への値の代入も必要になります。)メソッドを呼び出して、その値をまず計算するようにしています。>変数NPV_が、なぜmutableで宣言されているかの説明に興味を持たれるかも知れません。calculationを実装する際には、この問題が常に発生するからです。)メソッドは、論理的にはconstメソッドであり、商品の価格計算は、データを変更しないという事です。従って、Libraryのユーザーは、そのようなメソッドをconstなインスタンスから呼び出しても、意図せざるデータ変更が為される事はないという事を期待してかまいません。)などのメソッドもconstで宣言しなければなりません。我々が目的とするところの、価格計算をlazilyに行ったり、計算結果を一時保存したりする機能を実装しようとすると、そういったメソッドの本体中にデータ書き換えが可能な変数を必要とします。データを一時保存する為のメンバー変数をmutableとして宣言することによりそういった問題が解決されます。)メソッドのconst化と、メンバー変数のlazyな役割を担わせる事、が達せられます。11では、constメソッドをマルチスレッドでも安全性を持たせる必要がある点を注意しなければなりません。Sutterの著書を参照)。新しいC++のスタンダードに準拠するために、mutableとして宣言されたメンバー変数をmutexで保護しなければなりません。デザインの変更が必要になってくると思われます。2013.<ライセンス表示>QuantLibのソースコードを使う場合は、ライセンス表示とDisclaimerの表示が義務付けられているので、添付します。