mirror of
https://github.com/corda/corda.git
synced 2025-04-30 07:50:05 +00:00
Universal: completed Cap unit test, full life cycle
This commit is contained in:
parent
2299b3beae
commit
c328655f68
@ -115,13 +115,17 @@ class UniversalContract : Contract {
|
|||||||
val nextStart = schedule.first()
|
val nextStart = schedule.first()
|
||||||
// todo: look into schedule for final dates
|
// todo: look into schedule for final dates
|
||||||
|
|
||||||
// todo: we may have to save original start date in order to roll out correctly
|
|
||||||
val newRollOut = RollOut(nextStart, end, rollOut.frequency, rollOut.template)
|
|
||||||
|
|
||||||
val arr = replaceStartEnd(rollOut.template, start.toInstant(), nextStart.toInstant())
|
val arr = replaceStartEnd(rollOut.template, start.toInstant(), nextStart.toInstant())
|
||||||
|
|
||||||
|
if (nextStart < end) {
|
||||||
|
// todo: we may have to save original start date in order to roll out correctly
|
||||||
|
val newRollOut = RollOut(nextStart, end, rollOut.frequency, rollOut.template)
|
||||||
return replaceNext(arr, newRollOut )
|
return replaceNext(arr, newRollOut )
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return removeNext(arr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun<T> replaceStartEnd(p: Perceivable<T>, start: Instant, end: Instant) : Perceivable<T> =
|
fun<T> replaceStartEnd(p: Perceivable<T>, start: Instant, end: Instant) : Perceivable<T> =
|
||||||
when (p) {
|
when (p) {
|
||||||
@ -156,6 +160,21 @@ class UniversalContract : Contract {
|
|||||||
else -> throw NotImplementedError("replaceNext " + arrangement.javaClass.name)
|
else -> throw NotImplementedError("replaceNext " + arrangement.javaClass.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun removeNext(arrangement: Arrangement) : Arrangement =
|
||||||
|
when (arrangement) {
|
||||||
|
is Actions -> Actions(arrangement.actions.map { Action(it.name, it.condition, it.actors, removeNext(it.arrangement)) }.toSet())
|
||||||
|
is And -> {
|
||||||
|
val a = arrangement.arrangements.map { removeNext(it) }.filter { it != zero }
|
||||||
|
if (a.count() > 1)
|
||||||
|
And(a.toSet())
|
||||||
|
else
|
||||||
|
a.single()
|
||||||
|
}
|
||||||
|
is Transfer -> arrangement
|
||||||
|
is Zero -> arrangement
|
||||||
|
is Continuation -> zero
|
||||||
|
else -> throw NotImplementedError("replaceNext " + arrangement.javaClass.name)
|
||||||
|
}
|
||||||
|
|
||||||
override fun verify(tx: TransactionForContract) {
|
override fun verify(tx: TransactionForContract) {
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ class Cap {
|
|||||||
|
|
||||||
val tradeDate: LocalDate = LocalDate.of(2016, 9, 1)
|
val tradeDate: LocalDate = LocalDate.of(2016, 9, 1)
|
||||||
|
|
||||||
val contract = arrange {
|
val contractInitial = arrange {
|
||||||
rollOut("2016-09-01".ld, "2017-09-01".ld, Frequency.Quarterly) {
|
rollOut("2016-09-01".ld, "2017-09-01".ld, Frequency.SemiAnnual) {
|
||||||
actions {
|
actions {
|
||||||
(acmeCorp or highStreetBank).may {
|
(acmeCorp or highStreetBank).may {
|
||||||
"exercise".anytime {
|
"exercise".anytime {
|
||||||
@ -43,14 +43,14 @@ class Cap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val contractFixed = arrange {
|
val contractAfterFixingFirst = arrange {
|
||||||
actions {
|
actions {
|
||||||
(acmeCorp or highStreetBank).may {
|
(acmeCorp or highStreetBank).may {
|
||||||
"exercise".anytime() {
|
"exercise".anytime() {
|
||||||
val floating1 = interest(notional, "act/365", 1.0.bd, "2016-09-01", "2016-12-01")
|
val floating1 = interest(notional, "act/365", 1.0.bd, "2016-09-01", "2017-03-01")
|
||||||
val fixed1 = interest(notional, "act/365", 0.5.bd, "2016-09-01", "2016-12-01")
|
val fixed1 = interest(notional, "act/365", 0.5.bd, "2016-09-01", "2017-03-01")
|
||||||
highStreetBank.gives(acmeCorp, floating1 - fixed1, currency)
|
highStreetBank.gives(acmeCorp, floating1 - fixed1, currency)
|
||||||
rollOut("2016-12-01".ld, "2017-09-01".ld, Frequency.Quarterly) {
|
rollOut("2017-03-01".ld, "2017-09-01".ld, Frequency.SemiAnnual) {
|
||||||
actions {
|
actions {
|
||||||
(acmeCorp or highStreetBank).may {
|
(acmeCorp or highStreetBank).may {
|
||||||
"exercise".anytime {
|
"exercise".anytime {
|
||||||
@ -71,56 +71,7 @@ class Cap {
|
|||||||
}
|
}
|
||||||
acmeCorp.may {
|
acmeCorp.may {
|
||||||
"skip".anytime {
|
"skip".anytime {
|
||||||
rollOut("2016-12-01".ld, "2017-09-01".ld, Frequency.Quarterly) {
|
rollOut("2017-03-01".ld, "2017-09-01".ld, Frequency.SemiAnnual) {
|
||||||
actions {
|
|
||||||
(acmeCorp or highStreetBank).may {
|
|
||||||
"exercise".anytime {
|
|
||||||
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("3M")), start, end)
|
|
||||||
val fixed = interest(notional, "act/365", 0.5.bd, start, end)
|
|
||||||
highStreetBank.gives(acmeCorp, floating - fixed, currency)
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
acmeCorp.may {
|
|
||||||
"skip".anytime {
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val contractFixed2 = arrange {
|
|
||||||
actions {
|
|
||||||
(acmeCorp or highStreetBank).may {
|
|
||||||
"exercise".anytime() {
|
|
||||||
val floating1 = interest(notional, "act/365", 1.0.bd, "2016-12-01", "2017-03-01")
|
|
||||||
val fixed1 = interest(notional, "act/365", 0.5.bd, "2016-12-01", "2017-03-01")
|
|
||||||
highStreetBank.gives(acmeCorp, floating1 - fixed1, currency)
|
|
||||||
rollOut("2017-03-01".ld, "2017-09-01".ld, Frequency.Quarterly) {
|
|
||||||
actions {
|
|
||||||
(acmeCorp or highStreetBank).may {
|
|
||||||
"exercise".anytime {
|
|
||||||
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("3M")), start, end)
|
|
||||||
val fixed = interest(notional, "act/365", 0.5.bd, start, end)
|
|
||||||
highStreetBank.gives(acmeCorp, floating - fixed, currency)
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
acmeCorp.may {
|
|
||||||
"skip".anytime {
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
acmeCorp.may {
|
|
||||||
"skip".anytime {
|
|
||||||
rollOut("2017-03-01".ld, "2017-09-01".ld, Frequency.Quarterly) {
|
|
||||||
actions {
|
actions {
|
||||||
(acmeCorp or highStreetBank).may {
|
(acmeCorp or highStreetBank).may {
|
||||||
"exercise".anytime {
|
"exercise".anytime {
|
||||||
@ -142,8 +93,24 @@ class Cap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val contractAfterExecute = arrange {
|
val contractAfterFixingFinal = arrange {
|
||||||
rollOut("2016-12-01".ld, "2017-09-01".ld, Frequency.Quarterly) {
|
actions {
|
||||||
|
(acmeCorp or highStreetBank).may {
|
||||||
|
"exercise".anytime() {
|
||||||
|
val floating1 = interest(notional, "act/365", 1.0.bd, "2017-03-01", "2017-09-01")
|
||||||
|
val fixed1 = interest(notional, "act/365", 0.5.bd, "2017-03-01", "2017-09-01")
|
||||||
|
highStreetBank.gives(acmeCorp, floating1 - fixed1, currency)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
acmeCorp.may {
|
||||||
|
"skip".anytime {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val contractAfterExecutionFirst = arrange {
|
||||||
|
rollOut("2017-03-01".ld, "2017-09-01".ld, Frequency.SemiAnnual) {
|
||||||
actions {
|
actions {
|
||||||
(acmeCorp or highStreetBank).may {
|
(acmeCorp or highStreetBank).may {
|
||||||
"exercise".anytime {
|
"exercise".anytime {
|
||||||
@ -163,19 +130,21 @@ class Cap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val paymentFirst = arrange { highStreetBank.gives(acmeCorp, 250.K, EUR) }
|
val paymentFirst = arrange { highStreetBank.gives(acmeCorp, 250.K, EUR) }
|
||||||
|
val paymentFinal = arrange { highStreetBank.gives(acmeCorp, 250.K, EUR) }
|
||||||
|
|
||||||
|
|
||||||
val stateStart = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contract)
|
val stateInitial = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contractInitial)
|
||||||
|
|
||||||
val stateFixed = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contractFixed)
|
val stateAfterFixingFirst = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contractAfterFixingFirst)
|
||||||
|
|
||||||
val stateAfterExecute = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contractAfterExecute)
|
val stateAfterExecutionFirst = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contractAfterExecutionFirst)
|
||||||
val statePaymentFirst = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), paymentFirst)
|
val statePaymentFirst = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), paymentFirst)
|
||||||
|
|
||||||
val stateFixed2 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contractFixed2)
|
val stateAfterFixingFinal = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contractAfterFixingFinal)
|
||||||
|
val statePaymentFinal = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), paymentFinal)
|
||||||
|
|
||||||
val contractLimitedCap = arrange {
|
val contractLimitedCap = arrange {
|
||||||
rollOut("2016-04-01".ld, "2017-04-01".ld, Frequency.Quarterly, object {
|
rollOut("2016-04-01".ld, "2017-04-01".ld, Frequency.SemiAnnual, object {
|
||||||
val limit = variable(150.K)
|
val limit = variable(150.K)
|
||||||
}) {
|
}) {
|
||||||
actions {
|
actions {
|
||||||
@ -200,7 +169,7 @@ class Cap {
|
|||||||
@Test
|
@Test
|
||||||
fun issue() {
|
fun issue() {
|
||||||
transaction {
|
transaction {
|
||||||
output { stateStart }
|
output { stateInitial }
|
||||||
timestamp(TEST_TX_TIME_1)
|
timestamp(TEST_TX_TIME_1)
|
||||||
|
|
||||||
this `fails with` "transaction has a single command"
|
this `fails with` "transaction has a single command"
|
||||||
@ -219,8 +188,8 @@ class Cap {
|
|||||||
@Test
|
@Test
|
||||||
fun `first fixing`() {
|
fun `first fixing`() {
|
||||||
transaction {
|
transaction {
|
||||||
input { stateStart }
|
input { stateInitial }
|
||||||
output { stateFixed }
|
output { stateAfterFixingFirst }
|
||||||
timestamp(TEST_TX_TIME_1)
|
timestamp(TEST_TX_TIME_1)
|
||||||
|
|
||||||
tweak {
|
tweak {
|
||||||
@ -264,8 +233,8 @@ class Cap {
|
|||||||
@Test
|
@Test
|
||||||
fun `first execute`() {
|
fun `first execute`() {
|
||||||
transaction {
|
transaction {
|
||||||
input { stateFixed }
|
input { stateAfterFixingFirst }
|
||||||
output { stateAfterExecute }
|
output { stateAfterExecutionFirst }
|
||||||
output { statePaymentFirst }
|
output { statePaymentFirst }
|
||||||
|
|
||||||
timestamp(TEST_TX_TIME_1)
|
timestamp(TEST_TX_TIME_1)
|
||||||
@ -281,11 +250,30 @@ class Cap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `final execute`() {
|
||||||
|
transaction {
|
||||||
|
input { stateAfterFixingFinal }
|
||||||
|
output { statePaymentFinal }
|
||||||
|
|
||||||
|
timestamp(TEST_TX_TIME_1)
|
||||||
|
|
||||||
|
tweak {
|
||||||
|
command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") }
|
||||||
|
this `fails with` "action must be defined"
|
||||||
|
}
|
||||||
|
|
||||||
|
command(highStreetBank.owningKey) { UniversalContract.Commands.Action("exercise") }
|
||||||
|
|
||||||
|
this.verifies()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `second fixing`() {
|
fun `second fixing`() {
|
||||||
transaction {
|
transaction {
|
||||||
input { stateAfterExecute }
|
input { stateAfterExecutionFirst }
|
||||||
output { stateFixed2 }
|
output { stateAfterFixingFinal }
|
||||||
timestamp(TEST_TX_TIME_1)
|
timestamp(TEST_TX_TIME_1)
|
||||||
|
|
||||||
tweak {
|
tweak {
|
||||||
@ -295,32 +283,32 @@ class Cap {
|
|||||||
|
|
||||||
tweak {
|
tweak {
|
||||||
// wrong source
|
// wrong source
|
||||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBORx", BusinessCalendar.parseDateFromString("2016-12-01"), Tenor("3M")), 1.0.bd))) }
|
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBORx", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("3M")), 1.0.bd))) }
|
||||||
|
|
||||||
this `fails with` "relevant fixing must be included"
|
this `fails with` "relevant fixing must be included"
|
||||||
}
|
}
|
||||||
|
|
||||||
tweak {
|
tweak {
|
||||||
// wrong date
|
// wrong date
|
||||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2016-12-01").plusYears(1), Tenor("3M")), 1.0.bd))) }
|
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01").plusYears(1), Tenor("3M")), 1.0.bd))) }
|
||||||
|
|
||||||
this `fails with` "relevant fixing must be included"
|
this `fails with` "relevant fixing must be included"
|
||||||
}
|
}
|
||||||
|
|
||||||
tweak {
|
tweak {
|
||||||
// wrong tenor
|
// wrong tenor
|
||||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2016-12-01"), Tenor("9M")), 1.0.bd))) }
|
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("9M")), 1.0.bd))) }
|
||||||
|
|
||||||
this `fails with` "relevant fixing must be included"
|
this `fails with` "relevant fixing must be included"
|
||||||
}
|
}
|
||||||
|
|
||||||
tweak {
|
tweak {
|
||||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2016-12-01"), Tenor("3M")), 1.5.bd))) }
|
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("3M")), 1.5.bd))) }
|
||||||
|
|
||||||
this `fails with` "output state does not reflect fix command"
|
this `fails with` "output state does not reflect fix command"
|
||||||
}
|
}
|
||||||
|
|
||||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2016-12-01"), Tenor("3M")), 1.0.bd))) }
|
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("3M")), 1.0.bd))) }
|
||||||
|
|
||||||
this.verifies()
|
this.verifies()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user