QuantLib OpenOffice/Excel YIELD / PRICE 函数

Posted

技术标签:

【中文标题】QuantLib OpenOffice/Excel YIELD / PRICE 函数【英文标题】:QuantLib OpenOffice/Excel YIELD / PRICE functions 【发布时间】:2011-07-10 10:28:11 【问题描述】:

谁能提供一个示例,说明如何使用 QuantLib 复制 Excel/OpenOffice YIELDPRICE 函数?

我有几个示例,但我还不太了解所有设置。当我尝试更改某些值时,我要么得到零,要么得到一些无意义的值。理想情况下,我想创建等效于 YIELD/PRICE 函数的 c++。

在我的第一步中,我不需要复制 Excel 日期建模中的缺陷。我可以等到稍后再制作一个完全相同的副本。不过如果你知道那也很棒。


PRICE 示例,在 OpenOffice 中:

PRICE("2008-02-15","2010-11-15",5%,7%,100,2,1) = 95.068419616675

我的 QuantLib 代码能够获取 95.066759,这有点不对劲。至少我有基本的价格功能,我现在想得到一个完全匹配的结果。


我不能轻易包含所有的包装代码,但基本代码如下。

#include <ql/time/calendar.hpp>
#include <ql/time/daycounters/actualactual.hpp>
#include <ql/time/daycounters/actual365fixed.hpp>
#include <ql/time/schedule.hpp>
#include <ql/time/calendars/unitedstates.hpp>
#include <ql/time/calendars/nullcalendar.hpp>

#include <ql/settings.hpp>
#include <ql/handle.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/instruments/bonds/fixedratebond.hpp>

#include <ql/pricingengines/bond/discountingbondengine.hpp>
#include <ql/utilities/dataformatters.hpp>

#include <iostream>
#include <iomanip>

#include "boost/date_time/gregorian/gregorian.hpp"
using namespace QuantLib;

Date convert_date( boost::gregorian::date const & date )

    unsigned mon = date.month();
    return Date( date.day(), Month(mon), date.year() );


shared_ptr<Bond> create_bond( boost::gregorian::date const & settlement_, boost::gregorian::date const & maturity_,
    double coupon_, double yield_, double redemption_, unsigned frequency_ )

    // date set up
    //Calendar calendar = UnitedStates(UnitedStates::GovernmentBond);
    Calendar calendar = NullCalendar(); //small improvement

    Date settlementDate( convert_date( settlement_ ) );
    // the settlement date must be a business day
    settlementDate = calendar.adjust(settlementDate);

    Integer fixingDays = 0; //1;
    Natural settlementDays = 0; //1

    Date evalDate = calendar.advance(settlementDate, -fixingDays, Days);
    // Evaluation date (TODO: What should this actually be?)
    Settings::instance().evaluationDate() = evalDate;

    // bond set up
    Real faceAmount = 100;
    Real redemption = redemption_;
    Date issueDate( 1, January, 2001); //NOTE: shouldn't be relevant for price/yield calculations
    Date maturity( convert_date( maturity_ ) );
    Real couponRate = coupon_;
    Real yield = yield_;

    //ActualActual dayCounter( ActualActual::Bond );
    ActualActual dayCounter;
    //Actual365Fixed dayCounter;

    RelinkableHandle<YieldTermStructure> discountingTermStructure;
    boost::shared_ptr<YieldTermStructure> flatTermStructure(
        new FlatForward(
            settlementDate,
            yield,
            dayCounter,
            Compounded,
            Frequency( frequency_ ) ));
    discountingTermStructure.linkTo(flatTermStructure);

    boost::shared_ptr<PricingEngine> bondEngine(
        new DiscountingBondEngine(discountingTermStructure));

    Schedule fixedBondSchedule(
        issueDate,
        maturity,
        Period( Frequency( frequency_ ) ),
        calendar,
        Unadjusted,
        Unadjusted,
        DateGeneration::Backward,
        false /*EOM*/); //strangely makes no difference in our calculations

    boost::shared_ptr<Bond> fixedRateBond( new FixedRateBond(
        settlementDays,
        faceAmount,
        fixedBondSchedule,
        std::vector<Rate>(1, couponRate),
        dayCounter,
        Unadjusted,
        redemption) );

    fixedRateBond->setPricingEngine(bondEngine);
    return fixedRateBond;


//OpenOffice: PRICE("2008-02-15","2010-11-15",5%,7%,100,2,1)
double bond_price( boost::gregorian::date const & settlement_, boost::gregorian::date const & maturity_,
    double coupon_, double yield_, double redemption_, unsigned frequency_ )

    shared_ptr<Bond> bond( create_bond( settlement_, maturity_, coupon_, yield_, redemption_, frequency_ ) );
    return bond->cleanPrice();


//OpenOffice: PRICE("2008-02-15","2010-11-15",5%,7%,100,2,1)
double bond_yield( boost::gregorian::date const & settlement_, boost::gregorian::date const & maturity_,
    double coupon_, double price_, double redemption_, unsigned frequency_ )

    shared_ptr<Bond> bond( create_bond( settlement_, maturity_, coupon_, 0, redemption_, frequency_ ) );
    ActualActual dayCounter;
    return bond->yield( price_, dayCounter, Compounded, Frequency(frequency_) );

【问题讨论】:

这表示浮点类型存在数值不稳定或舍入问题。尝试使用 gmp 多精度类型执行计算。另请注意,财务日期计数有很多变化,也许 oo 版本与 quantlib 中可用的版本不同。 差异足够大,我不确定这是否是浮点错误。然而,它足够低,不会在日计数器中出现单日差异。我查看了 OO 代码,它有时是/有问题的/,但它与 Excel 完全相关。我在这里更倾向于信任 QuantLib,但如果配置能够产生相同的结果,那就太好了。 我得到了和你一样的结果,我基本上做了和你一样的假设。这可能是我缺乏使用 quantlib 的经验,但是价格取决于 FlatForward 构造器似乎很奇怪。我不确定,这是对平坦收益率曲线建模的正确方法。在我看来,平坦的收益率曲线应该是一个函数 rate(time) ,每次返回相同的值。所以一个唯一的值应该足以明确地指定它。 【参考方案1】:

如果你对OpenOffice中PRICE函数的实现感兴趣,可以看AnalysisAddIn::getPrice的实现中的代码。这是指analysis helper.cxx 中的getPrice_ 函数。也许你会发现那里发生了什么。

请注意,OpenGrok 似乎在这里配置错误,因此单击功能可能不起作用。但我想你可以在 /OOO340_m0/scaddins/source/analysis 目录中的文件中找到所有你需要的东西。

【讨论】:

以上是关于QuantLib OpenOffice/Excel YIELD / PRICE 函数的主要内容,如果未能解决你的问题,请参考以下文章

openoffice excel word 转换pdf

OpenOffice 搜索表以编程方式

QuantLib 金融计算——基本组件之 Date 类

QuantLib 金融计算——基本组件之 ExchangeRateManager 类

QuantLib 金融计算——收益率曲线之构建曲线

从 C# 调用 QuantLib 方法的最佳方法是啥