Quantlib的FX vanilla电话价格与Bloomberg

时间:2018-02-14 02:23:09

标签: quantlib

香草欧洲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页"

这是BBG截图 enter image description here

国内/国外费率(复合方式MMkt): enter image description here

和代码

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;

}

2 个答案:

答案 0 :(得分:2)

你是对的;目前,没有办法考虑不同的交货日期。作为解决方法,您可以尝试通过到期日和交付日之间的额外折扣因子来修正价格(您必须将其计算为两个相应折扣因子的比率)。

另一方面,曲线的不同时间(结算折扣,从交易到到期的波动)可能已经通过处理相应曲线的参考日期获得;

之类的东西
FlatForward(in.settlementDate, ...)

的费率和

BlackConstantVol(in.evaluationDate, ...)

应该适用于使用分析引擎的vanilla选项(但不适用于有限差分或蒙特卡罗引擎,不幸的是需要一个共同的时间轴)。

我会尝试以上内容并在我有更多时间时报告我的结果。

答案 1 :(得分:1)

我遇到了同样的问题。对于一年期的欧元/美元普通看涨期权,通过调用Quantlib并遵循克拉克一书中的公式,它将产生略小于1个基点的微小差异。

经过彻底的测试,我能够确定为什么会出现这种差异。 Quantlib Black Scholes库使用两个日期进行所有计算,即评价日期(即今天)和交付日期。

因此,如果有四个日期:评估日期(即今天),SpotDate,到期日期(即到期日)和交付日期。 Quantlib Black Scholes公式将仅假设两个日期,即交货日期付款,并且所有相关条款都折算回评价日期。

如果可以访问源代码,则cpp文件,即d1 d2的实际计算如下图中突出显示的部分: enter image description here

请注意, 上面的远期是交货日期的远期汇率,它是基于评估日期的汇率,国内外市场的交货日期与评估日期之间的折现因子得出的。 stdDev只是波动率* sqrt(T)。

最后,该选项的值是在同一文件blackcalculator.cpp中计算的,如下所示: enter image description here

上图中的折扣是评估日期和交货日期之间的国内折扣系数。这样我们就可以在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)公式显示的进行结算调整的结果。