From 5a504ffa31909d5e84791968442ed2cfb9a68684 Mon Sep 17 00:00:00 2001 From: lunaticbum Date: Wed, 8 Apr 2026 15:45:18 +0900 Subject: [PATCH] ... --- src/main/kotlin/service/AutoTradingManager.kt | 114 +++++++++--------- 1 file changed, 54 insertions(+), 60 deletions(-) diff --git a/src/main/kotlin/service/AutoTradingManager.kt b/src/main/kotlin/service/AutoTradingManager.kt index 8d9e26f..4138471 100644 --- a/src/main/kotlin/service/AutoTradingManager.kt +++ b/src/main/kotlin/service/AutoTradingManager.kt @@ -127,7 +127,7 @@ object AutoTradingManager { addToReanalysis(RankingStock(decision.stockCode, decision.stockName)) } } else { - + } } @@ -368,8 +368,6 @@ object AutoTradingManager { "${if ("Y".equals(marketCode)) "시간외 단일가" else "대체거래소"} 시세로 ${holding.profitRate} 수익 예상" ) - targetPrice = MarketUtil.roundToTickSize(targetPrice + MarketUtil.getTickSize(targetPrice)) - tradeService.postOrder( stockCode = holding.code, qty = holding.availOrderCount, @@ -383,14 +381,14 @@ object AutoTradingManager { holding.code, targetPrice.toString(), "SELL", - "🎊 시간외 단일가 주식 재고털이 주문 완료" + "🎊 ${if(marketCode.equals("Y"))"시간외 단일가" else "대체거래소"} 주식 재고털이 주문 완료" ) }.onFailure { TradingLogStore.addSellLog( holding.code, targetPrice.toString(), "SELL", - "🎊 시간외 단일가 주식 재고털이 주문 실패[${it.message}] " + "🎊 ${if(marketCode.equals("Y"))"시간외 단일가" else "대체거래소"} 주식 재고털이 주문 실패[${it.message}] " ) } } else { @@ -405,57 +403,59 @@ object AutoTradingManager { suspend fun resumePendingSellOrders(tradeService: KisTradeService,balance : UnifiedBalance) { val now = LocalTime.now() val currentMinute = now.minute -// if (now.isBefore(H16) && now.isAfter(H08M35)) { - println("resumePendingSellOrders") - balance.holdings.forEach { holding -> - if (BLACKLISTEDSTOCKCODES.contains(holding.code)){ - println("❌ 차단 처리된 주식 : ${holding.name}") - TradingLogStore.addAnalyzer( - holding.name, - holding.code, - "거랙 차단 대상 : ${holding.currentPrice}[${holding.quantity}주] 보유, 수익률(${holding.profitRate.toDouble()})" - ) - } else { - if (holding != null && holding.quantity.toInt() > 0 && holding.availOrderCount.toInt() > 0 && holding.profitRate.toDouble() > KisSession.config.SELL_PROFIT) { - var targetPrice = holding.currentPrice.toDouble() - val now = LocalTime.now() - val currentMinute = now.minute - var isBefore930 = false - if (now.hour == 9 && currentMinute < 30) { - targetPrice = targetPrice - isBefore930 = true - } else { - targetPrice = MarketUtil.roundToTickSize(targetPrice + MarketUtil.getTickSize(targetPrice)) - } - println("🔄 [보유 주식 주문] ${holding.name} (${holding.code}) 매도 목표 ${targetPrice} 미체결 매도 건 재주문 시도") - tradeService.postOrder( - stockCode = holding.code, - qty = holding.availOrderCount, - price = targetPrice.toInt().toString(), - isBuy = false, - ).onSuccess { newOrderNo -> - println("✅ [보유 주식 주문 완료] ${holding.name}: $newOrderNo") - TradingLogStore.addSellLog( - holding.code, - targetPrice.toString(), - "SELL", - "🎊 보유 주식[예상수익 : ${holding.profitRate}] ${if (isBefore930) "09:30 이전 현시세{${holding.currentPrice}}로 매도[$targetPrice] 주문" else "09:30 이후 시세{${holding.currentPrice}} 기준 호가 위 매도[$targetPrice] 주문"} 완료" - ) - }.onFailure { - TradingLogStore.addSellLog( - holding.code, - targetPrice.toString(), - "SELL", - "🎊 보유 주식 매도 주문 실패[${it.message}] " - ) - } + if (now.isBefore(H15M30) && now.isAfter(H08M45)) { + + + println("resumePendingSellOrders") + balance.holdings.forEach { holding -> + if (BLACKLISTEDSTOCKCODES.contains(holding.code)){ + println("❌ 차단 처리된 주식 : ${holding.name}") + TradingLogStore.addAnalyzer( + holding.name, + holding.code, + "거랙 차단 대상 : ${holding.currentPrice}[${holding.quantity}주] 보유, 수익률(${holding.profitRate.toDouble()})" + ) } else { - analyzeDeepLossHoldingsAfterMarket(holding) + if (holding != null && holding.quantity.toInt() > 0 && holding.availOrderCount.toInt() > 0 && holding.profitRate.toDouble() > KisSession.config.SELL_PROFIT) { + var targetPrice = holding.currentPrice.toDouble() + val now = LocalTime.now() + val currentMinute = now.minute + var isBefore930 = false + if (now.hour == 9 && currentMinute < 30) { + targetPrice = targetPrice + isBefore930 = true + } else { + targetPrice = MarketUtil.roundToTickSize(targetPrice + MarketUtil.getTickSize(targetPrice)) + } + println("🔄 [보유 주식 주문] ${holding.name} (${holding.code}) 매도 목표 ${targetPrice} 미체결 매도 건 재주문 시도") + tradeService.postOrder( + stockCode = holding.code, + qty = holding.availOrderCount, + price = targetPrice.toInt().toString(), + isBuy = false, + ).onSuccess { newOrderNo -> + println("✅ [보유 주식 주문 완료] ${holding.name}: $newOrderNo") + TradingLogStore.addSellLog( + holding.code, + targetPrice.toString(), + "SELL", + "🎊 보유 주식[예상수익 : ${holding.profitRate}] ${if (isBefore930) "09:30 이전 현시세{${holding.currentPrice}}로 매도[$targetPrice] 주문" else "09:30 이후 시세{${holding.currentPrice}} 기준 호가 위 매도[$targetPrice] 주문"} 완료" + ) + }.onFailure { + TradingLogStore.addSellLog( + holding.code, + targetPrice.toString(), + "SELL", + "🎊 보유 주식 매도 주문 실패[${it.message}] " + ) + } + } else { + analyzeDeepLossHoldingsAfterMarket(holding) + } + delay(200) // API 호출 부하 방지 } - delay(200) // API 호출 부하 방지 } } -// } } private suspend fun analyzeDeepLossHoldingsAfterMarket(holding: UnifiedStockHolding) { // 💡 [신규 추가] 수익률이 크게 마이너스인 종목(-5.0% 이하) 심층 가이드 분석 @@ -577,7 +577,7 @@ object AutoTradingManager { currentTimeMillis = System.currentTimeMillis() lastTickTime.set(System.currentTimeMillis()) // 생존 신고 when { - now.isAfter(H18) || now.isBefore(H08M00) -> { + now.isAfter(H18) || now.isBefore(H07M50) -> { prepareMarketOpen(now) } now.isBefore(H18) && now.isAfter(H08M00) -> { @@ -601,11 +601,6 @@ object AutoTradingManager { } } } -// -// //장외 -// now.isAfter(H16) || now.isBefore(H08M35) -> { -// finalizeMarketClose(now) -// } else ->{ waitTime = 3.0 } @@ -722,7 +717,7 @@ object AutoTradingManager { while (iterator.hasNext()) { totalCount-- val stock = iterator.next() - if (now.isBefore(H16) && now.isAfter(H08M45)) { + if (now.isBefore(H15M30) && now.isAfter(H08M45)) { if (BLACKLISTEDSTOCKCODES.contains(stock.code)) { println("❌ 차단 처리된 주식 : ${stock.name}") } else { @@ -746,7 +741,6 @@ object AutoTradingManager { val now = LocalTime.now() val currentMinute = now.minute - println("매도 스케줄 체크") if (now.hour == 9 && (currentMinute % 10 == 1 || currentMinute % 10 == 7)) { if (lastForceCheckMinute != currentMinute) { TradingLogStore.addAnalyzer(" - ", " - ", "⏰ [강제 스케줄 실행] 오전 9시 ${currentMinute}분 - 보유주식 매도 체크를 시작합니다.", true)