리포팅 테스트
This commit is contained in:
@@ -1,11 +1,17 @@
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import kotlinx.serialization.Serializable
|
||||
import model.AppConfig
|
||||
import network.TradingDecision
|
||||
import model.TradingDecision
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
import org.jetbrains.exposed.sql.javatime.datetime
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import report.TradingReportManager
|
||||
import report.TradingReportService
|
||||
import report.database.AssetSnapshotTable
|
||||
import report.database.ExecutionDetailsTable
|
||||
import report.database.SnapshotHoldingsTable
|
||||
import report.database.TradeHistoryTable
|
||||
import java.io.File
|
||||
import java.time.LocalDateTime
|
||||
import java.time.LocalTime
|
||||
@@ -116,21 +122,40 @@ object HolidayTable : Table("holiday_cache") {
|
||||
}
|
||||
|
||||
object DatabaseFactory {
|
||||
val reporter: TradingReportService get() = TradingReportManager
|
||||
lateinit var mainDb: Database
|
||||
lateinit var reportDb: Database
|
||||
|
||||
fun init() {
|
||||
val dbPath = File("db/autotrade_db").absolutePath
|
||||
Database.connect(
|
||||
"jdbc:h2:$dbPath;DB_CLOSE_DELAY=-1;",
|
||||
mainDb = Database.connect(
|
||||
"jdbc:h2:${File("db/autotrade_db").absolutePath};DB_CLOSE_DELAY=-1;",
|
||||
driver = "org.h2.Driver"
|
||||
)
|
||||
|
||||
transaction {
|
||||
reportDb = Database.connect(
|
||||
"jdbc:h2:${File("db/trade_report").absolutePath};DB_CLOSE_DELAY=-1;",
|
||||
driver = "org.h2.Driver"
|
||||
)
|
||||
|
||||
transaction(reportDb) {
|
||||
SchemaUtils.createMissingTablesAndColumns(
|
||||
AssetSnapshotTable,
|
||||
SnapshotHoldingsTable,
|
||||
TradeHistoryTable,
|
||||
ExecutionDetailsTable
|
||||
)
|
||||
}
|
||||
|
||||
transaction(mainDb) {
|
||||
// 테이블 생성 (AutoTradeTable 포함)
|
||||
SchemaUtils.createMissingTablesAndColumns(ConfigTable, TradeLogTable, AutoTradeTable,HolidayTable)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun saveHoliday(date: String, holiday: Boolean) = transaction {
|
||||
fun saveHoliday(date: String, holiday: Boolean) = transaction(mainDb) {
|
||||
HolidayTable.replace {
|
||||
it[bassDt] = date
|
||||
it[isHoliday] = holiday
|
||||
@@ -138,7 +163,7 @@ object DatabaseFactory {
|
||||
}
|
||||
|
||||
// 특정 날짜의 휴장 여부 조회
|
||||
fun getHoliday(date: String): Boolean? = transaction {
|
||||
fun getHoliday(date: String): Boolean? = transaction(mainDb) {
|
||||
HolidayTable.select { HolidayTable.bassDt eq date }
|
||||
.map { it[HolidayTable.isHoliday] }
|
||||
.singleOrNull()
|
||||
@@ -147,7 +172,7 @@ object DatabaseFactory {
|
||||
/**
|
||||
* 새로운 자동매매 건 등록 (주로 PENDING_BUY 상태로 시작)
|
||||
*/
|
||||
fun saveAutoTrade(item: AutoTradeItem) = transaction {
|
||||
fun saveAutoTrade(item: AutoTradeItem) = transaction(mainDb) {
|
||||
AutoTradeTable.insert {
|
||||
it[stockCode] = item.code
|
||||
it[stockName] = item.name
|
||||
@@ -165,7 +190,7 @@ object DatabaseFactory {
|
||||
/**
|
||||
* 상태 변경 및 가격 업데이트 (예: PENDING_BUY -> MONITORING)
|
||||
*/
|
||||
fun updateAutoTrade(item: AutoTradeItem) = transaction {
|
||||
fun updateAutoTrade(item: AutoTradeItem) = transaction(mainDb) {
|
||||
val id = item.id ?: return@transaction
|
||||
AutoTradeTable.update({ AutoTradeTable.id eq id }) {
|
||||
it[targetPrice] = item.targetPrice
|
||||
@@ -178,7 +203,7 @@ object DatabaseFactory {
|
||||
/**
|
||||
* 감시 중인 모든 종목 리스트 반환 (ActiveTradeSection UI용)
|
||||
*/
|
||||
fun getActiveAutoTrades(): List<AutoTradeItem> = transaction {
|
||||
fun getActiveAutoTrades(): List<AutoTradeItem> = transaction(mainDb) {
|
||||
AutoTradeTable.select {
|
||||
AutoTradeTable.status inList listOf("MONITORING", "SELLING", "PENDING_BUY")
|
||||
}.map { mapToAutoTradeItem(it) }
|
||||
@@ -187,18 +212,18 @@ object DatabaseFactory {
|
||||
/**
|
||||
* 종목코드로 현재 감시 중인 설정이 있는지 확인 (UI 체크박스 상태용)
|
||||
*/
|
||||
fun findConfigByCode(code: String): AutoTradeItem? = transaction {
|
||||
fun findConfigByCode(code: String): AutoTradeItem? = transaction(mainDb) {
|
||||
AutoTradeTable.select {
|
||||
(AutoTradeTable.stockCode eq code) and (AutoTradeTable.status eq "MONITORING")
|
||||
}.lastOrNull()?.let { mapToAutoTradeItem(it) }
|
||||
}
|
||||
|
||||
fun deleteAutoTrade(id: Int) = transaction {
|
||||
fun deleteAutoTrade(id: Int) = transaction(mainDb) {
|
||||
AutoTradeTable.deleteWhere { AutoTradeTable.id eq id }
|
||||
}
|
||||
|
||||
fun findAllPendingBuyCodes(): Set<String> {
|
||||
return transaction {
|
||||
return transaction(mainDb) {
|
||||
AutoTradeTable.select {
|
||||
(AutoTradeTable.status eq "PENDING_BUY") or (AutoTradeTable.status eq "ORDERED")
|
||||
}.map { it[AutoTradeTable.stockCode] }.toSet()
|
||||
@@ -206,7 +231,7 @@ object DatabaseFactory {
|
||||
}
|
||||
|
||||
fun findAllMonitoringTrades(): List<AutoTradeItem> {
|
||||
return transaction {
|
||||
return transaction(mainDb) {
|
||||
AutoTradeTable.select {
|
||||
AutoTradeTable.status neq "COMPLETED"
|
||||
}.map { mapToAutoTradeItem(it) }
|
||||
@@ -230,7 +255,7 @@ object DatabaseFactory {
|
||||
// --- 기존 설정 및 로그 관련 함수 ---
|
||||
|
||||
fun saveTradeLog(code: String, name: String, type: String, price: Double, qty: Int, msg: String) {
|
||||
transaction {
|
||||
transaction(mainDb) {
|
||||
TradeLogTable.insert {
|
||||
it[stockCode] = code
|
||||
it[stockName] = name
|
||||
@@ -243,7 +268,7 @@ object DatabaseFactory {
|
||||
}
|
||||
}
|
||||
|
||||
fun findConfigByAccount(accountNo: String): AppConfig? = transaction {
|
||||
fun findConfigByAccount(accountNo: String): AppConfig? = transaction(mainDb) {
|
||||
ConfigTable.select {
|
||||
(ConfigTable.realAccountNo eq accountNo) or (ConfigTable.vtsAccountNo eq accountNo)
|
||||
}.lastOrNull()?.let {
|
||||
@@ -287,8 +312,8 @@ object DatabaseFactory {
|
||||
stop_Loss = it[ConfigTable.stop_Loss],
|
||||
take_profit = it[ConfigTable.take_profit],
|
||||
loss_min = it[ConfigTable.loss_minrate],
|
||||
loss_max = it[ConfigTable.loss_maxrate],
|
||||
loss_money = it[ConfigTable.loss_max_money],
|
||||
loss_max = it[ConfigTable.loss_maxrate],
|
||||
loss_money = it[ConfigTable.loss_max_money],
|
||||
MAX_COUNT = it[ConfigTable.max_count],
|
||||
max_holding_count = it[ConfigTable.max_holding_count],
|
||||
)
|
||||
@@ -296,7 +321,7 @@ object DatabaseFactory {
|
||||
}
|
||||
|
||||
fun saveConfig(config: AppConfig) {
|
||||
transaction {
|
||||
transaction(mainDb) {
|
||||
ConfigTable.deleteAll()
|
||||
ConfigTable.insert {
|
||||
it[realAppKey] = config.realAppKey
|
||||
@@ -346,7 +371,7 @@ object DatabaseFactory {
|
||||
}
|
||||
}
|
||||
|
||||
fun saveOrUpdate(item: AutoTradeItem) = transaction {
|
||||
fun saveOrUpdate(item: AutoTradeItem) = transaction(mainDb) {
|
||||
val existing = AutoTradeTable.select { AutoTradeTable.orderNo eq item.orderNo }.firstOrNull()
|
||||
if (existing == null) {
|
||||
AutoTradeTable.insert {
|
||||
@@ -371,7 +396,7 @@ object DatabaseFactory {
|
||||
/**
|
||||
* 주문번호로 항목 조회 (가장 핵심적인 식별자)
|
||||
*/
|
||||
fun findByOrderNo(orderNo: String): AutoTradeItem? = transaction {
|
||||
fun findByOrderNo(orderNo: String): AutoTradeItem? = transaction(mainDb) {
|
||||
AutoTradeTable.select { AutoTradeTable.orderNo eq orderNo }
|
||||
.map { mapToAutoTradeItem(it) }
|
||||
.singleOrNull()
|
||||
@@ -380,7 +405,7 @@ object DatabaseFactory {
|
||||
/**
|
||||
* 서버 동기화: DB에는 PENDING_BUY/MONITORING인데 서버 미체결 내역에 없는 경우 EXPIRED로 변경
|
||||
*/
|
||||
fun syncWithServer(serverOrderNos: List<String>) = transaction {
|
||||
fun syncWithServer(serverOrderNos: List<String>) = transaction(mainDb) {
|
||||
AutoTradeTable.update({
|
||||
(AutoTradeTable.status inList listOf(TradeStatus.PENDING_BUY, TradeStatus.MONITORING)) and
|
||||
(AutoTradeTable.orderNo notInList serverOrderNos)
|
||||
@@ -392,7 +417,7 @@ object DatabaseFactory {
|
||||
/**
|
||||
* 상태 업데이트 및 주문번호 갱신 (예: 매수체결 시 신규 익절 주문번호로 교체)
|
||||
*/
|
||||
fun updateStatusAndOrderNo(id: Int, newStatus: String, newOrderNo: String? = null) = transaction {
|
||||
fun updateStatusAndOrderNo(id: Int, newStatus: String, newOrderNo: String? = null) = transaction(mainDb) {
|
||||
AutoTradeTable.update({ AutoTradeTable.id eq id }) {
|
||||
it[status] = newStatus
|
||||
if (newOrderNo != null) it[orderNo] = newOrderNo
|
||||
@@ -402,7 +427,7 @@ object DatabaseFactory {
|
||||
/**
|
||||
* 감시 중인 모든 종목 리스트 (Status별 필터링 용이하게 수정)
|
||||
*/
|
||||
fun getAutoTradesByStatus(statusList: List<String>): List<AutoTradeItem> = transaction {
|
||||
fun getAutoTradesByStatus(statusList: List<String>): List<AutoTradeItem> = transaction(mainDb) {
|
||||
AutoTradeTable.select { AutoTradeTable.status inList statusList }
|
||||
.map { mapToAutoTradeItem(it) }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user