Merged in rg_todo_irs_676 (pull request #140)

Two TODOs in IRS - about calculating the actual payment date as an offset
This commit is contained in:
Richard Green 2016-06-14 16:37:06 +01:00
commit fdd8446b29
3 changed files with 32 additions and 22 deletions

View File

@ -1,6 +1,5 @@
package com.r3corda.contracts
import com.r3corda.core.*
import com.r3corda.core.contracts.*
import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.SecureHash
@ -672,15 +671,17 @@ class InterestRateSwap() : Contract {
// Create a schedule for the fixed payments
for (periodEndDate in dates) {
val paymentDate = BusinessCalendar.getOffsetDate(periodEndDate, Frequency.Daily, fixedLeg.paymentDelay)
val paymentEvent = FixedRatePaymentEvent(
// TODO: We are assuming the payment date is the end date of the accrual period.
periodEndDate, periodStartDate, periodEndDate,
paymentDate,
periodStartDate,
periodEndDate,
fixedLeg.dayCountBasisDay,
fixedLeg.dayCountBasisYear,
fixedLeg.notional,
fixedLeg.fixedRate
)
fixedLegPaymentSchedule[periodEndDate] = paymentEvent
fixedLegPaymentSchedule[paymentDate] = paymentEvent
periodStartDate = periodEndDate
}
@ -695,8 +696,9 @@ class InterestRateSwap() : Contract {
// Now create a schedule for the floating and fixes.
for (periodEndDate in dates) {
val paymentDate = BusinessCalendar.getOffsetDate(periodEndDate, Frequency.Daily, floatingLeg.paymentDelay)
val paymentEvent = FloatingRatePaymentEvent(
periodEndDate,
paymentDate,
periodStartDate,
periodEndDate,
floatingLeg.dayCountBasisDay,
@ -706,7 +708,7 @@ class InterestRateSwap() : Contract {
ReferenceRate(floatingLeg.indexSource, floatingLeg.indexTenor, floatingLeg.index)
)
floatingLegPaymentSchedule.put(periodEndDate, paymentEvent)
floatingLegPaymentSchedule[paymentDate] = paymentEvent
periodStartDate = periodEndDate
}

View File

@ -27,7 +27,7 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State {
rollConvention = DateRollConvention.ModifiedFollowing,
dayInMonth = 10,
paymentRule = PaymentRule.InArrears,
paymentDelay = 0,
paymentDelay = 3,
paymentCalendar = BusinessCalendar.getInstance("London", "NewYork"),
interestPeriodAdjustment = AccrualAdjustment.Adjusted
)
@ -47,7 +47,7 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State {
dayInMonth = 10,
resetDayInMonth = 10,
paymentRule = PaymentRule.InArrears,
paymentDelay = 0,
paymentDelay = 3,
paymentCalendar = BusinessCalendar.getInstance("London", "NewYork"),
interestPeriodAdjustment = AccrualAdjustment.Adjusted,
fixingPeriod = DateOffset.TWODAYS,
@ -360,7 +360,7 @@ class IRSTests {
for (i in stuffToPrint) {
println(i)
var z = dummyIRS.evaluateCalculation(LocalDate.of(2016, 9, 12), Expression(i))
var z = dummyIRS.evaluateCalculation(LocalDate.of(2016, 9, 15), Expression(i))
println(z.javaClass)
println(z)
println("-----------")

View File

@ -8,7 +8,6 @@ import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import com.r3corda.core.contracts.CommandData
import java.math.BigDecimal
import java.time.DayOfWeek
import java.time.LocalDate
@ -251,25 +250,28 @@ enum class DateOffset {
*/
enum class Frequency(val annualCompoundCount: Int) {
Annual(1) {
override fun offset(d: LocalDate) = d.plusYears(1)
override fun offset(d: LocalDate, n: Long) = d.plusYears(1 * n)
},
SemiAnnual(2) {
override fun offset(d: LocalDate) = d.plusMonths(6)
override fun offset(d: LocalDate, n: Long) = d.plusMonths(6 * n)
},
Quarterly(4) {
override fun offset(d: LocalDate) = d.plusMonths(3)
override fun offset(d: LocalDate, n: Long) = d.plusMonths(3 * n)
},
Monthly(12) {
override fun offset(d: LocalDate) = d.plusMonths(1)
override fun offset(d: LocalDate, n: Long) = d.plusMonths(1 * n)
},
Weekly(52) {
override fun offset(d: LocalDate) = d.plusWeeks(1)
override fun offset(d: LocalDate, n: Long) = d.plusWeeks(1 * n)
},
BiWeekly(26) {
override fun offset(d: LocalDate) = d.plusWeeks(2)
override fun offset(d: LocalDate, n: Long) = d.plusWeeks(2 * n)
},
Daily(365) {
override fun offset(d: LocalDate, n: Long) = d.plusDays(1 * n)
};
abstract fun offset(d: LocalDate): LocalDate
abstract fun offset(d: LocalDate, n: Long = 1): LocalDate
// Daily() // Let's not worry about this for now.
}
@ -317,18 +319,24 @@ open class BusinessCalendar private constructor(val calendars: Array<out String>
var currentDate = startDate
while (true) {
currentDate = period.offset(currentDate)
val scheduleDate = calendar.applyRollConvention(currentDate, dateRollConvention)
currentDate = getOffsetDate(currentDate, period)
if (periodOffset == null || periodOffset <= ctr)
ret.add(scheduleDate)
ret.add(calendar.applyRollConvention(currentDate, dateRollConvention))
ctr += 1
// TODO: Fix addl period logic
if ((ctr > noOfAdditionalPeriods ) || (currentDate >= endDate ?: currentDate ))
if ((ctr > noOfAdditionalPeriods) || (currentDate >= endDate ?: currentDate))
break
}
return ret
}
/** Calculates the date from @startDate moving forward @steps of time size @period. Does not apply calendar
* logic / roll conventions.
*/
fun getOffsetDate(startDate: LocalDate, period: Frequency, steps: Int = 1): LocalDate {
if (steps == 0) return startDate
return period.offset(startDate, steps.toLong())
}
}
override fun equals(other: Any?): Boolean = if (other is BusinessCalendar) {