Carloシミュレーションの仕組みを使って、PricingEngineをどの様に構築するか、具体例を使って説明しましょう。例として使う商品は、株のバスケットを対象資産とするシンプルなヨーロピアンオプションです。オプションの保有者は、株のバスケット全体を、事前に決めた価格で買う権利あるいは売る権利を保有します。バスケットの中の各株式の数量は事前に契約で決められています。(BasketOptionクラス)の実装内容は示しません。Engineで使うargumentsクラスにも同様の追加が為されています)。Greeksの説明もここでは行いません。)といったメソッドは(対象商品の数に対応する)配列で値を返すことになります。PricingEngineになります。publicクラスとして派生します。McSimulationクラステンプレートからも、privateクラスとして派生します。of”」という関係が構築されます。publicでの継承を必要としません。a”」の関係が構築されてしまいます。Engineであり、シミュレーション方法をモデル化したものではありません。複数のクラスから派生させる事は、一部の方からは敬遠されており、実際にこのケースではそれを避ける事も可能でした。コンポジション(結合)で作る方法、すなわちMcSimulationクラスのインスタンスを持たせる事も可能でした。Engineのデザインがさらに複雑になるといった影響がでるでしょう。PricingEngineの中での実装が可能になります。Methodパターンを使わないようにしなければならないでしょう。PathPricerのインスタンスを引数として取る具体的クラスとして作り直す事です。過去のバージョンとの互換性の問題もさることながら、その手間をかける意味があるかどうか確信が持てません。)最後に、Templateパラメータを見て下さい。MultiVariateクラスをデフォールトで指定しています。Listingでは省略)、引数として、対象資産の確率過程インスタンス、現在価値割引用のイールドカーブ、およびシミュレーションに必要ないくつかのパラメータを取っています。(antitheticVariateフラッグを除く。Structureインスタンスに登録します。)メソッドは、PricingEngineクラスのインターフェースとして(仮想関数なので)実装が必要です。ここでは、McSimulationクラスの持つ、同じ名前のメソッドを呼び出し、それに必要なパラメータを渡します。statisticsインスタンスを受け取り、そこから平均値と、(計算されていれば)推定誤差を取りだして保存します。McEngineクラスを作って、そのインターフェースとして抽象化する事も可能です。すると概念的なオブジェクトモデルをごちゃまぜにしてしまいます。PricingEngineクラスから派生させる事も十分合理的に推定できます。BasketOption::engineクラスの両方から派生させる事になり、忌まわしい継承のダイアモンド形が出来てしまいます。PricingEngineから派生させず別のクラス経由にしたとすると(それをMcEngineAdapterなどと呼んでもいいと思います)、継承の階層にさらに複雑さを加えることになります。MCEuropeanBasketEngineクラスの間に、新たな階層を加える事になり、複雑性を全く取り除けていない事になります。従って、今のままにしておくのがいいと思います。Listingで示したコードで残りの部分は、McSimulationクラスの3つのインターフェースを実装しており、これによって、このクラスは実際に動作するクラスとなります。)メソッドは、シミュレーションに必要な離散時間のステップを、行使日を基準にした最終期日と、ステップの数を使って生成します。PricingEngineのコンストラクターに渡される引数によって、与えられた総ステップ数であったり(最初のif文)、1年あたりのステップ数であったりします(次のif文)。いずれの場合も、総ステップ数に換算されて、TimeGridクラスのコンストラクターに渡されます。いずれの指定も無かった場合は(else文の後)、エラー処理が走ります。(当然ながら、上記の2つの数字の積です)、疑似乱数列の生成装置を構築します。timeGridを使って、MultiPathGeneratorインスタンスを生成します。Payoffを判定するのに必要なデータを集めます。Payoffオブジェクトそのもの、行使日における残高および割引率(いずれもこのメソッドが事前に計算している)で、それらを使って、EuropeanBasketPathPricerクラスのインスタンスを生成します。PathPricerは、引数で取ったデータを保存し、それを使ってオプションの実現価値を計算します。)関数をオーバーロードして実装されています。実装内容は、オプション期日における対象商品のバスケットの価値を計算し、その計算結果(すなわちPayoff)を現在価値に割引いて返します。loop計算で、保存された対象商品の数量の配列と、オプション満期時におけるそれらの価格(各商品に対応するPathの最後の値)を使って為されます。これで、PricingEngineは完成ですが、まだ少しインスタンスを生成するには使いづらい所があります。Factoryクラスを加えてもいいかも知れません。すると、次のようなプログラムコードになるでしょう。.withAntitheticVariate();ここでは、その実装内容を示しませんが、QuantLibライブラリーでこのような例がたくさんありますので、目を通してみて下さい。すると、気づかれると思いますが、これらのプログラム例は、できるだけシンプルに作ったので、汎用性のあるプログラムコードにしなかった部分もあります。別のPathPricerでは、オプション期日とは異なる日付の価格を使う場合もあり、それに合わせてTimeGridインスタンスも生成されなければなりません。Payoffが、Pathの経路に依存しているケースもあり、その場合PathPricerはPathの最後の値のみならず、経路の途中の価格も見に行く必要があります。これらに対応するようなプログラムコードを書くのは、ユーザーの方にはそれ程難しい事では無いと思います。>これまで通り、今まで説明してきたいくつかのクラスについて、どの(ソース)ファイルに置くべきか示してきませんでした。基本原則として、「カプセル化できるものは、できるだけそうする」ようにしています。従って、helperクラスなどは、publicなインターフェースからは、隠すべきでしょう。EuropeanBasketPathPricerクラスなどは、PricingEngineの中で使われるのみであり、ユーザーが再利用できないように、隠した方が良いでしょう。その為の最適な方法は、.cppファイルの中の匿名のnamespaceの中で定義する事でしょう。それが常に可能な訳ではありません。Engineクラスの場合、Templateクラスなので、その選択肢は取れません。QuantLibライブラリーの中での基本的な決め事としては、helperクラスはヘッダーファイルの中で宣言し、実装内容は“detail”という名前のnamespaceの中に入れ込んでしまう事にしています。ユーザーの方は紳士協定に(当然淑女協定にも)従って、それに触らないようにして下さい。PricingEngineで使うような場合)、その内容をヘッダーファイルに移す事もできます。ヘッダーファイルに含まれている場合は、実装内容をメインとなる“QuantLib”のnamespaceに移して、誰にでもアクセス可能なように出来ます。**********************************************************************************これまでのすべての説明を聞いた後でも、まだ疑問があるかも知れません。「このPricingEngineクラスはどの程度汎用的なのか?」と。私が望んでいたレベル程ではないです。Engineを利用でき、かつきちんと動く、という意味では汎用的です。exoticな商品にも対応可能です。decorateパターンを使えばもっと素晴らしい)。それを、PricingEngineのコードには一切触らず、使う事ができます。Volatility自体も確率変動すると仮定したモデル)。VolatilityのPathなのか区別するすべが無いという事です。PathPricerのプログラムコードを作成するというのも方法ですが、もう少し再利用可能なアイデアを提供したいと思います。PathPricerクラスで、プログラム上の決め事を同じにする事です。Pathと決めてしまう事です。PathPricerはきちんと動きます。loopは、Processの数ではなく、対象資産の数だけ繰り返しを行っているという所を見れば、解ると思います。この方法では、Processクラスの方で、この決め事を守らなかった場合、そのバグがチェックされないままエラーが発生するリスクを高めます。decorateし、そのクラスでは確率変数として対象資産の価格のみ外に取りだせるようにし、それ以外の確率変数は隠すようにする事です。Processオブジェクトと同じ数の確率変数を要求しますが、外にはそれより少ない確率変数しか出さないようにします。(その値は、他のメソッドに渡されないでしょう)の動きを監視しなければならないので、その状態変数を保持できるようにしなければなりません。)を呼び出し、追加の確率変数の更新値をメンバー変数に保持して次のメソッドを呼び出す時に使えるようにし、最後に対象資産の価格だけを返すようにしなければなりません。私はこの解決方法が好きではありません。このデザインでは、decorateされたメソッドが、予想された順序で呼び出されない限りきちんと動きません。そのメソッドを、全く同じ引数(初期値と確率変数)を使って2回呼び出した場合、隠された状態変数が更新されている為、異なる値が返ってくることになります。(訳注:適切な日本語が見つからないので英文のままにします)を失う事」になります。短く言えば、「インターフェースが嘘」という事です。Processクラスの手を借りて、フィルターをかける役割を負わせる事です。bool変数の配列で、[i]番目の値がtrueであれば、[i]番目のPathは対象資産の価格である事を示すもの)を返すメソッドを提供できれば、PathGeneratorクラスはその情報を使って、確率変数の推移を正しくシミュレートし、同時にMultiPathクラスに対象資産の価格の情報のみを書き込むことが出来るでしょう。PathGeneratorクラスに渡せるようにしなければなりません。StochasticProcessベースクラスは、空のマスクを返すメソッドをデフォールトで実装しなければなりません。マスクの情報が渡されなかった場合は、PathGeneratorは、今実装されている通常の動作に戻すようにします。必要であれば、そのメソッドをより汎用的にして、対象資産の価格だけでなく、他の確率変数のマスクにも使えるように出来ます。Swapでは、対象資産の価格ではなく、Volatilityの方の情報を必要とするでしょう。PricingEngineには、いくつかの前提が組み込まれており、その前提を変える場合は、プログラムコードの書き換えが必要になる点を指摘しておきます。オプション行使日における割引率は、決まっているものとして取り扱っています。PathPricerクラスのプログラムコードを用意しなければなりません。幸運なことに、ユーザー自身でプログラムすべきは、その部分だけであり、モンテカルロの全体のフレームワークの中の、他の部分は引き続き使う事ができます。<ライセンス表示>QuantLibのソースコードを使う場合は、ライセンス表示とDisclaimerの表示が義務付けられているので、添付します。