Tagged: CNY Swap
- This topic has 1 reply, 1 voice, and was last updated 1 year, 9 months ago by
Anonymous.
-
AuthorPosts
-
May 3, 2019 at 8:32 am #6638
Anonymous
InactiveDear all,
I am trying to value a CNY Swap.
The floating leg of CNY Swap is a 7 day repo rate.
The payment freq of floating leg and fixed leg is quarterly.
The interest rate of floating leg is compounded by 7 day repo rates.I use the SubPeriodsSwap/SubPeriodSwapHelper/SubperiodsCoupon in QuantExt.
I make an instance of 3 year swap. I compare the NPV with Bloomberg on some backdated trades.
Currently, there is no CNY 7d Repo index in QuantLib, so I make a cnyrepo.cppMy result comparison with Bloomberg and code are as below. Thanks.
Curve1 : the market curve on 2019/2/14.
Curve2 : I raise the 3 year swap rate to 3.0%.==Curve Terms==
Today Valuation Date
2019/2/14 2019/2/15==Swap Terms==
Settlement Date 2018/9/3
Tenor 3 years
Fixed Rate 2.611%Curve_1 My Result Bloomberg Result
NPV 727.19 1,001.61
FairRate 2.5837% 2.5734%Curve_2 My Result Bloomberg Result
NPV 5,494.60 4,388.60
FairRate 2.8200% 2.7758%I think the difference is not OK. I am not sure if I did any thing wrong.
The code to vlaue CNY Swap and the cnyrepo.cpp are as below.//Code to Value CNY Swap
//=============================================================================================//using namespace QuantLib; using namespace QuantExt; using namespace std; int main() { try { /********************* *** MARKET DATA *** *********************/ Calendar calendar = China(China::IB); calendar.removeHoliday(Date(30, December, 2018)); calendar.removeHoliday(Date(2, February, 2019)); calendar.removeHoliday(Date(3, February, 2019)); calendar.addHoliday(Date(4, February, 2019)); calendar.addHoliday(Date(5, February, 2019)); calendar.addHoliday(Date(6, February, 2019)); calendar.addHoliday(Date(7, February, 2019)); calendar.addHoliday(Date(8, February, 2019)); Date valuationDate(15, February, 2019); valuationDate = calendar.adjust(valuationDate); Integer fixingDays = 1; Date todaysDate = calendar.advance(valuationDate, -fixingDays, Days); Settings::instance().evaluationDate() = todaysDate; todaysDate = Settings::instance().evaluationDate(); std::cout << "Today: " << todaysDate.weekday() << ", " << todaysDate << std::endl; std::cout << "Settlement date: " << valuationDate.weekday() << ", " << valuationDate << std::endl; // deposits Rate d1DQuote = 0.0174; Rate d7DQuote = 0.024; // swaps Rate s3mQuote = 0.0245875; Rate s6mQuote = 0.024600; Rate s9mQuote = 0.024600; Rate s1yQuote = 0.024750; Rate s2yQuote = 0.025150; Rate s3yQuote = 0.026110; Rate s4yQuote = 0.0272510; Rate s5yQuote = 0.028250; Rate s7yQuote = 0.029550; Rate s10yQuote = 0.03140; /******************** *** QUOTES *** ********************/ // deposits boost::shared_ptr<Quote> d1DRate(new SimpleQuote(d1DQuote)); boost::shared_ptr<Quote> d7DRate(new SimpleQuote(d7DQuote)); // swaps boost::shared_ptr<Quote> s3mRate(new SimpleQuote(s3mQuote)); boost::shared_ptr<Quote> s6mRate(new SimpleQuote(s6mQuote)); boost::shared_ptr<Quote> s9mRate(new SimpleQuote(s9mQuote)); boost::shared_ptr<Quote> s1yRate(new SimpleQuote(s1yQuote)); boost::shared_ptr<Quote> s2yRate(new SimpleQuote(s2yQuote)); boost::shared_ptr<Quote> s3yRate(new SimpleQuote(s3yQuote)); boost::shared_ptr<Quote> s4yRate(new SimpleQuote(s4yQuote)); boost::shared_ptr<Quote> s5yRate(new SimpleQuote(s5yQuote)); boost::shared_ptr<Quote> s7yRate(new SimpleQuote(s7yQuote)); boost::shared_ptr<Quote> s10yRate(new SimpleQuote(s10yQuote)); /********************* *** RATE HELPERS *** *********************/ // deposits DayCounter depositDayCounter = Actual365Fixed(); boost::shared_ptr<RateHelper> d1D(new DepositRateHelper(Handle<Quote>(d1DRate), 1 * Days, fixingDays, calendar, ModifiedFollowing, false, depositDayCounter)); boost::shared_ptr<RateHelper> d7D(new DepositRateHelper(Handle<Quote>(d7DRate), 7 * Days, fixingDays, calendar, ModifiedFollowing, false, depositDayCounter)); // setup swaps Frequency swFixedLegFrequency = Quarterly; BusinessDayConvention swFixedLegConvention = ModifiedFollowing; DayCounter swFixedLegDayCounter = Actual365Fixed(); boost::shared_ptr<IborIndex> swFloatingLegIndex(new CNYRepo7D); boost::shared_ptr<RateHelper> s3m(new SubPeriodsSwapHelper(Handle<Quote>(s3mRate), 3 * Months, // SwapTenor 3 * Months, // fixedTenor calendar, swFixedLegDayCounter, swFixedLegConvention, 3 * Months, // floatpayTenor swFloatingLegIndex, swFixedLegDayCounter)); boost::shared_ptr<RateHelper> s6m(new SubPeriodsSwapHelper(Handle<Quote>(s6mRate), 6 * Months, // SwapTenor 3 * Months, // fixedTenor calendar, swFixedLegDayCounter, swFixedLegConvention, 3 * Months, // floatpayTenor swFloatingLegIndex, swFixedLegDayCounter)); boost::shared_ptr<RateHelper> s9m(new SubPeriodsSwapHelper(Handle<Quote>(s9mRate), 9 * Months, // SwapTenor 3 * Months, // fixedTenor calendar, swFixedLegDayCounter, swFixedLegConvention, 3 * Months, // floatpayTenor swFloatingLegIndex, swFixedLegDayCounter)); boost::shared_ptr<RateHelper> s1y(new SubPeriodsSwapHelper(Handle<Quote>(s1yRate), 1 * Years, // SwapTenor 3 * Months, // fixedTenor calendar, swFixedLegDayCounter, swFixedLegConvention, 3 * Months, // floatpayTenor swFloatingLegIndex, swFixedLegDayCounter)); boost::shared_ptr<RateHelper> s2y(new SubPeriodsSwapHelper(Handle<Quote>(s2yRate), 2 * Years, // SwapTenor 3 * Months, // fixedTenor calendar, swFixedLegDayCounter, swFixedLegConvention, 3 * Months, // floatpayTenor swFloatingLegIndex, swFixedLegDayCounter)); boost::shared_ptr<RateHelper> s3y(new SubPeriodsSwapHelper(Handle<Quote>(s3yRate), 3 * Years, // SwapTenor 3 * Months, // fixedTenor calendar, swFixedLegDayCounter, swFixedLegConvention, 3 * Months, // floatpayTenor swFloatingLegIndex, swFixedLegDayCounter)); boost::shared_ptr<RateHelper> s4y(new SubPeriodsSwapHelper(Handle<Quote>(s4yRate), 4 * Years, // SwapTenor 3 * Months, // fixedTenor calendar, swFixedLegDayCounter, swFixedLegConvention, 3 * Months, // floatpayTenor swFloatingLegIndex, swFixedLegDayCounter)); boost::shared_ptr<RateHelper> s5y(new SubPeriodsSwapHelper(Handle<Quote>(s5yRate), 5 * Years, // SwapTenor 3 * Months, // fixedTenor calendar, swFixedLegDayCounter, swFixedLegConvention, 3 * Months, // floatpayTenor swFloatingLegIndex, swFixedLegDayCounter)); boost::shared_ptr<RateHelper> s7y(new SubPeriodsSwapHelper(Handle<Quote>(s7yRate), 7 * Years, // SwapTenor 3 * Months, // fixedTenor calendar, swFixedLegDayCounter, swFixedLegConvention, 3 * Months, // floatpayTenor swFloatingLegIndex, swFixedLegDayCounter)); boost::shared_ptr<RateHelper> s10y(new SubPeriodsSwapHelper(Handle<Quote>(s10yRate), 10 * Years, // SwapTenor 3 * Months, // fixedTenor calendar, swFixedLegDayCounter, swFixedLegConvention, 3 * Months, // floatpayTenor swFloatingLegIndex, swFixedLegDayCounter)); /********************* ** CURVE BUILDING ** *********************/ DayCounter termStructureDayCounter = Actual365Fixed(); double tolerance = 1.0e-15; // A depo-swap curve std::vector<boost::shared_ptr<RateHelper>> depoSwapInstruments; depoSwapInstruments.push_back(d1D); depoSwapInstruments.push_back(d7D); depoSwapInstruments.push_back(s3m); depoSwapInstruments.push_back(s6m); depoSwapInstruments.push_back(s9m); depoSwapInstruments.push_back(s1y); depoSwapInstruments.push_back(s2y); depoSwapInstruments.push_back(s3y); depoSwapInstruments.push_back(s4y); depoSwapInstruments.push_back(s5y); depoSwapInstruments.push_back(s7y); depoSwapInstruments.push_back(s10y); boost::shared_ptr<YieldTermStructure> depoSwapTermStructure(new PiecewiseYieldCurve<Discount, LogLinear>( valuationDate, depoSwapInstruments, termStructureDayCounter, tolerance)); // Term structures that will be used for pricing: // the one used for discounting cash flows RelinkableHandle<YieldTermStructure> discountingTermStructure; // the one used for forward rate forecasting RelinkableHandle<YieldTermStructure> forecastingTermStructure; /********************* * SWAPS TO BE PRICED * **********************/ // constant nominal 1,000,000 Real nominal = 1000000.0; Calendar cdr=China(China::IB); Integer lenghtInYears = 3; VanillaSwap::Type swapType = VanillaSwap::Payer; Date settlementDate(3, September, 2018); Date maturity = settlementDate + lenghtInYears * Years; // fixed leg Period fixedLegFrequency = 3 * Months; BusinessDayConvention fixedLegConvention = ModifiedFollowing; DayCounter fixedLegDayCounter = Actual365Fixed(); Rate fixedRate = 0.02611; // floating leg Period floatingLegFrequency = 3 * Months; BusinessDayConvention floatingLegConvention = ModifiedFollowing; DayCounter floatingLegDayCounter = Actual365Fixed(); boost::shared_ptr<IborIndex> cnyrepoIndex(new CNYRepo7D(forecastingTermStructure)); cnyrepoIndex->addFixing(Date(30, November, 2018), 0.028); cnyrepoIndex->addFixing(Date(7, December, 2018), 0.0261); cnyrepoIndex->addFixing(Date(14, December, 2018), 0.028); cnyrepoIndex->addFixing(Date(21, December, 2018), 0.0263); cnyrepoIndex->addFixing(Date(30, December, 2018), 0.0296); cnyrepoIndex->addFixing(Date(4, January, 2019), 0.0248); cnyrepoIndex->addFixing(Date(11, January, 2019), 0.0253); cnyrepoIndex->addFixing(Date(18, January, 2019), 0.026); cnyrepoIndex->addFixing(Date(25, January, 2019), 0.026); cnyrepoIndex->addFixing(Date(3, February, 2019), 0.0233); // Swap Object SubPeriodsSwap spot3YearSwap(settlementDate, nominal, lenghtInYears * Years, swapType == VanillaSwap::Payer, fixedLegFrequency, fixedRate, cdr, fixedLegDayCounter, fixedLegConvention, floatingLegFrequency, cnyrepoIndex, floatingLegDayCounter, DateGeneration::Forward, QuantExt::SubPeriodsCoupon::Compounding); /*************** * SWAP PRICING * ****************/ // utilities for reporting std::vector<std::string> headers(4); headers[0] = "term structure"; headers[1] = "net present value"; headers[2] = "fair spread"; headers[3] = "fair fixed rate"; std::string separator = " | "; Size width = headers[0].size() + separator.size() + headers[1].size() + separator.size() + headers[2].size() + separator.size() + headers[3].size() + separator.size() - 1; std::string rule(width, '-'), dblrule(width, '='); std::string tab(8, ' '); // calculations std::cout << dblrule << std::endl; std::cout << "3-year market swap-rate = " << std::setprecision(4) << io::rate(s3yRate->value()) << std::endl; std::cout << dblrule << std::endl; std::cout << tab << "3-years swap paying " << io::rate(fixedRate) << std::endl; std::cout << headers[0] << separator << headers[1] << separator << headers[2] << separator << headers[3] << separator << std::endl; std::cout << rule << std::endl; Real NPV; Rate fairRate; Spread fairSpread=0.0; boost::shared_ptr<PricingEngine> swapEngine(new DiscountingSwapEngine(discountingTermStructure)); spot3YearSwap.setPricingEngine(swapEngine); forecastingTermStructure.linkTo(depoSwapTermStructure); discountingTermStructure.linkTo(depoSwapTermStructure); NPV = spot3YearSwap.NPV(); fairSpread = spot3YearSwap.fairSpread(); fairRate = spot3YearSwap.fairRate(); std::cout << std::setw(headers[0].size()) << "depo-swap" << separator; std::cout << std::setw(headers[1].size()) << std::fixed << std::setprecision(4) << NPV << separator; std::cout << std::setw(headers[2].size()) << io::rate(fairSpread) << separator; std::cout << std::setw(headers[3].size()) << io::rate(fairRate) << separator; std::cout << std::endl; // I wanna change the three year swap rate and recalcualte the NPV and fairRate boost::shared_ptr<SimpleQuote> threeYearsRate = boost::dynamic_pointer_cast<SimpleQuote>(s3yRate); threeYearsRate->setValue(0.03); std::cout << dblrule << std::endl; std::cout << "3-year market swap-rate = " << io::rate(s3yRate->value()) << std::endl; std::cout << dblrule << std::endl; std::cout << tab << "3-years swap paying " << io::rate(fixedRate) << std::endl; std::cout << headers[0] << separator << headers[1] << separator << headers[2] << separator << headers[3] << separator << std::endl; std::cout << rule << std::endl; forecastingTermStructure.linkTo(depoSwapTermStructure); discountingTermStructure.linkTo(depoSwapTermStructure); NPV = spot3YearSwap.NPV(); fairSpread = spot3YearSwap.fairSpread(); fairRate = spot3YearSwap.fairRate(); std::cout << std::setw(headers[0].size()) << "depo-swap" << separator; std::cout << std::setw(headers[1].size()) << std::fixed << std::setprecision(2) << NPV << separator; std::cout << std::setw(headers[2].size()) << io::rate(fairSpread) << separator; std::cout << std::setw(headers[3].size()) << io::rate(fairRate) << separator; std::cout << std::endl; std::cout << rule << std::endl; return 0; } catch (std::exception& e) { std::cerr << e.what() << std::endl; return 1; } catch (...) { std::cerr << "unknown error" << std::endl; return 1; } }
//cnyrepo.cpp
//=============================================================================================//#ifndef quantlib_cny_repo_hpp #define quantlib_cny_repo_hpp #include <ql/currencies/asia.hpp> #include <ql/time/calendars/china.hpp> #include <ql/time/daycounters/actual365fixed.hpp> namespace QuantLib { //! %CNY %Repo rate class CNYRepo : public IborIndex { public: CNYRepo(const Period& tenor, const Handle<YieldTermStructure>& h = Handle<YieldTermStructure>()) : IborIndex("CNYRepo", tenor, 1, CNYCurrency(), China(China::IB), ModifiedFollowing, false, Actual365Fixed(), h) {} }; class CNYRepo7D : public CNYRepo { public: CNYRepo7D(const Handle<YieldTermStructure>& h = Handle<YieldTermStructure>()) : CNYRepo(Period(7, Days), h) {} }; class CNYRepoON : public CNYRepo { public: CNYRepoON(const Handle<YieldTermStructure>& h = Handle<YieldTermStructure>()) : CNYRepo(Period(1, Days), h) {} }; } // namespace QuantLib #endif
May 6, 2019 at 1:50 am #6641Anonymous
InactiveDear all,
Really need your help. Any suggestion and direction is welcome. Many Thanks. -
AuthorPosts
- You must be logged in to reply to this topic.