Пример #1
0
/*
***************************************************************************
** Deletes a holiday list structure.
***************************************************************************
*/
void JpmcdsHolidayListDelete
(THolidayList *hl)  /* (I) Holiday list to delete */
{
    if (hl != NULL)
    {
        JpmcdsFreeDateList (hl->dateList);
        FREE(hl);
    }
}
Пример #2
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;
}
Пример #3
0
/*
***************************************************************************
** Adds dates to a TDateList and frees the input date list.
**
** If the original date list and date list to be added are sorted, then
** the resulting date list will be sorted and duplicate dates will be
** removed. Sorting assumes ascending order ([0] < [1] etc).
**
** If either of the inputs are not sorted, then the resulting date list
** will not be sorted, and some duplicates may remain.
**
** For efficiency, we do not automatically try to sort the resulting
** date list for unsorted inputs. Sorting the date list each time appears
** to be a huge performance issue in some algorithms (where the input
** dates would all be sorted anyway).
**
** Note that if dl is NULL, then this will create a new date list from
** the given dates.
**
** Note that if numItems=0, this will copy the given date list.
**
** The input date list is FREE'd by this routine. Thus if you have an
** algorithm which involves building up a datelist gradually, you can
** do something like this:
**
**  TDateList* dl = NULL;
**  ...
**  dl = JpmcdsDateListAddDatesFreeOld (dl, numItems, array);
**  if (dl == NULL) goto done;
**  ..
**  dl = JpmcdsDateListAddDatesFreeOld (dl, numItems, array);
**  if (dl == NULL) goto done;
**  ..
**  etc.
**
** with the point being that you don't have to worry about the original
** date list at each step since this routine frees it for you.
***************************************************************************
*/
TDateList* JpmcdsDateListAddDatesFreeOld
(TDateList *dl,         /* (I/O) Initial date list - gets freed */
 int         numItems,   /* (I) Number of dates to add           */
 TDate     *array)      /* (I) [numItems] Dates to be added     */
{
    static char routine[] = "JpmcdsDateListAddDatesFreeOld";
    
    TDateList *output;

    output = JpmcdsDateListAddDates (dl, numItems, array);
    JpmcdsFreeDateList (dl);
    
    if (output == NULL)
        JpmcdsErrMsgFailure(routine);

    return output;
}
Пример #4
0
/*
***************************************************************************
** Adds dates to a TDateList. 
**
** If the original date list and date list to be added are sorted, then
** the resulting date list will be sorted and duplicate dates will be
** removed. Sorting assumes ascending order ([0] < [1] etc).
**
** If either of the inputs are not sorted, then the resulting date list
** will not be sorted, and some duplicates may remain.
**
** For efficiency, we do not automatically try to sort the resulting
** date list for unsorted inputs. Sorting the date list each time appears
** to be a huge performance issue in some algorithms (where the input
** dates would all be sorted anyway).
**
** Note that if dl is NULL, then this will create a new date list from
** the given dates.
**
** Note that if numItems=0, this will copy the given date list.
***************************************************************************
*/
TDateList* JpmcdsDateListAddDates
(TDateList *dl,          /* (I) Initial date list            */
 int         numItems,    /* (I) Number of dates to add       */
 TDate      *array)      /* (I) [numItems] Dates to be added */
{
    static char routine[] = "JpmcdsDateListAddDates";
    int         status    = FAILURE;

    TDateList tmp = {0, NULL};
    TDateList *result = NULL;

    REQUIRE (numItems >= 0);
    REQUIRE (dl == NULL || dl->fNumItems >= 0);

    if (dl == NULL)
    {
        result = JpmcdsNewDateListFromDates (array, numItems);
    }
    else if (numItems <= 0)
    {
        result = JpmcdsCopyDateList (dl);
    }
    else if (dl->fNumItems == 0 && numItems == 0)
    {
        result = JpmcdsNewDateListFromDates (NULL, 0);
    }
    else
    {
        int totalItems = dl->fNumItems + numItems;
        int i = 0;
        int j = 0;
        int k = 0;

        result = JpmcdsNewEmptyDateList (totalItems);
        if (result == NULL)
            goto done;

        while (i < dl->fNumItems && j < numItems)
        {
            if (dl->fArray[i] == array[j])
            {
                /* exclude duplicates */
                ++j;
                --totalItems;
            }
            else if (dl->fArray[i] < array[j])
            {
                result->fArray[k] = dl->fArray[i];
                ++i;
                ++k;
            }
            else
            {
                // assert (dl->fArray[i] > array[j]);
                result->fArray[k] = array[j];
                ++j;
                ++k;
            }
        }

        if (i < dl->fNumItems)
        {
            int n = dl->fNumItems - i;
            COPY_ARRAY (result->fArray+k, dl->fArray+i, TDate, n);
            k += n;
        }

        if (j < numItems)
        {
            int n = numItems - j;
            COPY_ARRAY (result->fArray+k, array+j, TDate, n);
            k += n;
        }

        // assert (k == totalItems);
        result->fNumItems = totalItems;
    }
    if (result == NULL)
        goto done;

    status = SUCCESS;

 done:

    if (status != SUCCESS)
    {
        JpmcdsErrMsgFailure (routine);
        JpmcdsFreeDateList (result);
        result = NULL;
    }

    FREE(tmp.fArray);
    
    return result;
}
Пример #5
0
/*
***************************************************************************
** Makes a date list from a given start date to a given end date with dates
** seperated by a given interval.
**
** Use the stub parameter to determine whether the stub appears at the
** start or the end of the date list, and whether the stub is long or
** short.
**
** The start date and end date are always both in the date list.
** The end date must be strictly after the start date.
** The date interval must be positive.
***************************************************************************
*/
TDateList* JpmcdsDateListMakeRegular
(TDate          startDate,  /* (I) Start date */
 TDate          endDate,    /* (I) End date */
 TDateInterval *interval,   /* (I) Date interval */
 TStubMethod   *stubType)   /* (I) Stub type */
{
    static char routine[] = "JpmcdsDateListMakeRegular";
    int         status = FAILURE;

    TDateList *dl = NULL;
    TDate      tmpDates[100];
    int        i;
    int        numIntervals;
    int        numTmpDates = sizeof(tmpDates) / sizeof(TDate);
    int        totalDates = 0;
    TDate      date;
    TDateInterval multiInterval;

    REQUIRE (interval != NULL);
    REQUIRE (interval->prd > 0);
    REQUIRE (endDate > startDate);

    /* we calculate tmpDates in blocks of 100 and add to the datelist */
    if (!stubType->stubAtEnd)
    {
        /* front stub - so we start at endDate and work backwards */
        numIntervals = 0;
        i            = numTmpDates;
        date         = endDate;
        while (date > startDate)
        {
            if (i == 0)
            {
                dl = JpmcdsDateListAddDatesFreeOld (dl, numTmpDates, tmpDates);
                if (dl == NULL)
                    goto done;
                i = numTmpDates;
            }
            --i;
            --numIntervals;
            ++totalDates;
            // assert (i >= 0);
            tmpDates[i] = date;

            SET_TDATE_INTERVAL(multiInterval, interval->prd * numIntervals, interval->prd_typ);
            if (JpmcdsDtFwdAny(endDate, &multiInterval, &date) != SUCCESS)
                goto done;
        }
        // assert (totalDates > 0);
        // assert (date <= startDate);
        if (date == startDate || totalDates == 1 || !stubType->longStub)
        {
            /* don't change existing tmpDates[] but need to add startDate */
            if (i == 0)
            {
                dl = JpmcdsDateListAddDatesFreeOld (dl, numTmpDates, tmpDates);
                if (dl == NULL)
                    goto done;
                i = numTmpDates;
            }
            --i;
            ++totalDates;
            tmpDates[i] = startDate;
        }
        else
        {
            // assert (!stubType->stubAtEnd && stubType->longStub);
            // assert (date < startDate);
            /* the existing date in tmpDates[] should be changed to be
               the start date */
            tmpDates[i] = startDate;
        }
        /* now add from tmpDates[i] to tmpDates[numTmpDates-1] to date list */
        dl = JpmcdsDateListAddDatesFreeOld (dl, numTmpDates-i, tmpDates+i);
        if (dl == NULL)
            goto done;
    }
    else
    {
        /* back stub - so we start at startDate and work forwards */
        numIntervals = 0;
        i            = -1;
        date         = startDate;
        while (date < endDate)
        {
            ++i;
            ++totalDates;
            if (i == numTmpDates)
            {
                dl = JpmcdsDateListAddDatesFreeOld (dl, numTmpDates, tmpDates);
                if (dl == NULL)
                    goto done;
                i = 0;
            }
            ++numIntervals;
            // assert (i < numTmpDates);
            tmpDates[i] = date;

            SET_TDATE_INTERVAL(multiInterval, interval->prd * numIntervals, interval->prd_typ);
            if (JpmcdsDtFwdAny(startDate, &multiInterval, &date) != SUCCESS)
                goto done;
        }
        // assert (totalDates > 0);
        // assert (date >= endDate);
        if (date == endDate || totalDates == 1 || stubType->stubAtEnd && !stubType->longStub)
        {
            /* don't change existing tmpDates[] but need to add endDate */
            ++i;
            ++totalDates;
            if (i == numTmpDates)
            {
                dl = JpmcdsDateListAddDatesFreeOld (dl, numTmpDates, tmpDates);
                if (dl == NULL)
                    goto done;
                i = 0;
            }
            tmpDates[i] = endDate;
        }
        else
        {
            // assert (stubType->stubAtEnd && stubType->longStub);
            // assert (date > endDate);
            /* the existing date in tmpDates[] should be changed to be
               the end date */
            tmpDates[i] = endDate;
        }
        /* now add from tmpDates[0] to tmpDates[i] to the date list */
        dl = JpmcdsDateListAddDatesFreeOld (dl, i+1, tmpDates);
        if (dl == NULL)
            goto done;
    }
    // ASSERT (totalDates >= 2);
    // ASSERT (dl->fNumItems == totalDates);
    status = SUCCESS;

 done:

    if (status != SUCCESS)
    {
        JpmcdsFreeDateList (dl);
        dl = NULL;
        JpmcdsErrMsgFailure (routine);
    }

    return dl;
}
Пример #6
0
/*
***************************************************************************
** Calculates the PV of a fee leg with fixed fee payments.
***************************************************************************
*/
int JpmcdsFeeLegPV
(TFeeLeg      *fl,
 TDate         today,
 TDate         stepinDate,
 TDate         valueDate,
 TCurve       *discCurve,
 TCurve       *spreadCurve,
 TBoolean      payAccruedAtStart,
 double       *pv)
{
    static char routine[] = "JpmcdsFeeLegPV";
    int         status    = FAILURE;
    int         i;
    double      myPv;
    double      valueDatePv;
    TDateList  *tl = NULL;
    TDate       matDate;

    REQUIRE (spreadCurve != NULL);

    REQUIRE (fl != NULL);
    REQUIRE (discCurve != NULL);
    REQUIRE (spreadCurve != NULL);
    REQUIRE (pv != NULL);
    REQUIRE (valueDate >= today);
    REQUIRE (stepinDate >= today);

    myPv = 0.0;

    if (fl->nbDates > 1)
    {
        /* it is more efficient to compute the timeLine just the once
           and truncate it for each payment */
        TDate startDate = fl->accStartDates[0];
        TDate endDate   = fl->accEndDates[fl->nbDates-1];
        
        tl = JpmcdsRiskyTimeLine(startDate,
                                 endDate,
                                 discCurve,
                                 spreadCurve);

        if (tl == NULL)
            goto done;
    }

    matDate = (fl->obsStartOfDay == TRUE ? 
               fl->accEndDates[fl->nbDates - 1] - 1 :
               fl->accEndDates[fl->nbDates - 1]);

    if(today > matDate || stepinDate > matDate)
    {
        status = SUCCESS;
        *pv = 0;
        goto done;
    }

    for (i = 0; i < fl->nbDates; ++i)
    {
        double thisPv = 0;
        
        if (FeePaymentPVWithTimeLine (fl->accrualPayConv,
                                      today,
                                      stepinDate,
                                      fl->accStartDates[i],
                                      fl->accEndDates[i],
                                      fl->payDates[i],
                                      fl->dcc,
                                      fl->notional,
                                      fl->couponRate,
                                      discCurve,
                                      spreadCurve,
                                      tl,
                                      fl->obsStartOfDay,
                                      &thisPv) != SUCCESS)
            goto done;

        myPv += thisPv;
    }

    valueDatePv = JpmcdsForwardZeroPrice (discCurve, today, valueDate);

    *pv = myPv / valueDatePv;
    
    if(payAccruedAtStart) /* clean price */
    {
        double ai;
        if(FeeLegAI(fl, stepinDate, &ai) == FAILURE)
        {
           JpmcdsErrMsg ("%s: accrued interest calculation failed.\n", routine);
           goto done;
        }
        *pv -= ai;
    }

    status = SUCCESS;

 done:

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

    JpmcdsFreeDateList (tl);

    return status;
}
Пример #7
0
/*
***************************************************************************
** Calculates the PV of the accruals which occur on default.
** Uses a pre-calculated timeline for efficiency.
***************************************************************************
*/
int JpmcdsAccrualOnDefaultPVWithTimeLine
(TDate           today,
 TDate           stepinDate,
 TDate           startDate,
 TDate           endDate,
 double          amount,
 TCurve         *discCurve,
 TCurve         *spreadCurve,
 TDateList      *criticalDates,
 double         *pv)
{
    static char routine[] = "JpmcdsAccrualOnDefaultPVWithTimeLine";
    int         status    = FAILURE;

    double  myPv = 0.0;
    int     i;

    double t;
    double s0;
    double s1;
    double df0;
    double df1;
    double accRate;
    TDate  subStartDate;

    TDateList  *tl = NULL;

    REQUIRE (endDate > startDate);
    REQUIRE (discCurve != NULL);
    REQUIRE (spreadCurve != NULL);
    REQUIRE (pv != NULL);
    
    /*
    ** Timeline is points on the spreadCurve between startDate and endDate,
    ** combined with points from the discCurve, plus
    ** the startDate and endDate.
    */
    if (criticalDates != NULL)
    {
        tl = JpmcdsTruncateTimeLine (criticalDates, startDate, endDate);
    }
    else
    {
        tl = JpmcdsRiskyTimeLine (startDate, endDate, discCurve, spreadCurve);
    }
    if (tl == NULL)
        goto done;

    /* the integration - we can assume flat forwards between points on
       the timeline - this is true for both curves 

       we are integrating -Zt dS/dt where Z is the discount factor and
       S is the survival probability and t is the accrual time

       assuming flat forwards on each part of the integration, this is an
       exact integral
    */
    
    subStartDate = MAX(stepinDate, startDate);
    t       = (double)(endDate-startDate)/365.0;
    accRate = amount/t;
    s0      = JpmcdsForwardZeroPrice(spreadCurve, today, subStartDate);
    df0     = JpmcdsForwardZeroPrice(discCurve, today, MAX(today, subStartDate));

    for (i = 1; i < tl->fNumItems; ++i)
    {
        double lambda;
        double fwdRate;
        double thisPv;
        double t0;
        double t1;
        double lambdafwdRate;
        if(tl->fArray[i] <= stepinDate)
            continue;

        s1  = JpmcdsForwardZeroPrice(spreadCurve, today, tl->fArray[i]);
        df1 = JpmcdsForwardZeroPrice(discCurve, today, tl->fArray[i]);

        t0  = (double)(subStartDate + 0.5 - startDate)/365.0;
        t1  = (double)(tl->fArray[i] + 0.5- startDate)/365.0;
        t   = t1-t0;

        lambda  = log(s0/s1)/t;
        fwdRate = log(df0/df1)/t;
        lambdafwdRate = lambda + fwdRate + 1.0e-50;

        thisPv  = lambda * accRate * s0 * df0 * (
            (t0 + 1.0/(lambdafwdRate))/(lambdafwdRate) -
            (t1 + 1.0/(lambdafwdRate))/(lambdafwdRate) * 
            s1/s0 * df1/df0);

        myPv += thisPv;
        s0  = s1;
        df0 = df1;
        subStartDate = tl->fArray[i];
    }

    status = SUCCESS;
    *pv = myPv;
        
 done:

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

    JpmcdsFreeDateList (tl);
    return status;
}
Пример #8
0
/*
***************************************************************************
** Reads a holiday file into memory as a holiday list.
**
** Structure of holiday file, ascii text file of lines like:
**     #            - commment (blank lines are also skipped)
**     19631026     - means 10/26/1963 is a holiday
**     # SATURDAY_NOT_ALWAYS_HOLIDAY  - sets "saturday isn't always a holiday"
**     # SUNDAY_NOT_ALWAYS_HOLIDAY    - sets "sunday isn't always a holiday"
**     # MONDAY_ALWAYS_HOLIDAY        - sets "monday as always a holiday"
**     # TUESDAY_ALWAYS_HOLIDAY       - sets "tuesday as always a holiday"
**     # WEDNESDAY_ALWAYS_HOLIDAY     - sets "wednesday as always a holiday"
**     # THURDSAY_ALWAYS_HOLIDAY      - sets "thursday as always a holiday"
**     # FRIDAY_ALWAYS_HOLIDAY        - sets "friday as always a holiday"
**
** Dates must be in increasing order.
***************************************************************************
*/
THolidayList* JpmcdsHolidayListRead
(char *fileName   /* (I) Name of file to read (may differ) */
)
{
    static char routine[] = "JpmcdsHolidayListRead";
    int         status = FAILURE;

    int        numHols;             /* count of holidays */
    int        idx;                 /* counts over holidays */
    char       buffer[MAX_BUFFER];  /* line of text from file */
    char       ucBuffer[MAX_BUFFER];/* upper case line of text from file */
    TFile     *fp = NULL;           /* file handle */
    THolidayList *hl = NULL;        /* to be returned */
    TDateList *dl = NULL;          /* date list read in */
    long       weekends;

    fp = JpmcdsFopen (fileName, JPMCDS_FREAD);
    if (fp == NULL)
    {
        JpmcdsErrMsg ("%s: Couldn't open file %s.\n", routine, fileName);
        goto done;
    }

    /* count number of holidays specified */
    numHols = 0;
    while (JpmcdsFgets (buffer, MAX_BUFFER, fp) == SUCCESS)
    {
        if (atol (buffer) > 16010101)
            numHols++;
    }

    if (JpmcdsFclose (fp) == FAILURE)  /* close file, reopen to read again */
    {
        fp = NULL;
        goto done;
    }
    fp = NULL;

    fp = JpmcdsFopen (fileName, JPMCDS_FREAD);
    if (fp == NULL)
    {
        JpmcdsErrMsg ("%s: Couldn't open file %s twice.\n", routine, fileName);
        goto done;
    }

    dl = JpmcdsNewEmptyDateList (numHols);

    if (dl == NULL)
        goto done;

    idx = 0;
    weekends = JPMCDS_WEEKEND_STANDARD; /* Includes SAT and SUN */

    while (JpmcdsFgets (buffer, MAX_BUFFER, fp) == SUCCESS)
    {
        if (buffer[0] == '#')
        {
            static char monString[] = "# MONDAY_ALWAYS_HOLIDAY";
            static char tueString[] = "# TUESDAY_ALWAYS_HOLIDAY";
            static char wedString[] = "# WEDNESDAY_ALWAYS_HOLIDAY";
            static char thuString[] = "# THURSDAY_ALWAYS_HOLIDAY";
            static char friString[] = "# FRIDAY_ALWAYS_HOLIDAY";
            static char satString[] = "# SATURDAY_NOT_ALWAYS_HOLIDAY";
            static char sunString[] = "# SUNDAY_NOT_ALWAYS_HOLIDAY";

            COPY_CAPITALIZE(ucBuffer, buffer, MAX_BUFFER-1);

            if (strncmp (buffer, monString, sizeof(monString)-1) == 0)
                weekends |= JPMCDS_WEEKEND_MONDAY;

            if (strncmp (buffer, tueString, sizeof(tueString)-1) == 0)
                weekends |= JPMCDS_WEEKEND_TUESDAY;

            if (strncmp (buffer, wedString, sizeof(wedString)-1) == 0)
                weekends |= JPMCDS_WEEKEND_WEDNESDAY;

            if (strncmp (buffer, thuString, sizeof(thuString)-1) == 0)
                weekends |= JPMCDS_WEEKEND_THURSDAY;

            if (strncmp (buffer, friString, sizeof(friString)-1) == 0)
                weekends |= JPMCDS_WEEKEND_FRIDAY;

            if (strncmp (buffer, satString, sizeof(satString)-1) == 0)
                weekends &= ~JPMCDS_WEEKEND_SATURDAY;

            if (strncmp (buffer, sunString, sizeof(sunString)-1) == 0)
                weekends &= ~JPMCDS_WEEKEND_SUNDAY;
        }
        else
        {
            long dateVal = atol (buffer);
            if (dateVal > 16010101)
            {
                TMonthDayYear   mdy;
                TDate           thisDate;

                if (idx >= numHols)
                {
                    JpmcdsErrMsg ("%s: More dates on second scan of file %s.\n", routine, fileName);
                    goto done;
                }

                mdy.year  = dateVal / 10000;
                mdy.month = (dateVal - mdy.year * 10000) / 100;
                mdy.day   = dateVal % 100;
                if (JpmcdsMDYToDate (&mdy, &thisDate) == FAILURE)
                {
                    JpmcdsErrMsg ("%s: invalid date: %s", routine, buffer);
                    goto done;
                }
                if (idx > 0 && dl->fArray[idx-1] >= thisDate)
                {
                    JpmcdsErrMsg ("%s: Date out of order: %s", routine, buffer);
                    goto done;
                }
                dl->fArray[idx] = thisDate;
                ++idx;
            }
        }
    }

    if (numHols < 1 && weekends == JPMCDS_WEEKEND_STANDARD)
    {
        JpmcdsErrMsg ("%s: No holiday information found in %s.\n", routine, fileName);
        JpmcdsErrMsg ("   Either week-end information or dates must be provided.\n");
        goto done;
    }

    if (idx != numHols)
    {
        JpmcdsErrMsg ("%s: Less dates on second scan of file %s\n", routine, fileName);
        goto done;
    }

    if (JpmcdsFclose (fp) == FAILURE)
    {
        fp = NULL;
        goto done;
    }
    fp = NULL;

    hl = JpmcdsHolidayListNewGeneral (dl, weekends);
    if (hl == NULL)
        goto done;

    status = SUCCESS;

done:

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

    return hl;
}
Пример #9
0
/*
***************************************************************************
** Computes a one period integral
***************************************************************************
*/
static int onePeriodIntegral
(TDate             today,
 TDate             startDate,
 TDate             endDate,
 TCurve           *discCurve,
 TCurve           *spreadCurve,
 double            recoveryRate,
 double           *pv)
{
    static char routine[] = "onePeriodIntegral";
    int         status    = FAILURE;

    double  myPv = 0.0;
    int     i;

    double t;
    double s0;
    double s1;
    double df0;
    double df1;
    double loss;

    TDateList *tl = NULL;

    REQUIRE (endDate > startDate);
    REQUIRE (discCurve != NULL);
    REQUIRE (spreadCurve != NULL);
    REQUIRE (pv != NULL);

    if (today > endDate)
    {
        myPv = 0.0;
        goto success;
    }

    tl = JpmcdsRiskyTimeLine (startDate, endDate, discCurve, spreadCurve);
    if (tl == NULL)
        goto done;

    /* the integration - we can assume flat forwards between points on
       the timeline - this is true for both curves

       we are integrating -Z dS/dt where Z is the discount factor and
       S is the survival probability

       assuming flat forwards on each part of the integration, this is an
       exact integral
    */

    s1  = JpmcdsForwardZeroPrice(spreadCurve, today, startDate);
    df1 = JpmcdsForwardZeroPrice(discCurve, today, MAX(today, startDate));
    loss = 1.0 - recoveryRate;

    for (i = 1; i < tl->fNumItems; ++i)
    {
        double lambda;
        double fwdRate;
        double thisPv;

        s0  = s1;
        df0 = df1;
        s1  = JpmcdsForwardZeroPrice(spreadCurve, today, tl->fArray[i]);
        df1 = JpmcdsForwardZeroPrice(discCurve, today, tl->fArray[i]);
        t   = (double)(tl->fArray[i] - tl->fArray[i-1])/365.0;

        lambda  = log(s0/s1)/t;
        fwdRate = log(df0/df1)/t;

        thisPv  = loss * lambda / (lambda + fwdRate) *
                  (1.0 - exp(-(lambda + fwdRate) * t)) * s0 * df0;

        myPv += thisPv;
    }

success:

    status = SUCCESS;
    *pv = myPv;

done:

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

    JpmcdsFreeDateList (tl);
    return status;
}
Пример #10
0
/*
***************************************************************************
** Makes a fixed fee leg for a vanilla CDS.
** Note that you are protected on both startDate and endDate.
***************************************************************************
*/
TFeeLeg* JpmcdsCdsFeeLegMake
(TDate           startDate,
 TDate           endDate,
 TBoolean        payAccOnDefault,
 TDateInterval  *dateInterval,
 TStubMethod    *stubType,
 double          notional,
 double          couponRate,
 long            paymentDcc,
 long            badDayConv,
 char           *calendar,
 TBoolean        protectStart)
{
    static char routine[] = "JpmcdsCdsFeeLegMake";
    int         status    = FAILURE;

    TDateList    *dl = NULL;
    TFeeLeg      *fl = NULL;
    TDateInterval ivl3M;
    TDate         prevDate;
    TDate         prevDateAdj;

    int i;

    SET_TDATE_INTERVAL(ivl3M,3,'M');
    if (dateInterval == NULL)
        dateInterval = &ivl3M;

    if(protectStart)
        REQUIRE (endDate >= startDate);
    else
        REQUIRE (endDate > startDate);

    if(protectStart && endDate == startDate)
    {
        TDate dates[2];
        dates[0] = startDate;
        dates[1] = endDate;
        dl = JpmcdsNewDateListFromDates(dates, 2);
    } else
    {
        dl = JpmcdsDateListMakeRegular (startDate, endDate, dateInterval, stubType);
    }
    if (dl == NULL)
        goto done;

    /* the datelist includes both start date and end date */
    /* therefore it has one more element than the fee leg requires */

    fl = JpmcdsFeeLegMakeEmpty (dl->fNumItems-1);
    if (fl == NULL)
        goto done;

    if (payAccOnDefault)
    {
        fl->accrualPayConv = ACCRUAL_PAY_ALL;
    }
    else
    {
        fl->accrualPayConv = ACCRUAL_PAY_NONE;
        /* and we will assume that it observes at end of the period */
    }
    fl->dcc = paymentDcc;

    prevDate = dl->fArray[0];
    prevDateAdj = prevDate; /* first date is not bad day adjusted */

    for (i = 0; i < fl->nbDates; ++i)
    {
        TDate nextDate = dl->fArray[i+1];
        TDate nextDateAdj;

        if (JpmcdsBusinessDay (nextDate, badDayConv, calendar, &nextDateAdj) != SUCCESS)
            goto done;

        fl->accStartDates[i] = prevDateAdj;
        fl->accEndDates[i]   = nextDateAdj;
        fl->payDates[i]      = nextDateAdj;

        prevDate    = nextDate;
        prevDateAdj = nextDateAdj;
    }

    fl->notional    = notional;
    fl->couponRate  = couponRate;

    /* the last accrual date is not adjusted */
    /* also we may have one extra day of accrued interest */
    if (protectStart)
    {
        fl->accEndDates[fl->nbDates-1] = prevDate+1;
        fl->obsStartOfDay              = TRUE;
    }
    else
    {
        fl->accEndDates[fl->nbDates-1] = prevDate;
        fl->obsStartOfDay              = FALSE;
    }
    status = SUCCESS;

 done:

    if (status != SUCCESS)
    {
        JpmcdsErrMsgFailure(routine);
        JpmcdsFeeLegFree (fl);
        fl = NULL;
    }

    JpmcdsFreeDateList (dl);

    return fl;
}
Пример #11
0
/*
***************************************************************************
** Makes a cashflow list from a DateList. Cashflows (for non stub payments) 
** are equal to the rate times the fraction of the year between  each date 
** and the previous date. The year fraction is calculated by the year 
** fraction function passed in. For stub payments, Actual/Actual is used.
**
** If there is a stub at the BEGINNING, then the first element of the 
** dateList is assumed to PRECEED startDate.
**
** If there is a stub at the END, then the last element of the dateList is 
** assumed to COME AFTER maturityDate.
***************************************************************************
*/
TCashFlowList* JpmcdsNewCFLFromDL3
    (TDateList *dates,                  /* (I) Dates */
     TDate startDate,                   /* (I) startDate */
     TDate maturityDate,                /* (I) MaturityDate */
     double rate,                       /* (I) Multiplied by yearFrac */
     long couponDayCountConv,           /* (I) Coupon calc  */
     TBoolean longStub,                 /* (I) Long stub */
     long accrualBadDayConv,            /* (I) Accrual bad day convention */
     long payBadDayConv,                /* (I) Pay bad day convention */
     char *accrualHolidayFile,          /* (I) Accrual Holiday file. */
     char *payHolidayFile,              /* (I) Payment Holiday file. */ 
     TBoolean usePreStartDate)          /* (I) Use prestart date if stub */
{
    static char routine[]="JpmcdsNewCFLFromDL3";
    int idx;
    int startIdx;                       /* First index for regular proc */
    int endIdx;                         /* Last index for regular proc */   
    int numDates = dates->fNumItems;
    TDate accrualStart, payStart;       /* Accrue and pay start dates */
    TDate accrualMaturity, payMaturity; /* Accrue and pay maturity dates */    
    TDateList *accrualDates = NULL;
    TDateList *payDates = NULL;
    TBoolean frontStub, backStub;
    TDateList *datesCopy = NULL;
    TCashFlowList *cfl = NULL;
    int status = FAILURE;

    if ( numDates == 0 )
    {
        cfl = JpmcdsNewEmptyCFL(0);
        if ( cfl == NULL )
            goto done;

        status = SUCCESS;
        goto done;
    }

    frontStub = ( startDate > dates->fArray[0] );
    backStub = ( maturityDate < dates->fArray[numDates-1] );

    /* For long stubs, simply coalesce first/last two coupon periods
     * (i.e. short stub + adjacent regular period) into one...
     */
    if ( longStub && (frontStub || backStub) && numDates > 2 )
    {
        datesCopy = JpmcdsNewEmptyDateList(numDates - 1);
        if ( datesCopy == NULL )
            goto done;

        if ( frontStub )
        {
            datesCopy->fArray[0] = dates->fArray[0];
            memcpy(&datesCopy->fArray[1], &dates->fArray[2], (numDates - 2) * sizeof(TDate));
            dates = datesCopy; /* simply overwrite pointer, hiding original */
            --numDates;
        }

        if (backStub)
        {
            memcpy(&datesCopy->fArray[0], &dates->fArray[0], (numDates - 2) * sizeof(TDate));
            datesCopy->fArray[numDates - 2] = dates->fArray[numDates - 1];
            dates = datesCopy; /* simply overwrite pointer, hiding original */
            --numDates;
        }
    }

    cfl = JpmcdsNewEmptyCFL(numDates);
    if( cfl == NULL )
        goto done;

    /* Get accrualDates
     */
    if (accrualBadDayConv == JPMCDS_BAD_DAY_NONE)
    {
        accrualDates = dates;            /* efficiency */
        accrualStart = startDate;
        accrualMaturity = maturityDate;
    }
    else
    {
        /* Adjust for bad days */
        accrualDates = JpmcdsNewDateListBusDayAdj(dates, accrualBadDayConv,
                                               accrualHolidayFile);
        if (accrualDates == NULL)
            goto done;
        
        if (JpmcdsBusinessDay(startDate, accrualBadDayConv, accrualHolidayFile,
                           &accrualStart) == FAILURE)
            goto done;

        if (JpmcdsBusinessDay(maturityDate, accrualBadDayConv, accrualHolidayFile,
                           &accrualMaturity) == FAILURE)
            goto done;
    }

    /* Get payDates
     */
    if (payBadDayConv == JPMCDS_BAD_DAY_NONE)
    {
        payDates = dates;            /* efficiency */
        payStart = startDate;
        payMaturity = maturityDate;
    }
    else
    {
        /* Adjust for bad days */
        payDates = JpmcdsNewDateListBusDayAdj(dates, payBadDayConv, payHolidayFile);
        if (payDates == NULL)
            goto done;

        if (JpmcdsBusinessDay(startDate, payBadDayConv, payHolidayFile,
                           &payStart) == FAILURE)
            goto done;

        if (JpmcdsBusinessDay(maturityDate, payBadDayConv, payHolidayFile,
                           &payMaturity) == FAILURE)
            goto done;
    }

    if (usePreStartDate)                /* Useful to JpmcdsTrinomialModel */
        cfl->fArray[0].fDate = payDates->fArray[0];
    else      
        cfl->fArray[0].fDate = payStart;
    
    cfl->fArray[0].fAmount = 0.;
    cfl->fArray[numDates-1].fDate = payMaturity;

    for (idx=1; idx < numDates-1; idx++)
        cfl->fArray[idx].fDate = payDates->fArray[idx];
    
    startIdx = 1;
    endIdx = numDates-1;
    if ( frontStub )
    {
        startIdx = 2;                   /* For non-stub processing */
        if (JpmcdsStubPayment(accrualDates->fArray[0], /*(I)Coupon start*/
                           accrualDates->fArray[1], /*(I)Coupon end */
                           accrualStart,            /*(I)Accrue start*/
                           accrualDates->fArray[1], /*(I)Accrue End */
                           rate,                            /*(I) */
                           couponDayCountConv,              /*(I)  */
                           &cfl->fArray[1].fAmount)         /*(O) */
            == FAILURE)
            goto done;
    }
    
    if ( backStub )
    {
        endIdx = numDates-2;            /* For non-stub processing */
        if (JpmcdsStubPayment(accrualDates->fArray[numDates-2], /*(I)Coup start*/
                           accrualDates->fArray[numDates-1], /*(I)Coupon end*/
                           accrualDates->fArray[numDates-2], /*(I)Accru start*/
                           accrualMaturity,                  /*(I)Accrue end*/
                           rate,                             /*(I)*/
                           couponDayCountConv,               /*(I)*/
                           &cfl->fArray[numDates-1].fAmount) /*(O)*/
                           == FAILURE)
            goto done;
    }

    
    /* Compute non-stub cashflows */
    for (idx=startIdx; idx <= endIdx; idx++)
    {
        double yearFrac;

        if (JpmcdsDayCountFraction(accrualDates->fArray[idx-1],
                                accrualDates->fArray[idx],
                                couponDayCountConv, &yearFrac) == FAILURE)
            goto done;

        cfl->fArray[idx].fAmount = rate * yearFrac;
    }

    status = SUCCESS;

done:

    JpmcdsFreeDateList(datesCopy);

    if (payDates != dates)
        JpmcdsFreeDateList(payDates);
    
    if (accrualDates != dates)
        JpmcdsFreeDateList(accrualDates);

    if (status == FAILURE)
    {
        JpmcdsFreeCFL(cfl);
        return NULL;
    }
    return cfl;
}
Пример #12
0
/*
***************************************************************************
** Makes a new  cash flow list.
**
** Depending on the value of flags, an initial paymemt of value 1 is 
** subtracted and/or  a final payment of 1 is added. If 
** JPMCDS_PRESTART_ZERO_PAYMENT is set, and there is a front stub, the first 
** date will be the payment date that would have occured before the start 
** date. In this case, JPMCDS_SUBTRACT_INITIAL cannot be set.
***************************************************************************
*/
TCashFlowList* JpmcdsMakeCFL
    (double couponRate,                 /* (I) Annual coupon Rate  */
     TDate startDate,                   /* (I) Date instrument begins at */
     TDateInterval *interval,           /* (I) Time between payments */
     TDate maturityDate,                /* (I) Date instrument matures at*/
     long couponDayCountConv,           /* (I) For coupon calculation */
     long stubPlacement,                /* (I) [Front / Back] + [Short (default) / Long] */
     long flags,                        /* (I) What type (See cashflow.h) */
     long accrualBadDayConv,            /* (I) Accrual bad day convention */
     long payBadDayConv,                /* (I) Pay bad day convention */
     char *holidayFile)                 /* (I) Holiday file */
{
    static char routine[]="JpmcdsMakeCFLRoll";

    TDateList *dl = NULL;
    TCashFlowList *cfl = NULL;
    
    if (maturityDate <= startDate)
    {
        JpmcdsErrMsg("%s: maturityDate(%s) <= startDate(%s)\n",
            routine, JpmcdsFormatDate(maturityDate), JpmcdsFormatDate(startDate));
        return NULL;
    }

    if ((flags & JPMCDS_SUBTRACT_INITIAL || flags & JPMCDS_KEEP_START_DATE) && flags & JPMCDS_PRESTART_ZERO_PAYMENT)
    {
        JpmcdsErrMsg("%s: cannot subtract initial payment at prestart date.\n", routine);
        JpmcdsErrMsg("\tAlso cannot keep both the start and prestart dates.\n");
        return NULL;        
    }

    if (flags & JPMCDS_POST_MATURITY_ZERO_PAYMENT)
    {
        if (stubPlacement & JPMCDS_STUB_POSN_MASK)
        {
            JpmcdsErrMsg("%s: no post maturity zero payment w/ stub at end.\n", routine);
            return NULL;        
        }
        else if (flags & JPMCDS_ADD_FINAL)
        {
            JpmcdsErrMsg("%s: no post maturity zero payment w/ final payment.\n", routine);
            return NULL;        
        }
        else                            /* Advance maturityDate by interval */
        {
            if (JpmcdsDtFwdAny(maturityDate, interval, &maturityDate) == FAILURE)
                goto done;
        }
    }
    
   /* Set up the TDateList of coupon dates; if stub at end, last date
    * could be later than maturityDate. If there is a stub at the start, 1st date
    * could be earlier than startDate.
    */
    dl = JpmcdsNewDateListExtendedRoll(startDate,
                                maturityDate,
                                startDate /* roll date */,
                                interval,
                                stubPlacement & JPMCDS_STUB_POSN_MASK);
    if (dl == (TDateList *)NULL)
        goto done;

    /* Make cash flow list based on an annual rate of couponRate.
    * The startDate is included, with a cashflow of 0. 
    */
    cfl = JpmcdsNewCFLFromDL3(dl, startDate, maturityDate, couponRate,
                           couponDayCountConv, stubPlacement & JPMCDS_STUB_LENGTH_LONG,
                           accrualBadDayConv, payBadDayConv, holidayFile, holidayFile,
                           (TBoolean)(flags & JPMCDS_PRESTART_ZERO_PAYMENT));

    JpmcdsFreeDateList(dl);                /* Free memory */
                          
    if (cfl == NULL)
        goto done;
    if( cfl->fNumItems == 0 )
        return cfl;

    /* Initial payment of principal */
    if (flags & JPMCDS_SUBTRACT_INITIAL)
    {
        cfl->fArray[0].fAmount-= 1.;
    }
    
    /* Add on the final repayment of principal */
    if (flags & JPMCDS_ADD_FINAL)
    {
        cfl->fArray[cfl->fNumItems-1].fAmount += 1.;
    }

    if (flags & JPMCDS_POST_MATURITY_ZERO_PAYMENT)
    {
        cfl->fArray[cfl->fNumItems-1].fAmount = 0.;
    }
    
    /* Dont want zero-cashflows around, so move
     * all cashflows back by one, unless JPMCDS_PRESTART_ZERO_PAYMENT
     * or JPMCDS_KEEP_START_DATE is set. Testing equality to zero
     * is no problem since no calculations were done.
     */
    if (!(flags & JPMCDS_PRESTART_ZERO_PAYMENT || flags & JPMCDS_KEEP_START_DATE) && cfl->fArray[0].fAmount == 0.)
    {
        int idx;
        for (idx=0; idx < cfl->fNumItems-1; idx++)
        {
            cfl->fArray[idx] = cfl->fArray[idx+1];
        }
        cfl->fNumItems--;
    }

done:
    if (cfl == NULL)
        JpmcdsErrMsg("%s: Failed.\n", routine);
    
    return cfl;
}