mirror of
https://github.com/corda/corda.git
synced 2025-04-24 21:09:50 +00:00
Universal: Fixing and reduction
This commit is contained in:
parent
e11732dad3
commit
2680687dcb
@ -58,4 +58,12 @@ data class RollOut(val startDate: String, val endDate: String, val frequency: Fr
|
|||||||
|
|
||||||
// Continuation of roll out
|
// Continuation of roll out
|
||||||
// May only be used inside template for RollOut
|
// May only be used inside template for RollOut
|
||||||
class Continuation : Arrangement
|
class Continuation() : Arrangement {
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
return other is Continuation
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,11 @@
|
|||||||
package com.r3corda.contracts.universal
|
package com.r3corda.contracts.universal
|
||||||
|
|
||||||
import com.r3corda.core.contracts.Amount
|
import com.r3corda.core.contracts.Amount
|
||||||
|
import com.r3corda.core.contracts.Tenor
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
import java.time.LocalDate
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,10 +69,12 @@ enum class Operation {
|
|||||||
PLUS, MINUS, TIMES, DIV
|
PLUS, MINUS, TIMES, DIV
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class UnaryPlus<T>(val arg: Perceivable<T>) : Perceivable<T>
|
||||||
|
|
||||||
data class PerceivableOperation<T>(val left: Perceivable<T>, val op: Operation, val right: Perceivable<T>) : Perceivable<T>
|
data class PerceivableOperation<T>(val left: Perceivable<T>, val op: Operation, val right: Perceivable<T>) : Perceivable<T>
|
||||||
|
|
||||||
operator fun Perceivable<BigDecimal>.plus(n: BigDecimal) = PerceivableOperation(this, Operation.PLUS, const(n))
|
operator fun Perceivable<BigDecimal>.plus(n: BigDecimal) = PerceivableOperation(this, Operation.PLUS, const(n))
|
||||||
fun Perceivable<BigDecimal>.plus() = PerceivableOperation(this, Operation.PLUS, const(BigDecimal(0))) // todo
|
fun<T> Perceivable<T>.plus() = UnaryPlus(this)
|
||||||
operator fun Perceivable<BigDecimal>.minus(n: BigDecimal) = PerceivableOperation(this, Operation.MINUS, const(n))
|
operator fun Perceivable<BigDecimal>.minus(n: BigDecimal) = PerceivableOperation(this, Operation.MINUS, const(n))
|
||||||
operator fun Perceivable<BigDecimal>.plus(n: Double) = PerceivableOperation(this, Operation.PLUS, const(BigDecimal(n)))
|
operator fun Perceivable<BigDecimal>.plus(n: Double) = PerceivableOperation(this, Operation.PLUS, const(BigDecimal(n)))
|
||||||
operator fun Perceivable<BigDecimal>.minus(n: Double) = PerceivableOperation(this, Operation.MINUS, const(BigDecimal(n)))
|
operator fun Perceivable<BigDecimal>.minus(n: Double) = PerceivableOperation(this, Operation.MINUS, const(BigDecimal(n)))
|
||||||
@ -89,3 +93,35 @@ data class ScaleAmount<T>(val left: Perceivable<BigDecimal>, val right: Perceiva
|
|||||||
|
|
||||||
operator fun Perceivable<BigDecimal>.times(n: Amount<Currency>) = ScaleAmount(this, const(n))
|
operator fun Perceivable<BigDecimal>.times(n: Amount<Currency>) = ScaleAmount(this, const(n))
|
||||||
//PerceivableOperation(this, Operation.TIMES, const(BigDecimal(n)))
|
//PerceivableOperation(this, Operation.TIMES, const(BigDecimal(n)))
|
||||||
|
|
||||||
|
|
||||||
|
class DummyPerceivable<T> : Perceivable<T>
|
||||||
|
|
||||||
|
data class Interest(val amount: Perceivable<Amount<Currency>>, val dayCountConvention: String,
|
||||||
|
val interest: Perceivable<BigDecimal>, val start: String, val end: String) : Perceivable<Amount<Currency>>
|
||||||
|
|
||||||
|
|
||||||
|
// observable of type T
|
||||||
|
// example:
|
||||||
|
val acmeCorporationHasDefaulted = DummyPerceivable<Boolean>()
|
||||||
|
|
||||||
|
|
||||||
|
fun libor(@Suppress("UNUSED_PARAMETER") amount: Amount<Currency>, @Suppress("UNUSED_PARAMETER") start: String, @Suppress("UNUSED_PARAMETER") end: String) : Perceivable<Amount<Currency>> = DummyPerceivable()
|
||||||
|
fun libor(@Suppress("UNUSED_PARAMETER") amount: Amount<Currency>, @Suppress("UNUSED_PARAMETER") start: Perceivable<Instant>, @Suppress("UNUSED_PARAMETER") end: Perceivable<Instant>) : Perceivable<Amount<Currency>> = DummyPerceivable()
|
||||||
|
|
||||||
|
fun interest(@Suppress("UNUSED_PARAMETER") amount: Amount<Currency>, @Suppress("UNUSED_PARAMETER") dayCountConvention: String, @Suppress("UNUSED_PARAMETER") interest: BigDecimal /* todo - appropriate type */,
|
||||||
|
@Suppress("UNUSED_PARAMETER") start: String, @Suppress("UNUSED_PARAMETER") end: String) : Perceivable<Amount<Currency>> = Interest(Const(amount), dayCountConvention, Const(interest), start, end)
|
||||||
|
|
||||||
|
fun interest(@Suppress("UNUSED_PARAMETER") amount: Amount<Currency>, @Suppress("UNUSED_PARAMETER") dayCountConvention: String, @Suppress("UNUSED_PARAMETER") interest: Perceivable<BigDecimal> /* todo - appropriate type */,
|
||||||
|
@Suppress("UNUSED_PARAMETER") start: String, @Suppress("UNUSED_PARAMETER") end: String) : Perceivable<Amount<Currency>> =
|
||||||
|
Interest(Const(amount), dayCountConvention, interest, start, end)
|
||||||
|
|
||||||
|
fun interest(@Suppress("UNUSED_PARAMETER") amount: Amount<Currency>, @Suppress("UNUSED_PARAMETER") dayCountConvention: String, @Suppress("UNUSED_PARAMETER") interest: BigDecimal /* todo - appropriate type */,
|
||||||
|
@Suppress("UNUSED_PARAMETER") start: Perceivable<Instant>, @Suppress("UNUSED_PARAMETER") end: Perceivable<Instant>) : Perceivable<Amount<Currency>> = DummyPerceivable()
|
||||||
|
|
||||||
|
fun interest(@Suppress("UNUSED_PARAMETER") rate: Amount<Currency>, @Suppress("UNUSED_PARAMETER") dayCountConvention: String, @Suppress("UNUSED_PARAMETER") interest: Perceivable<BigDecimal> /* todo - appropriate type */,
|
||||||
|
@Suppress("UNUSED_PARAMETER") start: Perceivable<Instant>, @Suppress("UNUSED_PARAMETER") end: Perceivable<Instant>) : Perceivable<Amount<Currency>> = DummyPerceivable()
|
||||||
|
|
||||||
|
class Fixing(val source: String, val date: LocalDate, val tenor: Tenor) : Perceivable<BigDecimal>
|
||||||
|
|
||||||
|
fun fix(source: String, date: LocalDate, tenor: Tenor): Perceivable<BigDecimal> = Fixing(source, date, tenor)
|
@ -3,8 +3,10 @@ package com.r3corda.contracts.universal
|
|||||||
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
|
||||||
|
import java.math.BigDecimal
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by sofusmortensen on 23/05/16.
|
* Created by sofusmortensen on 23/05/16.
|
||||||
@ -21,6 +23,8 @@ class UniversalContract : Contract {
|
|||||||
|
|
||||||
interface Commands : CommandData {
|
interface Commands : CommandData {
|
||||||
|
|
||||||
|
data class Fix(val fixes: List<com.r3corda.core.contracts.Fix>) : Commands
|
||||||
|
|
||||||
// transition according to business rules defined in contract
|
// transition according to business rules defined in contract
|
||||||
data class Action(val name: String) : Commands
|
data class Action(val name: String) : Commands
|
||||||
|
|
||||||
@ -32,23 +36,60 @@ class UniversalContract : Contract {
|
|||||||
class Issue : TypeOnlyCommandData(), Commands
|
class Issue : TypeOnlyCommandData(), Commands
|
||||||
}
|
}
|
||||||
|
|
||||||
fun eval(tx: TransactionForContract, condition: Perceivable<Instant>) : Instant = when (condition) {
|
fun eval(tx: TransactionForContract, expr: Perceivable<Instant>) : Instant = when (expr) {
|
||||||
is Const<Instant> -> condition.value
|
is Const<Instant> -> expr.value
|
||||||
else -> throw NotImplementedError()
|
else -> throw NotImplementedError()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun eval(tx: TransactionForContract, condition: Perceivable<Boolean>) : Boolean = when (condition) {
|
fun eval(tx: TransactionForContract, expr: Perceivable<Boolean>) : Boolean = when (expr) {
|
||||||
is PerceivableAnd -> eval(tx, condition.left) && eval(tx, condition.right)
|
is PerceivableAnd -> eval(tx, expr.left) && eval(tx, expr.right)
|
||||||
is PerceivableOr -> eval(tx, condition.right) || eval(tx, condition.right)
|
is PerceivableOr -> eval(tx, expr.right) || eval(tx, expr.right)
|
||||||
is Const<Boolean> -> condition.value
|
is Const<Boolean> -> expr.value
|
||||||
is TimePerceivable -> when (condition.cmp) {
|
is TimePerceivable -> when (expr.cmp) {
|
||||||
Comparison.LTE -> tx.timestamp!!.after!! <= eval(tx, condition.instant)
|
Comparison.LTE -> tx.timestamp!!.after!! <= eval(tx, expr.instant)
|
||||||
Comparison.GTE -> tx.timestamp!!.before!! >= eval(tx, condition.instant)
|
Comparison.GTE -> tx.timestamp!!.before!! >= eval(tx, expr.instant)
|
||||||
else -> throw NotImplementedError()
|
else -> throw NotImplementedError()
|
||||||
}
|
}
|
||||||
else -> throw NotImplementedError()
|
else -> throw NotImplementedError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun eval(tx: TransactionForContract, expr: Perceivable<BigDecimal>) : BigDecimal = when (expr) {
|
||||||
|
is Const -> expr.value
|
||||||
|
is Fixing -> {
|
||||||
|
requireThat { "Fixing must be included" by false }
|
||||||
|
BigDecimal(0.0)
|
||||||
|
}
|
||||||
|
else -> throw Error("fook")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun eval(tx: TransactionForContract, expr: Perceivable<Amount<Currency>>) : Perceivable<Amount<Currency>> = when (expr) {
|
||||||
|
is PerceivableOperation -> when (expr.op) {
|
||||||
|
Operation.DIV -> throw NotImplementedError()
|
||||||
|
Operation.MINUS -> {
|
||||||
|
eval(tx, expr.left)
|
||||||
|
eval(tx, expr.right)
|
||||||
|
throw NotImplementedError()
|
||||||
|
}
|
||||||
|
Operation.PLUS -> throw NotImplementedError()
|
||||||
|
Operation.TIMES -> throw NotImplementedError()
|
||||||
|
}
|
||||||
|
is UnaryPlus -> {
|
||||||
|
eval(tx, expr.arg)
|
||||||
|
expr
|
||||||
|
}
|
||||||
|
is Interest -> {
|
||||||
|
eval(tx, expr.interest)
|
||||||
|
expr
|
||||||
|
}
|
||||||
|
else -> expr
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkAndReduce(tx: TransactionForContract, arrangement: Arrangement) : Arrangement = when (arrangement)
|
||||||
|
{
|
||||||
|
is Transfer -> Transfer( eval(tx, arrangement.amount), arrangement.from, arrangement.to )
|
||||||
|
is And -> And( arrangement.arrangements.map { checkAndReduce(tx, it) }.toSet() )
|
||||||
|
else -> arrangement
|
||||||
|
}
|
||||||
|
|
||||||
override fun verify(tx: TransactionForContract) {
|
override fun verify(tx: TransactionForContract) {
|
||||||
|
|
||||||
@ -73,11 +114,13 @@ class UniversalContract : Contract {
|
|||||||
"condition must be met" by ( eval(tx, action.condition) )
|
"condition must be met" by ( eval(tx, action.condition) )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val arrangement = checkAndReduce(tx, action.arrangement)
|
||||||
|
|
||||||
when (tx.outputs.size) {
|
when (tx.outputs.size) {
|
||||||
1 -> {
|
1 -> {
|
||||||
val outState = tx.outputs.single() as State
|
val outState = tx.outputs.single() as State
|
||||||
requireThat {
|
requireThat {
|
||||||
"output state must match action result state" by (action.arrangement.equals(outState.details))
|
"output state must match action result state" by (arrangement.equals(outState.details))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0 -> throw IllegalArgumentException("must have at least one out state")
|
0 -> throw IllegalArgumentException("must have at least one out state")
|
||||||
@ -86,7 +129,7 @@ class UniversalContract : Contract {
|
|||||||
var allContracts = And( tx.outputs.map { (it as State).details }.toSet() )
|
var allContracts = And( tx.outputs.map { (it as State).details }.toSet() )
|
||||||
|
|
||||||
requireThat {
|
requireThat {
|
||||||
"output states must match action result state" by (action.arrangement.equals(allContracts))
|
"output states must match action result state" by (arrangement.equals(allContracts))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -109,10 +152,56 @@ class UniversalContract : Contract {
|
|||||||
(replaceParty(inState.details, value.from, value.to).equals(outState.details))
|
(replaceParty(inState.details, value.from, value.to).equals(outState.details))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
is Commands.Fix -> {
|
||||||
|
val inState = tx.inputs.single() as State
|
||||||
|
val outState = tx.outputs.single() as State
|
||||||
|
|
||||||
|
val unusedFixes = value.fixes.map { it.of }.toMutableSet()
|
||||||
|
val arr = replaceFixing(tx, inState.details,
|
||||||
|
value.fixes.associateBy({ it.of }, { it.value }), unusedFixes)
|
||||||
|
|
||||||
|
requireThat {
|
||||||
|
"relevant fixing must be included" by unusedFixes.isEmpty()
|
||||||
|
"output state does not reflect fix command" by
|
||||||
|
(arr.equals(outState.details))
|
||||||
|
}
|
||||||
|
}
|
||||||
else -> throw IllegalArgumentException("Unrecognised command")
|
else -> throw IllegalArgumentException("Unrecognised command")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> replaceFixing(tx: TransactionForContract, perceivable: Perceivable<T>,
|
||||||
|
fixings: Map<FixOf, BigDecimal>, unusedFixings: MutableSet<FixOf>): Perceivable<T> =
|
||||||
|
when (perceivable) {
|
||||||
|
is Const -> perceivable
|
||||||
|
is UnaryPlus -> UnaryPlus(replaceFixing(tx, perceivable.arg, fixings, unusedFixings))
|
||||||
|
is PerceivableOperation -> PerceivableOperation(replaceFixing(tx, perceivable.left, fixings, unusedFixings),
|
||||||
|
perceivable.op, replaceFixing(tx, perceivable.right, fixings, unusedFixings))
|
||||||
|
is Interest -> Interest( replaceFixing(tx, perceivable.amount, fixings, unusedFixings),
|
||||||
|
perceivable.dayCountConvention, replaceFixing(tx, perceivable.interest, fixings, unusedFixings),
|
||||||
|
perceivable.start, perceivable.end) as Perceivable<T>
|
||||||
|
is Fixing -> if (fixings.containsKey(FixOf(perceivable.source, perceivable.date, perceivable.tenor))) {
|
||||||
|
unusedFixings.remove(FixOf(perceivable.source, perceivable.date, perceivable.tenor))
|
||||||
|
Const(fixings[FixOf(perceivable.source, perceivable.date, perceivable.tenor)]!!) as Perceivable<T>
|
||||||
|
}
|
||||||
|
else perceivable
|
||||||
|
else -> throw NotImplementedError(perceivable.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun replaceFixing(tx: TransactionForContract, arr: Action,
|
||||||
|
fixings: Map<FixOf, BigDecimal>, unusedFixings: MutableSet<FixOf>) =
|
||||||
|
Action(arr.name, replaceFixing(tx, arr.condition, fixings, unusedFixings),
|
||||||
|
arr.actors, replaceFixing(tx, arr.arrangement, fixings, unusedFixings))
|
||||||
|
|
||||||
|
fun replaceFixing(tx: TransactionForContract, arr: Arrangement,
|
||||||
|
fixings: Map<FixOf, BigDecimal>, unusedFixings: MutableSet<FixOf>) : Arrangement =
|
||||||
|
when (arr) {
|
||||||
|
is Zero -> arr
|
||||||
|
is Transfer -> Transfer(replaceFixing(tx, arr.amount, fixings, unusedFixings), arr.from, arr.to)
|
||||||
|
is Or -> Or( arr.actions.map { replaceFixing(tx, it, fixings, unusedFixings) }.toSet() )
|
||||||
|
else -> throw NotImplementedError( arr.toString() )
|
||||||
|
}
|
||||||
|
|
||||||
override val legalContractReference: SecureHash
|
override val legalContractReference: SecureHash
|
||||||
get() = throw UnsupportedOperationException()
|
get() = throw UnsupportedOperationException()
|
||||||
|
|
||||||
|
@ -0,0 +1,128 @@
|
|||||||
|
package com.r3corda.contracts.universal
|
||||||
|
|
||||||
|
import com.r3corda.core.contracts.Fix
|
||||||
|
import com.r3corda.core.contracts.FixOf
|
||||||
|
import com.r3corda.core.contracts.Tenor
|
||||||
|
import com.r3corda.core.testing.DUMMY_NOTARY
|
||||||
|
import com.r3corda.core.testing.transaction
|
||||||
|
import org.junit.Test
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import java.time.Instant
|
||||||
|
import java.time.LocalDate
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by sofusmortensen on 25/08/16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Caplet {
|
||||||
|
|
||||||
|
val TEST_TX_TIME_1: Instant get() = Instant.parse("2017-09-02T12:00:00.00Z")
|
||||||
|
|
||||||
|
val dt = LocalDate.of(2016, 9, 1)
|
||||||
|
|
||||||
|
val fx = Fix(FixOf("LIBOR", dt, Tenor("6M")), BigDecimal.valueOf(0.31207))
|
||||||
|
|
||||||
|
val notional = 50.M*EUR
|
||||||
|
|
||||||
|
val contract =
|
||||||
|
(roadRunner or wileECoyote).may {
|
||||||
|
"exercise".anytime() {
|
||||||
|
val floating = interest(notional, "act/365", fix("LIBOR", dt, Tenor("6M")), "2016-04-01", "2016-10-01" )
|
||||||
|
val fixed = interest(notional, "act/365", BigDecimal.valueOf(1.0), "2016-04-01", "2016-10-01")
|
||||||
|
wileECoyote.gives(roadRunner, (floating - fixed).plus() )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val contractFixed =
|
||||||
|
(roadRunner or wileECoyote).may {
|
||||||
|
"exercise".anytime() {
|
||||||
|
val floating = interest(notional, "act/365", BigDecimal.valueOf(.01), "2016-04-01", "2016-10-01" )
|
||||||
|
val fixed = interest(notional, "act/365", BigDecimal.valueOf(1.0), "2016-04-01", "2016-10-01")
|
||||||
|
wileECoyote.gives(roadRunner, (floating - fixed).plus() )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val inState = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contract)
|
||||||
|
|
||||||
|
val outStateFixed = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contractFixed)
|
||||||
|
|
||||||
|
val transfer = arrange { wileECoyote.gives(roadRunner, 100.K*EUR )}
|
||||||
|
val outState = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transfer )
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun issue() {
|
||||||
|
transaction {
|
||||||
|
output { inState }
|
||||||
|
timestamp(TEST_TX_TIME_1)
|
||||||
|
|
||||||
|
this `fails with` "transaction has a single command"
|
||||||
|
|
||||||
|
tweak {
|
||||||
|
command(roadRunner.owningKey) { UniversalContract.Commands.Issue() }
|
||||||
|
this `fails with` "the transaction is signed by all liable parties"
|
||||||
|
}
|
||||||
|
|
||||||
|
command(wileECoyote.owningKey) { UniversalContract.Commands.Issue() }
|
||||||
|
|
||||||
|
this.verifies()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `execute - missing fixing `() {
|
||||||
|
transaction {
|
||||||
|
input { inState }
|
||||||
|
output { outState }
|
||||||
|
timestamp(TEST_TX_TIME_1)
|
||||||
|
|
||||||
|
tweak {
|
||||||
|
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("some undefined name") }
|
||||||
|
this `fails with` "action must be defined"
|
||||||
|
}
|
||||||
|
|
||||||
|
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("exercise") }
|
||||||
|
|
||||||
|
this `fails with` "fixing must be included"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `fixing`() {
|
||||||
|
transaction {
|
||||||
|
input { inState }
|
||||||
|
output { outStateFixed }
|
||||||
|
timestamp(TEST_TX_TIME_1)
|
||||||
|
|
||||||
|
tweak {
|
||||||
|
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("some undefined name") }
|
||||||
|
this `fails with` "action must be defined"
|
||||||
|
}
|
||||||
|
|
||||||
|
tweak {
|
||||||
|
// wrong source
|
||||||
|
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBORx", dt, Tenor("6M")), BigDecimal.valueOf(.01)))) }
|
||||||
|
|
||||||
|
this `fails with` "relevant fixing must be included"
|
||||||
|
}
|
||||||
|
|
||||||
|
tweak {
|
||||||
|
// wrong date
|
||||||
|
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt.plusYears(1), Tenor("6M")), BigDecimal.valueOf(.01)))) }
|
||||||
|
|
||||||
|
this `fails with` "relevant fixing must be included"
|
||||||
|
}
|
||||||
|
|
||||||
|
tweak {
|
||||||
|
// wrong tenor
|
||||||
|
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt, Tenor("3M")), BigDecimal.valueOf(.01)))) }
|
||||||
|
|
||||||
|
this `fails with` "relevant fixing must be included"
|
||||||
|
}
|
||||||
|
|
||||||
|
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt, Tenor("6M")), BigDecimal.valueOf(.01)))) }
|
||||||
|
|
||||||
|
this.verifies()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,34 +1,19 @@
|
|||||||
package com.r3corda.contracts.universal
|
package com.r3corda.contracts.universal
|
||||||
|
|
||||||
import com.r3corda.core.contracts.Amount
|
import com.r3corda.core.contracts.Amount
|
||||||
|
import com.r3corda.core.contracts.Tenor
|
||||||
import com.r3corda.core.crypto.Party
|
import com.r3corda.core.crypto.Party
|
||||||
import com.r3corda.core.crypto.generateKeyPair
|
import com.r3corda.core.crypto.generateKeyPair
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
import java.time.LocalDate
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by sofusmortensen on 08/06/16.
|
* Created by sofusmortensen on 08/06/16.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
class DummyPerceivable<T> : Perceivable<T>
|
|
||||||
|
|
||||||
|
|
||||||
// observable of type T
|
|
||||||
// example:
|
|
||||||
val acmeCorporationHasDefaulted = DummyPerceivable<Boolean>()
|
|
||||||
|
|
||||||
|
|
||||||
fun libor(@Suppress("UNUSED_PARAMETER") amount: Amount<Currency>, @Suppress("UNUSED_PARAMETER") start: String, @Suppress("UNUSED_PARAMETER") end: String) : Perceivable<Amount<Currency>> = DummyPerceivable()
|
|
||||||
fun libor(@Suppress("UNUSED_PARAMETER") amount: Amount<Currency>, @Suppress("UNUSED_PARAMETER") start: Perceivable<Instant>, @Suppress("UNUSED_PARAMETER") end: Perceivable<Instant>) : Perceivable<Amount<Currency>> = DummyPerceivable()
|
|
||||||
|
|
||||||
fun interest(@Suppress("UNUSED_PARAMETER") rate: Amount<Currency>, @Suppress("UNUSED_PARAMETER") dayCountConvention: String, @Suppress("UNUSED_PARAMETER") interest: Double /* todo - appropriate type */,
|
|
||||||
@Suppress("UNUSED_PARAMETER") start: String, @Suppress("UNUSED_PARAMETER") end: String) : Perceivable<Amount<Currency>> = DummyPerceivable()
|
|
||||||
fun interest(@Suppress("UNUSED_PARAMETER") rate: Amount<Currency>, @Suppress("UNUSED_PARAMETER") dayCountConvention: String, @Suppress("UNUSED_PARAMETER") interest: Double /* todo - appropriate type */,
|
|
||||||
@Suppress("UNUSED_PARAMETER") start: Perceivable<Instant>, @Suppress("UNUSED_PARAMETER") end: Perceivable<Instant>) : Perceivable<Amount<Currency>> = DummyPerceivable()
|
|
||||||
|
|
||||||
// Test parties
|
// Test parties
|
||||||
val roadRunner = Party("Road Runner", generateKeyPair().public)
|
val roadRunner = Party("Road Runner", generateKeyPair().public)
|
||||||
val wileECoyote = Party("Wile E. Coyote", generateKeyPair().public)
|
val wileECoyote = Party("Wile E. Coyote", generateKeyPair().public)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package com.r3corda.contracts.universal
|
package com.r3corda.contracts.universal
|
||||||
|
|
||||||
import com.r3corda.core.testing.DUMMY_NOTARY
|
import com.r3corda.core.testing.DUMMY_NOTARY
|
||||||
import com.r3corda.core.testing.DUMMY_NOTARY_KEY
|
|
||||||
import com.r3corda.core.testing.TEST_TX_TIME
|
|
||||||
import com.r3corda.core.testing.transaction
|
import com.r3corda.core.testing.transaction
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
@ -14,7 +14,7 @@ import java.math.BigDecimal
|
|||||||
class Swaption {
|
class Swaption {
|
||||||
|
|
||||||
val notional = 10.M * USD
|
val notional = 10.M * USD
|
||||||
val coupon = 1.5
|
val coupon = BigDecimal.valueOf(1.5)
|
||||||
|
|
||||||
val dreary_contract =
|
val dreary_contract =
|
||||||
(wileECoyote or roadRunner).may {
|
(wileECoyote or roadRunner).may {
|
||||||
@ -101,5 +101,4 @@ class Swaption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user