香草欧洲EURUSD看涨期权的Quantlib价格与bloomberg OVML价格不相符。
e.g。对于以下选项Quantlib值= 4.60991,BBG值= 4.6137,误差= 0.0038(虽然应该是~1e-6差异)
据我所知,波动的时间和折扣或漂移的时间应根据确切的时间和时间进行调整。例如,贴现期应从结算日到交货日,且波动期应从交易日到到期日。波动率参数也应通过考虑到期和交易时间的差异来正确表达。
但是,我没有在Quantlib中看到一个选项来说明与到期日期不同的交货日期。我如何考虑结算调整(例如,结算日期为EURUSD的T + 2,即现货/交易日后2天,或USDCAD的T + 1),以及延迟交割调整(交割日期为T + 2,即,到期后2天),如Clark所述,Iain J.外汇期权定价:从业者指南。 John Wiley&儿子,2011年。第33页, 和" Wystup,Uwe。外汇期权和结构性产品。 John Wiley&儿子,2015年。第26-29页"
和代码
int main(){
QuantLib::Real S = 100;
QuantLib::Real K = 105;
QuantLib::Spread f = 0.05;// Foreign rate (EUR in EURUSD)
QuantLib::Rate r = 0.02; // Domestic rate (USD in EURUSD)
QuantLib::Volatility vol = 0.2;
QuantLib::DayCounter dayCounter = Actual365Fixed();
QuantLib::Date evaluationDate = Date(13, Feb, 2018);
QuantLib::Date settlementDate = evaluationDate + Period(2, Days);//T+2 = Date(15, Feb, 2018);
QuantLib::Date expirationDate = settlementDate + Period(1, Years); //Date(15, May, 2019);
Calendar calendar = UnitedStates(UnitedStates::NYSE);
Exercise::Type exerciseType = Exercise::European;
Real result = 4.6137;
Real tol = 1e-3; // tolerance
Option::Type optionType = Option::Call;
Compounding compounding = Compounded;
Frequency compoundingFrequency = Semiannual;
VanillaOptionData vanillaOptionData = { S, K, f, r, vol, dayCounter, evaluationDate, settlementDate,
expirationDate, calendar,exerciseType, result, tol, optionType, compounding, compoundingFrequency };
calculator_fx_vanilla_black_scholes(vanillaOptionData);
//results
//calculated value=4.60991, expected value=4.6137, error=0.00379258
return 0;
}
void calculator_fx_vanilla_black_scholes(VanillaOptionData in) {
Calendar calendar = TARGET();
Settings::instance().evaluationDate() = in.evaluationDate;
boost::shared_ptr<Exercise> exercise= boost::make_shared<EuropeanExercise>(in.expirationDate);
Handle<Quote>underlyingH(boost::shared_ptr<Quote>(new SimpleQuote(in.S)));
Handle<YieldTermStructure> rTS(boost::shared_ptr<YieldTermStructure>(new FlatForward(in.settlementDate, in.r, in.dayCounter, in.compounding, in.compoundingFrequency)));
Handle<YieldTermStructure> fTS(boost::shared_ptr<YieldTermStructure>(new FlatForward(in.settlementDate, in.f, in.dayCounter, in.compounding, in.compoundingFrequency)));
Handle<BlackVolTermStructure> flatVolTS(boost::shared_ptr<BlackVolTermStructure>(new BlackConstantVol(in.settlementDate, calendar, in.vol, in.dayCounter)));
boost::shared_ptr<StrikedTypePayoff>payoff(new PlainVanillaPayoff(in.optionType, in.K));
boost::shared_ptr<GarmanKohlagenProcess>process(new GarmanKohlagenProcess(underlyingH, fTS, rTS, flatVolTS));
VanillaOption option(payoff, exercise);
boost::shared_ptr<PricingEngine> pe(new AnalyticEuropeanEngine(process));
option.setPricingEngine(pe);
Real calculated = option.NPV();
Real expected = in.result;
Real error = std::fabs(calculated - expected);
cout << "calculated value=" << calculated << ", expected value=" << expected << ", error=" << error << endl;
}
答案 0 :(得分:2)
你是对的;目前,没有办法考虑不同的交货日期。作为解决方法,您可以尝试通过到期日和交付日之间的额外折扣因子来修正价格(您必须将其计算为两个相应折扣因子的比率)。
另一方面,曲线的不同时间(结算折扣,从交易到到期的波动)可能已经通过处理相应曲线的参考日期获得;
之类的东西FlatForward(in.settlementDate, ...)
的费率和
BlackConstantVol(in.evaluationDate, ...)
应该适用于使用分析引擎的vanilla选项(但不适用于有限差分或蒙特卡罗引擎,不幸的是需要一个共同的时间轴)。
我会尝试以上内容并在我有更多时间时报告我的结果。
答案 1 :(得分:1)
我遇到了同样的问题。对于一年期的欧元/美元普通看涨期权,通过调用Quantlib并遵循克拉克一书中的公式,它将产生略小于1个基点的微小差异。
经过彻底的测试,我能够确定为什么会出现这种差异。 Quantlib Black Scholes库使用两个日期进行所有计算,即评价日期(即今天)和交付日期。
因此,如果有四个日期:评估日期(即今天),SpotDate,到期日期(即到期日)和交付日期。 Quantlib Black Scholes公式将仅假设两个日期,即交货日期付款,并且所有相关条款都折算回评价日期。
如果可以访问源代码,则cpp文件,即d1 d2的实际计算如下图中突出显示的部分:
请注意, 上面的远期是交货日期的远期汇率,它是基于评估日期的汇率,国内外市场的交货日期与评估日期之间的折现因子得出的。 stdDev只是波动率* sqrt(T)。
最后,该选项的值是在同一文件blackcalculator.cpp中计算的,如下所示:
上图中的折扣是评估日期和交货日期之间的国内折扣系数。这样我们就可以在Evaluation_date获得最终结果,表示为MV_evalDate。这与彭博社(Bloomberg)或穆雷克斯(Murex)的值不完全匹配,因为在穆雷克斯(Murex)上,其报价为现货日期。我们需要将评估日期上的结果转发到现货日期,然后获得现货日期的市场价值,为MV_spotDate = MV_evalDate * exp(domestic_rate * timefrac_between_evalDate_spotDate)= MV_evalDate / domestic_discountfactor_evalDate_spotDate。
然后我们可以得到当日市值的匹配结果,或者通过Clark著作的第32页的(2.86)公式显示的进行结算调整的结果。