채권 가격 계산 라이브러 개발을 위해 일반 채권 중 가장 기본이 되는 할인채와 이표채에 대한 설명을 한데 이어 단리채와 복리채에 대한 설명을 하고자 한다.
단리채는 매년 채권의 표면 이자율로 계산한 이자를 누적하여 만기에 일시 상환하는 채권이다. 즉 매년 이자 얼마 ( 원금 X 표면이자율 )를 계산해서 만기에는 “원금 + 그동안의 누적이자” 로 지급한다.
복리채는 채권의 이자를 복리로 계산해서 만기일에 일시 상환하는 채권이다. 즉, 채권의 원금을 지급하는 만기에 이자까지 한꺼번에 지급하는데 이 때 첫 해부터 지급되는 이자가 복리로 계속 쌓인다는 조건이다. ( 복리라 함은 이자에도 이자가 붙는 개념 )
복리채의 로직은 크게 어려울 것이 없다. 단리채와 동일한데 이자를 누적해서 그 누적된 이자에도 이자 계산을 해서 다시 누적해 주어야 한다.
/*-----------------------------------------------------------------------------
* fnSBCompoundBond : 복리채에 대한 가격 계산 함수
* Spot/YTM 모두 사용가능
* YTM의 갯수를 1개만 지정하는 경우 해당 YTM을 사용할 수 있으며,
* YTM의 갯수가 여러개인 경우 보간 하여 해당 YTM 사용
*
* total_coupon : total_year + days from issue to first coupon day
*
*---------------------------------------------------------------------------*/
UINT fnSBCompoundBond( DATETYPE dtPriceDay, /* 계산일 */
BONDINFO *pBondInfo, /* Bond Info Structure */
CURVE *pCurve, /* ytm/sport curve */
BONDPRICE *pBondPrice, /* Price Info Structure */
INT *error_code)
{
DATETYPE nextCouponDate;
DATETYPE prevCouponDate;
UINT nTotalCoupon;
UINT nResidueYear;
UINT nDaysToMaturity;
DOUBLE nBondPrice;
DOUBLE nDuration;
DOUBLE nMD;
DOUBLE nConvexity;
DOUBLE nFace;
DOUBLE nDiscountToday;
DOUBLE nIntRatio;
UINT nNextCouponRemDay;
UINT nCouponTermDay;
nDuration = 0.0;
nMD = 0.0;
nConvexity = 0.0;
nFace = 10000.0;
nIntRatio = pBondInfo->nIntMonth / 12.0;
/*------------------------------------------------------
* cashflow = face * 만기상환율 + coupon / 횟수 * ( rem / term + N - 1 )
*-----------------------------------------------------*/
nResidueYear = 0;
prevCouponDate = pBondInfo->dtDueDay;
while ( fnDatetoInt( prevCouponDate ) >= fnDatetoInt( dtPriceDay ) ) {
nextCouponDate = prevCouponDate;
prevCouponDate = fnAddDateInt( prevCouponDate, YEAR, -1 );
nResidueYear++;
}
if ( nResidueYear > 0 ) nResidueYear--;
nNextCouponRemDay = fnCountDate( dtPriceDay, nextCouponDate, DAY );
nCouponTermDay = fnCountDate( prevCouponDate, nextCouponDate, DAY ) ;
nDiscountToday = (DOUBLE) nNextCouponRemDay / (DOUBLE) nCouponTermDay;
nTotalCoupon = fnCountDate( pBondInfo->dtIssueDay, pBondInfo->dtDueDay, MONTH) / pBondInfo->nIntMonth;
nBondPrice = 0.0;
nDaysToMaturity = fnCountDate( dtPriceDay, pBondInfo->dtDueDay, DAY );
/* 해당 수익률이 하나만 입력되는 경우 하나의 YTM을 이용 */
if ( pCurve->nYieldCount == 1 )
{
pBondPrice->nYtm = pCurve->nYield[ 0 ];
}
else
{
/* 여러개의 YTM이 입력되는 경우 해당 잔존만기의 수익률을 선형보간으로 가져옴 */
pBondPrice->nYtm = fnGetRate( pCurve, nDaysToMaturity , LINEAR );
}
/* Spot 커브에 대한 부분은 생략 */
nBondPrice = nFace * pBondInfo->nReturnRate / 100.0 + nFace * pow( 1 + pBondInfo->nCouponRate * nIntRatio, nTotalCoupon ) - nFace;
nBondPrice = floor(nBondPrice) / ( (1 + pBondPrice->nYtm * nDiscountToday ) * pow( 1.0 + pBondPrice->nYtm, nResidueYear ) );
nDuration = nDaysToMaturity / 365.0;
nMD = Math_Round( nDuration / ( 1 + pBondPrice->nYtm ), 5 );
nConvexity = Math_Round( ( Math_Round( nDuration, 6 ) * ( Math_Round( nDuration, 6 ) + 1 ) ) / pow( 1.0 + pBondPrice->nYtm * pBondInfo->nIntMonth /12.0, 2 ), 5 );
pBondPrice->nPrice = nBondPrice;
pBondPrice->nDuration = Math_Round( nDuration, 5 );
pBondPrice->nMD = nMD;
pBondPrice->nConvexity = nConvexity;
return SUCCESS;
}
단리채는 채권 가격 계산 부분이 다음과 같이 변경되면 된다.
nBondPrice = floor( nFace * ( pBondInfo->nReturnRate / 100.0 + pBondInfo->nCouponRate / nCouponPerYear * (nTotalYear * nCouponPerYear + nRemDay / nLastCouponTermDay ) ) ); nBondPrice = nBondPrice / ( pow( 1.0 + pBondPrice->nYtm, nResidueYear ) * ( 1.0 + pBondPrice->nYtm * nDiscountToday ));