Example #1
0
/*
***************************************************************************
** Equivalent to JpmcdsIsBusinessDay but uses THolidayList structure in place
** of holiday file name.
**
** Indicates whether a date is a business day.
***************************************************************************
*/
int  JpmcdsHolidayListIsBusinessDay
(TDate         date,              /* (I) Input Date */
 THolidayList *hl,                /* (I) Holiday list structure */
 TBoolean     *isBusinessDay)      /* (O) TRUE if a business day */
{
    static char     routine[] = "JpmcdsHolidayListIsBusinessDay";
    TBoolean        aHoliday = FALSE;

    /* Must have a holiday list */
    if (hl == NULL)
    {
        JpmcdsErrMsg ("%s: hl is NULL.\n", routine);
        return FAILURE;
    }

    /* First check for week-ends */
    if (JPMCDS_IS_WEEKEND (date, hl->weekends))
    {
        *isBusinessDay = FALSE;
        return SUCCESS;
    }

    /* Check if it is a holiday. */
    if (JpmcdsHolidayListIsHoliday (date, hl, &aHoliday) == FAILURE)
    {
        JpmcdsErrMsg("%s: Failed.\n", routine);
        return FAILURE;
    }

    *isBusinessDay = !aHoliday;
    return SUCCESS;
}
Example #2
0
/*
***************************************************************************
** Read array of doubles from Excel.
***************************************************************************
*/
int ReadDoubleArray(TBoolean mandatory, OPER *oper, size_t n, double **values, char *routine, char *param)
{
    size_t i;
    
    if (mandatory && oper->type == xltypeMissing)
    {
        JpmcdsErrMsg("%s: %s parameter is required\n", routine, param);
        return FAILURE;
    }

    if (oper->type == xltypeMulti)
    {
        if (oper->val.array.rows != n)
        {
            JpmcdsErrMsg("%s: %s - incorrect number of elements, expected %d\n", routine, param, n);
            return FAILURE;
        }
        
        *values = NEW_ARRAY(double, n);
        if (*values == NULL)
            return FAILURE;
        
        for (i = 0 ; i < n ; i++)
        {
            if (JpmcdsExcelGetDouble(oper->val.array.lparray + i, *values + i) != SUCCESS)
                return FAILURE;
        }
    }
    else
    {
        if (n != 1)
Example #3
0
/*
***************************************************************************
** Validates a bad day convention.
***************************************************************************
*/
int  JpmcdsBadDayConvValid
(char *routine,
 long  badDayConv)
{
    switch (badDayConv)
    {
    case JPMCDS_BAD_DAY_FOLLOW:
    case JPMCDS_BAD_DAY_PREVIOUS:
    case JPMCDS_BAD_DAY_NONE:
    case JPMCDS_BAD_DAY_MODIFIED:
        return SUCCESS;

    default:
        /*
        ** There's a good chance that the user entered a lower-case
        ** version of a valid bad day convention.
        */
        switch (toupper((int)badDayConv))
        {
        case JPMCDS_BAD_DAY_FOLLOW:
        case JPMCDS_BAD_DAY_PREVIOUS:
        case JPMCDS_BAD_DAY_NONE:
        case JPMCDS_BAD_DAY_MODIFIED:
            JpmcdsErrMsg ("%s: Bad day convention %ld must be uppercase\n",
                              routine, badDayConv);
            break;
        default:
            JpmcdsErrMsg ("%s: unknown bad day convention %ld\n",
                       routine, badDayConv);
            break;
        }
        return FAILURE;
    }
}
Example #4
0
/*
***************************************************************************
** Checks whether a rate is valid between two dates.
***************************************************************************
*/
int JpmcdsRateValidYearFrac(
    char  *routine,           /* (I) Routine name to print */
    double rate,              /* (I) Rate to validate */
    double yearFraction,      /* (I) Fraction of year */
    double basis)             /* (I) Compounding basis */
{
    int status = FAILURE;

    switch ((long) basis)
    {
    case JPMCDS_SIMPLE_BASIS:
        if (rate * yearFraction <= -1.0)
        {
            JpmcdsErrMsg("%s: Simple Rate (%f) * Year Fraction (%f) must "
                      "be > -1.0.\n",
                      routine, rate, yearFraction);
            goto done;
        }
        break;
        
    case JPMCDS_DISCOUNT_RATE:
        if (rate * yearFraction >= 1.0)
        {
            JpmcdsErrMsg("%s: Discount Rate (%f) * Year Fraction (%f) must "
                      "be < 1.0.\n",
                      routine, rate, yearFraction);
            goto done;
        }
        break;

    case JPMCDS_CONTINUOUS_BASIS:
        /* Any rate is valid */
        status = SUCCESS;
        goto done;

    case JPMCDS_DISCOUNT_FACTOR:
        if (rate <= 0.0)
        {
            JpmcdsErrMsg("%s: Discount factor (%f) must be > 0.0.\n",
                      routine, rate);
            goto done;
        }
        break;

    default:
        if (rate <= -basis)
        {
            JpmcdsErrMsg("%s: Rate (%f) must be greater than -basis (%f).\n",
                      routine, rate, -basis);
            goto done;
        }
        break;
    }

    status = SUCCESS;

 done:
    return status;
}
Example #5
0
/*
***************************************************************************
** Convert from a given rate to a discount factor.
***************************************************************************
*/
int JpmcdsRateToDiscount
    (double         rate,             /* (I) Rate */
     TDate          startDate,        /* (I) Start date */
     TDate          endDate,          /* (I) End date */
     long           rateDayCountConv, /* (I) Day count convention for rate */
     long           rateBasis,        /* (I) Basis for the rate */
     double        *discount)         /* (O) Discount factor */
{
    int status = FAILURE;               /* Until proven successful */
    static char routine[] = "JpmcdsRateToDiscount" ;
    double      rateYF ;

    if (rateBasis == JPMCDS_DISCOUNT_FACTOR)
    {
       if (rate <= 0.0)
       {
           JpmcdsErrMsg("%s: Bad rate (discount factor) %f\n",routine,rate);
           goto done;
       }
       *discount = rate;
       return SUCCESS;
    }
       
    if (rateBasis < JPMCDS_SIMPLE_BASIS)
    {
        JpmcdsErrMsg ("%s: Basis (%ld) < %d.\n",routine,rateBasis,
                   JPMCDS_SIMPLE_BASIS);
        goto done;                      /* Failed */
    }

    /* get year fractions for rate */
    if (JpmcdsDayCountFraction(startDate, 
                            endDate, 
                            rateDayCountConv, 
                            &rateYF) == FAILURE)
    {
        goto done;                      /* Failed */
    }

    if (JpmcdsRateToDiscountYearFrac(rate, 
                                  rateYF, 
                                  (double)rateBasis,
                                  discount) != SUCCESS)
    {
        goto done;
    }

    status = SUCCESS;
    
done:
    if (status == FAILURE)
    {
        JpmcdsErrMsg("%s: Failed.\n", routine);
    }    
    
    return status;
}
Example #6
0
/*
***************************************************************************
** Adds a holiday list to the holiday cache. If the entry already exists
** in the cache, then the old version will be deleted.
***************************************************************************
*/
int JpmcdsHolidayListAddToCache
(char         *name,   /* (I) Name to associate holidays with */
 THolidayList *hl      /* (I) Adds shallow copy */
)
{
    static char routine[] = "JpmcdsHolidayListAddToCache";
    int         status    = FAILURE;

    THoliday   *hol;
    THoliday   *oldHol;

    /* JpmcdsNewHoliday creates a holiday structure with the holiday list
       as a shallow copy, but a deep copy of the capitalized name.
       This shallow copy is for efficiency. We do this call first so
       that we can be sure that either hl is owned by hol or hl is
       deleted. */
    hol = JpmcdsNewHoliday(hl, name);
    if (hol == NULL)
        goto done;

    /* If necessary get rid of the old entry with the same name. 
       Use hol->name since this has been capitalized. */
    oldHol = holidayFind(hol->name);
    if (oldHol != NULL)
    {
        /*
        ** Cannot delete NONE or NO_WEEKENDS at this point. This is a sign
        ** that somebody is trying to overwrite these standard names.
        */
        if (hol->name[0] == 'N')
        {
            if (strcmp(hol->name, "NONE") == 0 || strcmp (hol->name, "NO_WEEKENDS") == 0)
            {
                JpmcdsErrMsg ("%s: Attempt to over-write standard holiday %s\n", routine, hol->name);
                goto done;
            }
        }

        holidayDelete(oldHol);
    }

    /* Insert into cache */
    hol->next = cache;
    cache = hol;
    hol = NULL; /* Now owned by cache */
    status = SUCCESS;

done:
    JpmcdsFreeHoliday (hol);

    if (status != SUCCESS)
        JpmcdsErrMsg ("%s: Failed.\n", routine);

    return status;
}
Example #7
0
/*
***************************************************************************
** This function verifies a holiday list. This means the following actions
** are performed:
** 1. Validates that dates are in strictly increasing order.
** 2. Removes dates which are already defined by being a week-end.
**
** Currently does not perform stage 2 since this causes the buscache test
** driver to fail. We will consider re-introducing this feature after the
** release of version 9.4.
***************************************************************************
*/
static int verifyHolidayList
(THolidayList *hl /* (I/O) Holiday list */
)
{
#undef CHECK_FOR_WEEKENDS

    static char routine[] = "verifyHolidayList";
    int         status    = FAILURE;

    long        idx;
    long        count;
    TDate       lastDate = 0;

    count = 0;

    for (idx = 0; idx < hl->dateList->fNumItems; ++idx)
    {
        TDate thisDate = hl->dateList->fArray[idx];

        if (thisDate <= lastDate)
        {
            JpmcdsErrMsg ("%s: Dates are not in strictly increasing order.\n", routine);
            JpmcdsErrMsg ("    [%ld] = %s; LastDate = %s.\n",
                       idx, JpmcdsFormatDate(thisDate), JpmcdsFormatDate(lastDate));
            goto done;
        }

        lastDate = thisDate;

        /* remove weekends */
        if (JPMCDS_IS_WEEKDAY(thisDate, hl->weekends))
        {
            hl->dateList->fArray[count] = thisDate;
            ++count;
        }
    }

    hl->dateList->fNumItems = count;

    status = SUCCESS;

done:

    if (status != SUCCESS)
        JpmcdsErrMsg ("%s: Failed.\n", routine);

    return status;
}
Example #8
0
/*
***************************************************************************
** Indicates whether a date is a business day.
***************************************************************************
*/
int  JpmcdsIsBusinessDay
(TDate      date,                   /* (I) Input Date */
 char      *name,                   /* (I) Filename w/ Holidays */
 TBoolean  *isBusinessDay)          /* (O) */
{
    static char   routine[] = "JpmcdsIsBusinessDay";
    THolidayList *hl = NULL;
    int           status = FAILURE;

    hl = JpmcdsHolidayListFromCache (name);
    if (hl == NULL)
        goto done;

    /* call the real routine, and return status */
    if (JpmcdsHolidayListIsBusinessDay (date, hl, isBusinessDay) != SUCCESS)
        goto done;

    status = SUCCESS;

done:

    if (status != SUCCESS)
        JpmcdsErrMsg ("%s: Failed.\n", routine);

    return status;
}
Example #9
0
/*
***************************************************************************
** Calculates a business date being at offset business days
** from the original date
***************************************************************************
*/
int  JpmcdsDateFromBusDaysOffset
(TDate     fromDate,       /* (I) input date                 */
 long      offset,         /* (I) number of business days    */
 char     *holidayFile,    /* (I) holiday file specification */
 TDate    *result)         /* (O) resulting business date    */
{
    static char          routine[]="JpmcdsDateFromBusDaysOffset";
    int                  status = FAILURE;

    THolidayList       * hl = NULL;

    /*
    ** Search for the holiday file in the cache.
    */
    hl = JpmcdsHolidayListFromCache (holidayFile);
    if (hl == NULL)
        goto done;

    /* call the real routine, and return status */
    if (JpmcdsHolidayListAddBusinessDays (fromDate, offset, hl, result) != SUCCESS)
        goto done;

    status = SUCCESS;

done:
    if (status != SUCCESS)
        JpmcdsErrMsg ("%s: Failed.\n", routine);

    return status;
}
Example #10
0
/*
***************************************************************************
** A convenience function for JpmcdsZerosToCouponsPointAdj with no bad-day 
** adjustment.
**
** Calls JpmcdsZerosToCouponsPoint with badDayConv = JPMCDS_BAD_DAY_NONE.
***************************************************************************
*/
int JpmcdsZerosToCouponsPoint
   (TCurve        *zc,                  /* (I) Zero-coupon rate curve */
    long           interpType,          /* (I) */
    TDate          startDate,           /* (I) Date instrument begins at */
    TDateInterval *interval,            /* (I) Time between payments */
    TDate          maturityDate,        /* (I) Date instrument matures at*/
    long           fixedDCC,            /* (I) See JpmcdsDayCountFraction */
    TBoolean       stubAtEnd,           /* (I) TRUE=Back, FALSE=Front*/
    double        *couponRate)          /* (O) Rate for this instrument */
{
    static char routine[]="JpmcdsZerosToCouponsPoint";
    int         status = FAILURE; 

    /* Turn off bad day adjustment. */
    if (JpmcdsZerosToCouponsPointAdj
        (zc, interpType, 
         startDate, interval, maturityDate, fixedDCC,
         stubAtEnd, 
         JPMCDS_BAD_DAY_NONE, JPMCDS_BAD_DAY_NONE, "NO_WEEKENDS",
         couponRate) == FAILURE)
        goto done;

    status = SUCCESS;

done:
    if (status == FAILURE)
        JpmcdsErrMsg("%s: Failed.\n", routine);

    return status;
}
Example #11
0
/*
***************************************************************************
** Computes the zero-coupon forward rate from startDate to the maturity 
** date using a zero-coupon curve.
**
** Note the routine does not check to make sure that the start date comes 
** before the maturity date, since zero curve creation requires the 
** calculation of forwards which go backwards (JpmcdsDiscountToRate should 
** handle that check anyway).
***************************************************************************
*/
int JpmcdsForwardFromZCurve(
    TCurve *zc,                         /* (I) Zero Curve */
    long interpType,                    /* (I) Type of interpolation */
    TDate startDate,                    /* (I) Start Date */
    TDate endDate,                      /* (I) End Date */
    long dayCountConv,                  /* (I) See ldate.h */
    long basis,                         /* (I) See cfinanci.h */
    double *rate)                       /* (O) rate from start to end */
{
    static char routine[]="JpmcdsForwardFromZCurve";
    int         status = FAILURE;               /* Until proven successful */
    double      startDiscount;
    double      endDiscount;
    double      forwardDiscount;

    if (JpmcdsDiscountDate(startDate, zc, interpType, &startDiscount) == FAILURE)
        goto done;

    if (JpmcdsDiscountDate(endDate, zc, interpType, &endDiscount) == FAILURE)
        goto done;
    
    forwardDiscount = endDiscount/startDiscount;

    if (JpmcdsDiscountToRate(forwardDiscount, startDate, endDate,
                          dayCountConv, basis, rate) == FAILURE)
        goto done;

    status = SUCCESS;

done:
    if (status == FAILURE)
        JpmcdsErrMsg("%s: failed.\n", routine);

    return status;
}
Example #12
0
/*
***************************************************************************
** Loads a holiday cache entry from a disk file, removing old one if it
** exists.
***************************************************************************
*/
EXPORT int JpmcdsHolidayLoadFromDisk
(char  *name,                        /* (I) name associated with holidays */
 char  *filename)                    /* (I) filename to load */
{
    static char routine[] = "JpmcdsHolidayLoadFromDisk";
    int         status    = FAILURE;

    THolidayList *hl;

    hl = JpmcdsHolidayListRead (filename);
    if (hl == NULL)
        goto done;

    if (JpmcdsHolidayListAddToCache (name, hl) != SUCCESS)
        goto done;

    status = SUCCESS;

done:

    if (status != SUCCESS)
        JpmcdsErrMsg ("%s: Failed.\n", routine);

    return status;
}
Example #13
0
/*
***************************************************************************
** Returns metric function to use for interpolation routines for a given 
** day count convention.
***************************************************************************
*/
TMetricDoubleFunc JpmcdsDayCountToMetricFunc(long dayCountConv)
{
    static char routine[]="JpmcdsDayCountToMetricFunc";

    switch(dayCountConv)
    {
        case JPMCDS_ACT_365F:
        case JPMCDS_ACT_365:
        case JPMCDS_ACT_360:
            return (TMetricDoubleFunc) actualDaysDiff;
            /*NOTREACHED*/
            
        case JPMCDS_B30_360:
            return (TMetricDoubleFunc) bondDaysDiff;
            /*NOTREACHED*/
            
        case JPMCDS_B30E_360:
            return (TMetricDoubleFunc) bondEDaysDiff;          
            /*NOTREACHED*/

        default:
            JpmcdsErrMsg("%s: Day count convention %ld unknown.\n", routine, dayCountConv);
            return (TMetricDoubleFunc) NULL;
    }
}
Example #14
0
File: stub.c Project: Kevin-Jin/CDS
/*
*********************************************************************
** Creates a TStubPos from a long.
*********************************************************************
*/
int JpmcdsStubPosMake
(long      stubPosValue, /* (I) Number representing stub position */
 TStubPos *stubPos)      /* (O) Stub position */
{
    static char routine[] = "JpmcdsStubPosMake";
    int         status = FAILURE;

    switch(stubPosValue)
    {
    case JPMCDS_STUB_POS_DEFAULT_AUTO:
        *stubPos = JPMCDS_STUB_POS_DEFAULT_AUTO;
        break;
    case JPMCDS_STUB_POS_DEFAULT_FRONT:
        *stubPos = JPMCDS_STUB_POS_DEFAULT_FRONT;
        break;
    case JPMCDS_STUB_POS_DEFAULT_BACK:
        *stubPos = JPMCDS_STUB_POS_DEFAULT_BACK;
        break;
    default:
        JpmcdsErrMsg("%s: Unknown stub pos %ld.\n", routine, stubPosValue);
        goto done;
    }

    status = SUCCESS;

done:
    if (status != SUCCESS)
        JpmcdsErrMsgFailure(routine);

    return status;
}
Example #15
0
/*
***************************************************************************
** The function first checks if the input name is really an encoded
** pointer. If it is, the function decodes the pointer and returns
** it. Otherwise, it checks whether the name is "NONE" or "NO_WEEKENDS".
** If it is either of those, the function returns a pointer to an
** appropriate static data structure (for efficiency). If it is
** none of the above, then the function searches for the name in the
** cache. If it finds the name, it returns a pointer to the cached
** holiday list. Otherwise, it interprets the name as a file name
** and tries to load the holiday file from disk.
**
** You can use name = "NONE" or name = "NO_WEEKENDS" and the resulting
** holiday list will be defined appropriately.
**
** This behaviour exactly duplicates the behaviour when using a holiday
** name as an input to any analytics function.
**
** Returns NULL on failure, a valid THolidayList pointer on success.
***************************************************************************
*/
THolidayList* JpmcdsHolidayListFromCache
(char *name)    /* (I) Name associated with the holidays */
{
    static char   routine[] = "JpmcdsHolidayListFromCache";
    int           status    = FAILURE;

    THolidayList  *hl = NULL; /* To be returned */
    THoliday      *hol;

    /* Must have a name. */
    if (name == NULL)
    {
        JpmcdsErrMsg ("%s: NULL inputs.\n", routine);
        goto done;
    }

    /* Use holidayFind to find in the cache. Note that NONE and NO_WEEKENDS are always in the cache. */
    hol = holidayFind (name);
    if (hol != NULL)
    {
        hl = hol->hl;
    }
    else
    {
        /* Not in the cache, so use JpmcdsHolidayListRead to read from file. */
        hl = JpmcdsHolidayListRead (name);
        if (hl == NULL)
            goto done;

        /* Now add hl to the cache. This takes a shallow copy, but is
           guaranteed to be destructive if the operation fails. */
        if (JpmcdsHolidayListAddToCache (name, hl) != SUCCESS)
            goto done;
    }

    status = SUCCESS;

done:

    if (status != SUCCESS)
    {
        JpmcdsErrMsg ("%s: Failed.\n", routine);
        return NULL;
    }

    return hl;
}
Example #16
0
/*
***************************************************************************
** Retrieve data for addin object.  Returns object (NULL if error).
***************************************************************************
*/
void* RetrieveObject(char* handle)
{
    static char *routine = "RetrieveObject";
    int          status = FAILURE;
    void        *data = NULL;
    char        *name = NULL;
    TObject     *node;
    char        *sep;

    if (handle == NULL)
    {
        JpmcdsErrMsg("%s: No object handle specified.\n", routine);
        goto done;
    }

    name = strdup(handle);
    if (name == NULL)
        goto done;

    /* remove version number from lookup string */
    sep = strchr(name, SEPARATOR);
    if (sep != NULL)
        *sep = '\0';

    node = FindNode(name);
    if (node == NULL)
    {
        JpmcdsErrMsg("%s: No object called %s found.\n", routine, name);
        goto done;
    }

    data = node->data;
    status = SUCCESS;

done:
    if (status != SUCCESS)
    {
        JpmcdsErrMsg("%s: Failed!\n", routine);
        data = NULL;
    }

    FREE(name);
    return data;
}
Example #17
0
/*
***************************************************************************
** Creates a new holiday structure.
**
** The date list can be NULL, in which case the resulting date list in the
** holiday structure will be a date list with no dates, e.g.
**      hl->dateList->fNumItems = 0;
***************************************************************************
*/
THolidayList* JpmcdsHolidayListNewGeneral
(TDateList *dateList,      /* (I) Date list to use */
 long       weekends       /* (I) Weekends flag - use JPMCDS_WEEKEND_... */
)
{
    static char   routine[] = "JpmcdsHolidayListNewGeneral";
    int           status = FAILURE;

    THolidayList *hl = NULL;
    TDateList    *dl = NULL;

    /* get new date list */
    if (dateList == NULL)
    {
        dl = JpmcdsNewEmptyDateList (0);
    }
    else
    {
        dl = JpmcdsCopyDateList (dateList);
    }
    if (dl == NULL)
    {
        goto done;
    }

    /* get new holiday list */
    hl = NEW(THolidayList);
    if (hl == NULL)
    {
        goto done;
    }

    /* fill in holiday list */
    hl->dateList     = dl;
    hl->weekends     = weekends;
    dl               = NULL; /* Now owned by hl */

    if (verifyHolidayList (hl) != SUCCESS)
        goto done;

    status = SUCCESS;

done:

    JpmcdsFreeDateList (dl);

    if (status != SUCCESS)
    {
        JpmcdsHolidayListDelete (hl);
        hl = NULL;
        JpmcdsErrMsg ("%s: Failed.\n", routine);
    }

    return hl;
}
Example #18
0
static int localUngetc(TFile *tFile, int c)
{
    if (tFile->hasLastChar == TRUE) 
    {
        JpmcdsErrMsg("Unexpected ungetchar.\n");
    }

    tFile->lastChar = c;
    tFile->hasLastChar = TRUE;

    return 0;
}
Example #19
0
/*
***************************************************************************
** Creates a new THoliday pointer. Takes shallow copy of the holiday list,
** takes a deep capitalized copy of the name.
***************************************************************************
*/
static THoliday* JpmcdsNewHoliday
(THolidayList *hl,   /* (I) Holiday list - takes shallow copy */
 char         *name  /* (I) Name - takes deep capitalized copy */
)
{
    static char routine[] = "JpmcdsNewHoliday";
    int         status    = FAILURE;

    THoliday   *hol = NULL;

    if (hl == NULL || name == NULL)
    {
        JpmcdsErrMsg ("%s: NULL inputs.\n", routine);
        goto done;
    }

    hol = NEW(THoliday);
    if (hol == NULL)
        goto done;

    hol->hl   = hl;
    hol->name = JpmcdsStringDuplicate(name);
    hl        = NULL; /* Now owned by hol */
    if (hol->name == NULL)
        goto done;

    hol->next = NULL;
    status = SUCCESS;

done:
    JpmcdsHolidayListDelete(hl);
    if (status != SUCCESS)
    {
        JpmcdsFreeHoliday (hol);
        hol = NULL;
        JpmcdsErrMsg ("%s: Failed.\n", routine);
    }

    return hol;
}
Example #20
0
/*
***************************************************************************
** Equivalent to JpmcdsIsHoliday, but uses a THolidayList structure instead of
** a holiday file name (and output type is TBoolean rather than long).
**
** Does not take week-ends into account.
***************************************************************************
*/
int  JpmcdsHolidayListIsHoliday
(TDate         date,      /* (I) Arbitrary date          */
 THolidayList *hl,        /* (I) Holiday list structure  */
 TBoolean     *isHoliday) /* (O) 0 = not a holiday, 1 = is a holiday */
{
    static char   routine[] = "JpmcdsHolidayListIsHoliday";

    TDate       * dates;
    TDate       * bRet;

    *isHoliday = FALSE;

    if (hl == NULL || hl->dateList == NULL)
    {
        JpmcdsErrMsg("%s: hl is NULL.\n", routine);
        return FAILURE;
    }

    if (IS_EMPTY_DATELIST( hl->dateList ))
    {
        return SUCCESS;
    }

    dates = hl->dateList->fArray ;
    if (dates == NULL)
    {
        /* Should only be possible if numItems == zero. */
        PROGRAM_BUG();
        return FAILURE;
    }

    /*
    ** Do a binary search of the date list to see if date
    ** is in the list.
    */
    bRet = (TDate *) bsearch ((void *) &date,
                              (void *) &dates[0],
                              (size_t) hl->dateList->fNumItems,
                              (size_t) sizeof(TDate),
                              holidayCompare);

    if (bRet != NULL)                  /* found == holiday */
    {
        *isHoliday = TRUE;
    }


    return SUCCESS;
}
Example #21
0
/*
***************************************************************************
** Makes a new empty TCashFlowList.
***************************************************************************
*/
TCashFlowList* JpmcdsNewEmptyCFL(int numItems)
{
    static char    routine[]="JpmcdsNewEmptyCFL";
    TCashFlowList *cfl = NULL;
    
    if (numItems < 0)
    {
        JpmcdsErrMsg("%s: # cashflows (%d) must be >= 0.\n", routine, numItems);
        goto done;
    }
    
    cfl = NEW(TCashFlowList);
    if (cfl == NULL)
        goto done;
    
    cfl->fNumItems = numItems;
    if (numItems > 0)
    {
        cfl->fArray = NEW_ARRAY (TCashFlow, numItems);
        if (cfl->fArray == NULL)
            goto done;
    }
    else
    {
        cfl->fArray = NULL;
    }
    /* Success
     */
    return cfl;


  done:
    JpmcdsErrMsg("%s: Failed.\n", routine);
    JpmcdsFreeCFL(cfl);
    return NULL;
}
Example #22
0
/*
***************************************************************************
** Calculates the coupon rate for an instrument, such that cashflows 
** discounted by the zero-rates equal the present value.
**
** Uses:
** 1) zero-coupon rates in the zc structure,
** 2) cashFlowList, which contains coupons payments for an instrument based
**    on an annual rate of 1 (100%), (in other words,  fraction of annual
**    coupon which should be paid at the given date)
** 3) the present Value of the instrument
** 
** It is assumed that the last payment represents a coupon plus principal.
***************************************************************************
*/
static int JpmcdsCalcCoupon(
    TCurve *zc,                         /* (I) Zero-coupon rate curve */
    long interpType,                    /* (I) Interpolation */
    TCashFlowList *cfl,                 /* (I) Cash Flow list */
    double presentValue,                /* (I) Present value */
    double *couponRate)                 /* (O) Annual coupon rate */
{
    static char routine[]="JpmcdsCalcCoupon";
    int         status = FAILURE;

    int num_pts = cfl->fNumItems;
    double coupons_PV;                  /* Present value of coupons */
    double last_PV;                     /* Present value of final payment */
    
    if (JpmcdsCashFlowPV(cfl, zc, interpType, &coupons_PV) == FAILURE)
        goto done;

    if (coupons_PV == 0.)
    {
        JpmcdsErrMsg("JpmcdsCalcCoupon: coupons have zero present value.\n");
        goto done;
    }

    if (JpmcdsDiscountDate(cfl->fArray[num_pts-1].fDate, zc, interpType, &last_PV) == FAILURE)
        goto done;

    *couponRate = (presentValue - last_PV) / coupons_PV;

    status = SUCCESS;

  done:
    if (status == FAILURE)
        JpmcdsErrMsg("%s: Failed.\n", routine);

    return status;
}
Example #23
0
/*
***************************************************************************
** Maps day count conventions to (private) strings.
***************************************************************************
*/
char* JpmcdsFormatDayCountConv(long dayCountConv)
{
    static char routine[]="JpmcdsFormatDayCountConv";

    switch(dayCountConv)
    {
    case JPMCDS_DEFAULT:
        return JPMCDS_DEFAULT_STR;
        /*NOTREACHED*/

    case JPMCDS_ACT_365F:
        return JPMCDS_ACT_365F_STR;
        /*NOTREACHED*/

    case JPMCDS_ACT_365:
        return  JPMCDS_ACT_365_STR;
        /*NOTREACHED*/

    case JPMCDS_ACT_360:
        return JPMCDS_ACT_360_STR;
        /*NOTREACHED*/

    case JPMCDS_B30_360:
        return JPMCDS_B30_360_STR;
        /*NOTREACHED*/

    case JPMCDS_B30E_360:
        return JPMCDS_B30E_360_STR;
        /*NOTREACHED*/
 
    case JPMCDS_EFFECTIVE_RATE:
        return JPMCDS_EFFECTIVE_RATE_STR;
        /*NOTREACHED*/

    default:
        goto done;
    }

 done:
    JpmcdsErrMsg("%s: Day count convention %ld unknown.\n", routine, dayCountConv);
    return "unrecognized";
    /*NOTREACHED*/
}
Example #24
0
/*
***************************************************************************
** Converts date to a valid business date using the holiday list and bad
** day convention passed in.
**
** Returns SUCCESS if convention OK, FAILURE otherwise.
**
** Equivalent to JpmcdsBusinessDay except using a THolidayList structure
** instead of a holiday file. Should be used if efficiency is an issue.
***************************************************************************
*/
int  JpmcdsHolidayListBusinessDay
(TDate         date,       /* (I) Arbitrary date. */
 long          badDayConv, /* (I) Bad day convention for adjusting
                              non-business days. Use one of the following:
                              JPMCDS_BAD_DAY_FOLLOW
                              JPMCDS_BAD_DAY_PREVIOUS
                              JPMCDS_BAD_DAY_MODIFIED
                              JPMCDS_BAD_DAY_NONE */
 THolidayList *hl,         /* (I) Holiday file list. */
 TDate        *outDate)    /* (O) Valid business day. */

{
    static char          routine[] = "JpmcdsHolidayListBusinessDay";
    int                  status;

    /* just pass call down to JpmcdsMultiHolidayListBusinessDay */

    status = JpmcdsMultiHolidayListBusinessDay(date, badDayConv, 1, &hl, outDate);

    if (status != SUCCESS)
        JpmcdsErrMsg("%s: Failed.\n", routine);

    return status;
}
Example #25
0
/*
***************************************************************************
** Using business day conventions (Following, Preceding, and Modified
** Following) calculates the next bisiness day if the input date is not a
** business day. Input and Output dates are represented as TDate types.
***************************************************************************
*/
int  JpmcdsBusinessDay
(TDate   date,                       /* Input Date */
 long    method,                     /* See ldate.h */
 char   *holidayFile,                /* Filename w/ Holidays */
 TDate  *outDate)                    /* output date */
{
    static char   routine[] = "JpmcdsBusinessDay";
    THolidayList *hl = NULL;
    int           status = FAILURE;

    /* determine whether we should do anything */
    if (method == JPMCDS_BAD_DAY_NONE)
    {
        *outDate = date;
        status = SUCCESS;
        goto done; /* success */
    }

    /* if method is other than NONE, pass to hl routine */
    hl = JpmcdsHolidayListFromCache (holidayFile);
    if (hl == NULL)
        goto done;

    /* call the real routine, and return status */
    if (JpmcdsHolidayListBusinessDay (date, method, hl, outDate) != SUCCESS)
        goto done;

    status = SUCCESS;

done:

    if (status != SUCCESS)
        JpmcdsErrMsg ("%s: Failed.\n", routine);

    return status;
}
Example #26
0
/*f
***************************************************************************
** Calculates a date being at a business or calendar days offset from the 
** input date.
***************************************************************************
*/
int JpmcdsDtFwdAdj
   (TDate          startDate,    /* (I) input date       */
    TDateAdjIntvl *adjIvl,       /* (I) in business or calendar days  */
    TDate         *result)       /* (O) resulting date   */
{
    int         status = FAILURE;
    static char routine[]="JpmcdsDtFwdAdj";

    switch (adjIvl->isBusDays)
    {
    case JPMCDS_DATE_ADJ_TYPE_BUSINESS:  /* offset by business days */
        if (adjIvl->interval.prd_typ == 'D')
        {
            if (JpmcdsDateFromBusDaysOffset
                (startDate,
                 adjIvl->interval.prd, /* Number days */
                 adjIvl->holidayFile,
                 result) != SUCCESS)
            {
                goto done;
            }
        }
        else
        {
            /*
            ** Non-daily interval and offset by business days.
            ** This means that if the start date is the end of the business
            ** month, then the end date must also be the end of the month.
            ** Actually we do adjust the end date by the bad day convention,
            ** but in the context of generating a set of cash flow dates,
            ** this is often not done when computing the maturity date.
            */
            TDate businessEOM;
            TDate endDate;
            
            if (JpmcdsDateToBusinessEOM (startDate,
                                      adjIvl->holidayFile,
                                      &businessEOM) != SUCCESS)
            {
                goto done;
            }

            if (JpmcdsDtFwdAny (startDate,
                             &adjIvl->interval,
                             &endDate) != SUCCESS)
            {
                goto done;
            }

            if (startDate == businessEOM)
            {
                if (JpmcdsDateToEOM (endDate, &endDate) != SUCCESS)
                    goto done;
            }

            if (JpmcdsBusinessDay (endDate, adjIvl->badDayConv,
                                adjIvl->holidayFile, result) != SUCCESS)
            {
                goto done;
            }
        }
        break;

    case JPMCDS_DATE_ADJ_TYPE_CALENDAR:
        /* offset by calendar period */
        if (JpmcdsDateFwdThenAdjust
            (startDate, &adjIvl->interval,
             adjIvl->badDayConv, adjIvl->holidayFile, result) != SUCCESS)
        {
            goto done;
        }
        break;

    case JPMCDS_DATE_ADJ_TYPE_WEEKDAY:
        /* Adjust interval as weekdays, and then bad day adjust the result. */
        if (adjIvl->interval.prd_typ == 'D')
        {
            if (JpmcdsDateFromBusDaysOffset
                (startDate,
                 adjIvl->interval.prd, /* Number days */
                 "NONE", /* A holiday file with week-ends only */
                 result) != SUCCESS)
            {
                goto done;
            }
            if (JpmcdsBusinessDay (*result, 
                                adjIvl->badDayConv, 
                                adjIvl->holidayFile,
                                result) != SUCCESS)
            {
                goto done;
            }
        }
        else
        {
            JpmcdsErrMsg ("%s: Weekday adjustment requires date interval "
                       "%s to be in days.\n",
                       routine, JpmcdsFormatDateInterval (&adjIvl->interval));
            goto done;
        }
        break;

    default:
        JpmcdsErrMsg ("%s: Invalid date adjustment type %d.\n", routine, adjIvl->isBusDays);
        goto done;
    }
   
    status = SUCCESS;

done:
    
    if (status != SUCCESS)
        JpmcdsErrMsg("%s: Failed.\n", routine);

    return status;
}  
Example #27
0
/*
*****************************************************************************
** Adds a number of business days to the original date.
**
** Equivalent to JpmcdsDateFromBusDaysOffset, except using a THolidayList
** structure instead of a holiday file name. Should be used if efficiency
** is an issue.
****************************************************************************
*/
int  JpmcdsHolidayListAddBusinessDays
    (TDate         fromDate,     /* (I) Input date                 */
     long          numBusDays,   /* (I) Number of business days    */
     THolidayList *hl,           /* (I) Holiday list structure     */
     TDate        *resultDate)   /* (O) Resulting business date    */
{

    static char        routine[] = "JpmcdsHolidayListAddBusinessDays";
    int                status = FAILURE;

    long               intervalSign   = SIGN( numBusDays );
    long               numBusDaysLeft = ABS( numBusDays );
    long               busDaysPerWeek = -1;

    if (hl == NULL)
    {
        JpmcdsErrMsg ("%s: hl is NULL.\n", routine);
        goto done;
    }

    /*
    ** Get the number of business days per week. In-line for speed.
    */
    switch (hl->weekends)
    {
    case JPMCDS_WEEKEND_STANDARD:
        busDaysPerWeek = 5;
        break;
    case JPMCDS_WEEKEND_NO_WEEKENDS:
        busDaysPerWeek = 7;
        break;
    default:
        busDaysPerWeek = 7;
        if (hl->weekends & JPMCDS_WEEKEND_SUNDAY) busDaysPerWeek--;
        if (hl->weekends & JPMCDS_WEEKEND_MONDAY) busDaysPerWeek--;
        if (hl->weekends & JPMCDS_WEEKEND_TUESDAY) busDaysPerWeek--;
        if (hl->weekends & JPMCDS_WEEKEND_WEDNESDAY) busDaysPerWeek--;
        if (hl->weekends & JPMCDS_WEEKEND_THURSDAY) busDaysPerWeek--;
        if (hl->weekends & JPMCDS_WEEKEND_FRIDAY) busDaysPerWeek--;
        if (hl->weekends & JPMCDS_WEEKEND_SATURDAY) busDaysPerWeek--;
        break;
    }

    if (IS_EMPTY_DATELIST (hl->dateList) &&
        hl->weekends == JPMCDS_WEEKEND_NO_WEEKENDS)
    {
        /*
        ** No adjustments at all.
        */
        *resultDate = fromDate + (intervalSign * numBusDaysLeft);
    }
    else if (intervalSign == 1 && hl->weekends == JPMCDS_WEEKEND_STANDARD)
    {
        /* First, check for special case. The code for this case
         * was provided by Tom Robbins-Milne. It is much faster
         * than the general algorithm.
         */

        if (numBusDaysLeft == 0)
        {
            *resultDate = fromDate;
        }
        else
        {
           /*
            * Calculate result if no holidays are involved.
            *
            * Move forward over a week for every 5 business days.
            * Use a table for moving 0..4 bus days from each day of the week.
            */
            *resultDate = fromDate +  7 * (numBusDaysLeft / 5) +
                             offsetTable[ fromDate % 7 ][ numBusDaysLeft % 5 ];

           /*
            * Now adjust for any holidays
            */
            if (hl->dateList->fNumItems > 0)
            {
                if (holAdjustStandardWeekends (fromDate,
                                               hl->dateList,
                                               resultDate) != SUCCESS)
                    goto done;
            }
        }
    }
    else
    {
        if (forwardNonStandardWeekends (fromDate,
                                        numBusDaysLeft,
                                        intervalSign,
                                        hl->weekends,
                                        busDaysPerWeek,
                                        hl->dateList,
                                        resultDate) != SUCCESS)
            goto done;
    }

    status = SUCCESS;

done:
    if (status == FAILURE)
        JpmcdsErrMsg("%s: Failed.\n", routine);

    return status;
}
Example #28
0
/*
*****************************************************************************
** Calculates the number of business days between two dates (FROM & TO).
**
** Algorithm:
** 1. if FROM = TO, the result is 0
** 2. if FROM < TO, the result is the number of business days in the CLOSED
**    interval of [FROM+1,TO]
** 3. if FROM > TO, the result is negated number of business days in the
**    CLOSED interval of [TO,FROM-1]
**
** Equivalent to JpmcdsBusinessDaysDiff but uses a THolidayList structure
** instead of a holiday file name. Should be used if efficiency is an
** issue.
****************************************************************************
*/
int  JpmcdsHolidayListBusinessDaysDiff
    (TDate         fromDate,     /* (I) Earlier date       */
     TDate         toDate,       /* (I) Later date         */
     THolidayList *hl,           /* (I) Holiday list structure  */
     long         *result)       /* (O) Result value       */
{

    static char           routine[] = "JpmcdsHolidayListBusinessDaysDiff";
    int                   busDaysPerWeek = -1;

    long                  nrExtraDays;
    long                  numWeeks = 0L;

    int                   signum = 1;  /* assume going forward by default */
    long                  numHolidays = 0L;
    TDate                 curDate = fromDate;

/*
 * The following tables are used to calculate the number of business days
 * between weekdays.
 * If (toDate > fromDate) use fwdDiffTable.
 * eg NumDays = fwdDiffTable[ fromDate % 7 ][ toDate % 7 ]
 *
 * If (fromDate > toDate) use -bwdDiffTable.
 * eg NumDays = bwdDiffTable[ toDate % 7 ][ fromDate % 7 ]
 *
 * The values of the table were chosen so that the current ALIB behaviour
 * was left unchanged. Note that because fwdDiffTable is not identical
 * to (-1 x bwdDiffTable), swapping fromDate and toDate in the call to this
 * function does not simply reverse the sign of the result.
 */
    static long           fwdDiffTable[7][7] =

                              {/*   Mo Tu We Th Fr Sa Su*/

                                  {  0, 1, 2, 3, 4, 4, 4 },  /* Monday */
                                  {  4, 0, 1, 2, 3, 3, 3 },  /* Tuesday */
                                  {  3, 4, 0, 1, 2, 2, 2 },  /* Wednesday */
                                  {  2, 3, 4, 0, 1, 1, 1 },  /* Thursday */
                                  {  1, 2, 3, 4, 0, 0, 0 },  /* Friday */
                                  {  1, 2, 3, 4, 5, 0, 0 },  /* Saturday */
                                  {  1, 2, 3, 4, 5, 5, 0 }   /* Sunday */
                              };

    static long           bwdDiffTable[7][7] =

                              {/*   Mo Tu We Th Fr Sa Su*/

                                  {  0,-1,-2,-3,-4,-5,-5 },  /* Monday */
                                  { -4, 0,-1,-2,-3,-4,-4 },  /* Tuesday */
                                  { -3,-4, 0,-1,-2,-3,-3 },  /* Wednesday */
                                  { -2,-3,-4, 0,-1,-2,-2 },  /* Thursday */
                                  { -1,-2,-3,-4, 0,-1,-1 },  /* Friday */
                                  { -0,-1,-2,-3,-4, 0, 0 },  /* Saturday */
                                  { -0,-1,-2,-3,-4,-5, 0 }   /* Sunday */
                              };

    if (hl == NULL)
    {
        JpmcdsErrMsg ("%s: hl is NULL.\n", routine);
        return FAILURE;
    }

    *result = 0L; /* TDate EQ long */

    if (fromDate == toDate)
        return SUCCESS;

    /* Set the direction. */
    if (toDate < fromDate)
    {
        signum = -1;
    }

    /*
    ** First, compute the date difference adjusting for weekends only.
    */


    /*
    ** Get the number of business days per week. In-line for speed.
    */
    switch (hl->weekends)
    {
    case JPMCDS_WEEKEND_STANDARD:
        busDaysPerWeek = 5;
        numWeeks = (toDate - fromDate) / JPMCDS_DAYS_PER_WEEK;
        curDate += JPMCDS_DAYS_PER_WEEK * numWeeks;
        if (curDate > toDate)  /* backwards */
        {
            nrExtraDays = bwdDiffTable [ toDate %7 ][ fromDate % 7 ];
        }
        else
        {
            nrExtraDays = fwdDiffTable [ fromDate %7 ][ toDate % 7 ];
        }
        *result = numWeeks * busDaysPerWeek + nrExtraDays;
        break;
    case JPMCDS_WEEKEND_NO_WEEKENDS:
        *result = toDate - fromDate;
        break;
    default:
        busDaysPerWeek = 7;
        if (hl->weekends & JPMCDS_WEEKEND_SUNDAY) busDaysPerWeek--;
        if (hl->weekends & JPMCDS_WEEKEND_MONDAY) busDaysPerWeek--;
        if (hl->weekends & JPMCDS_WEEKEND_TUESDAY) busDaysPerWeek--;
        if (hl->weekends & JPMCDS_WEEKEND_WEDNESDAY) busDaysPerWeek--;
        if (hl->weekends & JPMCDS_WEEKEND_THURSDAY) busDaysPerWeek--;
        if (hl->weekends & JPMCDS_WEEKEND_FRIDAY) busDaysPerWeek--;
        if (hl->weekends & JPMCDS_WEEKEND_SATURDAY) busDaysPerWeek--;
        numWeeks    = ABS((toDate - fromDate) / JPMCDS_DAYS_PER_WEEK);
        curDate    += (JPMCDS_DAYS_PER_WEEK * numWeeks * signum);
        nrExtraDays = 0L;

        while ( ABS(curDate - toDate) > 0 )
        {
            curDate += signum;
            if (JPMCDS_IS_WEEKDAY( curDate, hl->weekends ))
            {
                nrExtraDays++;
            }
        }

        (*result) = ((numWeeks * busDaysPerWeek) + nrExtraDays) * signum;
        break;
    }


    /*
    ** Now count the number of weekday holidays
    ** and adjust the date difference by the result. The
    ** call to calcNumWeekdayHolidays searches the
    ** holiday list at most once.
    */

    if (! IS_EMPTY_DATELIST( hl->dateList ))
    {
        TBoolean      doneSearching = FALSE;
        long          holIdx = -1;

        if (findFirstHolidayIdx (fromDate + signum, hl->dateList,
                                 signum, &holIdx, &doneSearching)
            != SUCCESS)
            return FAILURE;

        if (!doneSearching)
        {
            numHolidays     = calcNumWeekdayHolidays (toDate, holIdx,
                                          signum, hl->weekends,
                                          hl->dateList, &holIdx);
        }
    }

    (*result) -= numHolidays * signum;

    return SUCCESS;
}
Example #29
0
/*
***************************************************************************
** Compute the date of next business day, given a start date and
** a holiday list. The function currently always returns SUCCESS.
***************************************************************************
*/
static int getNextBusDate
(TDate          startDate,    /* (I) starting date. */
 long           direction,    /* (I) +1=forwards, -1=backwards */
 THolidayList * hl,           /* (I) holiday list */
 TDate        * nextDate      /* (O) next business day */
)
{
    TBoolean               doneSearchingList;
    TBoolean               aHoliday;
    long                   holIdx;

    long                   numHols = hl->dateList->fNumItems;
    TDate                * holArray = hl->dateList->fArray;
    TDate                  curDate = startDate;

    if (IS_EMPTY_DATELIST(hl->dateList))
    {
        doneSearchingList = TRUE;
    }
    else
    {
        if (findFirstHolidayIdx (startDate, hl->dateList,
                                 direction, &holIdx, &doneSearchingList)
            != SUCCESS)
        {
            JpmcdsErrMsg ("getNextBusDate: Failed.\n");
            return FAILURE;
        }
    }

    /*
    ** holIdx should now point to the first holiday on or before
    ** (after) the start date. Now loop though each day until
    ** you reach the first business day.
    */

    aHoliday = TRUE;

    do
    {   /* Check if it's a holiday first. */
        if (!doneSearchingList && curDate == holArray[ holIdx ])
        {
            holIdx  += direction;
            curDate += direction;
            doneSearchingList =
              (TBoolean)(holIdx < 0 || holIdx >= numHols);
        }
        else
        {
          /* Day is not a holiday. Check if it's a week-end day. */
            if (JPMCDS_IS_WEEKEND (curDate, hl->weekends))
            {
                 curDate += direction;
            }
            else
            {
                 aHoliday = FALSE;
            }
        }
    }
    while ( aHoliday == TRUE );

    *nextDate = curDate;

    return SUCCESS;
}
Example #30
0
/*
***************************************************************************
** (See getNextBusDate.)
***************************************************************************
*/
static int getNextBusDateMulti
(TDate          startDate,        /* (I) starting date. */
 long           direction,        /* (I) +1=forwards, -1=backwards */
 int            numHolidayLists,  /* (I) Size of holidayLists[] array. */
 THolidayList  *holidayLists[],   /* (I) Holiday lists. */
 TDate         *nextDate          /* (O) next business day */
)
{
    static char          routine[] = "getNextBusDateMulti";
    int                  status = FAILURE;
    int                  n;
    TDate                adjDate;

    *nextDate = startDate;

    /* this loop executes getNextBusDate for each market in sequence; whenever weekends/
       holidays force an adjustment, the process recommences at the first market; eventually,
       a date will be reached which is a business day in all markets, whereupon the loop
       will execute to completion

       we can be certain that all of the skipped dates were weekends/holidays in at least
       one of the markets, i.e. output will be the _first_ suitable day */

    n = 0;
    while (n < numHolidayLists)
    {
        if ( getNextBusDate(*nextDate, direction, holidayLists[n], &adjDate) != SUCCESS )
        {
            goto done;
        }

        if ( adjDate != *nextDate )
        {
            *nextDate = adjDate;

            /* date has changed to acommodate this market; now
               have to recommence testing for all other markets */

            /* in fact, this date does not need retesting for the current market,
               and we exploit this in the special case below, which avoids a redundant
               duplicate test in "single holiday list" usage */

            n = ( n == 0 ) ? 1 : 0;

            /* ^-- if adjusted for first market, now move on to second; in all
               other cases, recommence testing from scratch */
        }
        else
        {
            n++; /* next market */
        }
    }

    status = SUCCESS;

done:
    if (status != SUCCESS)
        JpmcdsErrMsg("%s: Failed.\n", routine);

    return status;
}