mirror of
https://github.com/corda/corda.git
synced 2025-06-01 23:20:54 +00:00
Merged in mike-fix-irs (pull request #244)
Fix how the IRS contract uses fix commands
This commit is contained in:
commit
5167ed7df2
@ -77,7 +77,7 @@ abstract class RatePaymentEvent(date: LocalDate,
|
|||||||
// TODO : Fix below (use daycount convention for division, not hardcoded 360 etc)
|
// TODO : Fix below (use daycount convention for division, not hardcoded 360 etc)
|
||||||
val dayCountFactor: BigDecimal get() = (BigDecimal(days).divide(BigDecimal(360.0), 8, RoundingMode.HALF_UP)).setScale(4, RoundingMode.HALF_UP)
|
val dayCountFactor: BigDecimal get() = (BigDecimal(days).divide(BigDecimal(360.0), 8, RoundingMode.HALF_UP)).setScale(4, RoundingMode.HALF_UP)
|
||||||
|
|
||||||
open fun asCSV() = "$accrualStartDate,$accrualEndDate,$dayCountFactor,$days,$date,${notional.token},${notional},$rate,$flow"
|
open fun asCSV() = "$accrualStartDate,$accrualEndDate,$dayCountFactor,$days,$date,${notional.token},$notional,$rate,$flow"
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
@ -114,8 +114,7 @@ class FixedRatePaymentEvent(date: LocalDate,
|
|||||||
val CSVHeader = RatePaymentEvent.CSVHeader
|
val CSVHeader = RatePaymentEvent.CSVHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
override val flow: Amount<Currency> get() =
|
override val flow: Amount<Currency> get() = Amount(dayCountFactor.times(BigDecimal(notional.quantity)).times(rate.ratioUnit!!.value).toLong(), notional.token)
|
||||||
Amount<Currency>(dayCountFactor.times(BigDecimal(notional.quantity)).times(rate.ratioUnit!!.value).toLong(), notional.token)
|
|
||||||
|
|
||||||
override fun toString(): String =
|
override fun toString(): String =
|
||||||
"FixedRatePaymentEvent $accrualStartDate -> $accrualEndDate : $dayCountFactor : $days : $date : $notional : $rate : $flow"
|
"FixedRatePaymentEvent $accrualStartDate -> $accrualEndDate : $dayCountFactor : $days : $date : $notional : $rate : $flow"
|
||||||
@ -140,13 +139,13 @@ class FloatingRatePaymentEvent(date: LocalDate,
|
|||||||
|
|
||||||
override val flow: Amount<Currency> get() {
|
override val flow: Amount<Currency> get() {
|
||||||
// TODO: Should an uncalculated amount return a zero ? null ? etc.
|
// TODO: Should an uncalculated amount return a zero ? null ? etc.
|
||||||
val v = rate.ratioUnit?.value ?: return Amount<Currency>(0, notional.token)
|
val v = rate.ratioUnit?.value ?: return Amount(0, notional.token)
|
||||||
return Amount<Currency>(dayCountFactor.times(BigDecimal(notional.quantity)).times(v).toLong(), notional.token)
|
return Amount(dayCountFactor.times(BigDecimal(notional.quantity)).times(v).toLong(), notional.token)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = "FloatingPaymentEvent $accrualStartDate -> $accrualEndDate : $dayCountFactor : $days : $date : $notional : $rate (fix on $fixingDate): $flow"
|
override fun toString(): String = "FloatingPaymentEvent $accrualStartDate -> $accrualEndDate : $dayCountFactor : $days : $date : $notional : $rate (fix on $fixingDate): $flow"
|
||||||
|
|
||||||
override fun asCSV(): String = "$accrualStartDate,$accrualEndDate,$dayCountFactor,$days,$date,${notional.token},${notional},$fixingDate,$rate,$flow"
|
override fun asCSV(): String = "$accrualStartDate,$accrualEndDate,$dayCountFactor,$days,$date,${notional.token},$notional,$fixingDate,$rate,$flow"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for making immutables.
|
* Used for making immutables.
|
||||||
@ -450,7 +449,7 @@ class InterestRateSwap() : ClauseVerifier() {
|
|||||||
|
|
||||||
override val clauses: List<SingleClause> = listOf(Clause.Timestamped(), Clause.Group())
|
override val clauses: List<SingleClause> = listOf(Clause.Timestamped(), Clause.Group())
|
||||||
override fun extractCommands(tx: TransactionForContract): Collection<AuthenticatedObject<CommandData>>
|
override fun extractCommands(tx: TransactionForContract): Collection<AuthenticatedObject<CommandData>>
|
||||||
= tx.commands.select<Commands>() + tx.commands.select<TimestampCommand>()
|
= tx.commands.select<Commands>() + tx.commands.select<TimestampCommand>()
|
||||||
|
|
||||||
interface Clause {
|
interface Clause {
|
||||||
/**
|
/**
|
||||||
@ -498,8 +497,9 @@ class InterestRateSwap() : ClauseVerifier() {
|
|||||||
fun getFloatingLegPaymentsDifferences(payments1: Map<LocalDate, Event>, payments2: Map<LocalDate, Event>): List<Pair<LocalDate, Pair<FloatingRatePaymentEvent, FloatingRatePaymentEvent>>> {
|
fun getFloatingLegPaymentsDifferences(payments1: Map<LocalDate, Event>, payments2: Map<LocalDate, Event>): List<Pair<LocalDate, Pair<FloatingRatePaymentEvent, FloatingRatePaymentEvent>>> {
|
||||||
val diff1 = payments1.filter { payments1[it.key] != payments2[it.key] }
|
val diff1 = payments1.filter { payments1[it.key] != payments2[it.key] }
|
||||||
val diff2 = payments2.filter { payments1[it.key] != payments2[it.key] }
|
val diff2 = payments2.filter { payments1[it.key] != payments2[it.key] }
|
||||||
val ret = (diff1.keys + diff2.keys).map { it to Pair(diff1.get(it) as FloatingRatePaymentEvent, diff2.get(it) as FloatingRatePaymentEvent) }
|
return (diff1.keys + diff2.keys).map {
|
||||||
return ret
|
it to Pair(diff1[it] as FloatingRatePaymentEvent, diff2[it] as FloatingRatePaymentEvent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,6 +513,7 @@ class InterestRateSwap() : ClauseVerifier() {
|
|||||||
// Group by Trade ID for in / out states
|
// Group by Trade ID for in / out states
|
||||||
return tx.groupStates() { state: InterestRateSwap.State -> state.common.tradeID }
|
return tx.groupStates() { state: InterestRateSwap.State -> state.common.tradeID }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val clauses: List<GroupClause<State, String>>
|
override val clauses: List<GroupClause<State, String>>
|
||||||
get() = listOf(Agree(), Fix(), Pay(), Mature())
|
get() = listOf(Agree(), Fix(), Pay(), Mature())
|
||||||
}
|
}
|
||||||
@ -530,12 +531,11 @@ class InterestRateSwap() : ClauseVerifier() {
|
|||||||
// derived as the correct notary
|
// derived as the correct notary
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
val command = tx.commands.getTimestampByName("Mock Company 0", "Notary Service", "Bank A")
|
val command = tx.commands.getTimestampByName("Mock Company 0", "Notary Service", "Bank A")
|
||||||
val time = command?.midpoint
|
?: throw IllegalArgumentException("must be timestamped")
|
||||||
if (time == null) throw IllegalArgumentException("must be timestamped")
|
return setOf(command)
|
||||||
|
|
||||||
return setOf(command!!)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Agree : AbstractIRSClause() {
|
class Agree : AbstractIRSClause() {
|
||||||
override val requiredCommands: Set<Class<out CommandData>>
|
override val requiredCommands: Set<Class<out CommandData>>
|
||||||
get() = setOf(Commands.Agree::class.java)
|
get() = setOf(Commands.Agree::class.java)
|
||||||
@ -572,16 +572,17 @@ class InterestRateSwap() : ClauseVerifier() {
|
|||||||
return setOf(command.value)
|
return setOf(command.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Fix : AbstractIRSClause() {
|
class Fix : AbstractIRSClause() {
|
||||||
override val requiredCommands: Set<Class<out CommandData>>
|
override val requiredCommands: Set<Class<out CommandData>>
|
||||||
get() = setOf(Commands.Fix::class.java)
|
get() = setOf(Commands.Refix::class.java)
|
||||||
|
|
||||||
override fun verify(tx: TransactionForContract,
|
override fun verify(tx: TransactionForContract,
|
||||||
inputs: List<State>,
|
inputs: List<State>,
|
||||||
outputs: List<State>,
|
outputs: List<State>,
|
||||||
commands: Collection<AuthenticatedObject<CommandData>>,
|
commands: Collection<AuthenticatedObject<CommandData>>,
|
||||||
token: String): Set<CommandData> {
|
token: String): Set<CommandData> {
|
||||||
val command = tx.commands.requireSingleCommand<Commands.Fix>()
|
val command = tx.commands.requireSingleCommand<Commands.Refix>()
|
||||||
val irs = outputs.filterIsInstance<State>().single()
|
val irs = outputs.filterIsInstance<State>().single()
|
||||||
val prevIrs = inputs.filterIsInstance<State>().single()
|
val prevIrs = inputs.filterIsInstance<State>().single()
|
||||||
val paymentDifferences = getFloatingLegPaymentsDifferences(prevIrs.calculation.floatingLegPaymentSchedule, irs.calculation.floatingLegPaymentSchedule)
|
val paymentDifferences = getFloatingLegPaymentsDifferences(prevIrs.calculation.floatingLegPaymentSchedule, irs.calculation.floatingLegPaymentSchedule)
|
||||||
@ -595,8 +596,7 @@ class InterestRateSwap() : ClauseVerifier() {
|
|||||||
|
|
||||||
val changedRates = paymentDifferences.single().second // Ignore the date of the changed rate (we checked that earlier).
|
val changedRates = paymentDifferences.single().second // Ignore the date of the changed rate (we checked that earlier).
|
||||||
val (oldFloatingRatePaymentEvent, newFixedRatePaymentEvent) = changedRates
|
val (oldFloatingRatePaymentEvent, newFixedRatePaymentEvent) = changedRates
|
||||||
val fixCommand = tx.commands.requireSingleCommand<com.r3corda.core.contracts.Fix>()
|
val fixValue = command.value.fix
|
||||||
val fixValue = fixCommand.value
|
|
||||||
// Need to check that everything is the same apart from the new fixed rate entry.
|
// Need to check that everything is the same apart from the new fixed rate entry.
|
||||||
requireThat {
|
requireThat {
|
||||||
"The fixed leg parties are constant" by (irs.fixedLeg.fixedRatePayer == prevIrs.fixedLeg.fixedRatePayer) // Although superseded by the below test, this is included for a regression issue
|
"The fixed leg parties are constant" by (irs.fixedLeg.fixedRatePayer == prevIrs.fixedLeg.fixedRatePayer) // Although superseded by the below test, this is included for a regression issue
|
||||||
@ -618,6 +618,7 @@ class InterestRateSwap() : ClauseVerifier() {
|
|||||||
return setOf(command.value)
|
return setOf(command.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Pay : AbstractIRSClause() {
|
class Pay : AbstractIRSClause() {
|
||||||
override val requiredCommands: Set<Class<out CommandData>>
|
override val requiredCommands: Set<Class<out CommandData>>
|
||||||
get() = setOf(Commands.Pay::class.java)
|
get() = setOf(Commands.Pay::class.java)
|
||||||
@ -634,6 +635,7 @@ class InterestRateSwap() : ClauseVerifier() {
|
|||||||
return setOf(command.value)
|
return setOf(command.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Mature : AbstractIRSClause() {
|
class Mature : AbstractIRSClause() {
|
||||||
override val requiredCommands: Set<Class<out CommandData>>
|
override val requiredCommands: Set<Class<out CommandData>>
|
||||||
get() = setOf(Commands.Mature::class.java)
|
get() = setOf(Commands.Mature::class.java)
|
||||||
@ -656,7 +658,7 @@ class InterestRateSwap() : ClauseVerifier() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Commands : CommandData {
|
interface Commands : CommandData {
|
||||||
class Fix : TypeOnlyCommandData(), Commands // Receive interest rate from oracle, Both sides agree
|
data class Refix(val fix: Fix) : Commands // Receive interest rate from oracle, Both sides agree
|
||||||
class Pay : TypeOnlyCommandData(), Commands // Not implemented just yet
|
class Pay : TypeOnlyCommandData(), Commands // Not implemented just yet
|
||||||
class Agree : TypeOnlyCommandData(), Commands // Both sides agree to trade
|
class Agree : TypeOnlyCommandData(), Commands // Both sides agree to trade
|
||||||
class Mature : TypeOnlyCommandData(), Commands // Trade has matured; no more actions. Cleanup. // TODO: Do we need this?
|
class Mature : TypeOnlyCommandData(), Commands // Trade has matured; no more actions. Cleanup. // TODO: Do we need this?
|
||||||
@ -713,7 +715,7 @@ class InterestRateSwap() : ClauseVerifier() {
|
|||||||
override fun generateAgreement(notary: Party): TransactionBuilder = InterestRateSwap().generateAgreement(floatingLeg, fixedLeg, calculation, common, notary)
|
override fun generateAgreement(notary: Party): TransactionBuilder = InterestRateSwap().generateAgreement(floatingLeg, fixedLeg, calculation, common, notary)
|
||||||
|
|
||||||
override fun generateFix(ptx: TransactionBuilder, oldState: StateAndRef<*>, fix: Fix) {
|
override fun generateFix(ptx: TransactionBuilder, oldState: StateAndRef<*>, fix: Fix) {
|
||||||
InterestRateSwap().generateFix(ptx, StateAndRef(TransactionState(this, oldState.state.notary), oldState.ref), Pair(fix.of.forDay, Rate(RatioUnit(fix.value))))
|
InterestRateSwap().generateFix(ptx, StateAndRef(TransactionState(this, oldState.state.notary), oldState.ref), fix)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun nextFixingOf(): FixOf? {
|
override fun nextFixingOf(): FixOf? {
|
||||||
@ -732,9 +734,9 @@ class InterestRateSwap() : ClauseVerifier() {
|
|||||||
fun evaluateCalculation(businessDate: LocalDate, expression: Expression = calculation.expression): Any {
|
fun evaluateCalculation(businessDate: LocalDate, expression: Expression = calculation.expression): Any {
|
||||||
// TODO: Jexl is purely for prototyping. It may be replaced
|
// TODO: Jexl is purely for prototyping. It may be replaced
|
||||||
// TODO: Whatever we do use must be secure and sandboxed
|
// TODO: Whatever we do use must be secure and sandboxed
|
||||||
var jexl = JexlBuilder().create()
|
val jexl = JexlBuilder().create()
|
||||||
var expr = jexl.createExpression(expression.expr)
|
val expr = jexl.createExpression(expression.expr)
|
||||||
var jc = MapContext()
|
val jc = MapContext()
|
||||||
jc.set("fixedLeg", fixedLeg)
|
jc.set("fixedLeg", fixedLeg)
|
||||||
jc.set("floatingLeg", floatingLeg)
|
jc.set("floatingLeg", floatingLeg)
|
||||||
jc.set("calculation", calculation)
|
jc.set("calculation", calculation)
|
||||||
@ -783,12 +785,12 @@ class InterestRateSwap() : ClauseVerifier() {
|
|||||||
floatingLeg.rollConvention,
|
floatingLeg.rollConvention,
|
||||||
endDate = floatingLeg.terminationDate)
|
endDate = floatingLeg.terminationDate)
|
||||||
|
|
||||||
var floatingLegPaymentSchedule: MutableMap<LocalDate, FloatingRatePaymentEvent> = HashMap()
|
val floatingLegPaymentSchedule: MutableMap<LocalDate, FloatingRatePaymentEvent> = HashMap()
|
||||||
periodStartDate = floatingLeg.effectiveDate
|
periodStartDate = floatingLeg.effectiveDate
|
||||||
|
|
||||||
// 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 paymentDate = BusinessCalendar.getOffsetDate(periodEndDate, Frequency.Daily, floatingLeg.paymentDelay)
|
||||||
val paymentEvent = FloatingRatePaymentEvent(
|
val paymentEvent = FloatingRatePaymentEvent(
|
||||||
paymentDate,
|
paymentDate,
|
||||||
periodStartDate,
|
periodStartDate,
|
||||||
@ -818,13 +820,13 @@ class InterestRateSwap() : ClauseVerifier() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Replace with rates oracle
|
fun generateFix(tx: TransactionBuilder, irs: StateAndRef<State>, fixing: Fix) {
|
||||||
fun generateFix(tx: TransactionBuilder, irs: StateAndRef<State>, fixing: Pair<LocalDate, Rate>) {
|
|
||||||
tx.addInputState(irs)
|
tx.addInputState(irs)
|
||||||
|
val fixedRate = FixedRate(RatioUnit(fixing.value))
|
||||||
tx.addOutputState(
|
tx.addOutputState(
|
||||||
irs.state.data.copy(calculation = irs.state.data.calculation.applyFixing(fixing.first, FixedRate(fixing.second))),
|
irs.state.data.copy(calculation = irs.state.data.calculation.applyFixing(fixing.of.forDay, fixedRate)),
|
||||||
irs.state.notary
|
irs.state.notary
|
||||||
)
|
)
|
||||||
tx.addCommand(Commands.Fix(), listOf(irs.state.data.floatingLeg.floatingRatePayer.owningKey, irs.state.data.fixedLeg.fixedRatePayer.owningKey))
|
tx.addCommand(Commands.Refix(fixing), listOf(irs.state.data.floatingLeg.floatingRatePayer.owningKey, irs.state.data.fixedLeg.fixedRatePayer.owningKey))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,21 +11,10 @@ import java.util.*
|
|||||||
/**
|
/**
|
||||||
* A utility class to prevent the various mixups between percentages, decimals, bips etc.
|
* A utility class to prevent the various mixups between percentages, decimals, bips etc.
|
||||||
*/
|
*/
|
||||||
open class RatioUnit(value: BigDecimal) { // TODO: Discuss this type
|
open class RatioUnit(val value: BigDecimal) { // TODO: Discuss this type
|
||||||
val value = value
|
override fun equals(other: Any?) = (other as? RatioUnit)?.value == value
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other) return true
|
|
||||||
if (other?.javaClass != javaClass) return false
|
|
||||||
|
|
||||||
other as RatioUnit
|
|
||||||
|
|
||||||
if (value != other.value) return false
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode() = value.hashCode()
|
override fun hashCode() = value.hashCode()
|
||||||
|
override fun toString() = value.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,21 +52,16 @@ open class Rate(val ratioUnit: RatioUnit? = null) {
|
|||||||
* for equality.
|
* for equality.
|
||||||
*/
|
*/
|
||||||
override fun hashCode() = ratioUnit?.hashCode() ?: 0
|
override fun hashCode() = ratioUnit?.hashCode() ?: 0
|
||||||
|
override fun toString() = ratioUnit.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A very basic subclass to represent a fixed rate.
|
* A very basic subclass to represent a fixed rate.
|
||||||
*/
|
*/
|
||||||
class FixedRate(ratioUnit: RatioUnit) : Rate(ratioUnit) {
|
class FixedRate(ratioUnit: RatioUnit) : Rate(ratioUnit) {
|
||||||
|
|
||||||
constructor(otherRate: Rate) : this(ratioUnit = otherRate.ratioUnit!!)
|
|
||||||
|
|
||||||
override fun toString(): String = "$ratioUnit"
|
|
||||||
|
|
||||||
fun isPositive(): Boolean = ratioUnit!!.value > BigDecimal("0.0")
|
fun isPositive(): Boolean = ratioUnit!!.value > BigDecimal("0.0")
|
||||||
|
|
||||||
override fun equals(other: Any?) = other?.javaClass == javaClass && super.equals(other)
|
override fun equals(other: Any?) = other?.javaClass == javaClass && super.equals(other)
|
||||||
|
|
||||||
override fun hashCode() = super.hashCode()
|
override fun hashCode() = super.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,14 +294,16 @@ class IRSTests {
|
|||||||
@Test
|
@Test
|
||||||
fun generateIRSandFixSome() {
|
fun generateIRSandFixSome() {
|
||||||
var previousTXN = generateIRSTxn(1)
|
var previousTXN = generateIRSTxn(1)
|
||||||
var currentIRS = previousTXN.outputs.map { it.data }.filterIsInstance<InterestRateSwap.State>().single()
|
fun currentIRS() = previousTXN.outputs.map { it.data }.filterIsInstance<InterestRateSwap.State>().single()
|
||||||
println(currentIRS.prettyPrint())
|
|
||||||
|
val txns = HashSet<LedgerTransaction>()
|
||||||
|
txns += previousTXN
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
val nextFixingDate = currentIRS.calculation.nextFixingDate() ?: break
|
val nextFix: FixOf = currentIRS().nextFixingOf() ?: break
|
||||||
println("\n\n\n ***** Applying a fixing to $nextFixingDate \n\n\n")
|
|
||||||
val fixTX: LedgerTransaction = run {
|
val fixTX: LedgerTransaction = run {
|
||||||
val tx = TransactionType.General.Builder()
|
val tx = TransactionType.General.Builder()
|
||||||
val fixing = Pair(nextFixingDate, FixedRate("0.052".percent))
|
val fixing = Fix(nextFix, "0.052".percent.value)
|
||||||
InterestRateSwap().generateFix(tx, previousTXN.outRef(0), fixing)
|
InterestRateSwap().generateFix(tx, previousTXN.outRef(0), fixing)
|
||||||
with(tx) {
|
with(tx) {
|
||||||
setTime(TEST_TX_TIME, DUMMY_NOTARY, 30.seconds)
|
setTime(TEST_TX_TIME, DUMMY_NOTARY, 30.seconds)
|
||||||
@ -311,10 +313,10 @@ class IRSTests {
|
|||||||
}
|
}
|
||||||
tx.toSignedTransaction().verifyToLedgerTransaction(MOCK_IDENTITY_SERVICE, attachments)
|
tx.toSignedTransaction().verifyToLedgerTransaction(MOCK_IDENTITY_SERVICE, attachments)
|
||||||
}
|
}
|
||||||
currentIRS = previousTXN.outputs.map { it.data }.filterIsInstance<InterestRateSwap.State>().single()
|
|
||||||
println(currentIRS.prettyPrint())
|
|
||||||
previousTXN = fixTX
|
previousTXN = fixTX
|
||||||
|
txns += fixTX
|
||||||
}
|
}
|
||||||
|
TransactionGroup(txns, emptySet()).verify()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move these later as they aren't IRS specific.
|
// Move these later as they aren't IRS specific.
|
||||||
@ -385,10 +387,7 @@ class IRSTests {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
command(ORACLE_PUBKEY) {
|
command(ORACLE_PUBKEY) {
|
||||||
InterestRateSwap.Commands.Fix()
|
InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd))
|
||||||
}
|
|
||||||
command(ORACLE_PUBKEY) {
|
|
||||||
Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)
|
|
||||||
}
|
}
|
||||||
timestamp(TEST_TX_TIME)
|
timestamp(TEST_TX_TIME)
|
||||||
this.verifies()
|
this.verifies()
|
||||||
@ -580,32 +579,25 @@ class IRSTests {
|
|||||||
// Templated tweak for reference. A corrent fixing applied should be ok
|
// Templated tweak for reference. A corrent fixing applied should be ok
|
||||||
tweak {
|
tweak {
|
||||||
command(ORACLE_PUBKEY) {
|
command(ORACLE_PUBKEY) {
|
||||||
InterestRateSwap.Commands.Fix()
|
InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd))
|
||||||
}
|
}
|
||||||
timestamp(TEST_TX_TIME)
|
timestamp(TEST_TX_TIME)
|
||||||
command(ORACLE_PUBKEY) {
|
|
||||||
Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)
|
|
||||||
}
|
|
||||||
output() { newIRS }
|
output() { newIRS }
|
||||||
this.verifies()
|
this.verifies()
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test makes sure that verify confirms the fixing was applied and there is a difference in the old and new
|
// This test makes sure that verify confirms the fixing was applied and there is a difference in the old and new
|
||||||
tweak {
|
tweak {
|
||||||
command(ORACLE_PUBKEY) { InterestRateSwap.Commands.Fix() }
|
command(ORACLE_PUBKEY) { InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)) }
|
||||||
timestamp(TEST_TX_TIME)
|
timestamp(TEST_TX_TIME)
|
||||||
command(ORACLE_PUBKEY) { Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd) }
|
|
||||||
output() { oldIRS }
|
output() { oldIRS }
|
||||||
this `fails with` "There is at least one difference in the IRS floating leg payment schedules"
|
this `fails with` "There is at least one difference in the IRS floating leg payment schedules"
|
||||||
}
|
}
|
||||||
|
|
||||||
// This tests tries to sneak in a change to another fixing (which may or may not be the latest one)
|
// This tests tries to sneak in a change to another fixing (which may or may not be the latest one)
|
||||||
tweak {
|
tweak {
|
||||||
command(ORACLE_PUBKEY) { InterestRateSwap.Commands.Fix() }
|
command(ORACLE_PUBKEY) { InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)) }
|
||||||
timestamp(TEST_TX_TIME)
|
timestamp(TEST_TX_TIME)
|
||||||
command(ORACLE_PUBKEY) {
|
|
||||||
Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)
|
|
||||||
}
|
|
||||||
|
|
||||||
val firstResetKey = newIRS.calculation.floatingLegPaymentSchedule.keys.first()
|
val firstResetKey = newIRS.calculation.floatingLegPaymentSchedule.keys.first()
|
||||||
val firstResetValue = newIRS.calculation.floatingLegPaymentSchedule[firstResetKey]
|
val firstResetValue = newIRS.calculation.floatingLegPaymentSchedule[firstResetKey]
|
||||||
@ -625,9 +617,8 @@ class IRSTests {
|
|||||||
|
|
||||||
// This tests modifies the payment currency for the fixing
|
// This tests modifies the payment currency for the fixing
|
||||||
tweak {
|
tweak {
|
||||||
command(ORACLE_PUBKEY) { InterestRateSwap.Commands.Fix() }
|
command(ORACLE_PUBKEY) { InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)) }
|
||||||
timestamp(TEST_TX_TIME)
|
timestamp(TEST_TX_TIME)
|
||||||
command(ORACLE_PUBKEY) { Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd) }
|
|
||||||
|
|
||||||
val latestReset = newIRS.calculation.floatingLegPaymentSchedule.filter { it.value.rate is FixedRate }.maxBy { it.key }
|
val latestReset = newIRS.calculation.floatingLegPaymentSchedule.filter { it.value.rate is FixedRate }.maxBy { it.key }
|
||||||
val modifiedLatestResetValue = latestReset!!.value.copy(notional = Amount(latestReset.value.notional.quantity, Currency.getInstance("JPY")))
|
val modifiedLatestResetValue = latestReset!!.value.copy(notional = Amount(latestReset.value.notional.quantity, Currency.getInstance("JPY")))
|
||||||
@ -711,10 +702,7 @@ class IRSTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
command(ORACLE_PUBKEY) {
|
command(ORACLE_PUBKEY) {
|
||||||
InterestRateSwap.Commands.Fix()
|
InterestRateSwap.Commands.Refix(Fix(FixOf("ICE LIBOR", ld1, Tenor("3M")), bd1))
|
||||||
}
|
|
||||||
command(ORACLE_PUBKEY) {
|
|
||||||
Fix(FixOf("ICE LIBOR", ld1, Tenor("3M")), bd1)
|
|
||||||
}
|
}
|
||||||
timestamp(TEST_TX_TIME)
|
timestamp(TEST_TX_TIME)
|
||||||
this.verifies()
|
this.verifies()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user