QuantLib 101之Instrument
时间:2010-10-01 来源:xxmplus
Instrument是QuantLib里最基本的类,所有金融概念里的实体都可以映射到这个类上来,作为一个基类,它应该包含所有金融产品共通的方法。由于金融市场上各种交易产品以及衍生产品所附加的复杂概念,这个类的方法其实是非常少的:最基本的是返回它当前的价值,以及标明它当前是否已经到期(过期)。
#include <ql/instrument.hpp> #include <ql/patterns/observable.hpp> class LazyObject : public virtual Observer, public virtual Observable { protected: mutable bool calculated_, frozen_; virtual void performCalculations() const = 0; void calculate() const { if(!calculated_ && !frozen_) { calculated_ = true; try { performCalculations(); } catch (...) { calculated_ = false; throw; } } } public: void update() { if(!frozen_ && calculated_) notifyObservers(); // from observable.hpp calculated_ = false; } void recalculate() { bool wasFrozen = frozen_; calculated_ = frozen_ = false; try { calculate(); } catch (...) { frozen_ = wasFrozen; notifyObservers(); throw; } frozen_ = wasFrozen; notifyObservers(); } } class Instrument : public LazyObject { protected: mutable Real NPV_; public: // return the net present value of the instrument Real NPV() const { calculate(); return NPV_; } void calculate() const { if(isExpired()) { setupExpired(); calculated_ = true; } else { LazyObject::calculate(); } } virtual void setupExpired() const { NPV_ = 0.0; } // return the error estimate on the NPV when available Real errorEstimate() const; // return whether the instrument might have value > 0 virtual bool isExpired() const = 0; }
- 不同的instrument会采用不同的定价机制,这是很典型的策略模式。
- instrument的价值取决于市场上的数据,这些数据随时随地都在变化,因此instrument的价值也会随之改变。另外,数据可能有多个来源,当出现不同时,instrument应当获取最新的数据并据此计算出相应结果。在数据源之间转换的动作对用户来说应该是透明的。然而盲目地计算只会降低效率,instrument会缓存上一次的计算结果,只在输入数据发生变化时才重新计算。这是典型的观察者模式和模板函数模式。
- 显然在这里instrument是观察者,而输入数据是被观察者。instrument需要维护一个表示输入的对象的引用,可是一个指针还不够,因为不但数据会变化,数据源也会变化。由于这个指针是观察者(instrument)的私有成员,无法让它指向另一个对象。QuantLib为此实现了Handle类模板。
- 复制Handle后的副本会共享指向同一个对象的指针,当这个指针指向另一个对象时,所有的副本都会得到通知,这样它们的拥有者就可以去访问新的对象了。
- 被观察数据可以保存在Handle里,其中最基本的是Quote类,它表示了市场数据单个变化。其他类型的instrument可能会有更复杂的对象,比如yield。不过这些也都最终依赖于Quote实例。
- LazyObject被抽象出来以实现模板函数模式。即instrument会保存并重新计算缓存结果,而具体的计算则留给派生类去实现。
相关阅读 更多 +