Commit bbe6cbad authored by jpekka's avatar jpekka
Browse files

Implemented MDURATION().

parent b96e8963
2002-07-07 Jukka Pekka <jiivonen@hutcs.cs.hut.fi>
* functions (gnumeric_cumprinc, gnumeric_cumipmt): Implemented.
* functions (gnumeric_cumprinc, gnumeric_cumipmt, gnumeric_mduration):
Implemented.
* sc-fin.c (GetRmz,GetZw,get_cumprinc,get_cumipmt): Added.
* sc-fin.c (GetRmz,GetZw,Duration,get_cumprinc,get_cumipmt,
get_mduration): Added.
2002-07-07 Jukka Pekka <jiivonen@hutcs.cs.hut.fi>
......
......@@ -3390,7 +3390,34 @@ static const char *help_mduration = {
static Value *
gnumeric_mduration (FunctionEvalInfo *ei, Value **argv)
{
return value_new_error (ei->pos, "#UNIMPLEMENTED!");
GDate *nSettle, *nMat;
gnum_float fCoup, fYield;
gint nFreq, nBase;
gnum_float fNumOfCoups;
Value *result;
nSettle = datetime_value_to_g (argv[0]);
nMat = datetime_value_to_g (argv[1]);
fCoup = value_get_as_float (argv[2]);
fYield = value_get_as_float (argv[3]);
nFreq = value_get_as_float (argv[4]);
nBase = argv[5] ? value_get_as_int (argv[5]) : 0;
if ( nBase < 0 || nBase > 4 || nSettle == NULL || nMat == NULL
|| (nFreq != 1 && nFreq != 2 && nFreq != 4) ) {
result = value_new_error (ei->pos, gnumeric_err_NUM);
goto out;
}
fNumOfCoups = coupnum (nSettle, nMat, nFreq, nBase, FALSE);
result = get_mduration (nSettle, nMat, fCoup, fYield, nFreq,
nBase, fNumOfCoups);
out:
datetime_g_free (nSettle);
datetime_g_free (nMat);
return result;
}
/***************************************************************************/
......
......@@ -202,6 +202,36 @@ GetZw ( gnum_float fZins, gnum_float fZzr, gnum_float fRmz, gnum_float fBw,
return -fZw;
}
static gnum_float
Duration (GDate *nSettle, GDate *nMat, gnum_float fCoup, gnum_float fYield,
gint nFreq, gint nBase, gnum_float fNumOfCoups)
{
gnum_float fYearfrac = GetYearFrac ( nSettle, nMat, nBase );
gnum_float fDur = 0.0;
gnum_float t, p = 0.0;
const gnum_float f100 = 100.0;
fCoup *= f100 / (gnum_float) nFreq; /* fCoup is used as cash flow */
fYield /= nFreq;
fYield += 1.0;
for ( t = 1.0 ; t < fNumOfCoups ; t++ )
fDur += t * ( fCoup ) / pow ( fYield, t );
fDur += fNumOfCoups * ( fCoup + f100 ) / pow ( fYield, fNumOfCoups );
for ( t = 1.0 ; t < fNumOfCoups ; t++ )
p += fCoup / pow ( fYield, t );
p += ( fCoup + f100 ) / pow ( fYield, fNumOfCoups );
fDur /= p;
fDur /= (gnum_float) nFreq;
return ( fDur );
}
/***************************************************************************/
Value *
......@@ -350,30 +380,22 @@ Value * get_duration (GDate *nSettle, GDate *nMat, gnum_float fCoup,
gnum_float fYield, gint nFreq, gint nBase,
gnum_float fNumOfCoups)
{
gnum_float fYearfrac = GetYearFrac ( nSettle, nMat, nBase );
gnum_float fDur = 0.0;
gnum_float t, p = 0.0;
const gnum_float f100 = 100.0;
fCoup *= f100 / (gnum_float) nFreq; /* fCoup is used as cash flow */
fYield /= nFreq;
fYield += 1.0;
for ( t = 1.0 ; t < fNumOfCoups ; t++ )
fDur += t * ( fCoup ) / pow ( fYield, t );
fDur += fNumOfCoups * ( fCoup + f100 ) / pow ( fYield, fNumOfCoups );
return value_new_float ( Duration (nSettle, nMat, fCoup, fYield, nFreq,
nBase, fNumOfCoups) );
}
for ( t = 1.0 ; t < fNumOfCoups ; t++ )
p += fCoup / pow ( fYield, t );
/***************************************************************************/
p += ( fCoup + f100 ) / pow ( fYield, fNumOfCoups );
Value * get_mduration (GDate *nSettle, GDate *nMat, gnum_float fCoup,
gnum_float fYield, gint nFreq, gint nBase,
gnum_float fNumOfCoups)
{
gnum_float fRet = Duration (nSettle, nMat, fCoup, fYield, nFreq, nBase,
fNumOfCoups);
fDur /= p;
fDur /= (gnum_float) nFreq;
fRet /= 1.0 + ( fYield / (gnum_float) nFreq );
return value_new_float ( fDur );
return value_new_float ( fRet );
}
/***************************************************************************/
......
......@@ -21,6 +21,9 @@ Value * get_oddlyield (GDate *nSettle, GDate *nMat, GDate *nLastCoup,
Value * get_duration (GDate *nSettle, GDate *nMat, gnum_float fCoup,
gnum_float fYield, gint nFreq, gint nBase,
gnum_float fNumOfCoups);
Value * get_mduration (GDate *nSettle, GDate *nMat, gnum_float fCoup,
gnum_float fYield, gint nFreq, gint nBase,
gnum_float fNumOfCoups);
Value * get_cumprinc (gnum_float fRate, gint nNumPeriods, gnum_float fVal,
gint nStartPer, gint nEndPer, gint nPayType);
Value * get_cumipmt (gnum_float fRate, gint nNumPeriods, gnum_float fVal,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment