代码改变世界

QuantLib 101之PricingEngine

2010-10-07 14:02  xxmplus  阅读(798)  评论(0)    收藏  举报
  • 同一个instrument也会采用不同的定价机制,正如第一篇所述,这是标准的策略模式。
  • 此外,不同的instrument所需的数据是大相径庭的,返回数据也是一样,因此这里引入了arguments和results两个辅助类。
#include <ql/patterns/observable.hpp>

class PricingEngine : public Observable {
public:
    class arguments;
    class results;
    virtual ~PricingEngine() {}
    virtual arguments* getArguments() const = 0;
    virtual const results* getResults() const = 0;
    virtual void reset() = 0;
    virtual void calculate() const = 0;
};

class PricingEngine::arguments {
public:
    virtual ~arguments() {}
    virtual void validate() const = 0;
};

class PricingEngine::results {
public:
    virtual ~results() {}
    virtual void reset() = 0;
};

template<class ArgumentsType, class ResultsType>
class GenericEngine : public PricingEngine, public Observer {
public:
    PricingEngine::arguments* getArguments() const { return &arguments_; }
    const PricingEngine::results* getResults() const { return &results_; }
    void reset() { results_.reset(); }
    void update() { notifyObservers(); }
protected:
    mutable ArgumentsType arguments_;
    mutable ResultType results_;
};
  • Instrument的大致接口参见这里。下面是实现部分:
#include <ql/patterns/lazyobject.hpp>
#include <ql/pricingengine.hpp>
#include <ql/utilities/null.hpp>
#include <ql/time/date.hpp>
#include <boost/any.hpp>
#include <map>
#include <string>

class Instrument : public LazyObject {
// ...
};

inline void Instrument::setPricingEngine(const boost::shared_ptr& e) {
    if(engine_) unregisterWith(engine_);
    engine_ = e;
    if(engine_) registerWith(engine_);
    update();
}

// Strategy Pattern!
inline void Instrument::calculate() const {
    if(isExpired()) {
        setupExpired();
        calculated_ = true;
    } else {
        LazyObject::calculate();
    }
}

inline void Instrument::setupExpired() const {
    NPV_ = errorEstimate_ = 0.0;
    valuationDate_ = Date();
    additionalResults_.clear();
}

// This is typical Template Method Pattern!
inline void Instrument::performCalculations() const {
    QL_REQUIRE(engine_, "null pricing engine");
    engine_->reset();
    setupArguments(engine_->getArguments());
    engine_->getArguments()->validate();
    engine_->calculate();
    fetchResults(engine_->getResults());
}

inline void setupArguments(PricingEngine::arguments*) const {
    QL_FAIL("Instrument::setupArguments() not implemented");
}

inline void Instrument::fetchResults(const PricingEngine::results* r) const {
    const Instrument::results* results = dynamic_cast<const Instrument::results*>(r);
    QL_ENSURE(results != 0, "no results returned from pricing engine");

    NPV_ = results->value;
    errorEstimate_ = results->errorEstimate;
    valuationDate_ = results->valuationDate;
    additionalResults_ = results->additionalResults;
}
cont.