/* *************************************************************************** ** Computes the non-contingent cash flows for a fee leg. *************************************************************************** */ TCashFlowList* JpmcdsFeeLegFlows (TFeeLeg *fl) { static char routine[] = "JpmcdsFeeLegFlows"; int status = FAILURE; TCashFlowList *cfl = NULL; int i; cfl = JpmcdsNewEmptyCFL(fl->nbDates); if (cfl == NULL) goto done; for (i = 0; i < fl->nbDates; ++i) { double amount; double time; if(JpmcdsDayCountFraction(fl->accStartDates[i], fl->accEndDates[i], fl->dcc, &time) != SUCCESS) { goto done; } amount = time * fl->couponRate * fl->notional; cfl->fArray[i].fDate = fl->payDates[i]; cfl->fArray[i].fAmount = amount; } status = SUCCESS; done: if (status != SUCCESS) { JpmcdsFreeCFL(cfl); cfl = NULL; JpmcdsErrMsgFailure(routine); } return cfl; }
/* *************************************************************************** ** Makes a new TCashFlowList. *************************************************************************** */ TCashFlowList* JpmcdsNewCFL(TDate *dates, /* (I) Dates */ double *amounts, /* (I) Amounts */ int numItems) /* (I) Length of arrays */ { int idx; TCashFlowList *cfl; cfl = JpmcdsNewEmptyCFL(numItems); if( cfl == NULL ) return NULL; for (idx = 0; idx < numItems; idx++) { cfl->fArray[idx].fDate = dates[idx]; cfl->fArray[idx].fAmount = amounts[idx]; } return cfl; }
/* *************************************************************************** ** Merges two cash flow lists. *************************************************************************** */ TCashFlowList* JpmcdsMergeCFL( TCashFlowList *a, /* (I) first cash flow list */ TCashFlowList *b) /* (I) second cash flow list */ { static char routine[] = "JpmcdsMergeCFL"; TCashFlowList *cfl = NULL; /* cash flow list to return */ int i; /* where to add next cf in cfl */ int ia; /* iterates over cfs in a */ int ib; /* iterates over cfs in b */ if (a == NULL || b == NULL) { JpmcdsErrMsg ("%s: NULL inputs\n", routine); goto done; } cfl = JpmcdsNewEmptyCFL(a->fNumItems + b->fNumItems); if (cfl == NULL) goto done; i = 0; ia = 0; ib = 0; while (ia<a->fNumItems && ib<b->fNumItems) { TDate aDate = a->fArray[ia].fDate; TDate bDate = b->fArray[ib].fDate; if (aDate < bDate) { cfl->fArray[i++] = a->fArray[ia++]; } else if (aDate > bDate) { cfl->fArray[i++] = b->fArray[ib++]; } else { cfl->fArray[i].fDate = aDate; cfl->fArray[i++].fAmount = a->fArray[ia++].fAmount + b->fArray[ib++].fAmount; } } while (ia<a->fNumItems) /* add any from A left over */ { cfl->fArray[i++] = a->fArray[ia++]; } while (ib<b->fNumItems) /* add any from B left over */ { cfl->fArray[i++] = b->fArray[ib++]; } cfl->fNumItems = i; done: if (cfl == NULL) JpmcdsErrMsg("%s: FAILED\n",routine); return cfl; }
/* *************************************************************************** ** 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; }