mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
cleanup, testing rollout syntax
This commit is contained in:
parent
757bddb9f9
commit
f0fc8f414f
@ -3,7 +3,9 @@ package com.r3corda.contracts.universal
|
|||||||
import com.google.common.collect.ImmutableSet
|
import com.google.common.collect.ImmutableSet
|
||||||
import com.google.common.collect.Sets
|
import com.google.common.collect.Sets
|
||||||
import com.r3corda.core.contracts.Amount
|
import com.r3corda.core.contracts.Amount
|
||||||
|
import com.r3corda.core.contracts.Frequency
|
||||||
import com.r3corda.core.crypto.Party
|
import com.r3corda.core.crypto.Party
|
||||||
|
import java.math.BigDecimal
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -15,15 +17,21 @@ interface Arrangement
|
|||||||
|
|
||||||
|
|
||||||
// A base arrangement with no rights and no obligations. Contract cancellation/termination is a transition to ``Zero``.
|
// A base arrangement with no rights and no obligations. Contract cancellation/termination is a transition to ``Zero``.
|
||||||
data class Zero(val dummy: Int = 0) : Arrangement
|
class Zero() : Arrangement {
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
return other is Zero
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A basic arrangement representing immediate transfer of Cash - X amount of currency CCY from party A to party B.
|
||||||
// A base arrangement representing immediate transfer of Cash - X amount of currency CCY from party A to party B.
|
|
||||||
// X is an observable of type BigDecimal.
|
// X is an observable of type BigDecimal.
|
||||||
//
|
//
|
||||||
// todo: should be replaced with something that uses Corda assets and/or cash?
|
// todo: should be replaced with something that uses Corda assets and/or cash?
|
||||||
data class Transfer(val amount: Perceivable<Long>, val currency: Currency, val from: Party, val to: Party) : Arrangement {
|
data class Transfer(val amount: Perceivable<Amount<Currency>>, val from: Party, val to: Party) : Arrangement {
|
||||||
constructor(amount: Amount<Currency>, from: Party, to: Party ) : this(const(amount.quantity), amount.token, from, to)
|
constructor(amount: Amount<Currency>, from: Party, to: Party ) : this(const(amount), from, to)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -42,3 +50,6 @@ data class Action(val name: String, val condition: Perceivable<Boolean>,
|
|||||||
|
|
||||||
// only actions can be or'ed togetherA combinator that can only be used on action arrangements. This means only one of the action can be executed. Should any one action be executed, all other actions are discarded.
|
// only actions can be or'ed togetherA combinator that can only be used on action arrangements. This means only one of the action can be executed. Should any one action be executed, all other actions are discarded.
|
||||||
data class Or(val actions: Set<Action>) : Arrangement
|
data class Or(val actions: Set<Action>) : Arrangement
|
||||||
|
|
||||||
|
|
||||||
|
data class RollOut(val startDate: String, val endDate: String, val frequency: Frequency, val arrangement: Arrangement) : Arrangement
|
@ -1,5 +1,6 @@
|
|||||||
package com.r3corda.contracts.universal
|
package com.r3corda.contracts.universal
|
||||||
|
|
||||||
|
import com.r3corda.core.contracts.Amount
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@ -62,7 +63,16 @@ enum class Operation {
|
|||||||
|
|
||||||
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>
|
||||||
|
|
||||||
infix 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))
|
||||||
infix 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))
|
||||||
infix fun Perceivable<BigDecimal>.times(n: BigDecimal) = PerceivableOperation(this, Operation.TIMES, const(n))
|
operator fun Perceivable<BigDecimal>.plus(n: Double) = PerceivableOperation(this, Operation.PLUS, const(BigDecimal(n)))
|
||||||
infix fun Perceivable<BigDecimal>.div(n: BigDecimal) = PerceivableOperation(this, Operation.DIV, const(n))
|
operator fun Perceivable<BigDecimal>.minus(n: Double) = PerceivableOperation(this, Operation.MINUS, const(BigDecimal(n)))
|
||||||
|
operator fun Perceivable<BigDecimal>.times(n: BigDecimal) = PerceivableOperation(this, Operation.TIMES, const(n))
|
||||||
|
operator fun Perceivable<BigDecimal>.div(n: BigDecimal) = PerceivableOperation(this, Operation.DIV, const(n))
|
||||||
|
operator fun Perceivable<BigDecimal>.times(n: Double) = PerceivableOperation(this, Operation.TIMES, const(BigDecimal(n)))
|
||||||
|
operator fun Perceivable<BigDecimal>.div(n: Double) = PerceivableOperation(this, Operation.DIV, const(BigDecimal(n)))
|
||||||
|
|
||||||
|
data class ScaleAmount<T>(val left: Perceivable<BigDecimal>, val right: Perceivable<Amount<T>>) : Perceivable<Amount<T>>
|
||||||
|
|
||||||
|
operator fun Perceivable<BigDecimal>.times(n: Amount<Currency>) = ScaleAmount(this, const(n))
|
||||||
|
//PerceivableOperation(this, Operation.TIMES, const(BigDecimal(n)))
|
||||||
|
@ -27,7 +27,7 @@ class UniversalContract : Contract {
|
|||||||
// must be signed by all parties present in contract before and after command
|
// must be signed by all parties present in contract before and after command
|
||||||
class Move(val from: Party, val to: Party) : TypeOnlyCommandData(), Commands
|
class Move(val from: Party, val to: Party) : TypeOnlyCommandData(), Commands
|
||||||
|
|
||||||
// must be signed by all parties present in contract
|
// must be signed by all liable parties present in contract
|
||||||
class Issue : TypeOnlyCommandData(), Commands
|
class Issue : TypeOnlyCommandData(), Commands
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ fun replaceParty(action: Action, from: Party, to: Party) : Action {
|
|||||||
fun replaceParty(arrangement: Arrangement, from: Party, to: Party) : Arrangement {
|
fun replaceParty(arrangement: Arrangement, from: Party, to: Party) : Arrangement {
|
||||||
return when (arrangement) {
|
return when (arrangement) {
|
||||||
is Zero -> arrangement
|
is Zero -> arrangement
|
||||||
is Transfer -> Transfer( arrangement.amount, arrangement.currency,
|
is Transfer -> Transfer( arrangement.amount,
|
||||||
if (arrangement.from == from) to else arrangement.from,
|
if (arrangement.from == from) to else arrangement.from,
|
||||||
if (arrangement.to == from) to else arrangement.to )
|
if (arrangement.to == from) to else arrangement.to )
|
||||||
is Action -> replaceParty(arrangement, from, to)
|
is Action -> replaceParty(arrangement, from, to)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
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.Frequency
|
||||||
import com.r3corda.core.crypto.Party
|
import com.r3corda.core.crypto.Party
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -30,10 +31,14 @@ class ContractBuilder {
|
|||||||
contracts.add( Transfer(amount, this, beneficiary))
|
contracts.add( Transfer(amount, this, beneficiary))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Party.gives(beneficiary: Party, amount: Perceivable<Long>, currency: Currency) {
|
fun Party.gives(beneficiary: Party, amount: Perceivable<Amount<Currency>>) {
|
||||||
contracts.add( Transfer(amount, currency, this, beneficiary))
|
contracts.add( Transfer(amount, this, beneficiary))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fun Party.gives(beneficiary: Party, amount: Perceivable<Long>, currency: Currency) {
|
||||||
|
contracts.add( Transfer(amount, currency, this, beneficiary))
|
||||||
|
}*/
|
||||||
|
|
||||||
fun final() =
|
fun final() =
|
||||||
when (contracts.size) {
|
when (contracts.size) {
|
||||||
0 -> zero
|
0 -> zero
|
||||||
@ -89,87 +94,21 @@ infix fun Set<Party>.or(party: Party) = this.plus(party)
|
|||||||
fun arrange(init: ContractBuilder.() -> Unit ) : Arrangement {
|
fun arrange(init: ContractBuilder.() -> Unit ) : Arrangement {
|
||||||
val b = ContractBuilder()
|
val b = ContractBuilder()
|
||||||
b.init()
|
b.init()
|
||||||
return b.final();
|
return b.final()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RolloutBuilder(val startDate: String, val endDate: String, val frequency: Frequency) {
|
||||||
|
|
||||||
|
val start = "start date"
|
||||||
|
val end = "end date"
|
||||||
|
fun recurse() = zero
|
||||||
|
|
||||||
/*
|
fun final() =
|
||||||
val my_cds_contract =
|
RollOut(startDate, endDate, frequency, zero)
|
||||||
|
}
|
||||||
|
|
||||||
roadRunner.may {
|
fun rollout(startDate: String, endDate: String, frequency: Frequency, init: RolloutBuilder.() -> Unit) : Arrangement {
|
||||||
"exercise".givenThat(acmeCorporationHasDefaulted and before("2017-09-01")) {
|
val b = RolloutBuilder(startDate, endDate, frequency)
|
||||||
wileECoyote.gives(roadRunner, 1.M*USD)
|
b.init()
|
||||||
}
|
return b.final()
|
||||||
} or (roadRunner or wileECoyote).may {
|
}
|
||||||
"expire".givenThat(after("2017-09-01")) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
val my_fx_swap =
|
|
||||||
|
|
||||||
(roadRunner or wileECoyote).may {
|
|
||||||
"execute".givenThat(after("2017-09-01")) {
|
|
||||||
wileECoyote.gives(roadRunner, 1200.K*USD)
|
|
||||||
roadRunner.gives(wileECoyote, 1.M*EUR)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val my_fx_option =
|
|
||||||
|
|
||||||
roadRunner.may {
|
|
||||||
"exercise".anytime {
|
|
||||||
(roadRunner or wileECoyote).may {
|
|
||||||
"execute".givenThat(after("2017-09-01")) {
|
|
||||||
wileECoyote.gives(roadRunner, 1200.K*USD)
|
|
||||||
roadRunner.gives(wileECoyote, 1.M*EUR)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} or wileECoyote.may {
|
|
||||||
"expire".givenThat(after("2017-09-01")) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
val my_fx_knock_out_barrier_option =
|
|
||||||
|
|
||||||
roadRunner.may {
|
|
||||||
"exercise".anytime {
|
|
||||||
(roadRunner or wileECoyote).may {
|
|
||||||
"execute".givenThat(after("2017-09-01")) {
|
|
||||||
wileECoyote.gives(roadRunner, 1200.K*USD)
|
|
||||||
roadRunner.gives(wileECoyote, 1.M*EUR)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} or wileECoyote.may {
|
|
||||||
"expire".givenThat(after("2017-09-01")) {}
|
|
||||||
"knock out".givenThat( EUR / USD gt 1.3 ) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
val my_fx_knock_in_barrier_option =
|
|
||||||
|
|
||||||
roadRunner.may {
|
|
||||||
"knock in".givenThat(EUR / USD gt 1.3) {
|
|
||||||
roadRunner.may {
|
|
||||||
"exercise".anytime {
|
|
||||||
(roadRunner or wileECoyote).may {
|
|
||||||
"execute".givenThat(after("2017-09-01")) {
|
|
||||||
wileECoyote.gives(roadRunner, 1200.K*USD)
|
|
||||||
roadRunner.gives(wileECoyote, 1.M*EUR)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} or wileECoyote.may {
|
|
||||||
"expire".givenThat(after("2017-09-01")) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} or wileECoyote.may {
|
|
||||||
"expire".givenThat(after("2017-09-01")) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
////
|
|
||||||
|
|
||||||
fun fwd(partyA: Party, partyB: Party, maturity: String, contract: Kontract) =
|
|
||||||
(partyA or partyB).may {
|
|
||||||
"execute".givenThat(after(maturity)).resolve(contract)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.r3corda.contracts.universal
|
package com.r3corda.contracts.universal
|
||||||
|
|
||||||
|
import com.r3corda.core.contracts.Amount
|
||||||
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
|
||||||
@ -18,8 +19,11 @@ class DummyPerceivable<T> : Perceivable<T>
|
|||||||
// example:
|
// example:
|
||||||
val acmeCorporationHasDefaulted = DummyPerceivable<Boolean>()
|
val acmeCorporationHasDefaulted = DummyPerceivable<Boolean>()
|
||||||
|
|
||||||
// example:
|
|
||||||
val euribor3M = DummyPerceivable<BigDecimal>()
|
fun libor(amount: Amount<Currency>, start: String, end: String) : Perceivable<Amount<Currency>> = DummyPerceivable()
|
||||||
|
|
||||||
|
fun interest(rate: Amount<Currency>, dayCountConvention: String, interest: Double /* todo - appropriate type */,
|
||||||
|
start: String, end: String) : Perceivable<Amount<Currency>> = DummyPerceivable()
|
||||||
|
|
||||||
// Test parties
|
// Test parties
|
||||||
val roadRunner = Party("Road Runner", generateKeyPair().public)
|
val roadRunner = Party("Road Runner", generateKeyPair().public)
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
package com.r3corda.contracts.universal
|
||||||
|
|
||||||
|
import com.r3corda.core.contracts.Frequency
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by sofusmortensen on 28/06/16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Swaption
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Swaption {
|
||||||
|
|
||||||
|
val notional = 10.M * USD
|
||||||
|
val coupon = 1.5
|
||||||
|
|
||||||
|
val contract =
|
||||||
|
(wileECoyote or roadRunner).may {
|
||||||
|
"proceed".givenThat(after("01/07/2015")) {
|
||||||
|
wileECoyote.gives(roadRunner, libor( notional, "01/04/2015", "01/07/2015" ) )
|
||||||
|
roadRunner.gives(wileECoyote, interest( notional, "act/365", coupon, "01/04/2015", "01/07/2015" ) )
|
||||||
|
(wileECoyote or roadRunner).may {
|
||||||
|
"proceed".givenThat(after("01/10/2015")) {
|
||||||
|
wileECoyote.gives(roadRunner, libor( notional, "01/07/2015", "01/10/2015" ) )
|
||||||
|
roadRunner.gives(wileECoyote, interest( notional, "act/365", coupon, "01/07/2015", "01/10/2015" ) )
|
||||||
|
|
||||||
|
(wileECoyote or roadRunner).may {
|
||||||
|
// etc ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} or roadRunner.may {
|
||||||
|
"cancel".anytime {
|
||||||
|
roadRunner.gives( wileECoyote, 10.K * USD )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} or roadRunner.may {
|
||||||
|
"cancel".anytime {
|
||||||
|
roadRunner.gives( wileECoyote, 10.K * USD )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val contract2 = rollout( "01/04/2015", "01/04/2025", Frequency.Quarterly ) {
|
||||||
|
(wileECoyote or roadRunner).may {
|
||||||
|
"proceed".givenThat(after(start)) {
|
||||||
|
wileECoyote.gives(roadRunner, libor( notional, start, end ) )
|
||||||
|
roadRunner.gives(wileECoyote, interest( notional, "act/365", coupon, start, end ) )
|
||||||
|
recurse()
|
||||||
|
}
|
||||||
|
} or roadRunner.may {
|
||||||
|
"cancel".anytime {
|
||||||
|
roadRunner.gives( wileECoyote, 10.K * USD )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val strike = 1.2
|
||||||
|
val tarf = rollout( "01/04/2015", "01/04/2016", Frequency.Quarterly ) {
|
||||||
|
roadRunner.may {
|
||||||
|
"exercise".givenThat(before(start)) {
|
||||||
|
wileECoyote.gives(roadRunner, (EUR / USD - strike) * notional )
|
||||||
|
recurse()
|
||||||
|
}
|
||||||
|
} or (roadRunner or wileECoyote).may {
|
||||||
|
"proceed".givenThat(after(start)) {
|
||||||
|
recurse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -8,7 +8,7 @@ import org.junit.Test
|
|||||||
* Created by sofusmortensen on 01/06/16.
|
* Created by sofusmortensen on 01/06/16.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ZCB {
|
class ZeroCouponBond {
|
||||||
|
|
||||||
val contract =
|
val contract =
|
||||||
(roadRunner or wileECoyote).may {
|
(roadRunner or wileECoyote).may {
|
@ -11,6 +11,7 @@ import java.util.*
|
|||||||
* Created by sofusmortensen on 23/05/16.
|
* Created by sofusmortensen on 23/05/16.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// various example arrangements using basic syntax
|
||||||
|
|
||||||
val cds_contract = Action("payout", acmeCorporationHasDefaulted and before("2017-09-01"),
|
val cds_contract = Action("payout", acmeCorporationHasDefaulted and before("2017-09-01"),
|
||||||
roadRunner,
|
roadRunner,
|
||||||
|
Loading…
Reference in New Issue
Block a user