2. "Implementing QuantLib"の和訳

Chapter-V Parameterized Models and Calibration

5.2 Parameters : モデルのパラメータ

“価格モデルは一定の数のパラメータを持つ”と言った場合、そこには曖昧な部分があります。仮に、それらのパラメータがすべて定数であれば、曖昧な部分はありません。例えば Hull-Whiteモデルは2つのパラメータ \( \alpha \) と \( \sigma \) を持ちます、と言っていいでしょう。しかし、もしそれらのパラメータが時間に依存していればどうでしょうか (\( \alpha (t) \) や \( \sigma (t) \) という関数形)。 言い換えれば、それらのパラメータが時間に依存する‘パラメトリックな式’で表現されるかも知れません。概念的には、それでもひとつのモデル変数として取り扱えますが、Calibrationの為に、さらにいくつかの追加の‘数字’が必要になるかも知れません (訳注:パラメータとしての関数が、さらにいくつかのパラメータを持つことになる)。 

下記 Listing 5.3 に示す Parameterクラスは、これを考慮して設計されていますが、その結果、判りにくさも同居する事になりました。このクラスは ”parameter” という用語をクラスのインスタンスそのもの (モデルのパラメータを意味します。それが定数でも、時間に依存する関数形であったとしても) と、そのパラメータが関数形 (パラメトリックな式) で表現される場合の、その関数で使われるパラメータの両方で使っています。プログラムコードの設計者である我々が悪いのですが、読者の方は、これからの説明でこの2つを混同しないように注意して下さい。 

Listing 5.3: Sketch of the Parameter class. 

    class Parameter {
      protected:
        class Impl {
          public:
            virtual ~Impl() {}
            virtual Real value(const Array& params, Time) const = 0;
        };
        boost::shared_ptr<Impl> impl_;
      public:
        Parameter();
        const Array& params() const;
        void setParam(Size i, Real x) { params_[i] = x; }
        bool testParams(const Array& params) const;
        Size size() const { return params_.size(); }
        Real operator()(Time t) const {
            return impl_->value(params_, t);
        }
      protected:
        Parameter(Size size,
                  const boost::shared_ptr<Impl>& impl,
                  const Constraint& constraint);
        Array params_;
        Constraint constraint_;
    }; 

 パラメータ毎の個別の動作については、派生クラスで実装されます (その内のいくつかについてこれから説明します)。しかし、その為に取った方法は、通常とは若干異なります。すなわち、仮想関数をクラスの本体で宣言するのではなく、内部クラスとして Implクラスが作られ、その中で純粋仮想関数である value( )メソッドが宣言されています。このおかしな事をしたのには理由があるのですが、今は飛ばしましょう (Wilmottフォーラムの参加者の誰かが、これは開発者の仕事を守る為だと言っていました。プログラムコードを分りにくくしておけば、開発者以外はメンテナンスできないという理由です。言いたい事は解りますが、それが理由ではありません)。この Idiom は他のクラスでも使われており、その説明は Appendix Aをご参照下さい。 

 Parameterクラスのインスタンスは、原則として時間に依存するパラメータをモデル化しており、配列変数である params_ には、モデルのパラメータが時間の関数形で表現される場合にその関数で使われるパラメータが保持されます。クラスのインターフェースの大半がこれらの付随するパラメータを取り扱うものです。params( )メソッドは、その配列全体を返し、setParam( )メソッドは、その数値を変更する為に使われ、size( )メソッドは、その数を返します。(訳注:原文では、モデルのパラメータをrepresented parameter、そのパラメータが関数形を取る場合にその関数で使われるパラメータをunderlying parameterと使い分けています。) 

 Parameterクラスのインスタンスは、関数で使われるパラメータが取り得る値の範囲を決める制約条件も保持します。testParam( )メソッドは、保持されているパラメータがその制約条件の範囲内かどうかチェックする手段を提供しています。最後に operator( ) は、モデルのパラメータを、(引数として渡された時間に対応する)パラメトリックな関数の計算結果として返します。すでに述べたように、その計算方法の実装は、内部クラスである Implクラスのインスタンスに委託されています。 

最後に、コンストラクターが2種類宣言されています。ひとつは protectedメソッドとして宣言され、派生クラスが自分自身のインスタンスを生成する際に使われます。もうひとつは publicメソッドで、何も動作しない (従って役に立たない)インスタンスを生成しまが、std::vector といったコンテナクラスと一緒に Parameterクラスを使えるようする為です。(この仕組みは、C++ 2011のバージョンを使えば不要になりますが、現段階では古いバージョンを使っているので残っています) 

次の Listing 5.4で、いくつか実際のパラメータの例を示しています。これらのクラスは Parameterベースクラスから派生し、Parameter::Implから派生する Impl内部クラスを宣言し、そのインターフェースを実装しています。 

Listing 5.4: Sketch of a few classes inherited from Parameter. 

    class ConstantParameter : public Parameter {
        class Impl : public Parameter::Impl {
          public:
            Real value(const Array& params, Time) const {
                return params[0];
            }
        };
      public:
        ConstantParameter(const Constraint& constraint)
        : Parameter(1, /* ... */) {}
    };

    class NullParameter : public Parameter {
        class Impl : public Parameter::Impl {
          public:
            Real value(const Array&, Time) const {
                return 0.0;
            }
        };
      public:
        NullParameter() : Parameter(0, /* ... */) {}
    };

    class PiecewiseConstantParameter : public Parameter {
        class Impl : public Parameter::Impl {
          public:
            Impl(const std::vector<Time>& times);
            Real value(const Array& params, Time t) const {
                for (Size i=0; i<times_.size(); i++) {
                    if (t<times_[i])
                        return params[i];
                }
                return params.back();
            }
          private:
            std::vector<Time> times_;
        };
      public:
        PiecewiseConstantParameter(const std::vector<Time>& times,
                                   const Constraint& constraint)
        : Parameter(times.size()+1, /* ... */) {}
    };

最初の派生クラスは、時間に依存しない定数パラメータをモデル化したものです。一般にモデルのパラメータと言う場合、このタイプが想定されており、かつ最も頻繁に使われるタイプです。関数で使われるパラメータを保持する配列 params_ には要素がひとつしか入らず (コンストラクターの引数で1が渡されている事でわかります)、Impl内部クラスの value( )メソッドは、引数で指定された時間に関係なくその値を返すよう実装されています。
 二つ目の派生クラスは、Null値を示す Parameterクラスで、それが保持するパラメータは 0 で、Calibrationでは使われない事を想定しています。この場合、Calibrationでは値が動かないので、params_の配列の要素の数は0です(コンストラクターの引数で 0 が渡されている事でわかります)。このクラスは、より汎用的な FixedParameterクラス (パラメータの値は0でない定数)の特殊なケースと考える事も可能です。  

最後に、三つ目のクラスは、時間に依存するパラメータのクラスです。このクラスは、時間の区間ごとに一定値をとるパラメータとしてモデル化されています。仮に Time-gridの数が n個だった場合、n+1個の値をとります (各 Time-gridの間と、両端の外側の値)。実装方法は、簡単な線形サーチで、Time-gridの数もそれほど多くない事を想定しています。その数を多くしすぎると Over-Calibrateしてしまうからです (訳注:多くの点を通る近似曲線を引く場合、曲線のパラメータの数を多くしすぎると、Over-fittingとなり逆に予測性能を落としてしまうこと)。 

QuantLibライブラリではその他の種類の Parameterクラスも実装しています (例えば、時間に依存するパラメータで、別のパラメトリックな方法で導出されたもの)。しかし、これ以上、読者の方をここに留めるのはやめましょう。ここからは、Calibrationをしてから使われるモデル (CalibratedModel) を'オブジェクト'モデル化したクラスの説明に移りましょう (まぎらわしい言い方ですが、これより間際らしくない表現を思いつきませんでした)。 

 

<ライセンス表示>

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

目次

Page Top に戻る

// // //