mirror of
https://github.com/corda/corda.git
synced 2024-12-19 04:57:58 +00:00
Updated with new Tenor class that verifies string during construction.
Now uses new Tenor class for Interest Rate Oracle
This commit is contained in:
parent
d7d05a2f70
commit
6c0e696107
@ -10,7 +10,6 @@ package core
|
||||
|
||||
import java.math.BigDecimal
|
||||
import java.time.DayOfWeek
|
||||
import java.time.Duration
|
||||
import java.time.LocalDate
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.*
|
||||
@ -79,7 +78,7 @@ fun Iterable<Amount>.sumOrZero(currency: Currency) = if (iterator().hasNext()) s
|
||||
//
|
||||
|
||||
/** A [FixOf] identifies the question side of a fix: what day, tenor and type of fix ("LIBOR", "EURIBOR" etc) */
|
||||
data class FixOf(val name: String, val forDay: LocalDate, val ofTenor: Duration)
|
||||
data class FixOf(val name: String, val forDay: LocalDate, val ofTenor: Tenor)
|
||||
/** A [Fix] represents a named interest rate, on a given day, for a given duration. It can be embedded in a tx. */
|
||||
data class Fix(val of: FixOf, val value: BigDecimal) : CommandData
|
||||
|
||||
@ -87,7 +86,13 @@ data class Fix(val of: FixOf, val value: BigDecimal) : CommandData
|
||||
|
||||
/**
|
||||
* Placeholder class for the Tenor datatype - which is a standardised duration of time until maturity */
|
||||
data class Tenor(var name:String) {
|
||||
data class Tenor(val name:String) {
|
||||
init {
|
||||
val verifier = Regex("([0-9])+([DMYW])") // Only doing Overnight, Day, Week, Month, Year for now.
|
||||
if (!(name == "ON" || verifier.containsMatchIn(name))) {
|
||||
throw IllegalArgumentException("Unrecognized tenor : $name")
|
||||
}
|
||||
}
|
||||
override fun toString(): String = "$name"
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ import org.junit.Test
|
||||
import java.time.LocalDate
|
||||
import java.util.*
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
class FinanceTypesTest {
|
||||
|
||||
@ -21,6 +22,19 @@ class FinanceTypesTest {
|
||||
assert("0.01" in x.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `valid tenor tests`() {
|
||||
val exampleTenors = ("ON,1D,2D,3D,4D,5D,6D,7D,1W,2W,3W,1M,3M,6M,1Y,2Y,3Y,5Y,10Y,12Y,20Y").split(",")
|
||||
exampleTenors.all { Tenor(it).name.length > 0 } // Slightly obtuse way of ensuring no exception thrown in construction.
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `invalid tenor tests`() {
|
||||
val exampleTenors = ("W,M,D,Z,2Q,p0,W1").split(",")
|
||||
for (t in exampleTenors) {
|
||||
assertFailsWith<java.lang.IllegalArgumentException> { Tenor(t) }
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `schedule generator 1`() {
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Some pretend noddy rate fixes, for the interest rate oracles.
|
||||
|
||||
LIBOR 2016-03-16 30 = 0.678
|
||||
LIBOR 2016-03-16 60 = 0.655
|
||||
EURIBOR 2016-03-15 30 = 0.123
|
||||
EURIBOR 2016-03-15 60 = 0.111
|
||||
LIBOR 2016-03-16 1M = 0.678
|
||||
LIBOR 2016-03-16 2M = 0.655
|
||||
EURIBOR 2016-03-15 1M = 0.123
|
||||
EURIBOR 2016-03-15 2M = 0.111
|
@ -33,7 +33,7 @@ import javax.annotation.concurrent.ThreadSafe
|
||||
* for signing.
|
||||
*/
|
||||
object NodeInterestRates {
|
||||
/** Parses a string of the form "LIBOR 16-March-2016 30 = 0.678" into a [FixOf] and [Fix] */
|
||||
/** Parses a string of the form "LIBOR 16-March-2016 1M = 0.678" into a [FixOf] and [Fix] */
|
||||
fun parseOneRate(s: String): Pair<FixOf, Fix> {
|
||||
val (key, value) = s.split('=').map { it.trim() }
|
||||
val of = parseFixOf(key)
|
||||
@ -41,10 +41,10 @@ object NodeInterestRates {
|
||||
return of to Fix(of, rate)
|
||||
}
|
||||
|
||||
/** Parses a string of the form "LIBOR 16-March-2016 30" into a [FixOf] */
|
||||
/** Parses a string of the form "LIBOR 16-March-2016 1M" into a [FixOf] */
|
||||
fun parseFixOf(key: String): FixOf {
|
||||
val (name, date, days) = key.split(' ')
|
||||
return FixOf(name, LocalDate.parse(date), days.toInt().days)
|
||||
val (name, date, tenorString) = key.split(' ')
|
||||
return FixOf(name, LocalDate.parse(date), Tenor(tenorString))
|
||||
}
|
||||
|
||||
/** Parses lines containing fixes */
|
||||
|
@ -37,7 +37,7 @@ fun main(args: Array<String>) {
|
||||
val oracleAddrArg = parser.accepts("oracle").withRequiredArg().required()
|
||||
val oracleIdentityArg = parser.accepts("oracle-identity-file").withRequiredArg().required()
|
||||
|
||||
val fixOfArg = parser.accepts("fix-of").withRequiredArg().defaultsTo("LIBOR 2016-03-16 30")
|
||||
val fixOfArg = parser.accepts("fix-of").withRequiredArg().defaultsTo("LIBOR 2016-03-16 1M")
|
||||
val expectedRateArg = parser.accepts("expected-rate").withRequiredArg().defaultsTo("0.67")
|
||||
val rateToleranceArg = parser.accepts("rate-tolerance").withRequiredArg().defaultsTo("0.1")
|
||||
|
||||
|
@ -11,6 +11,10 @@ package core.node.services
|
||||
import contracts.Cash
|
||||
import core.*
|
||||
import core.testing.MockNetwork
|
||||
import core.DOLLARS
|
||||
import core.Fix
|
||||
import core.TransactionBuilder
|
||||
import core.bd
|
||||
import core.testutils.*
|
||||
import core.utilities.BriefLogFormatter
|
||||
import org.junit.Test
|
||||
@ -20,16 +24,16 @@ import kotlin.test.assertFailsWith
|
||||
|
||||
class NodeInterestRatesTest {
|
||||
val TEST_DATA = NodeInterestRates.parseFile("""
|
||||
LIBOR 2016-03-16 30 = 0.678
|
||||
LIBOR 2016-03-16 60 = 0.655
|
||||
EURIBOR 2016-03-15 30 = 0.123
|
||||
EURIBOR 2016-03-15 60 = 0.111
|
||||
LIBOR 2016-03-16 1M = 0.678
|
||||
LIBOR 2016-03-16 2M = 0.655
|
||||
EURIBOR 2016-03-15 1M = 0.123
|
||||
EURIBOR 2016-03-15 2M = 0.111
|
||||
""".trimIndent())
|
||||
|
||||
val service = NodeInterestRates.Oracle(MEGA_CORP, MEGA_CORP_KEY).apply { knownFixes = TEST_DATA }
|
||||
|
||||
@Test fun `query successfully`() {
|
||||
val q = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 30")
|
||||
val q = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
|
||||
val res = service.query(listOf(q))
|
||||
assertEquals(1, res.size)
|
||||
assertEquals("0.678".bd, res[0].value)
|
||||
@ -37,8 +41,8 @@ class NodeInterestRatesTest {
|
||||
}
|
||||
|
||||
@Test fun `query with one success and one missing`() {
|
||||
val q1 = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 30")
|
||||
val q2 = NodeInterestRates.parseFixOf("LIBOR 2016-03-19 30")
|
||||
val q1 = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
|
||||
val q2 = NodeInterestRates.parseFixOf("LIBOR 2016-03-19 1M")
|
||||
val e = assertFailsWith<NodeInterestRates.UnknownFix> { service.query(listOf(q1, q2)) }
|
||||
assertEquals(e.fix, q2)
|
||||
}
|
||||
@ -56,7 +60,7 @@ class NodeInterestRatesTest {
|
||||
|
||||
@Test fun `sign successfully`() {
|
||||
val tx = makeTX()
|
||||
val fix = service.query(listOf(NodeInterestRates.parseFixOf("LIBOR 2016-03-16 30"))).first()
|
||||
val fix = service.query(listOf(NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M"))).first()
|
||||
tx.addCommand(fix, service.identity.owningKey)
|
||||
|
||||
// Sign successfully.
|
||||
@ -66,7 +70,7 @@ class NodeInterestRatesTest {
|
||||
|
||||
@Test fun `do not sign with unknown fix`() {
|
||||
val tx = makeTX()
|
||||
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 30")
|
||||
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
|
||||
val badFix = Fix(fixOf, "0.6789".bd)
|
||||
tx.addCommand(badFix, service.identity.owningKey)
|
||||
|
||||
@ -81,7 +85,7 @@ class NodeInterestRatesTest {
|
||||
NodeInterestRates.Service(n2).oracle.knownFixes = TEST_DATA
|
||||
|
||||
val tx = TransactionBuilder()
|
||||
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 30")
|
||||
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
|
||||
val protocol = RatesFixProtocol(tx, n2.legallyIdentifableAddress, fixOf, "0.675".bd, "0.1".bd)
|
||||
BriefLogFormatter.initVerbose("rates")
|
||||
val future = n1.smm.add("rates", protocol)
|
||||
|
Loading…
Reference in New Issue
Block a user