Problem with Swaps QuantLib vs. Bloomberg

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Problem with Swaps QuantLib vs. Bloomberg

dhoorens
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