2. "Implementing QuantLib"の和訳

Chapter-VI The Monte Carlo Framework

6.3 Putting it all together : すべての部品を使って組み立てる

 すでに、モデルに必要なすべての部品の説明を読まれたので、読者の方は、きちんと作動するモンテカルロモデルを構築する為に、それを統合するプロセスの説明に入る事を期待されているかもしれません。残念ながら、そうする前に、道具箱の中に入っているいくつかの特別な工具を取りだす必要があります。次のセクションの主題は、それについてです。その後でようやく(、開発者の功績である)モデルの組み立ての説明に入りましょう。 

6.3.1 Monte Carlo traits クラス

 すでに述べた通り、モンテカルロモデルを実装するには、(その装置について)数多くの選択肢があります。価格方程式や確率過程の次元によって、1次元あるいは多次元の Path、および Pathの生成装置を選択できます。また、乱数についても、疑似乱数を使うか準乱数を使うか選択できます
(注: これまでの説明に出てきていませんが、それぞれについて、さらに何種類かの生成装置が用意されています。) 

 少なくとも、その内のどれかを選ぶ際、動的な多相性(polymorphism)を持たせるのは選択肢にありません。例えば、Ⅰ次元と多次元の PathGeneratorクラスでは、入力データと戻り値のデータ型が異なる為、共通のインターフェースを持たす事はできません。従って、静的な polymorphismを持たせる方法を選択するしかなく、MonteCarlo Modelクラスに対し、必要な部品クラスを、テンプレート引数として渡すしかありません。 

 問題は、この方法だと、テンプレートクラスの宣言が、次の例のように、長くて解りにくいものになってしまい、非常に経験のあるプログラム開発者でさえも震えさせてしまうでしょう。 

MonteCarloModel<
        MultiPathGenerator<
            InverseCumulativeRsg< SobolRsg, InverseCumulativeNormal> > > 

 もちろん、typedefを使えば、少しはましになります。ユーザーはそれを使ってテンプレートの各選択肢に短い略称を付け、クラスの宣言をもっと短くできるでしょう。デフォールトのテンプレート引数を設定すると、やはりもう少し簡潔にできるでしょう。しかし、我々がとった方法は、まず、クラスの選択肢の中から汎用的に使うグループの略称を定義し、そこにヘルパー関数を組み合わせるメカニズムです。その仕組みを作る為、traits を使うことにしました。(訳注: traitsのうまい日本語訳が見つかりませんでしたので、英語のままにしました。ここでは、テンプレート引数となるクラスの選択肢から、特定のクラスを組合せたものを、ひとつのクラス型として定義してしまうような意味です。) 

 下記 Listing 6.12に、疑似乱数と準乱数の生成装置の為のデフォールトの traits クラスを示します。 

Listing 6.12: Example of random-number generation traits. 

    template <class URNG, class IC>
    struct GenericPseudoRandom {
        typedef URNG urng_type;
        typedef InverseCumulativeRng<urng_type,IC> rng_type;
        typedef RandomSequenceGenerator<urng_type> ursg_type;
        typedef InverseCumulativeRsg<ursg_type,IC> rsg_type;
        enum { allowsErrorEstimate = 1 };
        static rsg_type make_sequence_generator(Size dimension,
                                                BigNatural seed) {
            ursg_type g(dimension, seed);
            return rsg_type(g);
        }
    };

    typedef GenericPseudoRandom<MersenneTwisterUniformRng,
                                InverseCumulativeNormal>
        PseudoRandom;

    template <class URSG, class IC>
    struct GenericLowDiscrepancy {
        typedef URSG ursg_type;
        typedef InverseCumulativeRsg<ursg_type,IC> rsg_type;
        enum { allowsErrorEstimate = 0 };
        static rsg_type make_sequence_generator(Size dimension,
                                                BigNatural seed) {
            ursg_type g(dimension, seed);
            return rsg_type(g);
        }
    };

    typedef GenericLowDiscrepancy<SobolRsg,
                                  InverseCumulativeNormal>
        LowDiscrepancy; 

 最初に、GenericPseudoRandomクラステンプレートが宣言されています。このクラスはテンプレート引数として、一様疑似乱数を生成する RNGクラスと、標準正規分布関数の逆関数 (Inverse Cumulative Function)の関数オブジェクトを取ります。それをベースにいくつかの他の型を定義します。引数として渡された一様疑似乱数の RNGは typedefを使って urng_typeという型名が付けられます (この型名の中の u は uniform、n は number を意味している事に注意して下さい)。この型をベースに、新たに rng_type という型の乱数生成装置の型名が定義されますが、このクラスは標準正規分布関数の逆関数を使って一様乱数を標準正規乱数に変換するオブジェクトです (型名から uniform の u が抜けたのに注意して下さい)。さらに urng_type を使って、一様乱数列の RNG に ursg_typeという型名をつけています ( n が s に入れ替わって、単一の乱数から乱数になっている)。それを使って、標準正規分布の乱数列を生成する RNG に rsg_type という型名がつけられています。enum を使って、コンパイル時の定数として allowErrorEstimate が 1に設定されています (これはstatic const boolにすべきでした)が、この値は、RNGがモンテカルロ法による推定誤差をサンプル数の関数を使って推定していいかどうかを示すフラッグです (訳注:1がYes、0がNo)。そしてヘルパー関数である make_sequence_generator( ) は、引数を使って乱数列の生成装置を簡単に作れるようにしています。 

 その次に、我々が (Libraryの中で)用意している様々な部品の選択肢から、このクラステンプレートのインスタンスを作ります。基本的な疑似乱数生成装置として、MersenneTwisterUniformRngを使い、関数オブジェクトに InverseCumulativeNormalクラスを使っています。殆どのケースで標準正規分布する乱数が必要になるという想定です。こうして出来た traitsクラスは、デフォールトの疑似乱数の RNG になります。かっこいい名前をつけるのは、我々の得意分野ではありませんので、このクラスは単に PseudoRandomクラスと命名しました。 

 GenericLowDiscrepancyクラステンプレートも、同様な方法で定義されていますが、2点異なる部分があります。準乱数は乱数列のかたまりとして生成される為、1つだけ乱数を生成する RNG のタイプがありません。また、推定誤差を示す事が出来ないので、enumeration (allowErrorEstimateの値) の設定は 0 になっています(訳注:いずれも、準乱数の生成方法からすれば当然)。 LowDiscrepancy traitsクラスは、一様乱数の生成装置として SobolRsgクラスを使い、関数オブジェクトとして InverseCumulativeNormalクラスを使って作られています。 

 最後に、モンテカルロ法の動作を制御する様々な型を組み合わせた2つの traitsクラスを定義しています。その型とは、使われる Pathの型、PathGeneratorの型、および PathPricerの型です。その実装内容を下記 Listing 6.13に示します。SingleVariateクラスは、1-Dのモンテカルロモデルに必要な型をまとめたものです。MultiVariateクラスは、多次元のモンテカルロモデルに必要な型をまとめたものです。いずれも、テンプレートクラスで、テンプレートの引数として乱数生成装置の traitsクラスを取ります。 

Listing 6.13: Example of Monte Carlo traits. 

    template <class RNG = PseudoRandom>
    struct SingleVariate {
        typedef RNG rng_traits;
        typedef Path path_type;
        typedef PathPricer<path_type> path_pricer_type;
        typedef typename RNG::rsg_type rsg_type;
        typedef PathGenerator<rsg_type> path_generator_type;
        enum { allowsErrorEstimate = RNG::allowsErrorEstimate };
    };

    template <class RNG = PseudoRandom>
    struct MultiVariate {
        typedef RNG rng_traits;
        typedef MultiPath path_type;
        typedef PathPricer<path_type> path_pricer_type;
        typedef typename RNG::rsg_type rsg_type;
        typedef MultiPathGenerator<rsg_type> path_generator_type;
        enum { allowsErrorEstimate = RNG::allowsErrorEstimate };
    }; 

上記で説明したRNG traitsと Monte Carlo traitsクラスを組み合わせることによって(あるいはユーザーが好みの部品を組み合わせて独自の traits を定義したなら、それを使ってもいいです)、単に、すべて必要な情報がそろったモンテカルロモデルを提供できるだけでなく、それを下記のような極めて分かりやすい単語を使ったかたちで宣言できます。 

  MonteCarloModel<SingleVariate, LowDiscrepancy> ;

この方法は、複雑な部分を、ユーザーレベルでは無く、開発者レベルの負担で簡潔にする考え方です。この仕組みを機能させる為に、templateのテクニックを使わなければなりませんでしたが、うまくいけば、ユーザーにとって、上記のように非常に読みやすい(かつ書きやすい)ものが出来ます。これについては、次のセクションで説明します。
ついにモンテカルロモデルの構築です。 

 

<ライセンス表示>

QuantLibのソースコードを使う場合は、ライセンス表示とDisclaimerの表示が義務付けられているので、添付します。   ライセンス

目次

Page Top に戻る

// // //