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

View File

@ -27,7 +27,7 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State {
rollConvention = DateRollConvention.ModifiedFollowing, rollConvention = DateRollConvention.ModifiedFollowing,
dayInMonth = 10, dayInMonth = 10,
paymentRule = PaymentRule.InArrears, paymentRule = PaymentRule.InArrears,
paymentDelay = 0, paymentDelay = 3,
paymentCalendar = BusinessCalendar.getInstance("London", "NewYork"), paymentCalendar = BusinessCalendar.getInstance("London", "NewYork"),
interestPeriodAdjustment = AccrualAdjustment.Adjusted interestPeriodAdjustment = AccrualAdjustment.Adjusted
) )
@ -47,7 +47,7 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State {
dayInMonth = 10, dayInMonth = 10,
resetDayInMonth = 10, resetDayInMonth = 10,
paymentRule = PaymentRule.InArrears, paymentRule = PaymentRule.InArrears,
paymentDelay = 0, paymentDelay = 3,
paymentCalendar = BusinessCalendar.getInstance("London", "NewYork"), paymentCalendar = BusinessCalendar.getInstance("London", "NewYork"),
interestPeriodAdjustment = AccrualAdjustment.Adjusted, interestPeriodAdjustment = AccrualAdjustment.Adjusted,
fixingPeriod = DateOffset.TWODAYS, fixingPeriod = DateOffset.TWODAYS,
@ -360,7 +360,7 @@ class IRSTests {
for (i in stuffToPrint) { for (i in stuffToPrint) {
println(i) 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.javaClass)
println(z) println(z)
println("-----------") println("-----------")

View File

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