mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Universal: refactoring
This commit is contained in:
parent
7f08c80470
commit
1ceee48696
@ -27,6 +27,7 @@ class Zero() : Arrangement {
|
||||
// X is an observable of type BigDecimal.
|
||||
//
|
||||
// todo: should be replaced with something that uses Corda assets and/or cash?
|
||||
// todo: should only be allowed to transfer non-negative amounts
|
||||
data class Transfer(val amount: Perceivable<BigDecimal>, val currency: Currency, val from: Party, val to: Party) : Arrangement {
|
||||
constructor(amount: BigDecimal, currency: Currency, from: Party, to: Party ) : this(const(amount), currency, from, to)
|
||||
constructor(amount: Amount<Currency>, from: Party, to: Party ) : this(const(BigDecimal(amount.quantity)), amount.token, from, to)
|
||||
@ -42,7 +43,9 @@ data class And(val arrangements: Set<Arrangement>) : Arrangement
|
||||
// _condition_ is met. If the action is performed the arrangement state transitions into the specified arrangement.
|
||||
data class Action(val name: String, val condition: Perceivable<Boolean>,
|
||||
val actors: Set<Party>, val arrangement: Arrangement) : Arrangement {
|
||||
constructor(name: String, condition: Perceivable<Boolean>, actor: Party, arrangement: Arrangement) : this(name, condition, setOf(actor), arrangement)
|
||||
constructor(name: String, condition: Perceivable<Boolean>,
|
||||
actor: Party, arrangement: Arrangement)
|
||||
: this(name, condition, setOf(actor), arrangement)
|
||||
}
|
||||
|
||||
|
||||
|
@ -44,7 +44,7 @@ class EndDate : Perceivable<Instant>
|
||||
*/
|
||||
data class TimePerceivable(val cmp: Comparison, val instant: Perceivable<Instant>) : Perceivable<Boolean>
|
||||
|
||||
fun parseDate(str: String) = Instant.parse(str+"T00:00:00Z")
|
||||
fun parseDate(str: String) = Instant.parse(str+"T00:00:00Z")!!
|
||||
|
||||
fun before(expiry: Perceivable<Instant>) = TimePerceivable(Comparison.LTE, expiry)
|
||||
fun after(expiry: Perceivable<Instant>) = TimePerceivable(Comparison.GTE, expiry)
|
||||
@ -102,22 +102,17 @@ class DummyPerceivable<T> : Perceivable<T>
|
||||
|
||||
// todo: holidays
|
||||
data class Interest(val amount: Perceivable<BigDecimal>, val dayCountConvention: String,
|
||||
val interest: Perceivable<BigDecimal>, val start: String, val end: String) : Perceivable<BigDecimal>
|
||||
|
||||
// observable of type T
|
||||
// example:
|
||||
val acmeCorporationHasDefaulted = DummyPerceivable<Boolean>()
|
||||
|
||||
val interest: Perceivable<BigDecimal>, val start: LocalDate, val end: LocalDate) : Perceivable<BigDecimal>
|
||||
|
||||
fun libor(@Suppress("UNUSED_PARAMETER") amount: BigDecimal, @Suppress("UNUSED_PARAMETER") start: String, @Suppress("UNUSED_PARAMETER") end: String) : Perceivable<BigDecimal> = DummyPerceivable()
|
||||
fun libor(@Suppress("UNUSED_PARAMETER") amount: BigDecimal, @Suppress("UNUSED_PARAMETER") start: Perceivable<Instant>, @Suppress("UNUSED_PARAMETER") end: Perceivable<Instant>) : Perceivable<BigDecimal> = DummyPerceivable()
|
||||
|
||||
fun interest(@Suppress("UNUSED_PARAMETER") amount: BigDecimal, @Suppress("UNUSED_PARAMETER") dayCountConvention: String, @Suppress("UNUSED_PARAMETER") interest: BigDecimal /* todo - appropriate type */,
|
||||
@Suppress("UNUSED_PARAMETER") start: String, @Suppress("UNUSED_PARAMETER") end: String) : Perceivable<BigDecimal> = Interest(Const(amount), dayCountConvention, Const(interest), start, end)
|
||||
@Suppress("UNUSED_PARAMETER") start: String, @Suppress("UNUSED_PARAMETER") end: String) : Perceivable<BigDecimal> = Interest(Const(amount), dayCountConvention, Const(interest), parseDate(start).toLocalDate(), parseDate(end).toLocalDate())
|
||||
|
||||
fun interest(@Suppress("UNUSED_PARAMETER") amount: BigDecimal, @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<BigDecimal> =
|
||||
Interest(Const(amount), dayCountConvention, interest, start, end)
|
||||
Interest(Const(amount), dayCountConvention, interest, parseDate(start).toLocalDate(), parseDate(end).toLocalDate())
|
||||
|
||||
fun interest(@Suppress("UNUSED_PARAMETER") amount: BigDecimal, @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<BigDecimal> = DummyPerceivable()
|
||||
@ -125,6 +120,7 @@ fun interest(@Suppress("UNUSED_PARAMETER") amount: BigDecimal, @Suppress("UNUSED
|
||||
fun interest(@Suppress("UNUSED_PARAMETER") rate: BigDecimal, @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<BigDecimal> = DummyPerceivable()
|
||||
|
||||
class Fixing(val source: String, val date: LocalDate, val tenor: Tenor) : Perceivable<BigDecimal>
|
||||
class Fixing(val source: String, val date: Perceivable<Instant>, val tenor: Tenor) : Perceivable<BigDecimal>
|
||||
|
||||
fun fix(source: String, date: LocalDate, tenor: Tenor): Perceivable<BigDecimal> = Fixing(source, date, tenor)
|
||||
fun fix(source: String, date: Perceivable<Instant>, tenor: Tenor): Perceivable<BigDecimal> = Fixing(source, date, tenor)
|
||||
fun fix(source: String, date: LocalDate, tenor: Tenor): Perceivable<BigDecimal> = Fixing(source, const(date.toInstant()), tenor)
|
@ -6,11 +6,15 @@ import com.r3corda.core.crypto.SecureHash
|
||||
import com.r3corda.core.transactions.TransactionBuilder
|
||||
import java.math.BigDecimal
|
||||
import java.security.PublicKey
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
|
||||
/**
|
||||
* Created by sofusmortensen on 23/05/16.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
val UNIVERSAL_PROGRAM_ID = UniversalContract()
|
||||
|
||||
class UniversalContract : Contract {
|
||||
@ -40,6 +44,14 @@ class UniversalContract : Contract {
|
||||
else -> throw Error("Unable to evaluate")
|
||||
}
|
||||
|
||||
fun eval(@Suppress("UNUSED_PARAMETER") tx: TransactionForContract, expr: Perceivable<LocalDate>): LocalDate = when (expr) {
|
||||
is Const -> expr.value
|
||||
else -> throw Error("Unable to evaluate")
|
||||
}
|
||||
fun eval(@Suppress("UNUSED_PARAMETER") tx: TransactionForContract, expr: Perceivable<Instant>): Instant = when (expr) {
|
||||
is Const -> expr.value
|
||||
else -> throw Error("Unable to evaluate")
|
||||
}
|
||||
fun eval(tx: TransactionForContract, expr: Perceivable<Boolean>): Boolean = when (expr) {
|
||||
is PerceivableAnd -> eval(tx, expr.left) && eval(tx, expr.right)
|
||||
is PerceivableOr -> eval(tx, expr.right) || eval(tx, expr.right)
|
||||
@ -77,7 +89,7 @@ class UniversalContract : Contract {
|
||||
}
|
||||
is Fixing -> {
|
||||
requireThat { "Fixing must be included" by false }
|
||||
BigDecimal(0.0)
|
||||
0.0.bd
|
||||
}
|
||||
is Interest -> {
|
||||
val a = eval(tx, expr.amount)
|
||||
@ -85,7 +97,7 @@ class UniversalContract : Contract {
|
||||
|
||||
//todo
|
||||
|
||||
a * i / BigDecimal(100)
|
||||
a * i / 100.0.bd
|
||||
}
|
||||
else -> throw NotImplementedError("eval - BigDecimal - " + expr.javaClass.name)
|
||||
}
|
||||
@ -126,7 +138,11 @@ class UniversalContract : Contract {
|
||||
}
|
||||
|
||||
fun validateImmediateTransfers(tx: TransactionForContract, arrangement: Arrangement): Arrangement = when (arrangement) {
|
||||
is Transfer -> Transfer(eval(tx, arrangement.amount), arrangement.currency, arrangement.from, arrangement.to)
|
||||
is Transfer -> {
|
||||
val amount = eval(tx, arrangement.amount)
|
||||
requireThat { "transferred quantity is non-negative" by (amount >= BigDecimal.ZERO) }
|
||||
Transfer(amount, arrangement.currency, arrangement.from, arrangement.to)
|
||||
}
|
||||
is And -> And(arrangement.arrangements.map { validateImmediateTransfers(tx, it) }.toSet())
|
||||
else -> arrangement
|
||||
}
|
||||
@ -222,9 +238,9 @@ class UniversalContract : Contract {
|
||||
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>
|
||||
is Fixing -> if (fixings.containsKey(FixOf(perceivable.source, eval(tx, perceivable.date).toLocalDate(), perceivable.tenor))) {
|
||||
unusedFixings.remove(FixOf(perceivable.source, eval(tx, perceivable.date).toLocalDate(), perceivable.tenor))
|
||||
Const(fixings[FixOf(perceivable.source, eval(tx, perceivable.date).toLocalDate(), perceivable.tenor)]!!) as Perceivable<T>
|
||||
} else perceivable
|
||||
else -> throw NotImplementedError("replaceFixing - " + perceivable.javaClass.name)
|
||||
}
|
||||
|
@ -6,34 +6,37 @@ import com.r3corda.core.contracts.Amount
|
||||
import com.r3corda.core.crypto.Party
|
||||
import java.math.BigDecimal
|
||||
import java.security.PublicKey
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by sofusmortensen on 23/05/16.
|
||||
*/
|
||||
|
||||
fun Instant.toLocalDate() : LocalDate = LocalDate.ofEpochDay( this.epochSecond / 60 / 60 / 24 )
|
||||
fun LocalDate.toInstant() : Instant = Instant.ofEpochSecond( this.toEpochDay() * 60 * 60 * 24 )
|
||||
|
||||
/** returns list of potentially liable parties for a given contract */
|
||||
fun liableParties(contract: Arrangement) : Set<PublicKey> {
|
||||
|
||||
fun visit(arrangement: Arrangement) : ImmutableSet<PublicKey> {
|
||||
fun visit(arrangement: Arrangement) : ImmutableSet<PublicKey> =
|
||||
when (arrangement) {
|
||||
is Zero -> return ImmutableSet.of<PublicKey>()
|
||||
is Transfer -> return ImmutableSet.of(arrangement.from.owningKey)
|
||||
is Zero -> ImmutableSet.of<PublicKey>()
|
||||
is Transfer -> ImmutableSet.of(arrangement.from.owningKey)
|
||||
is Action ->
|
||||
if (arrangement.actors.size != 1)
|
||||
return visit(arrangement.arrangement)
|
||||
visit(arrangement.arrangement)
|
||||
else
|
||||
return Sets.difference(visit(arrangement.arrangement), ImmutableSet.of(arrangement.actors.single())).immutableCopy()
|
||||
Sets.difference(visit(arrangement.arrangement), ImmutableSet.of(arrangement.actors.single())).immutableCopy()
|
||||
is And ->
|
||||
return arrangement.arrangements.fold( ImmutableSet.builder<PublicKey>(), { builder, k -> builder.addAll( visit(k)) } ).build()
|
||||
arrangement.arrangements.fold( ImmutableSet.builder<PublicKey>(), { builder, k -> builder.addAll( visit(k)) } ).build()
|
||||
is Or ->
|
||||
return arrangement.actions.fold( ImmutableSet.builder<PublicKey>(), { builder, k -> builder.addAll( visit(k)) } ).build()
|
||||
arrangement.actions.fold( ImmutableSet.builder<PublicKey>(), { builder, k -> builder.addAll( visit(k)) } ).build()
|
||||
is RollOut -> visit( arrangement.template )
|
||||
else -> throw IllegalArgumentException("liableParties " + arrangement)
|
||||
}
|
||||
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
|
||||
return visit(contract)
|
||||
}
|
||||
|
||||
|
@ -16,13 +16,14 @@ fun swap(partyA: Party, amountA: BigDecimal, currencyA: Currency, partyB: Party,
|
||||
|
||||
fun fx_swap(expiry: String, notional: BigDecimal, strike: BigDecimal,
|
||||
foreignCurrency: Currency, domesticCurrency: Currency,
|
||||
partyA: Party, partyB: Party) =
|
||||
partyA: Party, partyB: Party) = arrange {
|
||||
|
||||
(partyA or partyB).may {
|
||||
"execute".givenThat( after(expiry) ) {
|
||||
swap(partyA, notional * strike, domesticCurrency, partyB, notional, foreignCurrency)
|
||||
}
|
||||
(partyA or partyB).may {
|
||||
"execute".givenThat(after(expiry)) {
|
||||
swap(partyA, notional * strike, domesticCurrency, partyB, notional, foreignCurrency)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// building an fx swap using abstract swap
|
||||
fun fx_swap2(expiry: String, notional: Long, strike: Double,
|
||||
|
@ -10,30 +10,54 @@ import java.util.*
|
||||
*/
|
||||
|
||||
|
||||
infix fun Arrangement.and(arrangement: Arrangement) = And( setOf(this, arrangement) )
|
||||
infix fun Action.or(arrangement: Action) = Or( setOf(this, arrangement) )
|
||||
infix fun Or.or(arrangement: Action) = Or( this.actions.plusElement(arrangement) )
|
||||
infix fun Or.or(ors: Or) = Or( this.actions.plus(ors.actions) )
|
||||
|
||||
// operator fun Long.times(currency: Currency) = Amount(this.toLong(), currency)
|
||||
// operator fun Double.times(currency: Currency) = Amount(BigDecimal(this.toDouble()), currency)
|
||||
|
||||
val Int.M: BigDecimal get() = BigDecimal(this) * BigDecimal(1000000)
|
||||
val Int.K: BigDecimal get() = BigDecimal(this) * BigDecimal(1000)
|
||||
|
||||
val Double.bd: BigDecimal get() = BigDecimal(this)
|
||||
|
||||
val zero = Zero()
|
||||
|
||||
class ContractBuilder {
|
||||
open class ContractBuilder {
|
||||
val contracts = mutableListOf<Arrangement>()
|
||||
|
||||
fun Party.gives(beneficiary: Party, amount: BigDecimal, currency: Currency) {
|
||||
contracts.add( Transfer(amount, currency, this, beneficiary))
|
||||
fun Party.gives(beneficiary: Party, amount: BigDecimal, currency: Currency) : Transfer {
|
||||
val c = Transfer(amount, currency, this, beneficiary)
|
||||
contracts.add( c )
|
||||
return c
|
||||
}
|
||||
|
||||
fun Party.gives(beneficiary: Party, amount: Perceivable<BigDecimal>, currency: Currency) {
|
||||
contracts.add( Transfer(amount, currency, this, beneficiary))
|
||||
fun Party.gives(beneficiary: Party, amount: Perceivable<BigDecimal>, currency: Currency) : Transfer {
|
||||
val c = Transfer(amount, currency, this, beneficiary)
|
||||
contracts.add( c )
|
||||
return c
|
||||
}
|
||||
|
||||
fun Party.may(init: ActionBuilder.() -> Unit) : Or {
|
||||
val b = ActionBuilder(setOf(this))
|
||||
b.init()
|
||||
val c = Or(b.actions.toSet())
|
||||
contracts.add(c)
|
||||
return c
|
||||
}
|
||||
|
||||
fun Set<Party>.may(init: ActionBuilder.() -> Unit) : Or {
|
||||
val b = ActionBuilder(this)
|
||||
b.init()
|
||||
val c = Or(b.actions.toSet())
|
||||
contracts.add(c)
|
||||
return c
|
||||
}
|
||||
|
||||
infix fun Party.or(party: Party) = setOf(this, party)
|
||||
infix fun Set<Party>.or(party: Party) = this.plus(party)
|
||||
|
||||
@Deprecated(level = DeprecationLevel.ERROR, message = "Not allowed")
|
||||
fun Action(@Suppress("UNUSED_PARAMETER") name: String, @Suppress("UNUSED_PARAMETER") condition: Perceivable<Boolean>,
|
||||
@Suppress("UNUSED_PARAMETER") actors: Set<Party>, @Suppress("UNUSED_PARAMETER") arrangement: Arrangement) {}
|
||||
|
||||
@Deprecated(level = DeprecationLevel.ERROR, message = "Not available")
|
||||
fun<T> String.anytime(@Suppress("UNUSED_PARAMETER") ignore: T ) {}
|
||||
|
||||
@ -47,7 +71,28 @@ class ContractBuilder {
|
||||
contracts.add( Transfer(amount, currency, this, beneficiary))
|
||||
}*/
|
||||
|
||||
fun final() =
|
||||
infix fun Arrangement.and(arrangement: Arrangement) = And( setOf(this, arrangement) )
|
||||
infix fun Action.or(arrangement: Action) = Or( setOf(this, arrangement) )
|
||||
infix fun Or.or(arrangement: Action) = Or( this.actions.plusElement(arrangement) )
|
||||
infix fun Or.or(ors: Or) = Or( this.actions.plus(ors.actions) )
|
||||
|
||||
fun rollOut(startDate: String, endDate: String, frequency: Frequency, init: RollOutBuilder<Dummy>.() -> Unit) : RollOut {
|
||||
val b = RollOutBuilder(startDate, endDate, frequency, Dummy())
|
||||
b.init()
|
||||
val c = b.final()
|
||||
contracts.add(c)
|
||||
return c
|
||||
}
|
||||
|
||||
fun <T> rollOut(startDate: String, endDate: String, frequency: Frequency, vars: T, init: RollOutBuilder<T>.() -> Unit) : RollOut {
|
||||
val b = RollOutBuilder(startDate, endDate, frequency, vars)
|
||||
b.init()
|
||||
val c = b.final()
|
||||
contracts.add(c)
|
||||
return c
|
||||
}
|
||||
|
||||
open fun final() =
|
||||
when (contracts.size) {
|
||||
0 -> zero
|
||||
1 -> contracts[0]
|
||||
@ -62,7 +107,7 @@ interface GivenThatResolve {
|
||||
class ActionBuilder(val actors: Set<Party>) {
|
||||
val actions = mutableListOf<Action>()
|
||||
|
||||
fun String.givenThat(condition: Perceivable<Boolean>, init: ContractBuilder.() -> Unit ) {
|
||||
fun String.givenThat(condition: Perceivable<Boolean>, init: ContractBuilder.() -> Arrangement ) {
|
||||
val b = ContractBuilder()
|
||||
b.init()
|
||||
actions.add( Action(this, condition, actors, b.final() ) )
|
||||
@ -84,21 +129,6 @@ class ActionBuilder(val actors: Set<Party>) {
|
||||
}
|
||||
}
|
||||
|
||||
fun Party.may(init: ActionBuilder.() -> Unit) : Or {
|
||||
val b = ActionBuilder(setOf(this))
|
||||
b.init()
|
||||
return Or(b.actions.toSet())
|
||||
}
|
||||
|
||||
fun Set<Party>.may(init: ActionBuilder.() -> Unit) : Or {
|
||||
val b = ActionBuilder(this)
|
||||
b.init()
|
||||
return Or(b.actions.toSet())
|
||||
}
|
||||
|
||||
infix fun Party.or(party: Party) = setOf(this, party)
|
||||
infix fun Set<Party>.or(party: Party) = this.plus(party)
|
||||
|
||||
fun arrange(init: ContractBuilder.() -> Unit ) : Arrangement {
|
||||
val b = ContractBuilder()
|
||||
b.init()
|
||||
@ -109,7 +139,7 @@ data class Parameter<T>(val initialValue: T) : Perceivable<T>
|
||||
|
||||
fun<T> variable(v: T) = Parameter<T>(v)
|
||||
|
||||
class RollOutBuilder<T>(val startDate: String, val endDate: String, val frequency: Frequency, val vars: T) {
|
||||
class RollOutBuilder<T>(val startDate: String, val endDate: String, val frequency: Frequency, val vars: T) : ContractBuilder() {
|
||||
|
||||
val start = StartDate()
|
||||
val end = EndDate()
|
||||
@ -123,22 +153,9 @@ class RollOutBuilder<T>(val startDate: String, val endDate: String, val frequenc
|
||||
@Suppress("UNUSED_PARAMETER") p2: kotlin.Pair<Parameter<T2>, Perceivable<T2>>,
|
||||
@Suppress("UNUSED_PARAMETER") p3: kotlin.Pair<Parameter<T3>, Perceivable<T3>>) = Continuation()
|
||||
|
||||
fun final() =
|
||||
RollOut(startDate, endDate, frequency, zero)
|
||||
override fun final() =
|
||||
RollOut(startDate, endDate, frequency, super.final())
|
||||
}
|
||||
|
||||
|
||||
class Dummy {}
|
||||
|
||||
fun rollOut(startDate: String, endDate: String, frequency: Frequency, init: RollOutBuilder<Dummy>.() -> Unit) : Arrangement {
|
||||
val b = RollOutBuilder(startDate, endDate, frequency, Dummy())
|
||||
b.init()
|
||||
return b.final()
|
||||
}
|
||||
|
||||
fun<T> rollOut(startDate: String, endDate: String, frequency: Frequency, vars: T, init: RollOutBuilder<T>.() -> Unit) : Arrangement {
|
||||
val b = RollOutBuilder(startDate, endDate, frequency, vars)
|
||||
b.init()
|
||||
|
||||
return b.final()
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
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
|
||||
|
||||
/**
|
||||
* Created by sofusmortensen on 05/09/16.
|
||||
*/
|
||||
|
||||
class Cap {
|
||||
|
||||
val TEST_TX_TIME_1: Instant get() = Instant.parse("2017-09-02T12:00:00.00Z")
|
||||
|
||||
val notional = 50.M
|
||||
val currency = EUR
|
||||
|
||||
val contract = arrange {
|
||||
rollOut("2016-04-01", "2017-04-01", Frequency.Quarterly) {
|
||||
(roadRunner or wileECoyote).may {
|
||||
"exercise".anytime {
|
||||
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("6M")), start, end)
|
||||
val fixed = interest(notional, "act/365", 0.5.bd, start, end)
|
||||
wileECoyote.gives(roadRunner, floating - fixed, currency)
|
||||
next()
|
||||
}
|
||||
} or roadRunner.may {
|
||||
"skip".anytime {
|
||||
next()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val stateStart = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contract)
|
||||
|
||||
|
||||
val contractTARN = arrange {
|
||||
rollOut("2016-04-01", "2017-04-01", Frequency.Quarterly, object {
|
||||
val limit = variable(150.K)
|
||||
}) {
|
||||
(roadRunner or wileECoyote).may {
|
||||
"exercise".anytime {
|
||||
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("6M")), start, end)
|
||||
val fixed = interest(notional, "act/365", 0.5.bd, start, end)
|
||||
val payout = (floating - fixed).plus()
|
||||
wileECoyote.gives(roadRunner, payout, currency)
|
||||
next(vars.limit to vars.limit - payout)
|
||||
}
|
||||
} or roadRunner.may {
|
||||
"skip".anytime {
|
||||
next()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun issue() {
|
||||
transaction {
|
||||
output { stateStart }
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -8,6 +8,7 @@ import org.junit.Test
|
||||
import java.math.BigDecimal
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by sofusmortensen on 25/08/16.
|
||||
@ -17,28 +18,30 @@ 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 dt: LocalDate = LocalDate.of(2016, 9, 1)
|
||||
|
||||
val notional = 50.M
|
||||
val currency = 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(0.5), "2016-04-01", "2016-10-01")
|
||||
wileECoyote.gives(roadRunner, (floating - fixed).plus(), currency )
|
||||
}
|
||||
val contract = arrange {
|
||||
(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", 0.5.bd, "2016-04-01", "2016-10-01")
|
||||
wileECoyote.gives(roadRunner, (floating - fixed).plus(), currency)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val contractFixed =
|
||||
(roadRunner or wileECoyote).may {
|
||||
"exercise".anytime() {
|
||||
val floating = interest(notional, "act/365", BigDecimal.valueOf(1.0), "2016-04-01", "2016-10-01" )
|
||||
val fixed = interest(notional, "act/365", BigDecimal.valueOf(0.5), "2016-04-01", "2016-10-01")
|
||||
wileECoyote.gives(roadRunner, (floating - fixed).plus(), currency )
|
||||
}
|
||||
val contractFixed = arrange {
|
||||
(roadRunner or wileECoyote).may {
|
||||
"exercise".anytime() {
|
||||
val floating = interest(notional, "act/365", 1.0.bd, "2016-04-01", "2016-10-01")
|
||||
val fixed = interest(notional, "act/365", 0.5.bd, "2016-04-01", "2016-10-01")
|
||||
wileECoyote.gives(roadRunner, (floating - fixed).plus(), currency)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val contractFinal = arrange { wileECoyote.gives(roadRunner, 250.K, EUR) }
|
||||
|
||||
@ -99,32 +102,32 @@ class Caplet {
|
||||
|
||||
tweak {
|
||||
// wrong source
|
||||
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBORx", dt, Tenor("6M")), BigDecimal(1.0)))) }
|
||||
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBORx", dt, Tenor("6M")), 1.0.bd))) }
|
||||
|
||||
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(1.0)))) }
|
||||
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt.plusYears(1), Tenor("6M")), 1.0.bd))) }
|
||||
|
||||
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(1.0)))) }
|
||||
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt, Tenor("3M")), 1.0.bd))) }
|
||||
|
||||
this `fails with` "relevant fixing must be included"
|
||||
}
|
||||
|
||||
tweak {
|
||||
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt, Tenor("6M")), BigDecimal.valueOf(1.5)))) }
|
||||
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt, Tenor("6M")), 1.5.bd))) }
|
||||
|
||||
this `fails with` "output state does not reflect fix command"
|
||||
}
|
||||
|
||||
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt, Tenor("6M")), BigDecimal.valueOf(1.0)))) }
|
||||
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt, Tenor("6M")), 1.0.bd))) }
|
||||
|
||||
this.verifies()
|
||||
}
|
||||
|
@ -14,47 +14,61 @@ val roadRunner = Party("Road Runner", generateKeyPair().public)
|
||||
val wileECoyote = Party("Wile E. Coyote", generateKeyPair().public)
|
||||
val porkyPig = Party("Porky Pig", generateKeyPair().public)
|
||||
|
||||
val acmeCorporationHasDefaulted = DummyPerceivable<Boolean>()
|
||||
|
||||
|
||||
// Currencies
|
||||
val USD = Currency.getInstance("USD")
|
||||
val GBP = Currency.getInstance("GBP")
|
||||
val EUR = Currency.getInstance("EUR")
|
||||
val KRW = Currency.getInstance("KRW")
|
||||
val USD: Currency = Currency.getInstance("USD")
|
||||
val GBP: Currency = Currency.getInstance("GBP")
|
||||
val EUR: Currency = Currency.getInstance("EUR")
|
||||
val KRW: Currency = Currency.getInstance("KRW")
|
||||
|
||||
|
||||
class ContractDefinition {
|
||||
|
||||
|
||||
val cds_contract = roadRunner.may {
|
||||
"payout".givenThat( acmeCorporationHasDefaulted and before("2017-09-01") ) {
|
||||
wileECoyote.gives(roadRunner, 1.M, USD)
|
||||
}
|
||||
} or wileECoyote.may {
|
||||
"expire".givenThat( after("2017-09-01") ) {}
|
||||
}
|
||||
|
||||
|
||||
val american_fx_option = roadRunner.may {
|
||||
"exercise".anytime {
|
||||
wileECoyote.gives(roadRunner, 1.M, EUR)
|
||||
roadRunner.gives(wileECoyote, 1200.K, USD)
|
||||
}
|
||||
} or wileECoyote.may {
|
||||
"expire".givenThat(after("2017-09-01")) {}
|
||||
}
|
||||
|
||||
|
||||
val european_fx_option = roadRunner.may {
|
||||
"exercise".anytime {
|
||||
(roadRunner or wileECoyote).may {
|
||||
"execute".givenThat( after("2017-09-01") ) {
|
||||
wileECoyote.gives( roadRunner, 1.M, EUR )
|
||||
roadRunner.gives( wileECoyote, 1200.K, USD )
|
||||
}
|
||||
val cds_contract = arrange {
|
||||
roadRunner.may {
|
||||
"payout".givenThat(acmeCorporationHasDefaulted and before("2017-09-01")) {
|
||||
wileECoyote.gives(roadRunner, 1.M, USD)
|
||||
}
|
||||
} or wileECoyote.may {
|
||||
"expire".givenThat(after("2017-09-01")) {
|
||||
zero
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val american_fx_option = arrange {
|
||||
roadRunner.may {
|
||||
"exercise".anytime {
|
||||
wileECoyote.gives(roadRunner, 1.M, EUR)
|
||||
roadRunner.gives(wileECoyote, 1200.K, USD)
|
||||
}
|
||||
} or wileECoyote.may {
|
||||
"expire".givenThat(after("2017-09-01")) {
|
||||
zero
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val european_fx_option = arrange {
|
||||
roadRunner.may {
|
||||
"exercise".anytime {
|
||||
(roadRunner or wileECoyote).may {
|
||||
"execute".givenThat(after("2017-09-01")) {
|
||||
wileECoyote.gives(roadRunner, 1.M, EUR)
|
||||
roadRunner.gives(wileECoyote, 1200.K, USD)
|
||||
}
|
||||
}
|
||||
}
|
||||
} or wileECoyote.may {
|
||||
"expire".givenThat(after("2017-09-01")) {
|
||||
zero
|
||||
}
|
||||
}
|
||||
} or wileECoyote.may {
|
||||
"expire".givenThat( after("2017-09-01")) {}
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,13 +14,14 @@ class FXSwap {
|
||||
val TEST_TX_TIME_1: Instant get() = Instant.parse("2017-09-02T12:00:00.00Z")
|
||||
val TEST_TX_TIME_TOO_EARLY: Instant get() = Instant.parse("2017-08-31T12:00:00.00Z")
|
||||
|
||||
val contract =
|
||||
(roadRunner or wileECoyote).may {
|
||||
"execute".givenThat(after("2017-09-01")) {
|
||||
wileECoyote.gives(roadRunner, 1200.K, USD)
|
||||
roadRunner.gives(wileECoyote, 1.M, EUR)
|
||||
}
|
||||
val contract = arrange {
|
||||
(roadRunner or wileECoyote).may {
|
||||
"execute".givenThat(after("2017-09-01")) {
|
||||
wileECoyote.gives(roadRunner, 1200.K, USD)
|
||||
roadRunner.gives(wileECoyote, 1.M, EUR)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val transfer1 = arrange { wileECoyote.gives(roadRunner, 1200.K, USD) }
|
||||
val transfer2 = arrange { roadRunner.gives(wileECoyote, 1.M, EUR) }
|
||||
|
@ -10,95 +10,100 @@ import java.math.BigDecimal
|
||||
// Swaption
|
||||
|
||||
|
||||
|
||||
class Swaption {
|
||||
|
||||
val notional = 10.M
|
||||
val currency = USD
|
||||
val coupon = BigDecimal.valueOf(1.5)
|
||||
val coupon = 1.5.bd
|
||||
|
||||
val dreary_contract =
|
||||
(wileECoyote or roadRunner).may {
|
||||
"proceed".givenThat(after("01/07/2015")) {
|
||||
wileECoyote.gives(roadRunner, libor( notional, "01/04/2015", "01/07/2015" ), currency )
|
||||
roadRunner.gives(wileECoyote, interest( notional, "act/365", coupon, "01/04/2015", "01/07/2015" ), currency )
|
||||
(wileECoyote or roadRunner).may {
|
||||
"proceed".givenThat(after("01/10/2015")) {
|
||||
wileECoyote.gives(roadRunner, libor( notional, "01/07/2015", "01/10/2015" ), currency )
|
||||
roadRunner.gives(wileECoyote, interest( notional, "act/365", coupon, "01/07/2015", "01/10/2015" ), currency )
|
||||
val dreary_contract = arrange {
|
||||
(wileECoyote or roadRunner).may {
|
||||
"proceed".givenThat(after("01/07/2015")) {
|
||||
wileECoyote.gives(roadRunner, libor(notional, "01/04/2015", "01/07/2015"), currency)
|
||||
roadRunner.gives(wileECoyote, interest(notional, "act/365", coupon, "01/04/2015", "01/07/2015"), currency)
|
||||
(wileECoyote or roadRunner).may {
|
||||
"proceed".givenThat(after("01/10/2015")) {
|
||||
wileECoyote.gives(roadRunner, libor(notional, "01/07/2015", "01/10/2015"), currency)
|
||||
roadRunner.gives(wileECoyote, interest(notional, "act/365", coupon, "01/07/2015", "01/10/2015"), currency)
|
||||
|
||||
(wileECoyote or roadRunner).may {
|
||||
// etc ...
|
||||
}
|
||||
}
|
||||
} or roadRunner.may {
|
||||
"cancel".anytime {
|
||||
roadRunner.gives( wileECoyote, 10.K, USD )
|
||||
(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 elegant_contract = rollOut( "01/04/2015", "01/04/2025", Frequency.Quarterly ) {
|
||||
(wileECoyote or roadRunner).may {
|
||||
"proceed".givenThat(after(start)) {
|
||||
wileECoyote.gives(roadRunner, libor( notional, start, end ), currency )
|
||||
roadRunner.gives(wileECoyote, interest( notional, "act/365", coupon, start, end ), currency )
|
||||
next()
|
||||
}
|
||||
} or roadRunner.may {
|
||||
"cancel".anytime {
|
||||
roadRunner.gives( wileECoyote, 10.K, currency )
|
||||
roadRunner.gives(wileECoyote, 10.K, USD)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val elegant_contract = arrange {
|
||||
rollOut("01/04/2015", "01/04/2025", Frequency.Quarterly) {
|
||||
(wileECoyote or roadRunner).may {
|
||||
"proceed".givenThat(after(start)) {
|
||||
wileECoyote.gives(roadRunner, libor(notional, start, end), currency)
|
||||
roadRunner.gives(wileECoyote, interest(notional, "act/365", coupon, start, end), currency)
|
||||
next()
|
||||
}
|
||||
} or roadRunner.may {
|
||||
"cancel".anytime {
|
||||
roadRunner.gives(wileECoyote, 10.K, currency)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val strike = 1.2
|
||||
|
||||
val tarf = rollOut( "01/04/2015", "01/04/2016", Frequency.Quarterly, object {
|
||||
val cap = variable( 150.K )
|
||||
}) {
|
||||
roadRunner.may {
|
||||
"exercise".givenThat(before(end)) {
|
||||
val payout = (EUR / USD - strike).plus() * notional
|
||||
val tarf = arrange {
|
||||
rollOut("01/04/2015", "01/04/2016", Frequency.Quarterly, object {
|
||||
val cap = variable(150.K)
|
||||
}) {
|
||||
roadRunner.may {
|
||||
"exercise".givenThat(before(end)) {
|
||||
val payout = (EUR / USD - strike).plus() * notional
|
||||
|
||||
(roadRunner or wileECoyote).may {
|
||||
"proceed".givenThat(after(end)) {
|
||||
wileECoyote.gives(roadRunner, payout, USD)
|
||||
next(vars.cap to vars.cap - payout)
|
||||
(roadRunner or wileECoyote).may {
|
||||
"proceed".givenThat(after(end)) {
|
||||
wileECoyote.gives(roadRunner, payout, USD)
|
||||
next(vars.cap to vars.cap - payout)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} or (roadRunner or wileECoyote).may {
|
||||
"proceedWithoutExercise".givenThat(after(end)) {
|
||||
next()
|
||||
} or (roadRunner or wileECoyote).may {
|
||||
"proceedWithoutExercise".givenThat(after(end)) {
|
||||
next()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val tarf2 = rollOut( "01/04/2015", "01/04/2016", Frequency.Quarterly, object {
|
||||
val uses = variable( 4 )
|
||||
}) {
|
||||
roadRunner.may {
|
||||
"exercise".givenThat(before(end)) {
|
||||
val payout = (EUR / USD - strike).plus() * notional
|
||||
val tarf2 = arrange {
|
||||
rollOut("01/04/2015", "01/04/2016", Frequency.Quarterly, object {
|
||||
val uses = variable(4)
|
||||
}) {
|
||||
roadRunner.may {
|
||||
"exercise".givenThat(before(end)) {
|
||||
val payout = (EUR / USD - strike).plus() * notional
|
||||
|
||||
(roadRunner or wileECoyote).may {
|
||||
"proceed".givenThat(after(end)) {
|
||||
wileECoyote.gives(roadRunner, payout, currency)
|
||||
next(vars.uses to vars.uses - 1)
|
||||
(roadRunner or wileECoyote).may {
|
||||
"proceed".givenThat(after(end)) {
|
||||
wileECoyote.gives(roadRunner, payout, currency)
|
||||
next(vars.uses to vars.uses - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} or (roadRunner or wileECoyote).may {
|
||||
"proceedWithoutExercise".givenThat(after(end)) {
|
||||
next()
|
||||
} or (roadRunner or wileECoyote).may {
|
||||
"proceedWithoutExercise".givenThat(after(end)) {
|
||||
next()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,20 +11,22 @@ import java.time.Instant
|
||||
|
||||
class ZeroCouponBond {
|
||||
|
||||
val contract =
|
||||
(roadRunner or wileECoyote).may {
|
||||
"execute".givenThat(after("2017-09-01")) {
|
||||
wileECoyote.gives(roadRunner, 100.K, GBP)
|
||||
}
|
||||
val contract = arrange {
|
||||
(roadRunner or wileECoyote).may {
|
||||
"execute".givenThat(after("2017-09-01")) {
|
||||
wileECoyote.gives(roadRunner, 100.K, GBP)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val contractMove =
|
||||
(porkyPig or wileECoyote).may {
|
||||
"execute".givenThat(after("2017-09-01")) {
|
||||
wileECoyote.gives(porkyPig, 100.K, GBP)
|
||||
}
|
||||
val contractMove = arrange {
|
||||
(porkyPig or wileECoyote).may {
|
||||
"execute".givenThat(after("2017-09-01")) {
|
||||
wileECoyote.gives(porkyPig, 100.K, GBP)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val TEST_TX_TIME_1: Instant get() = Instant.parse("2017-09-02T12:00:00.00Z")
|
||||
|
||||
|
@ -13,28 +13,62 @@ import java.util.*
|
||||
|
||||
// various example arrangements using basic syntax
|
||||
|
||||
val cds_contract = Action("payout", acmeCorporationHasDefaulted and before("2017-09-01"),
|
||||
roadRunner,
|
||||
Transfer(Amount(1.M, USD), wileECoyote, roadRunner))
|
||||
val cds_contract = arrange {
|
||||
roadRunner.may {
|
||||
"claim".givenThat(acmeCorporationHasDefaulted and before("2017-09-01")) {
|
||||
wileECoyote.gives(roadRunner, 1.M, USD)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fx swap
|
||||
// both parties have the right to trigger the exchange of cash flows
|
||||
val an_fx_swap = Action("execute", after("2017-09-01"), setOf(roadRunner, wileECoyote),
|
||||
Transfer(1200.K, USD, wileECoyote, roadRunner)
|
||||
and Transfer(1.M, EUR, roadRunner, wileECoyote))
|
||||
val an_fx_swap = arrange {
|
||||
(roadRunner or wileECoyote).may {
|
||||
"execute".givenThat(after("2017-09-01")) {
|
||||
wileECoyote.gives(roadRunner, 1200.K, USD)
|
||||
roadRunner.gives(wileECoyote, 1.M, EUR)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val american_fx_option = Action("exercise", before("2017-09-01"),
|
||||
roadRunner,
|
||||
Transfer(1200.K, USD, wileECoyote, roadRunner)
|
||||
and Transfer(1.M, EUR, roadRunner, wileECoyote))
|
||||
val american_fx_option = arrange {
|
||||
roadRunner.may {
|
||||
"exercise".givenThat(before("2017-09-01")) {
|
||||
wileECoyote.gives(roadRunner, 1200.K, USD)
|
||||
roadRunner.gives(wileECoyote, 1.M, EUR)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val european_fx_option = Action("exercise", before("2017-09-01"), roadRunner, fx_swap("2017-09-01", 1.M, BigDecimal(1.2), EUR, USD, roadRunner, wileECoyote)) or
|
||||
Action("expire", after("2017-09-01"), wileECoyote, zero)
|
||||
val european_fx_option = arrange {
|
||||
roadRunner.may {
|
||||
"exercise".givenThat(before("2017-09-01")) {
|
||||
fx_swap("2017-09-01", 1.M, 1.2.bd, EUR, USD, roadRunner, wileECoyote)
|
||||
}
|
||||
} or (roadRunner or wileECoyote).may {
|
||||
"expire".anytime {
|
||||
zero
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val zero_coupon_bond_1 = Action("execute", after("2017-09-01"), roadRunner, Transfer(1.M, USD, wileECoyote, roadRunner))
|
||||
val zero_coupon_bond_1 = arrange {
|
||||
roadRunner.may {
|
||||
"execute".givenThat(after("2017-09-01")) {
|
||||
wileECoyote.gives(roadRunner, 1.M, USD)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// maybe in the presence of negative interest rates you would want other side of contract to be able to take initiative as well
|
||||
val zero_coupon_bond_2 = Action("execute", after("2017-09-01"), setOf(roadRunner, wileECoyote), Transfer(1.M, USD, wileECoyote, roadRunner))
|
||||
val zero_coupon_bond_2 = arrange {
|
||||
(roadRunner or wileECoyote).may {
|
||||
"execute".givenThat(after("2017-09-01")) {
|
||||
wileECoyote.gives(roadRunner, 1.M, USD)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no touch
|
||||
// Party Receiver
|
||||
@ -45,8 +79,24 @@ import java.util.*
|
||||
//
|
||||
// Assume observable is using FX fixing
|
||||
//
|
||||
val no_touch = Action("execute", after("2017-09-01"), setOf(roadRunner, wileECoyote), Transfer(1.M, USD, wileECoyote, roadRunner)) or
|
||||
Action("knock out", EUR / USD gt 1.3, wileECoyote, zero)
|
||||
val no_touch = arrange {
|
||||
(roadRunner or wileECoyote).may {
|
||||
"execute".givenThat(after("2017-09-01")) {
|
||||
wileECoyote.gives(roadRunner, 1.M, USD)
|
||||
}
|
||||
} or wileECoyote.may {
|
||||
"knock out".givenThat(EUR/USD gt 1.3)
|
||||
}
|
||||
}
|
||||
|
||||
val one_touch = Action("expire", after("2017-09-01"), wileECoyote, zero) or
|
||||
Action("knock in", EUR / USD gt 1.3, roadRunner, Transfer(1.M, USD, wileECoyote, roadRunner))
|
||||
val one_touch = arrange {
|
||||
wileECoyote.may {
|
||||
"expire".givenThat(after("2017-09-01")) {
|
||||
zero
|
||||
}
|
||||
} or roadRunner.may {
|
||||
"knock in".givenThat(EUR / USD gt 1.3) {
|
||||
wileECoyote.gives(roadRunner, 1.M, USD)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user