diff --git a/src/main/kotlin/database/DatabaseFactory.kt b/src/main/kotlin/database/DatabaseFactory.kt index 8176959..a0f7bfd 100644 --- a/src/main/kotlin/database/DatabaseFactory.kt +++ b/src/main/kotlin/database/DatabaseFactory.kt @@ -242,7 +242,7 @@ object DatabaseFactory { fun findAllMonitoringTrades(): List { return transaction(mainDb) { AutoTradeTable.select { - AutoTradeTable.status neq "COMPLETED" + AutoTradeTable.status notInList listOf(TradeStatus.COMPLETED, TradeStatus.EXPIRED) }.map { mapToAutoTradeItem(it) } } } diff --git a/src/main/kotlin/network/KisTradeService.kt b/src/main/kotlin/network/KisTradeService.kt index 2c43907..97e29f1 100644 --- a/src/main/kotlin/network/KisTradeService.kt +++ b/src/main/kotlin/network/KisTradeService.kt @@ -654,7 +654,7 @@ object KisTradeService { pageCount++ trCont = "N" println("⏳ [연속 조회] 250ms 대기 후 다음 페이지 요청...") - delay(350) // API 과부하 방지 + delay(400) // API 과부하 방지 } } while (trCont == "N") diff --git a/src/main/kotlin/service/AutoTradingManager.kt b/src/main/kotlin/service/AutoTradingManager.kt index 3970f89..7fe1b92 100644 --- a/src/main/kotlin/service/AutoTradingManager.kt +++ b/src/main/kotlin/service/AutoTradingManager.kt @@ -1,7 +1,6 @@ package service import AutoTradeItem -import Defines.AUTOSELL import Defines.BLACKLISTEDSTOCKCODES import Defines.EMBEDDING_PORT import Defines.LLM_PORT @@ -40,7 +39,6 @@ import network.KisWebSocketManager import network.RagService import network.RagService.isSafetyBeltStockCodes import network.StockUniverseLoader -import report.SnapshotType import report.TradingReportManager import util.MarketUtil import java.time.LocalDate @@ -771,8 +769,9 @@ object AutoTradingManager { } withTimeout(CYCLE_TIMEOUT) { println("⏱️ [Cycle Start] ${LocalTime.now()}") - if (now.isAfter(KisSession.endTime())) { - executeClosingLiquidation(KisTradeService) + val activeTrades = DatabaseFactory.findAllMonitoringTrades() + if (now.isAfter(LocalTime.of(15, 30)) && activeTrades.isNotEmpty()) { + executeClosingLiquidation(activeTrades) } else { executeMarketLoop() } @@ -818,7 +817,7 @@ object AutoTradingManager { } } var loadedTops = mutableListOf>() - var defaultStockCount = 200 + var defaultStockCount = 150 fun poll100Stocks(): List> { loadedTops.shuffle() val count = minOf(loadedTops.size, defaultStockCount) @@ -946,9 +945,13 @@ object AutoTradingManager { if( it.quantity.toInt() > KisSession.tradeConfig.lowerAverageTargetCount && it.profitRate.toDouble() < (KisSession.tradeConfig.lowerAverageMaxRate * -1) && - it.profitRate.toDouble() > (KisSession.tradeConfig.lowerAverageMinRate * -1) ) + it.profitRate.toDouble() > (KisSession.tradeConfig.lowerAverageMinRate * -1) && + it.code !in pendingStocks && + it.code !in executionCache.values.map { it.code } && + it.code !in failList && + it.code !in isSafetyBeltStockCodes) { - candidates.add(RankingStock(mksc_shrn_iscd = it.code, hts_kor_isnm = it.name)) + remainingCandidates.add(RankingStock(mksc_shrn_iscd = it.code, hts_kor_isnm = it.name)) } } } @@ -982,7 +985,7 @@ object AutoTradingManager { iterator.remove() } println("남은 후보군 개수 : ${totalCount}") - delay(100) + delay(500) } } sellSchedule() @@ -1089,7 +1092,7 @@ object AutoTradingManager { val currentPrice = today.stck_prpr.toDouble() if ((myCash > 10L && currentPrice > myCash) || currentPrice > maxBudget || currentPrice > maxPrice || currentPrice < minPrice) { - print("-> 가격 정책으로 제외 [1주:${currentPrice}, 자산:${myCash}, 최소 기준:${minPrice}, 최대 기준:${maxPrice}] | ") + print("-> [${stock.name}] 가격 정책으로 제외 [1주:${currentPrice}, 자산:${myCash}, 최소 기준:${minPrice}, 최대 기준:${maxPrice}] | ") return@withTimeout } @@ -1174,18 +1177,10 @@ object AutoTradingManager { } - private suspend fun executeClosingLiquidation(tradeService: KisTradeService) { - val activeTrades = DatabaseFactory.findAllMonitoringTrades() - val balanceResult = tradeService.fetchIntegratedBalance().getOrNull() - val realHoldings = balanceResult?.getHoldings()?.associateBy { it.code } ?: emptyMap() - + private suspend fun executeClosingLiquidation(activeTrades: List) { activeTrades.forEach { trade -> try { - if (!realHoldings.containsKey(trade.code)) { - DatabaseFactory.updateStatusAndOrderNo(trade.id!!, TradeStatus.EXPIRED) - return@forEach - } - // 마감 정리 로직 (필요 시 주석 해제하여 사용) + DatabaseFactory.updateStatusAndOrderNo(trade.id!!, TradeStatus.EXPIRED) println("📢 [마감 정리 체크] ${trade.name}") } catch (e: Exception) { println("⚠️ [마감 에러] ${trade.name}: ${e.message}")