diff --git a/src/main/kotlin/model/AppConfig.kt b/src/main/kotlin/model/AppConfig.kt index ff7d13d..2d1aa1b 100644 --- a/src/main/kotlin/model/AppConfig.kt +++ b/src/main/kotlin/model/AppConfig.kt @@ -5,9 +5,10 @@ import java.time.LocalDateTime const val feesAndTaxRate = 0.33 const val minimumNetProfit = 0.35 const val buyWeight = 2.0 -val MAX_BUDGET = 40000.0 -val MAX_PRICE = 20000 -val MIN_PRICE = 1500 +val MAX_BUDGET = 60000.0 +val MAX_PRICE = 30000 +val MIN_PRICE = 1000 +val MIN_PURCHASE_SCORE = 65.0 data class AppConfig( // [DB 저장 데이터] // 실전 3종 diff --git a/src/main/kotlin/network/KisTradeService.kt b/src/main/kotlin/network/KisTradeService.kt index 920ff2a..c7fa080 100644 --- a/src/main/kotlin/network/KisTradeService.kt +++ b/src/main/kotlin/network/KisTradeService.kt @@ -83,7 +83,6 @@ object KisTradeService { val totalAmt = (domRes?.output2?.firstOrNull()?.tot_evlu_amt?.toLongOrNull() ?: 0L) + (ovsRes?.output2?.firstOrNull()?.tot_evlu_amt?.toLongOrNull() ?: 0L) val depositAmt = domRes?.output2?.firstOrNull()?.dnca_tot_amt?.toLongOrNull() ?: 0L - println("fetchIntegratedBalance O") Result.success(UnifiedBalance( totalAsset = String.format("%,d", totalAmt), totalProfitRate = domRes?.output2?.firstOrNull()?.evlu_pfls_rt ?: "0.0", diff --git a/src/main/kotlin/network/KisWebSocketManager.kt b/src/main/kotlin/network/KisWebSocketManager.kt index 55d021b..4d55b32 100644 --- a/src/main/kotlin/network/KisWebSocketManager.kt +++ b/src/main/kotlin/network/KisWebSocketManager.kt @@ -133,8 +133,7 @@ class KisWebSocketManager { // AES 복호화 실행 val decryptedData = AesCrypto.decrypt(parts[3], aesKey, aesIv) val dataRows = decryptedData.split("^") - - println("🔔 복호화된 체결 통보: ${dataRows[8]} ${dataRows[9]}주 ${dataRows[13]} 체결") + println("🔔 복호화된 체결 통보: ${if (dataRows[4] == "01") {"매도"} else {"매수"}} ${dataRows[8]} ${dataRows[9]}주 ${dataRows[13]} 체결") // UI 콜백 호출 (종목코드, 체결량, 체결가, 주문번호, 체결여부) onExecutionReceived?.invoke( diff --git a/src/main/kotlin/network/RagService.kt b/src/main/kotlin/network/RagService.kt index 309e8b1..83b704d 100644 --- a/src/main/kotlin/network/RagService.kt +++ b/src/main/kotlin/network/RagService.kt @@ -117,7 +117,7 @@ object RagService { embeddingStore.add(embedding, segment) } } - println("🔎 [Lucene] ${chunks.size}개의 청크로 인덱싱 완료") +// println("🔎 [Lucene] ${chunks.size}개의 청크로 인덱싱 완료") } object JsonSanitizer { diff --git a/src/main/kotlin/service/AutoTradingManager.kt b/src/main/kotlin/service/AutoTradingManager.kt index 5078f0c..759ad1d 100644 --- a/src/main/kotlin/service/AutoTradingManager.kt +++ b/src/main/kotlin/service/AutoTradingManager.kt @@ -42,7 +42,7 @@ object AutoTradingManager { // 설정 상수 private const val MIN_RISE_RATE = 0.1 - private const val MAX_RISE_RATE = 15.0 + private const val MAX_RISE_RATE = 19.0 private const val CYCLE_TIMEOUT = 30 * 60 * 1000L // 한 사이클 최대 10분 private const val WATCHDOG_CHECK_INTERVAL = 30 * 1000L // 30초마다 생존 확인 private const val STUCK_THRESHOLD = 5 * 60 * 1000L // 5분간 반응 없으면 'Stuck'으로 판단 @@ -88,10 +88,10 @@ object AutoTradingManager { // [프로세스 1] 장 마감 및 잔고 체크 val now = LocalTime.now(ZoneId.of("Asia/Seoul")) //&& now.isBefore(LocalTime.of(15, 30)) -// if (now.isAfter(LocalTime.of(15, 30)) ) { -// executeClosingLiquidation(tradeService) -// return@withTimeout -// } + if (now.isAfter(LocalTime.of(15, 0)) ) { + executeClosingLiquidation(tradeService) + return@withTimeout + } val balance = tradeService.fetchIntegratedBalance().getOrNull() val myCash = balance?.deposit?.replace(",", "")?.toLongOrNull() ?: 0L @@ -137,10 +137,10 @@ object AutoTradingManager { println("⏳ [Cycle Timeout] 사이클이 너무 길어져 초기화 후 재시작합니다.") } catch (e: Exception) { println("⚠️ [Loop Error] ${e.message}") - delay(10000) + delay(5000) } - waitForNextCycle(3) + waitForNextCycle(1) } } } diff --git a/src/main/kotlin/service/DynamicNewsScraper.kt b/src/main/kotlin/service/DynamicNewsScraper.kt index f906248..c256270 100644 --- a/src/main/kotlin/service/DynamicNewsScraper.kt +++ b/src/main/kotlin/service/DynamicNewsScraper.kt @@ -212,7 +212,7 @@ object DynamicNewsScraper { failCountMap[domain] = (failCountMap[domain] ?: 0) + 1 // 불필요한 스택트레이스 출력을 줄이기 위해 메시지만 출력 - println("❌ [Playwright] 실패 (${url.take(30)}...): ${e.localizedMessage}") +// println("❌ [Playwright] 실패 (${url.take(30)}...): ${e.localizedMessage}") "" } } @@ -254,7 +254,7 @@ object SafeScraper { suspend fun scrapeParallel(corpInfo: CorpInfo, urls: List) = coroutineScope { urls.forEach { item -> // map + awaitAll 대신 순차 처리가 현재 상황에선 더 안정적입니다. if (UrlCacheManager.isAlreadyProcessed(item.originallink)) { - println("✅ [학습완료 데이터 스킵] ${item.originallink}") +// println("✅ [학습완료 데이터 스킵] ${item.originallink}") return@forEach } @@ -262,7 +262,7 @@ object SafeScraper { try { withTimeout(25000L) { // 타임아웃 약간 증가 val content = DynamicNewsScraper.fetchFullContent(item.originallink) - if (content.isNotBlank()) { + if (content.isNotBlank() && content.length > 100) { RagService.ingestWithChunking( text = content, newsLink = item.originallink, @@ -272,7 +272,7 @@ object SafeScraper { corpCode = corpInfo.cCode, stcokName = corpInfo.stockName ) - println("✅ [학습완료] ${item.originallink}") +// println("✅ [학습완료] ${item.originallink}") } } } catch (e: Exception) { diff --git a/src/main/kotlin/ui/IntegratedOrderSection.kt b/src/main/kotlin/ui/IntegratedOrderSection.kt index 8345753..fbbaa23 100644 --- a/src/main/kotlin/ui/IntegratedOrderSection.kt +++ b/src/main/kotlin/ui/IntegratedOrderSection.kt @@ -21,6 +21,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import kotlinx.coroutines.launch import model.MAX_BUDGET +import model.MIN_PURCHASE_SCORE import model.buyWeight import model.feesAndTaxRate import model.minimumNetProfit @@ -185,11 +186,12 @@ fun IntegratedOrderSection( scope.launch { val tickSize = MarketUtil.getTickSize(basePrice) val oneTickLowerPrice = basePrice - (tickSize * when(investmentGrade) { - InvestmentGrade.LEVEL_5_STRONG_RECOMMEND -> 0 - InvestmentGrade.LEVEL_4_BALANCED_RECOMMEND -> 1 - InvestmentGrade.LEVEL_3_CAUTIOUS_RECOMMEND -> 1 - InvestmentGrade.LEVEL_2_HIGH_RISK -> 2 - InvestmentGrade.LEVEL_1_SPECULATIVE -> 3 + InvestmentGrade.LEVEL_5_STRONG_RECOMMEND -> 1 + InvestmentGrade.LEVEL_4_BALANCED_RECOMMEND -> 2 + InvestmentGrade.LEVEL_3_CAUTIOUS_RECOMMEND -> 3 + InvestmentGrade.LEVEL_2_HIGH_RISK -> 3 + InvestmentGrade.LEVEL_1_SPECULATIVE -> 4 + else -> 4 }) // 2. 주문 가격 설정 (직접 입력값이 없으면 한 틱 낮은 가격 사용) @@ -257,15 +259,10 @@ fun IntegratedOrderSection( "safe" to 0.4 // 중장기 점수 비중 강화 ) -// 2. 토탈 스코어 계산 val totalScore = (completeTradingDecision.shortPossible() * weights["short"]!!) + (completeTradingDecision.profitPossible() * weights["profit"]!!) + (completeTradingDecision.safePossible() * weights["safe"]!!) - -// 3. 매수 결정 문턱값 (예: 70점 이상이면 매수 가능) - val MIN_PURCHASE_SCORE = 68.0 - val HIGH_QUALITY_SCORE = 85.0 // 강력 추천 기준 println(""" corpName : ${completeTradingDecision.corpName} confidence : ${completeTradingDecision.confidence + append} diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..cb49365 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,7 @@ + + + + + + +