Posted by
dhoorens on
Mar 24, 2010; 12:03pm
URL: http://quantlib.414.s1.nabble.com/Swap-Price-QuantLib-vs-Bloomberg-tp8510.html
Hi
I'm trying to replicate a Swap price I can see on my Bloomberg page
I 'm not using the Quantlib xl code, because some people in my company are not yet ready to use objects in Excel (pfff) => I have created my own interface with Excel
Here is the code
double vanillaSwapPrice(int todaysDate_,
int tenorInYears,
double fixRate,
int forwardTenorInMonths,
int fltFrequency_,
xloper* yieldTermStructure,
double nominal,
char* type,
int settlementDays,
int fixFrequency_,
char* calendar_,
char* dayCounter_,
char* fixDayCounter_,
char* fltDayCounter_,
double spread,
char* results){
try{
QuantLib::Calendar calendar = toCalendar(calendar_, QuantLib::TARGET());
QuantLib::Calendar fixCalendar = calendar;
QuantLib::Calendar fltCalendar = calendar;
QuantLib::RelinkableHandle<QuantLib::YieldTermStructure> yTS;
QuantLib::Frequency fixFrequency = toFrequency(fixFrequency_);
QuantLib::Frequency fltFrequency = toFrequency(fltFrequency_, QuantLib::Semiannual);
QuantLib::DayCounter dayCounter = toDayCounter(dayCounter_, QuantLib::Actual360());
QuantLib::DayCounter fixDayCounter = toDayCounter(fixDayCounter_, QuantLib::Thirty360(QuantLib::Thirty360::BondBasis));
QuantLib::DayCounter fltDayCounter = toDayCounter(fltDayCounter_, QuantLib::Actual360());
boost::shared_ptr<QuantLib::IborIndex> index =
makeIborIndex(QuantLib::Period(fltFrequency),yTS)
.withSettlementDays(settlementDays)
.withCalendar(calendar)
.withDayCounter(fltDayCounter);
QuantLib::Date todaysDate = toDate(todaysDate_);
QuantLib::Settings::instance().evaluationDate() = todaysDate;
QuantLib::Date settlement = calendar.advance(todaysDate,settlementDays,QuantLib::Days);
yTS.linkTo(toYieldTermStructure(settlement, calendar, dayCounter, yieldTermStructure));
QuantLib::VanillaSwap::Type typ;
std::string type_ = std::string(type);
if (type_ == "R")
typ = QuantLib::VanillaSwap::Receiver;
else if (type_ == "P")
typ = QuantLib::VanillaSwap::Payer;
else
throw (std::string("unknwown type of Swap"));
if (nominal ==0.0)
nominal = 1.0;
boost::shared_ptr<QuantLib::VanillaSwap> sw =
makeVSwap(QuantLib::Period(tenorInYears,QuantLib::Years),
index,
fixRate,
QuantLib::Period(forwardTenorInMonths,QuantLib::Months))
.withType(typ)
.withNominal(nominal)
.withFixedLegTenor(QuantLib::Period(fixFrequency))
.withFixedLegCalendar(fixCalendar)
.withFixedLegDayCount(fixDayCounter)
.withFloatingLegTenor(QuantLib::Period(fltFrequency))
.withFloatingLegSpread(QuantLib::Spread(spread))
.withFloatingLegCalendar(fltCalendar)
.withFloatingLegDayCount(fltDayCounter);
//Depending on what I want as results i can choose between
return sw->NPV();
//return sw->fixedLegNPV();
//return sw->fixedLegBPS();
//return sw->floatingLegNPV();
//return sw->floatingLegBPS();
//return sw->fairRate();
}
catch (...) {
errMsg += "[" + functionCall->functionName() + "]" + "Unknown Error";
}
//not the real return but adapted here to say somthg :-/
return -1;
}
The toXXX functions (i.e. toFrequency, toDayCounter, etc) are converter of the inputs into QuantLib types. The (optionnal) second input is the default value, if the first value is not right
Here is the toYieldTermStructure function
boost::shared_ptr<YieldTermStructure> toYieldTermStructure (Date settlement,
Calendar calendar,
DayCounter dayCounter,
xloper* input,
Compounding comp= QuantLib::Continuous,
Frequency freq== QuantLib::Annual,
bool endOfMonth= true){
std::vector<std::vector<double> >m = ObjectHandler::operToMatrix<double>(*input ,"Input");
unsigned int rows, cols, sizeInput;
rows = m.size();
cols = m[0].size();
sizeInput = __max(rows,cols);
boost::shared_ptr<YieldTermStructure> curve;
if (sizeInput==1)
curve = boost::shared_ptr<YieldTermStructure>(
new FlatForward(settlement, m[0][0], dayCounter, comp, freq));
else{
std::vector<Date> vDate;
std::vector<Real> vPrice;
bool isDate = (m[0][0] >=367); //the first X-value of the curve is greater than 1/1/1901 => it's a date
if (rows ==2 && cols > 2){ //horizontal data
int j_init = 0;
if (m[1][0] != 1.0){
vDate.push_back(settlement);
vPrice.push_back(1.0);
j_init++;
}
else {
if ((isDate && toDate((long)m[0][0]) != settlement) || (!isDate && m[0][0] != 0.0))
throw (std::string("[toYieldTermStructure] Invalid first term value"));
}
for (unsigned int j = j_init; j< cols; j++){
if (isDate)
vDate.push_back(toDate((long)m[0][j]));
else
//It is not a date => we assume the value is in Months and we add it to the settlement
vDate.push_back(calendar.advance(settlement, (long)m[0][j], Months, QuantLib::Unadjusted, endOfMonth));
vPrice.push_back(m[1][j]);
}
}
else if (cols ==2 && rows > 2){ //vertical data
int i_init = 0;
if (m[0][1] != 1.0){
vDate.push_back(settlement);
vPrice.push_back(1.0);
i_init ++;
}
else {
if ((isDate && toDate((long)m[0][0]) != settlement) || (!isDate && m[0][0] != 0.0))
throw (std::string("[toYieldTermStructure] Invalid first term value"));
}
for (unsigned int i = i_init; i< rows; i++){
if (isDate)
vDate.push_back(toDate((long)m[i][0]));
else
//It is not a date => we assume the value is in Months and we add it to the settlement
vDate.push_back(calendar.advance(settlement, (long)m[i][0], Months, QuantLib::Unadjusted, endOfMonth));
vPrice.push_back(m[i][1]);
}
}
else
throw (std::string("[toYieldTermStructure] data has too much either cols or rows"));
curve = boost::shared_ptr<YieldTermStructure>(
new InterpolatedDiscountCurve<Cubic>(
vDate,
vPrice,
dayCounter,
calendar,
Cubic(CubicInterpolation::Spline,
false,
CubicInterpolation::SecondDerivative,
0.0,
CubicInterpolation::SecondDerivative,
0.0)));
}
return curve;
}
Finally in attach you can find the makeVSwap and makeIborIndex classes
When I enter in Excel as inputs:
int todaysDate_ = 40261 (ie 24/3/2010)
int tenorInYears = 5
double fixRate = 2.21207%
int forwardTenorInMonths = 0
int fltFrequency_ = 2
xloper* yieldTermStructure = the curve given by the the second gif file
double nominal = 10000000
char* type = R
int settlementDays = 0
int fixFrequency_ = 1
char* calendar_ = TARGET
char* dayCounter_ =THIRTY360
char* fixDayCounter_ = THIRTY360
char* fltDayCounter_ = ACTUAL360
double spread = 0
it returns a value for
NPV = -9252218
FixLegNPV = 1042594.49
FixLegBps = 4713.22
FltLegNPV = -1135118.66
FltLegBps = -4809.48
FairRate = 2.40837
Here are the questions
Why do I have differences with Bloomberg.
Is QuantLib coherent with Blmbg?
Why the market value of each leg is so different (Blmg vs QuantLib)? (example QuantLIb FixLegNPV = 1042596.49 and Blmbg FixLegNPV = 9904395.99)
Tks
David
QL_Blmbg.zip