2. "Implementing QuantLib"の和訳
Chapter-VI The Monte Carlo Framework
6.3 Putting it all together : すべての部品を使って組み立てる (つづき)
6.3.2 MonteCarloModel : モンテカルロモデル
下記 Listing 6.14に示すのは、MonteCarloModelクラスの実装です。このクラスはモンテカルロシミュレーションのベースとなる動作を担います。
Listing 6.14: Implementation of the MonteCarloModel class template.
template <template <class> class MC, class RNG,
class S = Statistics>
class MonteCarloModel {
public:
typedef MC<RNG> mc_traits;
typedef RNG rng_traits;
typedef typename MC<RNG>::path_generator_type
path_generator_type;
typedef typename MC<RNG>::path_pricer_type path_pricer_type;
typedef typename path_generator_type::sample_type
sample_type;
typedef typename path_pricer_type::result_type result_type;
typedef S stats_type;
MonteCarloModel(
const boost::shared_ptr<path_generator_type>&
pathGenerator,
const boost::shared_ptr<path_pricer_type>& pathPricer,
const stats_type& sampleAccumulator,
bool antitheticVariate,
const boost::shared_ptr<path_pricer_type>& cvPathPricer
= boost::shared_ptr<path_pricer_type>(),
result_type cvOptionValue = result_type(),
const boost::shared_ptr<path_generator_type>& cvGenerator
= boost::shared_ptr<path_generator_type>());
void addSamples(Size samples);
const stats_type& sampleAccumulator(void) const;
private:
boost::shared_ptr<path_generator_type> pathGenerator_;
boost::shared_ptr<path_pricer_type> pathPricer_;
stats_type sampleAccumulator_;
bool isAntitheticVariate_;
boost::shared_ptr<path_pricer_type> cvPathPricer_;
result_type cvOptionValue_;
bool isControlVariate_;
boost::shared_ptr<path_generator_type> cvPathGenerator_;
};
template <template <class> class MC, class RNG, class S>
MonteCarloModel<MC,RNG,S>::MonteCarloModel(
const boost::shared_ptr<path_generator_type>& pathGenerator,
...other arguments...)
: pathGenerator_(pathGenerator), ...other data... {
if (!cvPathPricer_)
isControlVariate_ = false;
else
isControlVariate_ = true;
}
template <template <class> class MC, class RNG, class S>
void MonteCarloModel<MC,RNG,S>::addSamples(Size samples) {
for (Size j = 1; j <= samples; j++) {
sample_type path = pathGenerator_->next();
result_type price = (*pathPricer_)(path.value);
if (isControlVariate_) {
if (!cvPathGenerator_) {
price += cvOptionValue_-(*cvPathPricer_)(path.value);
} else {
sample_type cvPath = cvPathGenerator_->next();
price +=
cvOptionValue_-(*cvPathPricer_)(cvPath.value);
}
}
if (isAntitheticVariate_) {
path = pathGenerator_->antithetic();
result_type price2 = (*pathPricer_)(path.value);
if (isControlVariate_) {
... // adjust the second price as above
}
sampleAccumulator_.add((price+price2)/2.0, path.weight);
} else {
sampleAccumulator_.add(price, path.weight);
}
}
}
このクラスは、Pathの生成、Path上での価格計算、および統計値の算出の機能を1つにまとめたクラスです。その機能を持たせる為、テンプレートの引数として、それらに対応したクラスを取ります。MC traits クラスはシミュレーションに関するクラスの型を定義し、RNG traitsクラスは乱数の生成、そして統計値算出の為のクラスの S はデフォールトとして Statisticsクラスが設定されています。(心配しないでください。また寄り道をすることはありません。興味のある方は Appendixにある Statisticsクラスの説明を参照下さい。) MCクラスは template template argumentで (テンプレートの引数としてテンプレートクラスを取る)、従って RNG traitsクラスを使う事ができます。(前のセクションで説明した通りです。例としては MultiVariateクラス)。
このクラスは、よく使われるクラスの型について略称を定義しています。そのほとんどは、MCクラステンプレートを RNGクラスでインスタンス化した traits から取りだしています。このクラスは typedefを使って、Path生成装置の型 (path_generator_type) と、使用される Path Pricerの型 (path_pricer_type) を提供しています。さらに、これらの型を使って SamplePathの型 (sample_type) と、その Path上の価格の計算結果の入れ物の型 (result_type) を得る事ができます。
コンストラクターは、引数として PathGenerator、PathPricer、Statisticsクラスの各インスタンス (へのポインター。上記 Listingで一部省略している事をお許し下さい)、および Antithetic Variate(対称変量法) を使うかどうかを示す bool変数を取ります。さらに、選択的に追加可能な引数として、Control Variate(制御変量法、訳注:モンテカルロシミュレーションの収束速度を上げる為の技術の1つ) に関連するものをいくつか取ります。すなわち、もう1つの PathPricer、制御変量となる解析解で計算した価格、及び、もう1つの PathGeneratorです。引数を、追加可能な選択肢として持たせるのは、最善の方法とは言えません。なぜなら、Control Variateに必要な PathPricerを渡したのに、制御変量となる解析解の値を渡し洩れても (エラーとならず)作動するからです。ひとつのコンストラクターを Control Variate に関連する引数を持たないものにしてしまって、別の Control Variate専用のコンストラクターをオーバーロードして、PathPricerと制御変量の解析解を選択不能な引数とし、PathGeneratorクラスだけを追加オプションとする方が安全だったかもしれません。しかし、今のバージョンでも、少なくともプログラムコードを数行節約できてはいます。コンストラクターは、渡された引数をメンバー変数にコピーし、Control Variateに関連する引数が取られているかどうかをチェックして、もう1つの bool変数(isControlVariate_) をセットします。
中心となる計算ロジックは、addSamples( )メソッドの中に書き込まれています。このメソッドは単純に loopを使って、Pathを生成し、その Path上での価格計算を行い、その計算結果を statisticsインスタンスに足しこんでいきます。但し、収束速度を上げるための手法を取り入れている場合は、少し複雑なステップになっています。まず生成すべきサンプルの数を引数で取り、その数だけ PathGeneratorに Pathを生成させ、その Pathを PathPricerに渡して Path毎の(オプション)価格を計算させます。最も簡単なケースでは、これだけです。計算された価格は statisticsインスタンスに足しこまれます (計算結果に加重を加える場合は、PathGeneratorからその情報を取ってきて、それもstatisticsに与えます)。このプロセスを、loopを使って繰り返します。もしユーザーが、Control Variateに関する引数を渡してきた場合は、もう少し興味深いプロセスを取ります。その場合まず、Control Variate用の PathGeneratorが指定されていなければ、メインのシミュレーションで生成したPathを、Control Variate用の PathPricerに渡します。Control Variate用の PathGeneratorが指定されていれば、それを使って Pathを生成します。いずれも場合も、Control Variate用のPathPricerで計算した計算結果と、制御変量価格との価格差を、ベースとなるPathPricerで計算したシミュレーション価格に加えていきます。
(訳注:制御変量法は、モンテカルロシミュレーションの収束速度を上げるテクニック。ここでは、ある複雑なオプション価格を、モンテカルロ法で求める場合に、まず一旦、解析解の判っているシンプルなオプションを使って、解析解価格とシミュレーション価格の価格差を計算し、次にそれを制御変量として、複雑なオプションのシミュレーション価格を調整する。)
それで終わりではありません。仮にユーザーが Antithetic Variates法を使った場合、プログラムは同じような応用動作を行います (この場合は、PathGeneratorに、直前に生成したPathの対称変量を要求し、PathPricerに渡します)。そして、通常の Pathと対称変量の Pathそれぞれでの価格の平均値を statisticsインスタンスに渡します。そうしない場合は、単に当初の Pathでの価格を使うだけです。泡立てて、すすぐ、というプロセスを必要なサンプル数になるまで繰り返します。
最後に、すべての計算結果 (当然、オプション価格を意味します)を sampleAccumulator( )メソッドを使って取り出す事ができます。そのメソッドは、保持されている statisticsインスタンスの参照を返します。“Accumulator”はSTL(Standard Template Library)の用語です。(意味が解りにくいので)STLからではなく金融に関するドメインからメソッド名を取ってくるべきでした。例えば、”statistics”とか。(あ~、それでも問題か。)
<ライセンス表示>
QuantLibのソースコードを使う場合は、ライセンス表示とDisclaimerの表示が義務付けられているので、添付します。 ライセンス