AnnivDates {BondValuation}  R Documentation 
AnnivDates returns a bond's timeinvariant characteristics and temporal structure as a list of three or four named data frames.
AnnivDates(Em = as.Date(NA), Mat = as.Date(NA), CpY = as.numeric(NA), FIPD = as.Date(NA), LIPD = as.Date(NA), FIAD = as.Date(NA), RV = as.numeric(NA), Coup = as.numeric(NA), DCC = as.numeric(NA), EOM = as.numeric(NA), DateOrigin = as.Date("19700101"), InputCheck = 1, FindEOM = FALSE, RegCF.equal = 0)
Em 
The bond's issue date. (required) 
Mat 
Maturity date, i.e. date on which the redemption value and the final interest are paid. (required) 
CpY 
Number of interest payments per year (nonnegative integer; element of the set {0,1,2,3,4,6,12}. Default: 2. 
FIPD 
First interest payment date after 
LIPD 
Last interest payment date prior to 
FIAD 
Date on which the interest accrual starts (socalled "dated date"). 
RV 
The redemption value of the bond. Default: 100. 
Coup 
Nominal interest rate per year in percent. Default: 
DCC 
The day count convention the bond follows. Default: 
EOM 
Boolean indicating whether the bond follows the EndofMonth rule. Default: 
DateOrigin 
Determines the starting point for the daycount in "Date" objects. Default: "19700101". 
InputCheck 
If 1, the input variables are checked for the correct format. Default: 1. 
FindEOM 
If 
RegCF.equal 
If 0, the amounts of regular cash flows are calculated according to the
stipulated 
AnnivDates generates a list of the three data frames Warnings
, Traits
and DateVectors
. If the variable Coup
is passed to the function,
the output contains additionally the data frame PaySched
. AnnivDates is meant to analyze
large data frames. Therefore some features are implemented to evaluate the quality of the data. The
output of these features is stored in the data frame Warnings
. Please see section Value
for a detailed description of the tests run and the meaning of the variables in Warnings
. The
data frame Traits
contains all timeinvariant bond characteristics that were either provided by
the user or calculated by the function. The data frame DateVectors
contains three vectors
of DateObjects named RealDates
, CoupDates
and AnnivDates
and three vectors of
numerics named RD_indexes
, CD_indexes
and AD_indexes
. These vectors are
used in the other functions of this package according to the methodology presented in Djatschenko (2018).
The data frame PaySched
matches CoupDates
to the actual amount of interest that the bond pays on the respective interest payment date. Section
Value provides further information on the output of the function AnnivDates. Below
information on the proper input format is provided. Subsequently follows information on the operating
principle of the function AnnivDates and on the assumptions that are met to
estimate the points in time needed to evaluate a bond.
The dates Em
, Mat
, FIPD
, LIPD
and FIAD
can be provided as
"Date" with format "%Y%m%d"
, or
"numeric" with the appropriate DateOrigin
, or
number of class "character" with the appropriate DateOrigin
, or
string of class "character" in the format "yyyymmdd"
.
CpY
, RV
and Coup
can be provided either as class "numeric" or as a number of
class "character".
The provided issue date (Em
) is instantly substituted by the first interest accrual
date (FIAD
) if FIAD
is available and different from Em
.
Before the determination of the bond's date characteristics begins, the code evaluates the provided calendar dates for plausibility. In this process implausible dates are dropped. The sort of corresponding implausibility is identified and stored in a warning flag. (See section Value for details.)
The remaining valid calendar dates are used to gauge whether the bond follows the EndofMonthRule. The resulting parameter est_EOM can take on the following values:
Case 1:  FIPD and LIPD are both NA 
___________  ____________________________________ 
est_EOM = 1  , if Mat is the last day of a month. 
est_EOM = 0  , else. 
==========  ================================ 
Case 2:  FIPD is NA and LIPD is a valid calendar date 
___________  ____________________________________ 
est_EOM = 1  , if LIPD is the last day of a month. 
est_EOM = 0  , else. 
==========  ================================ 
Case 3:  FIPD is a valid calendar date and LIPD is NA 
___________  ____________________________________ 
est_EOM = 1  , if FIPD is the last day of a month. 
est_EOM = 0  , else. 
==========  ================================ 
Case 4:  FIPD and LIPD are valid calendar dates 
___________  ____________________________________ 
est_EOM = 1  , if LIPD is the last day of a month. 
est_EOM = 0  , else. 
==========  ================================ 
If EOM
is initially missing or NA
or not element of {0,1}
, EOM
is set est_EOM
with a warning.
If the initially provided value of EOM
deviates from est_EOM
, the following two
cases apply:
________  _________________________________________ 
Case 1:  If EOM = 0 and est_EOM = 1 : 
EOM is not overridden and remains EOM = 0 

________  _________________________________________ 
Case 2:  If EOM = 1 and est_EOM = 0 : 
EOM is overridden and set EOM = 0 with a warning. 

Keeping EOM = 1 in this case would conflict with 

the provided Mat , FIPD or LIPD . 

________  _________________________________________ 
Note:  Set the option FindEOM=TRUE to always use 
est_EOM found by the code. 

=======  ==================================== 
If FIPD
and LIPD
are both available, the lengths of the first and final coupon
periods are determinate and can be "regular", "long" or "short". To find the interest payment dates
between FIPD
and LIPD
the following assumptions are met:
The interest payment dates between FIPD and LIPD are evenly distributed.
The value of EOM determines the location of all interest payment dates.
If assumption 1 is violated, the exact locatations of the interest payment dates between
FIPD
and LIPD
are ambiguous. The assumption is violated particularly, if
FIPD
and LIPD
are in the same month of the same year but not on the same day, or
the month difference between FIPD
and LIPD
is not a multiple of the number
of months implied by CpY
, or
FIPD
and LIPD
are not both last day in month,
their day figures differ and the day figure difference between FIPD
and LIPD
is not due to different month lengths.
In each of the three cases, FIPD
and LIPD
are dropped
with the flag IPD_CpY_Corrupt = 1
.
If neither FIPD
nor LIPD
are available the code
evaluates the bond based only upon the required variables Em
and
Mat
(and CpY
, which is 2
by default). Since FIPD is
not given, it is impossible to distinguish between a "short" and "long" odd
first coupon period, without an assumption on the number of interest
payment dates. Consequently the first coupon period is assumed to be either
"regular" or "short". The locations of FIPD
and LIPD
are
estimated under the following assumptions:
The final coupon period is "regular".
The interest payment dates between the estimated FIPD and Mat are evenly distributed.
The value of EOM determines the location of all interest payment dates.
If LIPD
is available but FIPD
is not, the length
of the final coupon payment period is determined by LIPD
and
Mat
and can be "regular", "long" or "short". The locations of
the interest payment dates are estimated under the following assumptions:
The first coupon period is either "regular" or "short".
The interest payment dates between the estimated FIPD and LIPD are evenly distributed.
The value of EOM determines the location of all interest payment dates.
If FIPD
is available but LIPD
is not, the length
of the first coupon payment period is determined by Em
and
FIPD
and can be "regular", "long" or "short". The locations of
the interest payment dates are estimated under the following assumptions:
The final coupon period is either "regular" or "short".
The interest payment dates between FIPD and the estimated LIPD are evenly distributed.
The value of EOM determines the location of all interest payment dates.
All dates are returned irrespective of whether they are on a business day or not.
A vector of Date class objects with format "%Y%m%d" in ascending order, that contains the issue date, all actual coupon payment dates and the maturity date.
A vector of numerics capturing the temporal structure of the bond.
A vector of Date class objects with format "%Y%m%d" in ascending order, that contains all actual coupon payment dates and the maturity date.
A vector of numerics capturing the temporal structure of the bond.
A vector of Date class objects with format "%Y%m%d" in ascending order, that contains all theoretical coupon anniversary dates. The first value of AnnivDates is the anniversary date immediately preceding the issue date, if the bond has an irregular first coupon period; otherwise it is the issue date. The final value of AnnivDates is the anniversary date immediately succeeding the maturity date, if the bond has an irregular final coupon period; otherwise it is the maturity date.
A vector of numerics capturing the temporal structure of the bond.
A vector of Date class objects with format "%Y%m%d" in ascending order, that contains all actual coupon payment dates and the maturity date.
A vector of class "numeric" objects, that contains the actual amounts of
interest that the bond pays on the respective coupon payment dates. The unit of these payments is the
same as that of RV
that was passed to the function. RV
is not included in the final
interest payment.
PaySched
is created only if the variable Coup
is provided.
The starting point for the daycount in "Date" objects.
Number of interest payments per year.
Date on which the interest accrual starts (socalled "dated date").
The bond's issue date that was used for calculations.
The bond's issue date that was entered.
The first interest payment date after Em
that was used for calculations.
If the entered FIPD
was dropped during the calculation process,
the value is NA
.
The first interest payment date after Em
that was entered.
The estimated first interest payment date after Em
. NA
, if
a valid FIPD
was entered.
The last interest payment date prior to Mat
that was used for
calculations. If the entered LIPD
was dropped during the calculation
process, the value is NA
.
The last interest payment date prior to Mat
that was entered.
The estimated last interest payment date prior to Mat
. NA
,
if a valid LIPD
was entered.
The maturity date that was entered.
Reference date that determines the day figures of all AnnivDates.
A character string indicating the type of the first coupon period. Values: "long", "regular", "short".
Length of the first coupon period as a fraction of a regular coupon period.
A character string indicating the type of the last coupon period. Values: "long", "regular", "short".
Length of the final coupon period as a fraction of a regular coupon period.
The redemption value of the bond.
Nominal interest rate per year in percent.
The day count convention the bond follows.
The value of EOM
that was entered.
The estimated value of EOM
.
The value of EOM
that was used in the calculations.
A set of flags that indicate the occurrence of warnings during the execution. Below they are listed according to the hierarchical structure within the function AnnivDates.
Em_FIAD_differ =  
1  , if the provided issue date (Em ) was substituted by the first 

interest accrual date (FIAD ). 

This happens, if FIAD is available and different from Em . 

________________________________________________  
Note: No warning is displayed.  
___________________  ___  ________________________________________________ 
0  , else.  
=================  ===  =========================================== 
EmMatMissing =  
1  , if either issue date (Em ) or maturity date (Mat ) or both 

are missing or NA . 

________________________________________________  
Output: RealDates = NA , CoupDates = NA , 

AnnivDates = NA , FCPType = NA , LCPType = NA . 

___________________  ___  ________________________________________________ 
0  , else.  
=================  ===  =========================================== 
CpYOverride =  
1  , if number of interest periods per year (CpY ) is missing or 

NA , or if the provided CpY is not element of {0,1,2,3,4,6,12}. 

________________________________________________  
Note: CpY is set 2, and the execution continues. 

________________________________________________  
Output: as if CpY = 2 was provided initially. 

___________________  ___  ________________________________________________ 
0  , else.  
=================  ===  =========================================== 
RV_set100percent =  
1  , if the redemption value (RV ) is missing or NA . 

________________________________________________  
Note: RV is set 100, and the execution continues. 

________________________________________________  
Output: as if RV = 100 was provided initially. 

___________________  ___  ________________________________________________ 
0  , else.  
=================  ===  =========================================== 
NegLifeFlag =  
1  , if the provided maturity date (Mat ) is before or on the 

provided issue date (Em ). 

________________________________________________  
Output: RealDates = NA , CoupDates = NA , 

AnnivDates = NA , FCPType = NA , LCPType = NA . 

___________________  ___  ________________________________________________ 
0  , else.  
=================  ===  =========================================== 
ZeroFlag =  
1  , if number of interest payments per year (CpY ) is 0 . 

________________________________________________  
Output: RealDates = (Em,Mat) , CoupDates = Mat , 

AnnivDates = (Em,Mat) , FCPType = NA , LCPType = NA . 

___________________  ___  ________________________________________________ 
0  , else.  
=================  ===  =========================================== 
Em_Mat_SameMY =  
1  , if the issue date (Em ) and the maturity date (Mat ) are in the 

same month of the same year but not on the same day, while  
CpY is an element of {1,2,3,4,6,12}. 

________________________________________________  
Output: RealDates = (Em,Mat) , CoupDates = Mat , 

FCPType = short , LCPType = short . 

___________________  ___  ________________________________________________ 
0  , else.  
=================  ===  =========================================== 
ChronErrorFlag =  
1  , if the provided dates are in a wrong chronological order.  
________________________________________________  
Note:  
The correct ascending chronological order is:  
issue date (Em ), first interest payment date (FIPD ), 

last interest payment date (LIPD ), maturity date (Mat ). 

FIPD and LIPD are set as.Date(NA) . 

________________________________________________  
Output: as if FIPD and LIPD were not provided initially. 

___________________  ___  ________________________________________________ 
0  , else.  
=================  ===  =========================================== 
FIPD_LIPD_equal =  
1  if Em < FIPD = LIPD < Mat . 

________________________________________________  
Output: AnnivDates contains FIPD and has at least 3 elements. 

RealDates = (Em,FIPD,Mat) , CoupDates = (FIPD,Mat) . 

FCPType and LCPType can be "short", "regular" or "long".  
___________________  ___  ________________________________________________ 
0  , else.  
=================  ===  =========================================== 
IPD_CpY_Corrupt =  
1  , if the provided first interest payment date (FIPD ) and last 

interest payment date (LIPD ) are inconsistent with the 

provided number of interest payments per year (CpY ). 

________________________________________________  
Note:  
Inconsistency occurs if  
1. FIPD and LIPD are in the same month of the same year 

but not on the same day, or  
2. the number of months between FIPD and LIPD is not a 

multiple of the number of months implied by CpY , or 

3. FIPD and LIPD are not both last day in month, their 

day figures differ and the day figure difference between  
FIPD and LIPD is not due to different month lengths. 

In each of the three cases keeping the provided values of  
FIPD and LIPD would violate the assumption, that the 

anniversary dates between FIPD and LIPD are evenly 

distributed.  
________________________________________________  
FIPD and LIPD are set as.Date(NA) 

and the execution continues.  
________________________________________________  
Output:  
as if FIPD and LIPD were not provided initially. 

___________________  ___  ________________________________________________ 
0  , else.  
=================  ===  =========================================== 
EOM_Deviation =  
1  , if the provided value of EOM deviates from the value that 

is inferred from the provided calendar dates.  
________________________________________________  
Note:  
The program analyses the valid values of Em , Mat , FIPD and 

LIPD to determine the appropriate value of EOM . 

If the initially provided value of EOM deviates from the value 

determined by the program, there might be an inconsistency  
in the provided data.  
___________________  ___  ________________________________________________ 
0  , else.  
=================  ===  =========================================== 
EOMOverride =  
1  , if the provided value of EOM is overridden by a value that 

is inferred from the provided calendar dates.  
________________________________________________  
Note:  
This happens automatically if EOM is initially missing or NA 

or not element of {0,1} and if the provided value of EOM 

conflicts with the provided values of FIPD , LIPD or Mat , 

e.g. if est_EOM = 0 but EOM = 1 . 

If EOM_Deviation = 1 and the option FindEOM is set TRUE , 

the initially provided value of EOM is also overridden by the 

value that is inferred from the provided calendar dates if  
est_EOM = 1 but EOM = 0 . 

________________________________________________  
Output:  
as if the value of EOM that is found by the program was 

provided initially.  
___________________  ___  ________________________________________________ 
0  , else.  
=================  ===  =========================================== 
DCCOverride =  
1  if DCC is missing or NA or not element of c(1:16). 

________________________________________________  
Note:  
If the program cannot process the provided day count  
identifier DCC , it overrides it with DCC = 2. 

________________________________________________  
Output:  
as if DCC = 2 was provided initially. 

___________________  ___  ________________________________________________ 
0  , else.  
=================  ===  =========================================== 
NoCoups =  
1  , if there are no coupon payments between the provided  
issue date (Em ) and the maturity date (Mat ), but the 

provided (CpY ) is not zero. 

________________________________________________  
Output:  
RealDates = (Em,Mat) , CoupDates = (Mat) , 

AnnivDates contains Mat and has either 

2 or 3 elements, FCPType = LCPType and 

can be "short" , "regular" or "long" . 

___________________  ___  ________________________________________________ 
0  , else.  
=================  ===  =========================================== 
Djatschenko, Wadim, The Nitty Gritty of Bond Valuation: A Generalized Methodology for Fixed Coupon Bond Analysis Allowing for Irregular Periods and Various Day Count Conventions (November 5, 2018). Available at SSRN: https://ssrn.com/abstract=3205167.
data(SomeBonds2016) # Applying the function AnnivDates to the data frame SomeBonds2016. system.time( FullAnalysis<apply(SomeBonds2016[,c('Issue.Date','Mat.Date','CpY.Input','FIPD.Input', 'LIPD.Input','FIAD.Input','RV.Input','Coup.Input','DCC.Input','EOM.Input')],1,function(y) AnnivDates(y[1],y[2],y[3],y[4],y[5],y[6],y[7],y[8],y[9],y[10],RegCF.equal=1)), gcFirst = TRUE) # warnings are due to apply's conversion of the variables' classes in # SomeBonds2016 to class "character" # The output stored in FullAnalysis ist a nested list. # Lets look at what is stored in FullAnalysis for a random bond: randombond<sample(c(1:nrow(SomeBonds2016)),1) FullAnalysis[[randombond]] # Extracting the data frame Warnings: AllWarnings<do.call(rbind,lapply(FullAnalysis, `[[`, 1)) summary(AllWarnings) # binding the Warnings to the bonds BondsWithWarnings<cbind(SomeBonds2016,AllWarnings) # Extracting the data frame Traits: AllTraits<do.call(rbind,lapply(FullAnalysis, `[[`, 2)) summary(AllTraits) # binding the Traits to the bonds BondsWithTraits<cbind(SomeBonds2016,AllTraits) # Extracting the data frame AnnivDates: AnnivDates<lapply(lapply(FullAnalysis, `[[`, 3), `[[`, 5) AnnivDates<lapply(AnnivDates, `length<`, max(lengths(AnnivDates))) AnnivDates<as.data.frame(do.call(rbind, AnnivDates)) AnnivDates<as.data.frame(lapply(AnnivDates, as.Date, as.Date(AllTraits$DateOrigin[1]))) # binding the AnnivDates to the bonds: BondsWithAnnivDates<cbind(SomeBonds2016,AnnivDates) # Extracting the data frames PaySched for each bond and creating a panel: CoupSched<lapply(FullAnalysis, `[[`, 4) CoupSchedPanel<SomeBonds2016[rep(row.names(SomeBonds2016),sapply(CoupSched, nrow)),] CoupSched<as.data.frame(do.call(rbind, CoupSched)) CoupSchedPanel<cbind(CoupSchedPanel,CoupSched)