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.Sets
|
||||
import com.r3corda.core.contracts.Amount
|
||||
import com.r3corda.core.contracts.Frequency
|
||||
import com.r3corda.core.crypto.Party
|
||||
import java.math.BigDecimal
|
||||
import java.security.PublicKey
|
||||
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``.
|
||||
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 base arrangement representing immediate transfer of Cash - X amount of currency CCY from party A to party B.
|
||||
// A basic arrangement representing immediate transfer of Cash - X amount of currency CCY from party A to party B.
|
||||
// X is an observable of type BigDecimal.
|
||||
//
|
||||
// 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 {
|
||||
constructor(amount: Amount<Currency>, from: Party, to: Party ) : this(const(amount.quantity), amount.token, from, to)
|
||||
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), 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.
|
||||
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
|
||||
|
||||
import com.r3corda.core.contracts.Amount
|
||||
import java.math.BigDecimal
|
||||
import java.text.DateFormat
|
||||
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>
|
||||
|
||||
infix 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))
|
||||
infix fun Perceivable<BigDecimal>.times(n: BigDecimal) = PerceivableOperation(this, Operation.TIMES, const(n))
|
||||
infix fun Perceivable<BigDecimal>.div(n: BigDecimal) = PerceivableOperation(this, Operation.DIV, const(n))
|
||||
operator fun Perceivable<BigDecimal>.plus(n: BigDecimal) = PerceivableOperation(this, Operation.PLUS, 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>.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
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ fun replaceParty(action: Action, from: Party, to: Party) : Action {
|
||||
fun replaceParty(arrangement: Arrangement, from: Party, to: Party) : Arrangement {
|
||||
return when (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.to == from) to else arrangement.to )
|
||||
is Action -> replaceParty(arrangement, from, to)
|
||||
|
@ -1,6 +1,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 java.math.BigDecimal
|
||||
import java.util.*
|
||||
@ -30,10 +31,14 @@ class ContractBuilder {
|
||||
contracts.add( Transfer(amount, this, beneficiary))
|
||||
}
|
||||
|
||||
fun Party.gives(beneficiary: Party, amount: Perceivable<Long>, currency: Currency) {
|
||||
contracts.add( Transfer(amount, currency, this, beneficiary))
|
||||
fun Party.gives(beneficiary: Party, amount: Perceivable<Amount<Currency>>) {
|
||||
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() =
|
||||
when (contracts.size) {
|
||||
0 -> zero
|
||||
@ -89,87 +94,21 @@ infix fun Set<Party>.or(party: Party) = this.plus(party)
|
||||
fun arrange(init: ContractBuilder.() -> Unit ) : Arrangement {
|
||||
val b = ContractBuilder()
|
||||
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
|
||||
|
||||
/*
|
||||
val my_cds_contract =
|
||||
fun final() =
|
||||
RollOut(startDate, endDate, frequency, zero)
|
||||
}
|
||||
|
||||
roadRunner.may {
|
||||
"exercise".givenThat(acmeCorporationHasDefaulted and before("2017-09-01")) {
|
||||
wileECoyote.gives(roadRunner, 1.M*USD)
|
||||
}
|
||||
} 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)
|
||||
}
|
||||
*/
|
||||
fun rollout(startDate: String, endDate: String, frequency: Frequency, init: RolloutBuilder.() -> Unit) : Arrangement {
|
||||
val b = RolloutBuilder(startDate, endDate, frequency)
|
||||
b.init()
|
||||
return b.final()
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.r3corda.contracts.universal
|
||||
|
||||
import com.r3corda.core.contracts.Amount
|
||||
import com.r3corda.core.crypto.Party
|
||||
import com.r3corda.core.crypto.generateKeyPair
|
||||
import org.junit.Test
|
||||
@ -18,8 +19,11 @@ class DummyPerceivable<T> : Perceivable<T>
|
||||
// example:
|
||||
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
|
||||
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.
|
||||
*/
|
||||
|
||||
class ZCB {
|
||||
class ZeroCouponBond {
|
||||
|
||||
val contract =
|
||||
(roadRunner or wileECoyote).may {
|
@ -11,6 +11,7 @@ import java.util.*
|
||||
* Created by sofusmortensen on 23/05/16.
|
||||
*/
|
||||
|
||||
// various example arrangements using basic syntax
|
||||
|
||||
val cds_contract = Action("payout", acmeCorporationHasDefaulted and before("2017-09-01"),
|
||||
roadRunner,
|
||||
|
Loading…
Reference in New Issue
Block a user