...
This commit is contained in:
parent
eee4f1bab7
commit
f830163940
@ -444,5 +444,10 @@ object TradingLogStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun clear() {
|
||||||
|
synchronized(this) {
|
||||||
|
decisionLogs.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package service
|
|||||||
import AutoTradeItem
|
import AutoTradeItem
|
||||||
import network.TradingDecision
|
import network.TradingDecision
|
||||||
import TradingLogStore
|
import TradingLogStore
|
||||||
|
import TradingLogStore.decisionLogs
|
||||||
import getLlamaBinPath
|
import getLlamaBinPath
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -395,9 +396,13 @@ object AutoTradingManager {
|
|||||||
} catch (e: Exception) {}
|
} catch (e: Exception) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var onMarketClosed: (() -> Unit)? = null
|
||||||
|
|
||||||
var now = LocalTime.now(ZoneId.of("Asia/Seoul"))
|
var now = LocalTime.now(ZoneId.of("Asia/Seoul"))
|
||||||
var currentTimeMillis = System.currentTimeMillis()
|
var currentTimeMillis = System.currentTimeMillis()
|
||||||
var waitTime = 0.2
|
var waitTime = 0.2
|
||||||
|
val H16 = LocalTime.of(16, 0)
|
||||||
|
val H08M50 = LocalTime.of(8, 50)
|
||||||
private fun runDiscoveryLoop(tradeService: KisTradeService, callback: TradingDecisionCallback) {
|
private fun runDiscoveryLoop(tradeService: KisTradeService, callback: TradingDecisionCallback) {
|
||||||
discoveryJob = scope.launch {
|
discoveryJob = scope.launch {
|
||||||
println("🚀 [AutoTrading] 발굴 루프 시작: ${LocalDateTime.now()}")
|
println("🚀 [AutoTrading] 발굴 루프 시작: ${LocalDateTime.now()}")
|
||||||
@ -406,9 +411,22 @@ object AutoTradingManager {
|
|||||||
now = LocalTime.now(ZoneId.of("Asia/Seoul"))
|
now = LocalTime.now(ZoneId.of("Asia/Seoul"))
|
||||||
currentTimeMillis = System.currentTimeMillis()
|
currentTimeMillis = System.currentTimeMillis()
|
||||||
lastTickTime.set(System.currentTimeMillis()) // 생존 신고
|
lastTickTime.set(System.currentTimeMillis()) // 생존 신고
|
||||||
|
// [수정] 16시 이후이거나 8시 30분 이전이면 모든 로직 중단 및 초기화
|
||||||
|
if (now.isAfter(LocalTime.of(16, 0)) || now.isBefore(LocalTime.of(8, 30))) {
|
||||||
|
println("🌙 [System] 마감 시간 도달. 자원 정리 후 대기 모드(설정 화면)로 전환합니다.")
|
||||||
|
SystemSleepPreventer.sleepDisplay() // 모니터 끄기
|
||||||
|
KisWebSocketManager.disconnect()
|
||||||
|
BrowserManager.closeIfIdle(0)
|
||||||
|
LlamaServerManager.stopAll() // AI 서버 완전 종료
|
||||||
|
TradingLogStore.clear()
|
||||||
|
onMarketClosed?.invoke() // Main.kt에 설정 화면으로 가라고 신호 전송
|
||||||
|
stopDiscovery() // 발굴 루프 완전 폭파 (내일 8시 30분에 다시 켜짐)
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
when {
|
when {
|
||||||
|
|
||||||
//장중
|
//장중
|
||||||
now.isBefore(LocalTime.of(16, 0)) && now.isAfter(LocalTime.of(8, 50)) -> {
|
now.isBefore(H16) && now.isAfter(H08M50) -> {
|
||||||
waitTime = 0.2
|
waitTime = 0.2
|
||||||
if (now.isAfter(LocalTime.of(8, 0)) && now.isBefore(LocalTime.of(15, 30))) {
|
if (now.isAfter(LocalTime.of(8, 0)) && now.isBefore(LocalTime.of(15, 30))) {
|
||||||
if (!KisSession.isMarketTokenValid() || !KisSession.isTradeTokenValid()) {
|
if (!KisSession.isMarketTokenValid() || !KisSession.isTradeTokenValid()) {
|
||||||
@ -491,7 +509,7 @@ object AutoTradingManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//장외
|
//장외
|
||||||
now.isAfter(LocalTime.of(18, 0)) || now.isBefore(LocalTime.of(8, 50)) -> {
|
now.isAfter(H16) || now.isBefore(H08M50) -> {
|
||||||
when {
|
when {
|
||||||
(now.hour == 0 && now.minute == 0 && (isSystemReadyToday || isSystemCleanedUpToday)) -> {
|
(now.hour == 0 && now.minute == 0 && (isSystemReadyToday || isSystemCleanedUpToday)) -> {
|
||||||
waitTime = 10.0
|
waitTime = 10.0
|
||||||
|
|||||||
@ -35,6 +35,7 @@ import network.KisTradeService
|
|||||||
import org.jetbrains.exposed.sql.deleteAll
|
import org.jetbrains.exposed.sql.deleteAll
|
||||||
import org.jetbrains.exposed.sql.insert
|
import org.jetbrains.exposed.sql.insert
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
import service.SystemSleepPreventer
|
||||||
|
|
||||||
|
|
||||||
// src/main/kotlin/ui/SettingsScreen.kt
|
// src/main/kotlin/ui/SettingsScreen.kt
|
||||||
@ -45,6 +46,61 @@ fun SettingsScreen(onAuthSuccess: () -> Unit) {
|
|||||||
var config by remember { mutableStateOf(KisSession.config) }
|
var config by remember { mutableStateOf(KisSession.config) }
|
||||||
var statusMessage by remember { mutableStateOf("정보를 입력하세요.") }
|
var statusMessage by remember { mutableStateOf("정보를 입력하세요.") }
|
||||||
|
|
||||||
|
val authenticateAndStart: suspend () -> Unit = {
|
||||||
|
var retryCount = 0
|
||||||
|
val maxRetries = 3
|
||||||
|
val totalDelaySeconds = 90
|
||||||
|
var isAuthCompleted = false
|
||||||
|
|
||||||
|
while (retryCount <= maxRetries && !isAuthCompleted) {
|
||||||
|
if (retryCount > 0) {
|
||||||
|
for (secondsLeft in totalDelaySeconds downTo 1) {
|
||||||
|
statusMessage = "⚠️ 인증 실패. ${secondsLeft}초 후 자동으로 다시 시도합니다. (시도 ${retryCount}/${maxRetries})"
|
||||||
|
delay(1000L)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statusMessage = if (retryCount == 0) "⏳ 인증 시도 중..." else "⏳ ${retryCount}차 재시도 중..."
|
||||||
|
|
||||||
|
KisSession.config = config
|
||||||
|
DatabaseFactory.saveConfig(config)
|
||||||
|
|
||||||
|
DartCodeManager.updateCorpCodes(HttpClient(CIO) {
|
||||||
|
install(ContentNegotiation) { json(Json { ignoreUnknownKeys = true }) }
|
||||||
|
})
|
||||||
|
|
||||||
|
val authSuccess = KisAuthService.refreshAllTokens()
|
||||||
|
val wsKeySuccess = KisTradeService.refreshWebsocketKey()
|
||||||
|
|
||||||
|
if (authSuccess && wsKeySuccess) {
|
||||||
|
statusMessage = "✅ 인증 성공! LLM 시작 중..."
|
||||||
|
isAuthCompleted = true
|
||||||
|
onAuthSuccess() // 여기서 대시보드로 넘어감
|
||||||
|
} else {
|
||||||
|
retryCount++
|
||||||
|
if (retryCount > maxRetries) {
|
||||||
|
statusMessage = "❌ 인증 실패. 3회 재시도 후 중단되었습니다."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(config) {
|
||||||
|
while (true) {
|
||||||
|
val now = java.time.LocalTime.now(java.time.ZoneId.of("Asia/Seoul"))
|
||||||
|
// 08:30 ~ 15:30 사이이고, 키값이 최소한 하나라도 존재할 때 자동 실행
|
||||||
|
if (now.isAfter(java.time.LocalTime.of(8, 30)) && now.isBefore(java.time.LocalTime.of(15, 30))) {
|
||||||
|
if (config.realAppKey.isNotEmpty() || config.vtsAppKey.isNotEmpty()) {
|
||||||
|
SystemSleepPreventer.wakeDisplay() // 모니터 켜기
|
||||||
|
statusMessage = "⏰ 자동 실행 시간(08:30)입니다. 시스템을 가동합니다."
|
||||||
|
authenticateAndStart()
|
||||||
|
break // 성공하면 루프 탈출
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delay(60_000 * 2) // 1분마다 시간 체크
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 계좌번호 입력 시 데이터 자동 로드 함수
|
// 계좌번호 입력 시 데이터 자동 로드 함수
|
||||||
fun checkAndLoadConfig(accountNo: String, isReal: Boolean) {
|
fun checkAndLoadConfig(accountNo: String, isReal: Boolean) {
|
||||||
val loaded = DatabaseFactory.findConfigByAccount(accountNo)
|
val loaded = DatabaseFactory.findConfigByAccount(accountNo)
|
||||||
@ -190,47 +246,7 @@ fun SettingsScreen(onAuthSuccess: () -> Unit) {
|
|||||||
modifier = Modifier.fillMaxWidth().height(50.dp),
|
modifier = Modifier.fillMaxWidth().height(50.dp),
|
||||||
onClick = {
|
onClick = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
var retryCount = 0
|
authenticateAndStart()
|
||||||
val maxRetries = 3
|
|
||||||
val totalDelaySeconds = 90 // 1분 30초 = 90초
|
|
||||||
var isAuthCompleted = false
|
|
||||||
|
|
||||||
while (retryCount <= maxRetries && !isAuthCompleted) {
|
|
||||||
// 재시도 시 대기 및 카운트다운 표시
|
|
||||||
if (retryCount > 0) {
|
|
||||||
for (secondsLeft in totalDelaySeconds downTo 1) {
|
|
||||||
statusMessage = "⚠️ 인증 실패. ${secondsLeft}초 후 자동으로 다시 시도합니다. (시도 ${retryCount}/${maxRetries})"
|
|
||||||
delay(1000L) // 1초 대기
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
statusMessage = if (retryCount == 0) "⏳ 인증 시도 중..." else "⏳ ${retryCount}차 재시도 중..."
|
|
||||||
|
|
||||||
// 1. 설정값 저장
|
|
||||||
KisSession.config = config
|
|
||||||
DatabaseFactory.saveConfig(config)
|
|
||||||
|
|
||||||
// 2. 법인코드 업데이트
|
|
||||||
DartCodeManager.updateCorpCodes(HttpClient(CIO) {
|
|
||||||
install(ContentNegotiation) { json(Json { ignoreUnknownKeys = true }) }
|
|
||||||
})
|
|
||||||
|
|
||||||
// 3. 토큰 및 웹소켓 키 갱신
|
|
||||||
val authSuccess = KisAuthService.refreshAllTokens()
|
|
||||||
val wsKeySuccess = KisTradeService.refreshWebsocketKey()
|
|
||||||
|
|
||||||
if (authSuccess && wsKeySuccess) {
|
|
||||||
statusMessage = "✅ 인증 성공! LLM 시작 중..."
|
|
||||||
isAuthCompleted = true
|
|
||||||
onAuthSuccess()
|
|
||||||
} else {
|
|
||||||
retryCount++
|
|
||||||
if (retryCount > maxRetries) {
|
|
||||||
statusMessage = "❌ 인증 실패. 3회 재시도 후 중단되었습니다. 키 정보를 확인하세요."
|
|
||||||
}
|
|
||||||
// 다음 루프에서 카운트다운 진입
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) { Text("설정 저장 및 실행") }
|
) { Text("설정 저장 및 실행") }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user