Puede alguien dar un ejemplo de cómo replicar el Excel/OpenOffice YIELD
y PRICE
funciones utilizando QuantLib?funciones QuantLib OpenOffice/Excel RENDIMIENTO/PRECIO
Tengo algunos ejemplos pero todavía no entiendo toda la configuración. Cuando trato de cambiar algunos valores, obtengo ceros o algunos valores sin sentido. Idealmente, me gustaría crear el C++ equivalente a las funciones RENDIMIENTO/PRECIO.
En mi primer paso no necesito replicar los defectos en el modelado de fechas de Excel. Puedo esperar hasta más tarde para producir un duplicado exacto. Aunque si sabes cómo eso también es genial.
PRICE
ejemplo, en OpenOffice:
PRICE("2008-02-15","2010-11-15",5%,7%,100,2,1) = 95.068419616675
código Mi QuantLib es capaz de conseguir 95.066759
que es un poco apagado. Al menos tengo la función de precio básico, me gustaría obtener una coincidencia exacta para los resultados ahora.
No puedo incluir fácilmente todo el código de envoltura, pero el código esencial es el siguiente.
#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_));
}
esto es indicativo de una inestabilidad numérica o un problema de redondeo con los tipos de coma flotante. intente realizar sus cálculos usando un tipo de multiplicidad de gmp. También tenga en cuenta que el conteo de fechas financieras tiene muchas variaciones, tal vez la versión oo es diferente a la disponible en quantlib. –
La diferencia es lo suficientemente alta como para no estar seguro de que sea un error de punto flotante. Sin embargo, es lo suficientemente bajo como para no ser una diferencia de un solo día en el contador de día. He revisado el código OO y es/cuestionable/a veces, pero se correlaciona exactamente con Excel. Estoy más inclinado a confiar en QuantLib aquí, pero sería muy agradable tener una configuración que produzca los mismos resultados. –
¿puedes agregar tu código de C++? –