mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Universal: started IRS contract/test, added min/max
This commit is contained in:
parent
ee637b79e2
commit
143c6d2d90
@ -3,6 +3,7 @@ package com.r3corda.contracts.universal
|
||||
import com.r3corda.core.contracts.Amount
|
||||
import com.r3corda.core.contracts.Frequency
|
||||
import com.r3corda.core.crypto.Party
|
||||
import com.r3corda.core.crypto.SecureHash
|
||||
import java.math.BigDecimal
|
||||
import java.time.LocalDate
|
||||
import java.util.*
|
||||
@ -60,4 +61,13 @@ class Continuation() : Arrangement {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other is Continuation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A smart contract template
|
||||
// todo: handle parameters
|
||||
//
|
||||
data class Template(val template: Arrangement)
|
||||
|
||||
data class TemplateApplication(val template: SecureHash, val parameters: Map<String, Any>) : Arrangement
|
||||
|
||||
data class Context(val arrangement: Arrangement, val parameters: Map<String, Any>) : Arrangement
|
||||
|
@ -5,6 +5,7 @@ import com.r3corda.core.contracts.Tenor
|
||||
import java.math.BigDecimal
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.Period
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
@ -30,15 +31,9 @@ data class Const<T>(val value: T) : Perceivable<T> {
|
||||
}
|
||||
if (other is Const<*>) {
|
||||
if (value is BigDecimal && other.value is BigDecimal) {
|
||||
if (this.value.compareTo(other.value) == 0)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
return this.value.compareTo(other.value) == 0
|
||||
}
|
||||
if(value.equals(other.value))
|
||||
return true
|
||||
else
|
||||
return false
|
||||
return value.equals(other.value)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -51,6 +46,12 @@ data class Const<T>(val value: T) : Perceivable<T> {
|
||||
|
||||
fun<T> const(k: T) = Const(k)
|
||||
|
||||
data class Max(val args: Set<Perceivable<BigDecimal>>) : Perceivable<BigDecimal>
|
||||
fun max(vararg args: Perceivable<BigDecimal>) = Max(args.toSet())
|
||||
|
||||
data class Min(val args: Set<Perceivable<BigDecimal>>) : Perceivable<BigDecimal>
|
||||
fun min(vararg args: Perceivable<BigDecimal>) = Min(args.toSet())
|
||||
|
||||
//
|
||||
class StartDate : Perceivable<Instant> {
|
||||
override fun hashCode(): Int {
|
||||
|
@ -45,7 +45,7 @@ open class ContractBuilder {
|
||||
return c
|
||||
}
|
||||
|
||||
fun Set<Party>.may(init: ActionBuilder.() -> Unit): Actions {
|
||||
fun Set<Party>.may(init: ActionBuilder.() -> Unit): Actions {
|
||||
val b = ActionBuilder(this)
|
||||
b.init()
|
||||
val c = Actions(b.actions.toSet())
|
||||
|
@ -26,7 +26,7 @@ class Cap {
|
||||
rollOut("2016-09-01".ld, "2017-04-01".ld, Frequency.Quarterly) {
|
||||
(acmeCorp or highStreetBank).may {
|
||||
"exercise".anytime {
|
||||
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("6M")), start, end)
|
||||
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).plus(), currency)
|
||||
next()
|
||||
@ -51,7 +51,7 @@ class Cap {
|
||||
rollOut("2016-12-01".ld, "2017-04-01".ld, Frequency.Quarterly) {
|
||||
(acmeCorp or highStreetBank).may {
|
||||
"exercise".anytime {
|
||||
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("6M")), start, end)
|
||||
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).plus(), currency)
|
||||
next()
|
||||
@ -70,7 +70,7 @@ class Cap {
|
||||
rollOut("2016-12-01".ld, "2017-04-01".ld, Frequency.Quarterly) {
|
||||
(acmeCorp or highStreetBank).may {
|
||||
"exercise".anytime {
|
||||
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("6M")), start, end)
|
||||
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).plus(), currency)
|
||||
next()
|
||||
@ -90,15 +90,15 @@ class Cap {
|
||||
|
||||
val stateFixed = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contractFixed)
|
||||
|
||||
val contractTARN = arrange {
|
||||
val contractLimitedCap = arrange {
|
||||
rollOut("2016-04-01".ld, "2017-04-01".ld, Frequency.Quarterly, object {
|
||||
val limit = variable(150.K)
|
||||
}) {
|
||||
(acmeCorp or highStreetBank).may {
|
||||
"exercise".anytime {
|
||||
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("6M")), start, end)
|
||||
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("3M")), start, end)
|
||||
val fixed = interest(notional, "act/365", 0.5.bd, start, end)
|
||||
val payout = (floating - fixed).plus()
|
||||
val payout = min(floating - fixed)
|
||||
highStreetBank.gives(acmeCorp, payout, currency)
|
||||
next(vars.limit to vars.limit - payout)
|
||||
}
|
||||
@ -142,39 +142,39 @@ class Cap {
|
||||
output { stateFixed }
|
||||
timestamp(TEST_TX_TIME_1)
|
||||
|
||||
/* tweak {
|
||||
tweak {
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") }
|
||||
this `fails with` "action must be defined"
|
||||
}
|
||||
|
||||
tweak {
|
||||
// wrong source
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBORx", tradeDate, Tenor("6M")), 1.0.bd))) }
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBORx", tradeDate, Tenor("3M")), 1.0.bd))) }
|
||||
|
||||
this `fails with` "relevant fixing must be included"
|
||||
}
|
||||
|
||||
tweak {
|
||||
// wrong date
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", tradeDate.plusYears(1), Tenor("6M")), 1.0.bd))) }
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", tradeDate.plusYears(1), Tenor("3M")), 1.0.bd))) }
|
||||
|
||||
this `fails with` "relevant fixing must be included"
|
||||
}
|
||||
|
||||
tweak {
|
||||
// wrong tenor
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("3M")), 1.0.bd))) }
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("9M")), 1.0.bd))) }
|
||||
|
||||
this `fails with` "relevant fixing must be included"
|
||||
}
|
||||
|
||||
tweak {
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("6M")), 1.5.bd))) }
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("3M")), 1.5.bd))) }
|
||||
|
||||
this `fails with` "output state does not reflect fix command"
|
||||
}*/
|
||||
}
|
||||
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("6M")), 1.0.bd))) }
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", tradeDate, Tenor("3M")), 1.0.bd))) }
|
||||
|
||||
this.verifies()
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
package com.r3corda.contracts.universal
|
||||
|
||||
import com.r3corda.core.contracts.Frequency
|
||||
import com.r3corda.core.contracts.Tenor
|
||||
import com.r3corda.core.utilities.DUMMY_NOTARY
|
||||
import com.r3corda.testing.transaction
|
||||
import org.junit.Test
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
|
||||
/**
|
||||
* Created by sofusmortensen on 12/09/16.
|
||||
*/
|
||||
|
||||
class IRS {
|
||||
|
||||
val TEST_TX_TIME_1: Instant get() = Instant.parse("2017-09-02T12:00:00.00Z")
|
||||
|
||||
val notional = 50.M
|
||||
val currency = EUR
|
||||
|
||||
val tradeDate: LocalDate = LocalDate.of(2016, 9, 1)
|
||||
|
||||
val contract = arrange {
|
||||
rollOut("2016-09-01".ld, "2018-09-01".ld, Frequency.Quarterly) {
|
||||
(acmeCorp or highStreetBank).may {
|
||||
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("3M")), start, end)
|
||||
val fixed = interest(notional, "act/365", 0.5.bd, start, end)
|
||||
|
||||
"pay 1".anytime {
|
||||
highStreetBank.gives(acmeCorp, floating - fixed, currency)
|
||||
next()
|
||||
}
|
||||
"pay 2".anytime {
|
||||
highStreetBank.gives(acmeCorp, fixed - floating, currency)
|
||||
next()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val stateStart = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contract)
|
||||
|
||||
@Test
|
||||
fun issue() {
|
||||
transaction {
|
||||
output { stateStart }
|
||||
timestamp(TEST_TX_TIME_1)
|
||||
|
||||
this `fails with` "transaction has a single command"
|
||||
|
||||
tweak {
|
||||
command(acmeCorp.owningKey) { UniversalContract.Commands.Issue() }
|
||||
this `fails with` "the transaction is signed by all liable parties"
|
||||
}
|
||||
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Issue() }
|
||||
|
||||
this.verifies()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -54,9 +54,9 @@ val european_fx_option = arrange {
|
||||
}
|
||||
}
|
||||
|
||||
val zero_coupon_bond_1 = arrange {
|
||||
val contractZeroCouponBond = arrange {
|
||||
acmeCorp.may {
|
||||
"execute".givenThat(after("2017-09-01")) {
|
||||
"execute".givenThat(after("2017-11-01")) {
|
||||
highStreetBank.gives(acmeCorp, 1.M, USD)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user