void MainApplication::fetchSchedule(Schedule* toReplace, const QUrl& url, const QString& dateFormat) { qDebug() << "fetch schedule url:" << url; QNetworkRequest request(url); QNetworkReply* reply = networkAccessManager_.get(request); connect(reply, &QNetworkReply::finished, [this, toReplace, reply, dateFormat]() { QByteArray data = reply->readAll(); qDebug() << data; if (!data.isEmpty()) { Schedule s = Schedule::fromOutlookCsvData(data, SF_TIME_ZONE, dateFormat); qDebug() << "downloaded schedule:" << s.size() << s.getEventsByDate(QDate::currentDate()); // Sanity check. if (s.size() > 0) { qDebug() << "replacing schedule"; *toReplace = s; this->updateEventTimes(); } } reply->deleteLater(); }); }
void ScheduleToXML::OneWFScheduleToXML(ofstream&f, Schedule ¤tSchedule, int currentWfNum){ int currentWfPackage = 0; for (Schedule::size_type i = 0; i < currentSchedule.size(); i++){ int packageNum = currentSchedule[i].get<0>(); int tBegin = currentSchedule[i].get<1>() * data.context.GetDelta(); int coresCount = currentSchedule[i].get<2>().size(); vector <int> cores = currentSchedule[i].get<2>(); int type = data.GetResourceType(cores[0]); int currBeginIndex = 0; // correct //cout << "type=" << type << " cores = " << coresCount << " package = " << packageNum << " "; double execTime = data.workflows[currentWfNum].GetExecTime(packageNum,type+1,coresCount); //cout << execTime << endl; int tEnd = tBegin + static_cast<int>(execTime); for (unsigned j = 0; j < cores.size(); j++){ f << "\t\t<node_statistics>" << endl; f << "\t\t <node_property name=\"id\" value=\"" << packageNum+1 <<"\"/>" << endl; f << "\t\t <node_property name=\"type\" value=\"computation\"/>" << endl; f << "\t\t <node_property name=\"start_time\" value=\"" << tBegin << "\"/>" << endl; f << "\t\t <node_property name=\"end_time\" value=\"" << tEnd << "\"/>" << endl; f << "\t\t <configuration>" << endl; f << "\t\t <conf_property name=\"cluster_id\" value=\"0\"/>" << endl; f << "\t\t <conf_property name=\"host_nb\" value=\"1\"/>" << endl; f << "\t\t <host_lists>" << endl; f << "\t\t <hosts start=\"" << cores[j] << "\" nb=\"1\"/>" << endl; f << "\t\t </host_lists>" << endl; f << "\t\t </configuration>" << endl; f << "\t\t</node_statistics>" << endl; } currentWfPackage++; } }
// get criteria value taling into account the average time of unscheduled tasks double ReservedTimeCriteria::GetCriteria (const Schedule &in, const int &wfNum){ double requiredDeadline = data.GetDeadline(wfNum); // max ending time double maxEndTime = 0; for (auto &sched: in){ double currentEndTime = sched.get<1>() + sched.get<3>(); if (maxEndTime < currentEndTime) maxEndTime = currentEndTime; } // if all tasks are unscheduled if (maxEndTime == 0) return 0; double deadline = requiredDeadline - maxEndTime; // if there are some unscheduled tasks int pCount = data.Workflows(wfNum).GetPackageCount(); if (in.size() != pCount){ vector <int> scheduled; for (const auto &sched : in){ scheduled.push_back(sched.get_head()); } for (int pNum = 0; pNum < pCount; pNum++){ // if package is unscheduled, add it avg exec time to deadline if (find(scheduled.begin(), scheduled.end(), pNum) == scheduled.end()) // we suppose that all unscheduled packages execute sequentially deadline += data.Workflows(wfNum).GetAvgExecTime(pNum); } } return deadline; }
const Real Gaussian1dModel::swapAnnuity(const Date &fixing, const Period &tenor, const Date &referenceDate, const Real y, boost::shared_ptr<SwapIndex> swapIdx) const { QL_REQUIRE(swapIdx != NULL, "no swap index given"); calculate(); Handle<YieldTermStructure> ytsd = swapIdx->discountingTermStructure(); // might be empty, then use // model curve boost::shared_ptr<VanillaSwap> underlying = underlyingSwap(swapIdx, fixing, tenor); Schedule sched = underlying->fixedSchedule(); Real annuity = 0.0; for (unsigned int j = 1; j < sched.size(); j++) { annuity += zerobond(sched.calendar().adjust( sched.date(j), underlying->paymentConvention()), referenceDate, y, ytsd) * swapIdx->dayCounter().yearFraction(sched.date(j - 1), sched.date(j)); } return annuity; }
ELSStepDownMonthlyR::ELSStepDownMonthlyR(Real notional, const Date& issueDate, Natural settlementDays, //const std::vector<boost::shared_ptr<Index>>& refIndex, const std::vector<boost::shared_ptr<StockIndex>>& refIndex, const Schedule& schedule, std::vector<Real>& earlyExTriggers, std::vector<Real>& redemCoupon, Real KILossCoupon, const std::vector<Real>& KIbarrier, CheckKIType checkKIType, const DayCounter& daycount, const Calendar& calendar ) :ELSStepDown(notional,issueDate,settlementDays,refIndex,schedule,earlyExTriggers,redemCoupon, KIbarrier,checkKIType,daycount,calendar), KILossCoupon_(KILossCoupon),checkKIType_(checkKIType) { pastKICount_=0; for(Size i=0;i<schedule.size();++i){ if(earlyExTriggers[i]>0.0){ fixingExDates_.push_back(schedule[i]); } } }
// implements staging scheme for finding the schedule for WFs set // <PRE> 0 <= firstWfNum < data.workflows.size() double Scheduler::StagedScheme(int firstWfNum){ cout << "StagedScheme(int) was called\n"; try{ int wfCount = data.GetWFCount(); if (firstWfNum < 0 || firstWfNum > wfCount) throw UserException("Scheduler::StagedScheme(int) error. Wrong init workflow number"); // creating XML with init time windows //xmlWriter->SetXMLBaseName("Init_"); Schedule oneWFsched; //xmlWriter->CreateXML(oneWFsched, -1); // ??!! think about it ! xmlWriter->SetXMLBaseName("Staged_"); //double stagedT = clock(); //string resFileName = "staged_scheme_" + to_string(firstWfNum) + ".txt"; //ofstream res(resFileName); //if (res.fail()) // throw UserException("Scheduler::StagedScheme(int) error. Unable to create res file"); //res << "Stage 1, workflow # " << firstWfNum << endl; //cout << "Stage 1, workflow # " << firstWfNum << endl; vector <double> eff; // applying settings of scheduling method for initial WF unique_ptr <SchedulingMethod> method = SchedulingFactory::GetMethod(data, methodsSet[firstWfNum], firstWfNum); // getting schedule for first WF double oneStepStart = clock(); eff.push_back(method->GetWFSchedule(oneWFsched)); // set local to global packages int initNum = data.GetInitPackageNumber(firstWfNum); for (int i = 0; i < oneWFsched.size(); i++) oneWFsched[i].get<0>() += initNum; fullSchedule = oneWFsched; //cout << "Elapsed time: " << (clock()-oneStepStart)/1000.0 << " sec" << endl; scheduledWFs.push_back(firstWfNum); //xmlWriter->CreateXML(oneWFsched, firstWfNum); // write result to XML data.FixBusyIntervals(); // write result to res file //PrintOneWFSched(res, oneWFsched, firstWfNum); // we need to store current busy intervals // of schedule that give the best efficiency // current best schedule is stored in oneWFsched vector<vector <BusyIntervals>> storedIntervals; Schedule storedSched; while (scheduledWFs.size() != wfCount ){ //cout << "Stage " << scheduledWFs.size() + 1 << endl; double stageMaxEff = numeric_limits<double>::infinity(); int bestWfNum = -1; for (int i = 0; i < wfCount; i++){ // if this WF wasn't scheduled yet if (find(scheduledWFs.begin(), scheduledWFs.end(), i) == scheduledWFs.end()){ //cout << "CurrentWfNum = " << i << " "; oneStepStart = clock(); method = SchedulingFactory::GetMethod(data, methodsSet[i], i); oneWFsched.clear(); double currentEff = method->GetWFSchedule(oneWFsched); //cout << "Elapsed time: " << (clock()-oneStepStart)/1000.0 << " sec" << endl; /*ReadData(i); directBellman = false; BackBellmanProcedure(); directBellman = true; double currentEff = DirectBellman(i);*/ if (stageMaxEff > currentEff){ stageMaxEff = currentEff; bestWfNum = i; storedSched = oneWFsched; storedIntervals.clear(); data.GetCurrentIntervals(storedIntervals); //GetBestBusyIntervals(bestBusyIntervals); } data.ResetBusyIntervals(); // newfag in my program //states.clear(); controls.clear(); nextStateNumbers.clear(); stagesCores.clear(); } } // set local to global packages int initNum = data.GetInitPackageNumber(bestWfNum); for (int i = 0; i < storedSched.size(); i++) storedSched[i].get<0>() += initNum; copy(storedSched.begin(), storedSched.end(), back_inserter(fullSchedule)); //copy(bestStagesCores.begin(), bestStagesCores.end(),back_inserter(allStagesCores)); scheduledWFs.push_back(bestWfNum); //usedNums = scheduledWFs; ??? //stagesCores = bestStagesCores; //currentWfNum = bestWfNum; eff.push_back(stageMaxEff); // set current intervals as stored intervals data.SetCurrentIntervals(storedIntervals); // write result to XML // xmlWriter->CreateXML(storedSched, bestWfNum); // write result to res file // PrintOneWFSched(res, storedSched, bestWfNum); data.FixBusyIntervals(); /*SetBestBusyIntervals(bestBusyIntervals); FixNewBusyIntervals(); BellmanToXML(true);*/ //std::system("pause"); } /*usedNums = scheduledWFs; ??? SetFirstBusyIntervals(); stagesCores = allStagesCores; BellmanToXML(false);*/ //PrintFooter(res, eff); double sumEff = 0.0; for (int i = 0; i < eff.size(); i++) sumEff += eff[i]; data.SetInitBusyIntervals(); //xmlWriter->CreateXML(fullSchedule, -1); //res.close(); cout << "Max eff: " << sumEff/maxPossible << endl; //cout << "Elapsed time: " << (clock()-stagedT)/1000.0 << " sec" << endl; return sumEff/maxPossible ; } catch (UserException& e){ cout<<"error : " << e.what() <<endl; std::system("pause"); exit(EXIT_FAILURE); } }
// scheduling ordered due to prioretization criteria void Scheduler::OrderedScheme(int criteriaNumber){ try{ maxEff = 0.0; // get pointer to criteria unique_ptr<CriteriaMethod> criteria = CriteriaFactory::GetMethod(data,criteriaNumber); bool tendsToMin = criteria->TendsToMin(); // unscheduled WF numbers vector <int> unscheduled; for (int i = 0; i < data.GetWFCount(); i++) unscheduled.push_back(i); int stage = 0; // while we have unscheduled WFs while (unscheduled.size() != 0){ //if (stage % 10 == 0) cout << "Stage " << stage << endl; stage++; // best schedule (from the prioretization criteria point of view) Schedule best; // and "best" wf number int bestWFNum = -1; // max eff (on this iteration) double currentBestEff = 0.0; // current best criteria value double bestCriteria = tendsToMin ? numeric_limits<double>::max() : -1 * numeric_limits<double>::max(); // busy intervals for best schedule vector<vector <BusyIntervals>> storedIntervals; // for each unscheduled WF for (auto &wfNum : unscheduled){ Schedule current; unique_ptr <SchedulingMethod> method = SchedulingFactory::GetMethod(data, methodsSet[wfNum], wfNum); // get current schedule in current variable double currentEff = method->GetWFSchedule(current); // get current criteria double currentCriteria = criteria->GetCriteria(current, wfNum); if (criteria->IsBetter(currentCriteria, bestCriteria)){ best = current; bestWFNum = wfNum; currentBestEff = currentEff; bestCriteria = currentCriteria; storedIntervals.clear(); data.GetCurrentIntervals(storedIntervals); } data.ResetBusyIntervals(); } // set local to global packages int initNum = data.GetInitPackageNumber(bestWFNum); for (int i = 0; i < best.size(); i++) best[i].get<0>() += initNum; // add best schedule to full schedule copy(best.begin(), best.end(), back_inserter(fullSchedule)); data.SetCurrentIntervals(storedIntervals); data.FixBusyIntervals(); maxEff += currentBestEff; //cout << "Best wf num: " << bestWFNum << " bestCriteria: " << bestCriteria << endl; if (bestWFNum == -1) { cout << "unscheduled.size() == " << unscheduled.size() << endl; break; } auto idx = find(unscheduled.begin(), unscheduled.end(), bestWFNum); if (idx == unscheduled.end()) throw UserException("Scheduler::OrderedScheme(int) error. Best wf number was not found"); unscheduled.erase(idx); } data.SetInitBusyIntervals(); maxEff /= maxPossible; cout << "Ordered scheme eff: " << maxEff << endl; xmlWriter->SetXMLBaseName("Ordered_"); // write result to XML xmlWriter->CreateXML(fullSchedule, -1); string resFileName = "ordered.txt"; ofstream res(resFileName); if (res.fail()) throw UserException("Scheduler::OrderedScheme error. Unable to create res file"); PrintOneWFSched(res, fullSchedule, -1); res.close(); } catch (UserException& e){ cout<<"error : " << e.what() <<endl; std::system("pause"); exit(EXIT_FAILURE); } }
void InflationTest::testZeroIndex() { BOOST_MESSAGE("Testing zero inflation indices..."); SavedSettings backup; EUHICP euhicp(true); if (euhicp.name() != "EU HICP" || euhicp.frequency() != Monthly || euhicp.revised() || !euhicp.interpolated() || euhicp.availabilityLag() != 1*Months) { BOOST_ERROR("wrong EU HICP data (" << euhicp.name() << ", " << euhicp.frequency() << ", " << euhicp.revised() << ", " << euhicp.interpolated() << ", " << euhicp.availabilityLag() << ")"); } UKRPI ukrpi(false); if (ukrpi.name() != "UK RPI" || ukrpi.frequency() != Monthly || ukrpi.revised() || ukrpi.interpolated() || ukrpi.availabilityLag() != 1*Months) { BOOST_ERROR("wrong UK RPI data (" << ukrpi.name() << ", " << ukrpi.frequency() << ", " << ukrpi.revised() << ", " << ukrpi.interpolated() << ", " << ukrpi.availabilityLag() << ")"); } // Retrieval test. //---------------- // make sure of the evaluation date Date evaluationDate(13, August, 2007); evaluationDate = UnitedKingdom().adjust(evaluationDate); Settings::instance().evaluationDate() = evaluationDate; // fixing data Date from(1, January, 2005); Date to(13, August, 2007); Schedule rpiSchedule = MakeSchedule().from(from).to(to) .withTenor(1*Months) .withCalendar(UnitedKingdom()) .withConvention(ModifiedFollowing); Real fixData[] = { 189.9, 189.9, 189.6, 190.5, 191.6, 192.0, 192.2, 192.2, 192.6, 193.1, 193.3, 193.6, 194.1, 193.4, 194.2, 195.0, 196.5, 197.7, 198.5, 198.5, 199.2, 200.1, 200.4, 201.1, 202.7, 201.6, 203.1, 204.4, 205.4, 206.2, 207.3, 206.1, -999.0 }; bool interp = false; boost::shared_ptr<UKRPI> iir(new UKRPI(interp)); for (Size i=0; i<rpiSchedule.size();i++) { iir->addFixing(rpiSchedule[i], fixData[i]); } Date todayMinusLag = evaluationDate - iir->availabilityLag(); std::pair<Date,Date> lim = inflationPeriod(todayMinusLag, iir->frequency()); todayMinusLag = lim.first; Real eps = 1.0e-8; // -1 because last value not yet available, // (no TS so can't forecast). for (Size i=0; i<rpiSchedule.size()-1;i++) { std::pair<Date,Date> lim = inflationPeriod(rpiSchedule[i], iir->frequency()); for (Date d=lim.first; d<=lim.second; d++) { if (d < inflationPeriod(todayMinusLag,iir->frequency()).first) { if (std::fabs(iir->fixing(d) - fixData[i]) > eps) BOOST_ERROR("Fixings not constant within a period: " << iir->fixing(d) << ", should be " << fixData[i]); } } } }
void InflationTest::testYYTermStructure() { BOOST_MESSAGE("Testing year-on-year inflation term structure..."); SavedSettings backup; // try the YY UK Calendar calendar = UnitedKingdom(); BusinessDayConvention bdc = ModifiedFollowing; Date evaluationDate(13, August, 2007); evaluationDate = calendar.adjust(evaluationDate); Settings::instance().evaluationDate() = evaluationDate; // fixing data Date from(1, January, 2005); Date to(13, August, 2007); Schedule rpiSchedule = MakeSchedule().from(from).to(to) .withTenor(1*Months) .withCalendar(UnitedKingdom()) .withConvention(ModifiedFollowing); Real fixData[] = { 189.9, 189.9, 189.6, 190.5, 191.6, 192.0, 192.2, 192.2, 192.6, 193.1, 193.3, 193.6, 194.1, 193.4, 194.2, 195.0, 196.5, 197.7, 198.5, 198.5, 199.2, 200.1, 200.4, 201.1, 202.7, 201.6, 203.1, 204.4, 205.4, 206.2, 207.3, -999.0, -999 }; RelinkableHandle<YoYInflationTermStructure> hy; bool interp = false; boost::shared_ptr<YYUKRPIr> iir(new YYUKRPIr(interp, hy)); for (Size i=0; i<rpiSchedule.size();i++) { iir->addFixing(rpiSchedule[i], fixData[i]); } boost::shared_ptr<YieldTermStructure> nominalTS = nominalTermStructure(); // now build the YoY inflation curve Datum yyData[] = { { Date(13, August, 2008), 2.95 }, { Date(13, August, 2009), 2.95 }, { Date(13, August, 2010), 2.93 }, { Date(15, August, 2011), 2.955 }, { Date(13, August, 2012), 2.945 }, { Date(13, August, 2013), 2.985 }, { Date(13, August, 2014), 3.01 }, { Date(13, August, 2015), 3.035 }, { Date(13, August, 2016), 3.055 }, // note that { Date(13, August, 2017), 3.075 }, // some dates will be on { Date(13, August, 2019), 3.105 }, // holidays but the payment { Date(15, August, 2022), 3.135 }, // calendar will roll them { Date(13, August, 2027), 3.155 }, { Date(13, August, 2032), 3.145 }, { Date(13, August, 2037), 3.145 } }; Period observationLag = Period(2,Months); DayCounter dc = Thirty360(); // now build the helpers ... std::vector<boost::shared_ptr<BootstrapHelper<YoYInflationTermStructure> > > helpers = makeHelpers<YoYInflationTermStructure,YearOnYearInflationSwapHelper, YoYInflationIndex>(yyData, LENGTH(yyData), iir, observationLag, calendar, bdc, dc); Rate baseYYRate = yyData[0].rate/100.0; boost::shared_ptr<PiecewiseYoYInflationCurve<Linear> > pYYTS( new PiecewiseYoYInflationCurve<Linear>( evaluationDate, calendar, dc, observationLag, iir->frequency(),iir->interpolated(), baseYYRate, Handle<YieldTermStructure>(nominalTS), helpers)); pYYTS->recalculate(); // validation // yoy swaps should reprice to zero // yy rates should not equal yySwap rates Real eps = 0.000001; // usual swap engine Handle<YieldTermStructure> hTS(nominalTS); boost::shared_ptr<PricingEngine> sppe(new DiscountingSwapEngine(hTS)); // make sure that the index has the latest yoy term structure hy.linkTo(pYYTS); for (Size j = 1; j < LENGTH(yyData); j++) { from = nominalTS->referenceDate(); to = yyData[j].date; Schedule yoySchedule = MakeSchedule().from(from).to(to) .withConvention(Unadjusted) // fixed leg gets calendar from .withCalendar(calendar) // schedule .withTenor(1*Years) .backwards() ; YearOnYearInflationSwap yyS2(YearOnYearInflationSwap::Payer, 1000000.0, yoySchedule,//fixed schedule, but same as yoy yyData[j].rate/100.0, dc, yoySchedule, iir, observationLag, 0.0, //spread on index dc, UnitedKingdom()); yyS2.setPricingEngine(sppe); BOOST_CHECK_MESSAGE(fabs(yyS2.NPV())<eps,"fresh yoy swap NPV!=0 from TS " <<"swap quote for pt " << j << ", is " << yyData[j].rate/100.0 <<" vs YoY rate "<< pYYTS->yoyRate(yyData[j].date-observationLag) <<" at quote date "<<(yyData[j].date-observationLag) <<", NPV of a fresh yoy swap is " << yyS2.NPV() <<"\n fair rate " << yyS2.fairRate() <<" payment "<<yyS2.paymentConvention()); } Size jj=3; for (Size k = 0; k < 14; k++) { from = nominalTS->referenceDate() - k*Months; to = yyData[jj].date - k*Months; Schedule yoySchedule = MakeSchedule().from(from).to(to) .withConvention(Unadjusted) // fixed leg gets calendar from .withCalendar(calendar) // schedule .withTenor(1*Years) .backwards() ; YearOnYearInflationSwap yyS3(YearOnYearInflationSwap::Payer, 1000000.0, yoySchedule,//fixed schedule, but same as yoy yyData[jj].rate/100.0, dc, yoySchedule, iir, observationLag, 0.0, //spread on index dc, UnitedKingdom()); yyS3.setPricingEngine(sppe); BOOST_CHECK_MESSAGE(fabs(yyS3.NPV())< 20000.0, "unexpected size of aged YoY swap, aged " <<k<<" months: YY aged NPV = " << yyS3.NPV() <<", legs "<< yyS3.legNPV(0) << " and " << yyS3.legNPV(1) ); } }
void InflationTest::testYYIndex() { BOOST_MESSAGE("Testing year-on-year inflation indices..."); SavedSettings backup; YYEUHICP yyeuhicp(true); if (yyeuhicp.name() != "EU YY_HICP" || yyeuhicp.frequency() != Monthly || yyeuhicp.revised() || !yyeuhicp.interpolated() || yyeuhicp.ratio() || yyeuhicp.availabilityLag() != 1*Months) { BOOST_ERROR("wrong year-on-year EU HICP data (" << yyeuhicp.name() << ", " << yyeuhicp.frequency() << ", " << yyeuhicp.revised() << ", " << yyeuhicp.interpolated() << ", " << yyeuhicp.ratio() << ", " << yyeuhicp.availabilityLag() << ")"); } YYEUHICPr yyeuhicpr(true); if (yyeuhicpr.name() != "EU YYR_HICP" || yyeuhicpr.frequency() != Monthly || yyeuhicpr.revised() || !yyeuhicpr.interpolated() || !yyeuhicpr.ratio() || yyeuhicpr.availabilityLag() != 1*Months) { BOOST_ERROR("wrong year-on-year EU HICPr data (" << yyeuhicpr.name() << ", " << yyeuhicpr.frequency() << ", " << yyeuhicpr.revised() << ", " << yyeuhicpr.interpolated() << ", " << yyeuhicpr.ratio() << ", " << yyeuhicpr.availabilityLag() << ")"); } YYUKRPI yyukrpi(false); if (yyukrpi.name() != "UK YY_RPI" || yyukrpi.frequency() != Monthly || yyukrpi.revised() || yyukrpi.interpolated() || yyukrpi.ratio() || yyukrpi.availabilityLag() != 1*Months) { BOOST_ERROR("wrong year-on-year UK RPI data (" << yyukrpi.name() << ", " << yyukrpi.frequency() << ", " << yyukrpi.revised() << ", " << yyukrpi.interpolated() << ", " << yyukrpi.ratio() << ", " << yyukrpi.availabilityLag() << ")"); } YYUKRPIr yyukrpir(false); if (yyukrpir.name() != "UK YYR_RPI" || yyukrpir.frequency() != Monthly || yyukrpir.revised() || yyukrpir.interpolated() || !yyukrpir.ratio() || yyukrpir.availabilityLag() != 1*Months) { BOOST_ERROR("wrong year-on-year UK RPIr data (" << yyukrpir.name() << ", " << yyukrpir.frequency() << ", " << yyukrpir.revised() << ", " << yyukrpir.interpolated() << ", " << yyukrpir.ratio() << ", " << yyukrpir.availabilityLag() << ")"); } // Retrieval test. //---------------- // make sure of the evaluation date Date evaluationDate(13, August, 2007); evaluationDate = UnitedKingdom().adjust(evaluationDate); Settings::instance().evaluationDate() = evaluationDate; // fixing data Date from(1, January, 2005); Date to(13, August, 2007); Schedule rpiSchedule = MakeSchedule().from(from).to(to) .withTenor(1*Months) .withCalendar(UnitedKingdom()) .withConvention(ModifiedFollowing); Real fixData[] = { 189.9, 189.9, 189.6, 190.5, 191.6, 192.0, 192.2, 192.2, 192.6, 193.1, 193.3, 193.6, 194.1, 193.4, 194.2, 195.0, 196.5, 197.7, 198.5, 198.5, 199.2, 200.1, 200.4, 201.1, 202.7, 201.6, 203.1, 204.4, 205.4, 206.2, 207.3, -999.0, -999.0 }; bool interp = false; boost::shared_ptr<YYUKRPIr> iir(new YYUKRPIr(interp)); boost::shared_ptr<YYUKRPIr> iirYES(new YYUKRPIr(true)); for (Size i=0; i<rpiSchedule.size();i++) { iir->addFixing(rpiSchedule[i], fixData[i]); iirYES->addFixing(rpiSchedule[i], fixData[i]); } Date todayMinusLag = evaluationDate - iir->availabilityLag(); std::pair<Date,Date> lim = inflationPeriod(todayMinusLag, iir->frequency()); todayMinusLag = lim.second + 1 - 2*Period(iir->frequency()); Real eps = 1.0e-8; // Interpolation tests //-------------------- // (no TS so can't forecast). for (Size i=13; i<rpiSchedule.size();i++) { std::pair<Date,Date> lim = inflationPeriod(rpiSchedule[i], iir->frequency()); std::pair<Date,Date> limBef = inflationPeriod(rpiSchedule[i-12], iir->frequency()); for (Date d=lim.first; d<=lim.second; d++) { if (d < todayMinusLag) { Rate expected = fixData[i]/fixData[i-12] - 1.0; Rate calculated = iir->fixing(d); BOOST_CHECK_MESSAGE(std::fabs(calculated - expected) < eps, "Non-interpolated fixings not constant within a period: " << calculated << ", should be " << expected); Real dp= lim.second + 1- lim.first; Real dpBef=limBef.second + 1 - limBef.first; Real dl = d-lim.first; // potentially does not work on 29th Feb Real dlBef = NullCalendar().advance(d, -1*Years, ModifiedFollowing) -limBef.first; Real linearNow = fixData[i] + (fixData[i+1]-fixData[i])*dl/dp; Real linearBef = fixData[i-12] + (fixData[i+1-12]-fixData[i-12])*dlBef/dpBef; Rate expectedYES = linearNow / linearBef - 1.0; Rate calculatedYES = iirYES->fixing(d); BOOST_CHECK_MESSAGE(fabs(expectedYES-calculatedYES)<eps, "Error in interpolated fixings: expect "<<expectedYES <<" see " << calculatedYES <<" flat " << calculated <<", data: "<< fixData[i-12] <<", "<< fixData[i+1-12] <<", "<< fixData[i] <<", "<< fixData[i+1] <<", fac: "<< dp <<", "<< dl <<", "<< dpBef <<", "<< dlBef <<", to: "<<linearNow<<", "<<linearBef ); } } } }
void InflationTest::testZeroTermStructure() { BOOST_MESSAGE("Testing zero inflation term structure..."); SavedSettings backup; // try the Zero UK Calendar calendar = UnitedKingdom(); BusinessDayConvention bdc = ModifiedFollowing; Date evaluationDate(13, August, 2007); evaluationDate = calendar.adjust(evaluationDate); Settings::instance().evaluationDate() = evaluationDate; // fixing data Date from(1, January, 2005); Date to(13, August, 2007); Schedule rpiSchedule = MakeSchedule().from(from).to(to) .withTenor(1*Months) .withCalendar(UnitedKingdom()) .withConvention(ModifiedFollowing); Real fixData[] = { 189.9, 189.9, 189.6, 190.5, 191.6, 192.0, 192.2, 192.2, 192.6, 193.1, 193.3, 193.6, 194.1, 193.4, 194.2, 195.0, 196.5, 197.7, 198.5, 198.5, 199.2, 200.1, 200.4, 201.1, 202.7, 201.6, 203.1, 204.4, 205.4, 206.2, 207.3, 206.1, -999.0 }; RelinkableHandle<ZeroInflationTermStructure> hz; bool interp = false; boost::shared_ptr<UKRPI> iiUKRPI(new UKRPI(interp, hz)); for (Size i=0; i<rpiSchedule.size();i++) { iiUKRPI->addFixing(rpiSchedule[i], fixData[i]); } boost::shared_ptr<ZeroInflationIndex> ii = boost::dynamic_pointer_cast<ZeroInflationIndex>(iiUKRPI); boost::shared_ptr<YieldTermStructure> nominalTS = nominalTermStructure(); // now build the zero inflation curve Datum zcData[] = { { Date(13, August, 2008), 2.93 }, { Date(13, August, 2009), 2.95 }, { Date(13, August, 2010), 2.965 }, { Date(15, August, 2011), 2.98 }, { Date(13, August, 2012), 3.0 }, { Date(13, August, 2014), 3.06 }, { Date(13, August, 2017), 3.175 }, { Date(13, August, 2019), 3.243 }, { Date(15, August, 2022), 3.293 }, { Date(14, August, 2027), 3.338 }, { Date(13, August, 2032), 3.348 }, { Date(15, August, 2037), 3.348 }, { Date(13, August, 2047), 3.308 }, { Date(13, August, 2057), 3.228 } }; Period observationLag = Period(2,Months); DayCounter dc = Thirty360(); Frequency frequency = Monthly; std::vector<boost::shared_ptr<BootstrapHelper<ZeroInflationTermStructure> > > helpers = makeHelpers<ZeroInflationTermStructure,ZeroCouponInflationSwapHelper, ZeroInflationIndex>(zcData, LENGTH(zcData), ii, observationLag, calendar, bdc, dc); Rate baseZeroRate = zcData[0].rate/100.0; boost::shared_ptr<PiecewiseZeroInflationCurve<Linear> > pZITS( new PiecewiseZeroInflationCurve<Linear>( evaluationDate, calendar, dc, observationLag, frequency, ii->interpolated(), baseZeroRate, Handle<YieldTermStructure>(nominalTS), helpers)); pZITS->recalculate(); // first check that the zero rates on the curve match the data // and that the helpers give the correct impled rates const Real eps = 0.00000001; bool forceLinearInterpolation = false; for (Size i=0; i<LENGTH(zcData); i++) { BOOST_REQUIRE_MESSAGE(std::fabs(zcData[i].rate/100.0 - pZITS->zeroRate(zcData[i].date, observationLag, forceLinearInterpolation)) < eps, "ZITS zeroRate != instrument " << pZITS->zeroRate(zcData[i].date, observationLag, forceLinearInterpolation) << " vs " << zcData[i].rate/100.0 << " interpolation: " << ii->interpolated() << " forceLinearInterpolation " << forceLinearInterpolation); BOOST_REQUIRE_MESSAGE(std::fabs(helpers[i]->impliedQuote() - zcData[i].rate/100.0) < eps, "ZITS implied quote != instrument " << helpers[i]->impliedQuote() << " vs " << zcData[i].rate/100.0); } // now test the forecasting capability of the index. hz.linkTo(pZITS); from = hz->baseDate(); to = hz->maxDate()-1*Months; // a bit of margin for adjustments Schedule testIndex = MakeSchedule().from(from).to(to) .withTenor(1*Months) .withCalendar(UnitedKingdom()) .withConvention(ModifiedFollowing); // we are testing UKRPI which is not interpolated Date bd = hz->baseDate(); Real bf = ii->fixing(bd); for (Size i=0; i<testIndex.size();i++) { Date d = testIndex[i]; Real z = hz->zeroRate(d, Period(0,Days)); Real t = hz->dayCounter().yearFraction(bd, d); if(!ii->interpolated()) // because fixing constant over period t = hz->dayCounter().yearFraction(bd, inflationPeriod(d, ii->frequency()).first); Real calc = bf * pow( 1+z, t); if (t<=0) calc = ii->fixing(d,false); // still historical if (std::fabs(calc - ii->fixing(d,true))/10000.0 > eps) BOOST_ERROR("ZC index does not forecast correctly for date " << d << " from base date " << bd << " with fixing " << bf << ", correct: " << calc << ", fix: " << ii->fixing(d,true) << ", t " << t); } //=========================================================================================== // Test zero-inflation-indexed (i.e. cpi ratio) cashflow // just ordinary indexed cashflow with a zero inflation index Date baseDate(1, January, 2006); Date fixDate(1, August, 2014); Date payDate=UnitedKingdom().adjust(fixDate+Period(3,Months),ModifiedFollowing); boost::shared_ptr<Index> ind = boost::dynamic_pointer_cast<Index>(ii); BOOST_REQUIRE_MESSAGE(ind,"dynamic_pointer_cast to Index from InflationIndex failed"); Real notional = 1000000.0;//1m IndexedCashFlow iicf(notional,ind,baseDate,fixDate,payDate); Real correctIndexed = ii->fixing(iicf.fixingDate())/ii->fixing(iicf.baseDate()); Real calculatedIndexed = iicf.amount()/iicf.notional(); BOOST_REQUIRE_MESSAGE(std::fabs(correctIndexed - calculatedIndexed) < eps, "IndexedCashFlow indexing wrong: " << calculatedIndexed << " vs correct = " << correctIndexed); //=========================================================================================== // Test zero coupon swap // first make one ... boost::shared_ptr<ZeroInflationIndex> zii = boost::dynamic_pointer_cast<ZeroInflationIndex>(ii); BOOST_REQUIRE_MESSAGE(zii,"dynamic_pointer_cast to ZeroInflationIndex from UKRPI failed"); ZeroCouponInflationSwap nzcis(ZeroCouponInflationSwap::Payer, 1000000.0, evaluationDate, zcData[6].date, // end date = maturity calendar, bdc, dc, zcData[6].rate/100.0, // fixed rate zii, observationLag); // N.B. no coupon pricer because it is not a coupon, effect of inflation curve via // inflation curve attached to the inflation index. Handle<YieldTermStructure> hTS(nominalTS); boost::shared_ptr<PricingEngine> sppe(new DiscountingSwapEngine(hTS)); nzcis.setPricingEngine(sppe); // ... and price it, should be zero BOOST_CHECK_MESSAGE(fabs(nzcis.NPV())<0.00001,"ZCIS does not reprice to zero " << nzcis.NPV() << evaluationDate << " to " << zcData[6].date << " becoming " << nzcis.maturityDate() << " rate " << zcData[6].rate << " fixed leg " << nzcis.legNPV(0) << " indexed-predicted inflated leg " << nzcis.legNPV(1) << " discount " << nominalTS->discount(nzcis.maturityDate()) ); //=========================================================================================== // Test multiplicative seasonality in price // //Seasonality factors NOT normalized //and UKRPI is not interpolated Date trueBaseDate = inflationPeriod(hz->baseDate(), ii->frequency()).second; Date seasonallityBaseDate(31,January,trueBaseDate.year()); std::vector<Rate> seasonalityFactors(12); seasonalityFactors[0] = 1.003245; seasonalityFactors[1] = 1.000000; seasonalityFactors[2] = 0.999715; seasonalityFactors[3] = 1.000495; seasonalityFactors[4] = 1.000929; seasonalityFactors[5] = 0.998687; seasonalityFactors[6] = 0.995949; seasonalityFactors[7] = 0.994682; seasonalityFactors[8] = 0.995949; seasonalityFactors[9] = 1.000519; seasonalityFactors[10] = 1.003705; seasonalityFactors[11] = 1.004186; //Creating two different seasonality objects // boost::shared_ptr<MultiplicativePriceSeasonality> seasonality_1(new MultiplicativePriceSeasonality()); std::vector<Rate> seasonalityFactors_1(12, 1.0); seasonality_1->set(seasonallityBaseDate,Monthly,seasonalityFactors_1); boost::shared_ptr<MultiplicativePriceSeasonality> seasonality_real( new MultiplicativePriceSeasonality(seasonallityBaseDate,Monthly,seasonalityFactors)); //Testing seasonality correction when seasonality factors are = 1 // Rate fixing[] = { ii->fixing(Date(14,January ,2013),true), ii->fixing(Date(14,February ,2013),true), ii->fixing(Date(14,March ,2013),true), ii->fixing(Date(14,April ,2013),true), ii->fixing(Date(14,May ,2013),true), ii->fixing(Date(14,June ,2013),true), ii->fixing(Date(14,July ,2013),true), ii->fixing(Date(14,August ,2013),true), ii->fixing(Date(14,September,2013),true), ii->fixing(Date(14,October ,2013),true), ii->fixing(Date(14,November ,2013),true), ii->fixing(Date(14,December ,2013),true) }; hz->setSeasonality(seasonality_1); QL_REQUIRE(hz->hasSeasonality(),"[44] incorrectly believes NO seasonality correction"); Rate seasonalityFixing_1[] = { ii->fixing(Date(14,January ,2013),true), ii->fixing(Date(14,February ,2013),true), ii->fixing(Date(14,March ,2013),true), ii->fixing(Date(14,April ,2013),true), ii->fixing(Date(14,May ,2013),true), ii->fixing(Date(14,June ,2013),true), ii->fixing(Date(14,July ,2013),true), ii->fixing(Date(14,August ,2013),true), ii->fixing(Date(14,September,2013),true), ii->fixing(Date(14,October ,2013),true), ii->fixing(Date(14,November ,2013),true), ii->fixing(Date(14,December ,2013),true) }; for(int i=0;i<12;i++){ if(std::fabs(fixing[i] - seasonalityFixing_1[i]) > eps) { BOOST_ERROR("Seasonality doesn't work correctly when seasonality factors are set = 1"); } } //Testing seasonality correction when seasonality factors are different from 1 // //0.998687 is the seasonality factor corresponding to June (the base CPI curve month) // Rate expectedFixing[] = { ii->fixing(Date(14,January ,2013),true) * 1.003245/0.998687, ii->fixing(Date(14,February ,2013),true) * 1.000000/0.998687, ii->fixing(Date(14,March ,2013),true) * 0.999715/0.998687, ii->fixing(Date(14,April ,2013),true) * 1.000495/0.998687, ii->fixing(Date(14,May ,2013),true) * 1.000929/0.998687, ii->fixing(Date(14,June ,2013),true) * 0.998687/0.998687, ii->fixing(Date(14,July ,2013),true) * 0.995949/0.998687, ii->fixing(Date(14,August ,2013),true) * 0.994682/0.998687, ii->fixing(Date(14,September,2013),true) * 0.995949/0.998687, ii->fixing(Date(14,October ,2013),true) * 1.000519/0.998687, ii->fixing(Date(14,November ,2013),true) * 1.003705/0.998687, ii->fixing(Date(14,December ,2013),true) * 1.004186/0.998687 }; hz->setSeasonality(seasonality_real); Rate seasonalityFixing_real[] = { ii->fixing(Date(14,January ,2013),true), ii->fixing(Date(14,February ,2013),true), ii->fixing(Date(14,March ,2013),true), ii->fixing(Date(14,April ,2013),true), ii->fixing(Date(14,May ,2013),true), ii->fixing(Date(14,June ,2013),true), ii->fixing(Date(14,July ,2013),true), ii->fixing(Date(14,August ,2013),true), ii->fixing(Date(14,September,2013),true), ii->fixing(Date(14,October ,2013),true), ii->fixing(Date(14,November ,2013),true), ii->fixing(Date(14,December ,2013),true) }; for(int i=0;i<12;i++){ if(std::fabs(expectedFixing[i] - seasonalityFixing_real[i]) > 0.01) { BOOST_ERROR("Seasonality doesn't work correctly when considering seasonality factors != 1 " << expectedFixing[i] << " vs " << seasonalityFixing_real[i]); } } //Testing Unset function // QL_REQUIRE(hz->hasSeasonality(),"[4] incorrectly believes NO seasonality correction"); hz->setSeasonality(); QL_REQUIRE(!hz->hasSeasonality(),"[5] incorrectly believes HAS seasonality correction"); Rate seasonalityFixing_unset[] = { ii->fixing(Date(14,January ,2013),true), ii->fixing(Date(14,February ,2013),true), ii->fixing(Date(14,March ,2013),true), ii->fixing(Date(14,April ,2013),true), ii->fixing(Date(14,May ,2013),true), ii->fixing(Date(14,June ,2013),true), ii->fixing(Date(14,July ,2013),true), ii->fixing(Date(14,August ,2013),true), ii->fixing(Date(14,September,2013),true), ii->fixing(Date(14,October ,2013),true), ii->fixing(Date(14,November ,2013),true), ii->fixing(Date(14,December ,2013),true) }; for(int i=0;i<12;i++){ if(std::fabs(seasonalityFixing_unset[i] - seasonalityFixing_1[i]) > eps) { BOOST_ERROR("UnsetSeasonality doesn't work correctly " << seasonalityFixing_unset[i] << " vs " << seasonalityFixing_1[i]); } } //============================================================================== // now do an INTERPOLATED index, i.e. repeat everything on a fake version of // UKRPI (to save making another term structure) bool interpYES = true; boost::shared_ptr<UKRPI> iiUKRPIyes(new UKRPI(interpYES, hz)); for (Size i=0; i<rpiSchedule.size();i++) { iiUKRPIyes->addFixing(rpiSchedule[i], fixData[i]); } boost::shared_ptr<ZeroInflationIndex> iiyes = boost::dynamic_pointer_cast<ZeroInflationIndex>(iiUKRPIyes); // now build the zero inflation curve // same data, bigger lag or it will be a self-contradiction Period observationLagyes = Period(3,Months); std::vector<boost::shared_ptr<BootstrapHelper<ZeroInflationTermStructure> > > helpersyes = makeHelpers<ZeroInflationTermStructure,ZeroCouponInflationSwapHelper, ZeroInflationIndex>(zcData, LENGTH(zcData), iiyes, observationLagyes, calendar, bdc, dc); boost::shared_ptr<PiecewiseZeroInflationCurve<Linear> > pZITSyes( new PiecewiseZeroInflationCurve<Linear>( evaluationDate, calendar, dc, observationLagyes, frequency, iiyes->interpolated(), baseZeroRate, Handle<YieldTermStructure>(nominalTS), helpersyes)); pZITSyes->recalculate(); // first check that the zero rates on the curve match the data // and that the helpers give the correct impled rates forceLinearInterpolation = false; // still for (Size i=0; i<LENGTH(zcData); i++) { BOOST_CHECK_MESSAGE(std::fabs(zcData[i].rate/100.0 - pZITSyes->zeroRate(zcData[i].date, observationLagyes, forceLinearInterpolation)) < eps, "ZITS INTERPOLATED zeroRate != instrument " << pZITSyes->zeroRate(zcData[i].date, observationLagyes, forceLinearInterpolation) << " date " << zcData[i].date << " observationLagyes " << observationLagyes << " vs " << zcData[i].rate/100.0 << " interpolation: " << iiyes->interpolated() << " forceLinearInterpolation " << forceLinearInterpolation); BOOST_CHECK_MESSAGE(std::fabs(helpersyes[i]->impliedQuote() - zcData[i].rate/100.0) < eps, "ZITS INTERPOLATED implied quote != instrument " << helpersyes[i]->impliedQuote() << " vs " << zcData[i].rate/100.0); } //====================================================================================== // now test the forecasting capability of the index. hz.linkTo(pZITSyes); from = hz->baseDate()+1*Months; // to avoid historical linear bit for rest of base month to = hz->maxDate()-1*Months; // a bit of margin for adjustments testIndex = MakeSchedule().from(from).to(to) .withTenor(1*Months) .withCalendar(UnitedKingdom()) .withConvention(ModifiedFollowing); // we are testing UKRPI which is FAKE interpolated for testing here bd = hz->baseDate(); bf = iiyes->fixing(bd); for (Size i=0; i<testIndex.size();i++) { Date d = testIndex[i]; Real z = hz->zeroRate(d, Period(0,Days)); Real t = hz->dayCounter().yearFraction(bd, d); Real calc = bf * pow( 1+z, t); if (t<=0) calc = iiyes->fixing(d); // still historical if (std::fabs(calc - iiyes->fixing(d)) > eps) BOOST_ERROR("ZC INTERPOLATED index does not forecast correctly for date " << d << " from base date " << bd << " with fixing " << bf << ", correct: " << calc << ", fix: " << iiyes->fixing(d) << ", t " << t << ", zero " << z); } //=========================================================================================== // Test zero coupon swap boost::shared_ptr<ZeroInflationIndex> ziiyes = boost::dynamic_pointer_cast<ZeroInflationIndex>(iiyes); BOOST_REQUIRE_MESSAGE(ziiyes,"dynamic_pointer_cast to ZeroInflationIndex from UKRPI-I failed"); ZeroCouponInflationSwap nzcisyes(ZeroCouponInflationSwap::Payer, 1000000.0, evaluationDate, zcData[6].date, // end date = maturity calendar, bdc, dc, zcData[6].rate/100.0, // fixed rate ziiyes, observationLagyes); // N.B. no coupon pricer because it is not a coupon, effect of inflation curve via // inflation curve attached to the inflation index. nzcisyes.setPricingEngine(sppe); // ... and price it, should be zero BOOST_CHECK_MESSAGE(fabs(nzcisyes.NPV())<0.00001,"ZCIS-I does not reprice to zero " << nzcisyes.NPV() << evaluationDate << " to " << zcData[6].date << " becoming " << nzcisyes.maturityDate() << " rate " << zcData[6].rate << " fixed leg " << nzcisyes.legNPV(0) << " indexed-predicted inflated leg " << nzcisyes.legNPV(1) << " discount " << nominalTS->discount(nzcisyes.maturityDate()) ); }
void CPISwapTest::cpibondconsistency() { CommonVars common; // ZeroInflationSwap aka CPISwap CPISwap::Type type = CPISwap::Payer; Real nominal = 1000000.0; bool subtractInflationNominal = true; // float+spread leg Spread spread = 0.0; DayCounter floatDayCount = Actual365Fixed(); BusinessDayConvention floatPaymentConvention = ModifiedFollowing; Natural fixingDays = 0; ext::shared_ptr<IborIndex> floatIndex(new GBPLibor(Period(6,Months), common.nominalTS)); // fixed x inflation leg Rate fixedRate = 0.1;//1% would be 0.01 Real baseCPI = 206.1; // would be 206.13871 if we were interpolating DayCounter fixedDayCount = Actual365Fixed(); BusinessDayConvention fixedPaymentConvention = ModifiedFollowing; Calendar fixedPaymentCalendar = UnitedKingdom(); ext::shared_ptr<ZeroInflationIndex> fixedIndex = common.ii; Period contractObservationLag = common.contractObservationLag; CPI::InterpolationType observationInterpolation = common.contractObservationInterpolation; // set the schedules Date startDate(2, October, 2007); Date endDate(2, October, 2052); Schedule floatSchedule = MakeSchedule().from(startDate).to(endDate) .withTenor(Period(6,Months)) .withCalendar(UnitedKingdom()) .withConvention(floatPaymentConvention) .backwards() ; Schedule fixedSchedule = MakeSchedule().from(startDate).to(endDate) .withTenor(Period(6,Months)) .withCalendar(UnitedKingdom()) .withConvention(Unadjusted) .backwards() ; CPISwap zisV(type, nominal, subtractInflationNominal, spread, floatDayCount, floatSchedule, floatPaymentConvention, fixingDays, floatIndex, fixedRate, baseCPI, fixedDayCount, fixedSchedule, fixedPaymentConvention, contractObservationLag, fixedIndex, observationInterpolation); Real floatFix[] = {0.06255,0.05975,0.0637,0.018425,0.0073438,-1,-1}; Real cpiFix[] = {211.4,217.2,211.4,213.4,-2,-2}; for(Size i=0;i<floatSchedule.size(); i++){ if (floatSchedule[i] < common.evaluationDate) { floatIndex->addFixing(floatSchedule[i], floatFix[i],true);//true=overwrite } ext::shared_ptr<CPICoupon> zic = ext::dynamic_pointer_cast<CPICoupon>(zisV.cpiLeg()[i]); if (zic) { if (zic->fixingDate() < (common.evaluationDate - Period(1,Months))) { fixedIndex->addFixing(zic->fixingDate(), cpiFix[i],true); } } } // simple structure so simple pricing engine - most work done by index ext::shared_ptr<DiscountingSwapEngine> dse(new DiscountingSwapEngine(common.nominalTS)); zisV.setPricingEngine(dse); // now do the bond equivalent std::vector<Rate> fixedRates(1,fixedRate); Natural settlementDays = 1;// cannot be zero! bool growthOnly = true; CPIBond cpiB(settlementDays, nominal, growthOnly, baseCPI, contractObservationLag, fixedIndex, observationInterpolation, fixedSchedule, fixedRates, fixedDayCount, fixedPaymentConvention); ext::shared_ptr<DiscountingBondEngine> dbe(new DiscountingBondEngine(common.nominalTS)); cpiB.setPricingEngine(dbe); QL_REQUIRE(fabs(cpiB.NPV() - zisV.legNPV(0))<1e-5,"cpi bond does not equal equivalent cpi swap leg"); // remove circular refernce common.hcpi.linkTo(ext::shared_ptr<ZeroInflationTermStructure>()); }
void CPISwapTest::consistency() { // check inflation leg vs calculation directly from inflation TS CommonVars common; // ZeroInflationSwap aka CPISwap CPISwap::Type type = CPISwap::Payer; Real nominal = 1000000.0; bool subtractInflationNominal = true; // float+spread leg Spread spread = 0.0; DayCounter floatDayCount = Actual365Fixed(); BusinessDayConvention floatPaymentConvention = ModifiedFollowing; Natural fixingDays = 0; ext::shared_ptr<IborIndex> floatIndex(new GBPLibor(Period(6,Months), common.nominalTS)); // fixed x inflation leg Rate fixedRate = 0.1;//1% would be 0.01 Real baseCPI = 206.1; // would be 206.13871 if we were interpolating DayCounter fixedDayCount = Actual365Fixed(); BusinessDayConvention fixedPaymentConvention = ModifiedFollowing; Calendar fixedPaymentCalendar = UnitedKingdom(); ext::shared_ptr<ZeroInflationIndex> fixedIndex = common.ii; Period contractObservationLag = common.contractObservationLag; CPI::InterpolationType observationInterpolation = common.contractObservationInterpolation; // set the schedules Date startDate(2, October, 2007); Date endDate(2, October, 2052); Schedule floatSchedule = MakeSchedule().from(startDate).to(endDate) .withTenor(Period(6,Months)) .withCalendar(UnitedKingdom()) .withConvention(floatPaymentConvention) .backwards() ; Schedule fixedSchedule = MakeSchedule().from(startDate).to(endDate) .withTenor(Period(6,Months)) .withCalendar(UnitedKingdom()) .withConvention(Unadjusted) .backwards() ; CPISwap zisV(type, nominal, subtractInflationNominal, spread, floatDayCount, floatSchedule, floatPaymentConvention, fixingDays, floatIndex, fixedRate, baseCPI, fixedDayCount, fixedSchedule, fixedPaymentConvention, contractObservationLag, fixedIndex, observationInterpolation); Date asofDate = Settings::instance().evaluationDate(); Real floatFix[] = {0.06255,0.05975,0.0637,0.018425,0.0073438,-1,-1}; Real cpiFix[] = {211.4,217.2,211.4,213.4,-2,-2}; for(Size i=0;i<floatSchedule.size(); i++){ if (floatSchedule[i] < common.evaluationDate) { floatIndex->addFixing(floatSchedule[i], floatFix[i],true);//true=overwrite } ext::shared_ptr<CPICoupon> zic = ext::dynamic_pointer_cast<CPICoupon>(zisV.cpiLeg()[i]); if (zic) { if (zic->fixingDate() < (common.evaluationDate - Period(1,Months))) { fixedIndex->addFixing(zic->fixingDate(), cpiFix[i],true); } } } // simple structure so simple pricing engine - most work done by index ext::shared_ptr<DiscountingSwapEngine> dse(new DiscountingSwapEngine(common.nominalTS)); zisV.setPricingEngine(dse); // get float+spread & fixed*inflation leg prices separately Real testInfLegNPV = 0.0; for(Size i=0;i<zisV.leg(0).size(); i++){ Date zicPayDate = (zisV.leg(0))[i]->date(); if(zicPayDate > asofDate) { testInfLegNPV += (zisV.leg(0))[i]->amount()*common.nominalTS->discount(zicPayDate); } ext::shared_ptr<CPICoupon> zicV = ext::dynamic_pointer_cast<CPICoupon>(zisV.cpiLeg()[i]); if (zicV) { Real diff = fabs( zicV->rate() - (fixedRate*(zicV->indexFixing()/baseCPI)) ); QL_REQUIRE(diff<1e-8,"failed "<<i<<"th coupon reconstruction as " << (fixedRate*(zicV->indexFixing()/baseCPI)) << " vs rate = " <<zicV->rate() << ", with difference: " << diff); } } Real error = fabs(testInfLegNPV - zisV.legNPV(0)); QL_REQUIRE(error<1e-5, "failed manual inf leg NPV calc vs pricing engine: " << testInfLegNPV << " vs " << zisV.legNPV(0)); Real diff = fabs(1-zisV.NPV()/4191660.0); #ifndef QL_USE_INDEXED_COUPON Real max_diff = 1e-5; #else Real max_diff = 3e-5; #endif QL_REQUIRE(diff<max_diff, "failed stored consistency value test, ratio = " << diff); // remove circular refernce common.hcpi.linkTo(ext::shared_ptr<ZeroInflationTermStructure>()); }
void ConvertibleBondTest::testRegression() { BOOST_TEST_MESSAGE( "Testing fixed-coupon convertible bond in known regression case..."); using namespace boost; SavedSettings backup; Date today = Date(23, December, 2008); Date tomorrow = today + 1; Settings::instance().evaluationDate() = tomorrow; Handle<Quote> u(shared_ptr<Quote>(new SimpleQuote(2.9084382818797443))); std::vector<Date> dates(25); std::vector<Rate> forwards(25); dates[0] = Date(29,December,2008); forwards[0] = 0.0025999342800; dates[1] = Date(5,January,2009); forwards[1] = 0.0025999342800; dates[2] = Date(29,January,2009); forwards[2] = 0.0053123275500; dates[3] = Date(27,February,2009); forwards[3] = 0.0197049598721; dates[4] = Date(30,March,2009); forwards[4] = 0.0220524845296; dates[5] = Date(29,June,2009); forwards[5] = 0.0217076395643; dates[6] = Date(29,December,2009); forwards[6] = 0.0230349627478; dates[7] = Date(29,December,2010); forwards[7] = 0.0087631647476; dates[8] = Date(29,December,2011); forwards[8] = 0.0219084299499; dates[9] = Date(31,December,2012); forwards[9] = 0.0244798766219; dates[10] = Date(30,December,2013); forwards[10] = 0.0267885498456; dates[11] = Date(29,December,2014); forwards[11] = 0.0266922867562; dates[12] = Date(29,December,2015); forwards[12] = 0.0271052126386; dates[13] = Date(29,December,2016); forwards[13] = 0.0268829891648; dates[14] = Date(29,December,2017); forwards[14] = 0.0264594744498; dates[15] = Date(31,December,2018); forwards[15] = 0.0273450367424; dates[16] = Date(30,December,2019); forwards[16] = 0.0294852614749; dates[17] = Date(29,December,2020); forwards[17] = 0.0285556119719; dates[18] = Date(29,December,2021); forwards[18] = 0.0305557764659; dates[19] = Date(29,December,2022); forwards[19] = 0.0292244738422; dates[20] = Date(29,December,2023); forwards[20] = 0.0263917004194; dates[21] = Date(29,December,2028); forwards[21] = 0.0239626970243; dates[22] = Date(29,December,2033); forwards[22] = 0.0216417108090; dates[23] = Date(29,December,2038); forwards[23] = 0.0228343838422; dates[24] = Date(31,December,2199); forwards[24] = 0.0228343838422; Handle<YieldTermStructure> r(shared_ptr<YieldTermStructure>( new ForwardCurve(dates, forwards, Actual360()))); Handle<BlackVolTermStructure> sigma(shared_ptr<BlackVolTermStructure>( new BlackConstantVol(tomorrow, NullCalendar(), 21.685235548092248, Thirty360(Thirty360::BondBasis)))); shared_ptr<BlackProcess> process(new BlackProcess(u,r,sigma)); Handle<Quote> spread(shared_ptr<Quote>( new SimpleQuote(0.11498700678012874))); Date issueDate(23, July, 2008); Date maturityDate(1, August, 2013); Calendar calendar = UnitedStates(); Schedule schedule = MakeSchedule().from(issueDate) .to(maturityDate) .withTenor(6*Months) .withCalendar(calendar) .withConvention(Unadjusted); Integer settlementDays = 3; shared_ptr<Exercise> exercise(new EuropeanExercise(maturityDate)); Real conversionRatio = 100.0/20.3175; std::vector<Rate> coupons(schedule.size()-1, 0.05); DayCounter dayCounter = Thirty360(Thirty360::BondBasis); CallabilitySchedule no_callability; DividendSchedule no_dividends; Real redemption = 100.0; ConvertibleFixedCouponBond bond(exercise, conversionRatio, no_dividends, no_callability, spread, issueDate, settlementDays, coupons, dayCounter, schedule, redemption); bond.setPricingEngine(shared_ptr<PricingEngine>( new BinomialConvertibleEngine<CoxRossRubinstein>(process, 600))); try { Real x = bond.NPV(); // should throw; if not, an INF was not detected. BOOST_FAIL("INF result was not detected: " << x << " returned"); } catch (Error&) { // as expected. Do nothing. // Note: we're expecting an Error we threw, not just any // exception. If something else is thrown, then there's // another problem and the test must fail. } }