Market order logging
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -39,5 +39,6 @@ out/
|
|||||||
### Kotlin ###
|
### Kotlin ###
|
||||||
.kotlin
|
.kotlin
|
||||||
|
|
||||||
# simpler tests
|
# testing sideeffects
|
||||||
test_steering_signals.log
|
*steering_signals.log
|
||||||
|
*market_orders.log
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.frankenergie.smartasset.client
|
||||||
|
|
||||||
|
import com.frankenergie.smartasset.model.MarketOrder
|
||||||
|
import org.springframework.beans.factory.annotation.Value
|
||||||
|
import org.springframework.stereotype.Component
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.nio.file.StandardOpenOption
|
||||||
|
|
||||||
|
@Component
|
||||||
|
class MarketOrderClient(
|
||||||
|
@Value("\${market.orders.file:market_orders.log}") private val filePath: String
|
||||||
|
) {
|
||||||
|
private val file: Path = Path.of(filePath)
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (!Files.exists(file)) {
|
||||||
|
Files.createFile(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendOrder(order: MarketOrder) {
|
||||||
|
val line = formatOrder(order)
|
||||||
|
Files.writeString(file, "$line\n", StandardOpenOption.APPEND)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAllOrders(): List<String> {
|
||||||
|
if (!Files.exists(file)) return emptyList()
|
||||||
|
return Files.readAllLines(file).filter { it.isNotBlank() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clear() {
|
||||||
|
Files.writeString(file, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun formatOrder(order: MarketOrder): String {
|
||||||
|
return "${order.timestamp}|${order.orderId}|${order.groupId}|${order.deliveryStart}|${order.deliveryEnd}|${order.side}|${order.quantity}|${order.price}"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.frankenergie.smartasset.model
|
||||||
|
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import java.time.Instant
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
|
data class MarketOrder(
|
||||||
|
val orderId: String,
|
||||||
|
val groupId: String,
|
||||||
|
val deliveryStart: LocalDateTime,
|
||||||
|
val deliveryEnd: LocalDateTime,
|
||||||
|
val side: OrderSide,
|
||||||
|
val quantity: BigDecimal,
|
||||||
|
val price: BigDecimal,
|
||||||
|
val timestamp: Instant = Instant.now()
|
||||||
|
)
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
package com.frankenergie.smartasset.client
|
||||||
|
|
||||||
|
import com.frankenergie.smartasset.model.MarketOrder
|
||||||
|
import com.frankenergie.smartasset.model.OrderSide
|
||||||
|
import org.junit.jupiter.api.AfterEach
|
||||||
|
import org.junit.jupiter.api.Assertions.*
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
|
class MarketOrderClientTest {
|
||||||
|
|
||||||
|
private val testFilePath = "./test_market_orders.log"
|
||||||
|
private lateinit var client: MarketOrderClient
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun setUp() {
|
||||||
|
Files.deleteIfExists(Path.of(testFilePath))
|
||||||
|
client = MarketOrderClient(testFilePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
fun tearDown() {
|
||||||
|
Files.deleteIfExists(Path.of(testFilePath))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `sendOrder writes order to file`() {
|
||||||
|
val order = MarketOrder(
|
||||||
|
orderId = "order-123",
|
||||||
|
groupId = "A",
|
||||||
|
deliveryStart = LocalDateTime.of(2024, 1, 15, 10, 0),
|
||||||
|
deliveryEnd = LocalDateTime.of(2024, 1, 15, 10, 15),
|
||||||
|
side = OrderSide.BUY,
|
||||||
|
quantity = BigDecimal("10"),
|
||||||
|
price = BigDecimal("50.00")
|
||||||
|
)
|
||||||
|
|
||||||
|
client.sendOrder(order)
|
||||||
|
|
||||||
|
val lines = client.getAllOrders()
|
||||||
|
assertEquals(1, lines.size)
|
||||||
|
assertTrue(lines[0].contains("order-123"))
|
||||||
|
assertTrue(lines[0].contains("A"))
|
||||||
|
assertTrue(lines[0].contains("BUY"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `multiple orders written on separate lines`() {
|
||||||
|
val order1 = MarketOrder(
|
||||||
|
"order-1",
|
||||||
|
"A",
|
||||||
|
LocalDateTime.of(2024, 1, 15, 10, 0),
|
||||||
|
LocalDateTime.of(2024, 1, 15, 10, 15),
|
||||||
|
OrderSide.BUY,
|
||||||
|
BigDecimal("10"),
|
||||||
|
BigDecimal("50.00")
|
||||||
|
)
|
||||||
|
val order2 = MarketOrder(
|
||||||
|
"order-2",
|
||||||
|
"B",
|
||||||
|
LocalDateTime.of(2024, 1, 15, 10, 15),
|
||||||
|
LocalDateTime.of(2024, 1, 15, 10, 30),
|
||||||
|
OrderSide.SELL,
|
||||||
|
BigDecimal("5"),
|
||||||
|
BigDecimal("55.00")
|
||||||
|
)
|
||||||
|
|
||||||
|
client.sendOrder(order1)
|
||||||
|
client.sendOrder(order2)
|
||||||
|
|
||||||
|
val lines = client.getAllOrders()
|
||||||
|
assertEquals(2, lines.size)
|
||||||
|
assertTrue(lines[0].contains("order-1"))
|
||||||
|
assertTrue(lines[0].contains("BUY"))
|
||||||
|
assertTrue(lines[1].contains("order-2"))
|
||||||
|
assertTrue(lines[1].contains("SELL"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `clear removes all orders`() {
|
||||||
|
val order = MarketOrder(
|
||||||
|
"order-1",
|
||||||
|
"A",
|
||||||
|
LocalDateTime.of(2024, 1, 15, 10, 0),
|
||||||
|
LocalDateTime.of(2024, 1, 15, 10, 15),
|
||||||
|
OrderSide.BUY,
|
||||||
|
BigDecimal("10"),
|
||||||
|
BigDecimal("50.00")
|
||||||
|
)
|
||||||
|
client.sendOrder(order)
|
||||||
|
|
||||||
|
client.clear()
|
||||||
|
|
||||||
|
assertTrue(client.getAllOrders().isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `tracks both buy and sell orders`() {
|
||||||
|
val buyOrder = MarketOrder(
|
||||||
|
"buy-1",
|
||||||
|
"A",
|
||||||
|
LocalDateTime.of(2024, 1, 15, 10, 0),
|
||||||
|
LocalDateTime.of(2024, 1, 15, 10, 15),
|
||||||
|
OrderSide.BUY,
|
||||||
|
BigDecimal("10"),
|
||||||
|
BigDecimal("50.00")
|
||||||
|
)
|
||||||
|
val sellOrder = MarketOrder(
|
||||||
|
"sell-1",
|
||||||
|
"A",
|
||||||
|
LocalDateTime.of(2024, 1, 15, 10, 0),
|
||||||
|
LocalDateTime.of(2024, 1, 15, 10, 15),
|
||||||
|
OrderSide.SELL,
|
||||||
|
BigDecimal("10"),
|
||||||
|
BigDecimal("55.00")
|
||||||
|
)
|
||||||
|
|
||||||
|
client.sendOrder(buyOrder)
|
||||||
|
client.sendOrder(sellOrder)
|
||||||
|
|
||||||
|
val lines = client.getAllOrders()
|
||||||
|
assertEquals(2, lines.size)
|
||||||
|
assertTrue(lines.any { it.contains("BUY") })
|
||||||
|
assertTrue(lines.any { it.contains("SELL") })
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user