问题
在给金融产品定价时,QuantLib底层的对象输入的参数较多,例如欧式期权需要输入:标的资产的价格、执行价格、波动率、到期日以及期权类型等,众多的输入参数,给用户带来的诸多的不便,比如输入参数的顺序问题,虽然可以使用C++的默认参数的特性,对于部分参数设置默认值,但是设置的默认参数需要放置在函数参数列表的最后。
下面是底层MyOption的类的定义,testingFactory1是如何使用MyOption的函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
class MyOption{
public:
enum Type{Call=1,Put=-1,None=0};
MyOption(Time mat, Volatility vol, Type type, Real spot,
Rate forRate, Rate domRate, Real strike):mat_(mat),vol_(vol),
type_(type),spot_(spot),forRate_(forRate),domRate_(domRate),
strike_(strike){
}
Time getMat()const{return mat_;}
Real getSpot()const{return spot_;}
Real getStrike()const{return strike_;}
private:
Time mat_; Volatility vol_;
Real spot_,strike_;
Rate forRate_,domRate_;
Type type_;
};
void testingFactory1(){
Real spot=100.0, strike=110.0;
Rate rd=0.03, rf=0.01;
Volatility vol=0.20;
Time mat=1.0;
MyOption::Type type(MyOption::Call);
MyOption option(mat,vol,type,spot,rf,rd,strike);
std::cout << "Mat:" << option.getMat() << std::endl;
std::cout << "Spot:" << option.getSpot() << std::endl;
std::cout << "Strike:" << option.getStrike() << std::endl;
}
|
上述测试结果如下:
1
2
3
|
Mat:1
Spot:100
Strike:110
|
工厂(Factory)模式
QuantLib中的工厂模式解决了这些问题,通过定义创建对的接口,封装了对象的创建,如本示例中,定义MakeMyOption类用来创建MyOption的对象,其类的代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
class MakeMyOption{
public:
MakeMyOption(): mat_(Null<Real>()),vol_(Null<Real>()),spot_(Null<Real>()),
strike_(Null<Real>()),forRate_(Null<Real>()),
domRate_(Null<Real>()),type_(MyOption::None){
}
MakeMyOption& withMat(const double& mat){
mat_=mat;
return *this;
}
MakeMyOption& withVol(const double& vol){
vol_=vol;
return *this;
}
MakeMyOption& withSpot(const double& spot){
spot_=spot;
return *this;
}
MakeMyOption& withStrike(const double& strike){
strike_=strike;
return *this;
}
MakeMyOption& withForRate(const double& forRate){
forRate_=forRate;
return *this;
}
MakeMyOption& withDomRate(const double& domRate){
domRate_=domRate;
return *this;
}
MakeMyOption& withType(const MyOption::Type& type){
type_=type;
return *this;
}
operator MyOption()const{
QL_REQUIRE(mat_!=Null<Real>(),"Maturity not set!");
// Check other parameters too
QL_REQUIRE(type_!=MyOption::None,"Option type not set!");
return MyOption(mat_,vol_,type_,spot_,forRate_,domRate_,strike_);
}
Time getMat()const{return mat_;}
Real getSpot()const{return spot_;}
Real getStrike()const{return strike_;}
private:
Time mat_;
Volatility vol_;
Real spot_,strike_;
Rate forRate_,domRate_;
MyOption::Type type_;
};
|
在MakeMyOption的类中,首先,构造函数无限输入期权的参数,同时提供了设置参数的的接口,其次,类中重载了"()“运算符,通过重载将MakeMyOption对象转化为原来的MyOption对象,并且在重载函数中,针对用户没有定义的参数进行了检查,如果使用者没有输入参数,程序会给出报错,我们可以通过下面的代码创建对象:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
void testingFactory2(){
Real spot=100.0, strike=110.0;
Rate rd=0.03, rf=0.01;
Volatility vol=0.20;
Time mat=1.0;
MyOption::Type type(MyOption::Call);
MyOption optionMade=MakeMyOption()
.withType(type)
.withMat(mat)
.withSpot(spot)
.withForRate(rf)
.withStrike(strike)
.withVol(vol)
.withDomRate(rd);
std::cout << "Mat Made:" << optionMade.getMat() << std::endl;
std::cout << "Spot Made:" << optionMade.getSpot() << std::endl;
std::cout << "Strike Made:" << optionMade.getStrike() << std::endl;
}
|
上述代码的输出结果为:
1
2
3
|
Mat Made:1
Spot Made:100
Strike Made:110
|