From 8a6897fa0e3e449c5b5f724ba0540cb8289c13e7 Mon Sep 17 00:00:00 2001 From: lunaticbum Date: Fri, 3 Apr 2026 17:47:56 +0900 Subject: [PATCH] .... --- src/main/kotlin/database/DatabaseFactory.kt | 15 ++++ src/main/kotlin/service/AutoTradingManager.kt | 71 ++++++++++--------- src/main/kotlin/ui/TradingDecisionLog.kt | 3 +- 3 files changed, 55 insertions(+), 34 deletions(-) diff --git a/src/main/kotlin/database/DatabaseFactory.kt b/src/main/kotlin/database/DatabaseFactory.kt index 3a3e3cc..d2bcbec 100644 --- a/src/main/kotlin/database/DatabaseFactory.kt +++ b/src/main/kotlin/database/DatabaseFactory.kt @@ -501,6 +501,21 @@ object TradingLogStore { } } + fun addAfterMarketLog(name : String, code : String, log: String) { + synchronized(this) { + if (decisionLogs.size > 1000) decisionLogs.removeAt(0) + decisionLogs.add( + LogEntry( + time = LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss")), + stockName = "$name[$code] 분석", + decision = "AFTER", + confidence = 100.0, + reason = log + ) + ) + } + } + fun addSettingLog(settingDesc : String, old : String, new : String, log: String) { synchronized(this) { if (decisionLogs.size > 1000) decisionLogs.removeAt(0) diff --git a/src/main/kotlin/service/AutoTradingManager.kt b/src/main/kotlin/service/AutoTradingManager.kt index 70d2a3d..60eae83 100644 --- a/src/main/kotlin/service/AutoTradingManager.kt +++ b/src/main/kotlin/service/AutoTradingManager.kt @@ -377,33 +377,39 @@ object AutoTradingManager { ) } else { println("${holding.name} - 매수 : ${holding.avgPrice} - 현재 : ${holding.currentPrice} , 주문 가능 : ${holding.availOrderCount}, 수익율 : ${holding.profitRate}") - if (holding != null && holding.quantity.toInt() > 0 && holding.availOrderCount.toInt() > 0 && holding.profitRate.toDouble() > KisSession.config.SELL_PROFIT) { + if (holding != null && holding.quantity.toInt() > 0 && holding.availOrderCount.toInt() > 0 && holding.profitRate.toDouble() > 0.5) { println("${holding.name} - 매수 : ${holding.avgPrice} - 현재 : ${holding.currentPrice} ") var targetPrice = holding.currentPrice.toDouble() + TradingLogStore.addAfterMarketLog( + holding.name, + holding.code, + "${if ("Y".equals(marketCode)) "시간외 단일가" else "대체거래소"} 시세로 ${holding.profitRate} 수익 예상" + ) + targetPrice = MarketUtil.roundToTickSize(targetPrice) - tradeService.postOrder( - stockCode = holding.code, - qty = holding.availOrderCount, - price = targetPrice.toInt().toString(), - isBuy = false, - orderDivision = if (marketCode.equals("Y")) "07" else "", - marketCode = if (marketCode.equals("Y")) "KRX" else "SOR" - ).onSuccess { newOrderNo -> - println("✅ [재주문 완료] ${holding.name}: $newOrderNo") - TradingLogStore.addSellLog( - holding.code, - targetPrice.toString(), - "SELL", - "🎊 시간외 단일가 주식 재고털이 주문 완료" - ) - }.onFailure { - TradingLogStore.addSellLog( - holding.code, - targetPrice.toString(), - "SELL", - "🎊 시간외 단일가 주식 재고털이 주문 실패[${it.message}] " - ) - } +// tradeService.postOrder( +// stockCode = holding.code, +// qty = holding.availOrderCount, +// price = targetPrice.toInt().toString(), +// isBuy = false, +// orderDivision = if (marketCode.equals("Y")) "07" else "", +// marketCode = if (marketCode.equals("Y")) "KRX" else "SOR" +// ).onSuccess { newOrderNo -> +// println("✅ [재주문 완료] ${holding.name}: $newOrderNo") +// TradingLogStore.addSellLog( +// holding.code, +// targetPrice.toString(), +// "SELL", +// "🎊 시간외 단일가 주식 재고털이 주문 완료" +// ) +// }.onFailure { +// TradingLogStore.addSellLog( +// holding.code, +// targetPrice.toString(), +// "SELL", +// "🎊 시간외 단일가 주식 재고털이 주문 실패[${it.message}] " +// ) +// } } delay(300) // API 호출 부하 방지 } @@ -619,12 +625,12 @@ object AutoTradingManager { if (AUTOSELL) balance?.let { resumePendingSellOrders(KisTradeService, it) } return balance } else { -// listOf("Y","X").forEach { code -> -// KisTradeService.fetchIntegratedBalance(code).getOrNull()?.let { -// sellingAfterMarketOnePrice(KisTradeService, it, code) -// } -// delay(1000) -// } + listOf("Y","X").forEach { code -> + KisTradeService.fetchIntegratedBalance(code).getOrNull()?.let { + sellingAfterMarketOnePrice(KisTradeService, it, code) + } + delay(1000) + } } return null } @@ -710,15 +716,14 @@ object AutoTradingManager { lastForceCheckMinute = currentMinute // 실행 완료 기록 } } - else if((now.hour == 16 || now.hour == 17) && (currentMinute == 31 || currentMinute == 36)) { + else if((now.hour == 16 || now.hour == 17) && (currentMinute % 10 == 3 || currentMinute % 10 == 9)) { if (lastForceCheckMinute != currentMinute) { TradingLogStore.addAnalyzer( " - ", " - ", - "⏰ [강제 스케줄 실행] 오후 ${now.hour}시 ${currentMinute}분 - 보유주식 시간외 단일가 매도 체크를 시작합니다.", + "⏰ [강제 스케줄 실행] 오후 ${now.hour}시 ${currentMinute}분 - 보유주식 시간외 단일가 또는 대체마켓 체크를 시작합니다.", true ) - println("⏰ [강제 스케줄 실행] 오후 ${now.hour}시 ${currentMinute}분 - 보유주식 시간외 단일가 매도 체크를 시작합니다.") checkBalance(false) lastForceCheckMinute = currentMinute // 실행 완료 기록 } diff --git a/src/main/kotlin/ui/TradingDecisionLog.kt b/src/main/kotlin/ui/TradingDecisionLog.kt index e981625..5014fab 100644 --- a/src/main/kotlin/ui/TradingDecisionLog.kt +++ b/src/main/kotlin/ui/TradingDecisionLog.kt @@ -35,7 +35,7 @@ fun TradingDecisionLog() { val coroutineScope = rememberCoroutineScope() var searchQuery by remember { mutableStateOf("") } var selectedFilters by remember { mutableStateOf(setOf("전체")) } - val filterOptions = listOf("전체", "BUY", "SELL", "HOLD", "SETTING","ANALYZER","PASS","WATCH","RETRY") + val filterOptions = listOf("전체", "BUY", "SELL", "HOLD", "SETTING","ANALYZER","PASS","WATCH","RETRY","AFTER") var llmAnalyser by remember { mutableStateOf(AutoTradingManager.llmAnalyser) } LaunchedEffect(AutoTradingManager.llmAnalyser) { llmAnalyser = AutoTradingManager.llmAnalyser @@ -164,6 +164,7 @@ fun TradingDecisionLog() { "PASS" -> Color.Yellow "RETRY" -> Color(0xFF00BCD4) // [추가] 하늘색 (재분석/대기열) "WATCH" -> Color(0xFF4CAF50) // [추가] 연초록 (관심 종목 감시) + "AFTER" -> Color.Red else -> Color.DarkGray }, fontWeight = FontWeight.ExtraBold