...
This commit is contained in:
@@ -70,6 +70,7 @@ fun AiAnalysisView(stockCode:String,stockName: String, currentPrice: String, tra
|
||||
AutoTradingManager.addStock(stockName,stockCode) { decision,success ->
|
||||
aiOpinion = decision.toString()
|
||||
isAnalyzing = !success
|
||||
tradingDecisionCallback.invoke(decision,success)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
aiOpinion = "분석 중 오류 발생: ${e.message}"
|
||||
|
||||
@@ -17,6 +17,7 @@ import model.KisSession
|
||||
import model.StockBasicInfo
|
||||
import network.KisTradeService
|
||||
import network.KisWebSocketManager
|
||||
import service.AutoTradingManager
|
||||
|
||||
@Composable
|
||||
fun DashboardScreen() {
|
||||
@@ -32,6 +33,27 @@ fun DashboardScreen() {
|
||||
var selectedStockInfo by remember { mutableStateOf<StockBasicInfo?>(null) } // 단순 종목 선택 시
|
||||
var completeTradingDecision by remember { mutableStateOf<TradingDecision?>(null) } // 단순 종목 선택 시
|
||||
|
||||
DisposableEffect(Unit) {
|
||||
// 1. 화면 진입 시: 자동 발굴 루프 시작
|
||||
// AI 분석 결과(decision)가 나오면 completeTradingDecision 상태를 업데이트하여
|
||||
// IntegratedOrderSection에서 자동으로 매수 로직이 실행되도록 연결합니다.
|
||||
AutoTradingManager.startAutoDiscoveryLoop(tradeService) { decision, isSuccess ->
|
||||
if (isSuccess && decision != null) {
|
||||
|
||||
selectedStockCode = decision.stockCode
|
||||
selectedStockName = decision.stockName
|
||||
isDomestic = true // 발굴 로직은 국내주식 기준이므로 true 고정
|
||||
|
||||
// 2. 결정 객체 업데이트 -> IntegratedOrderSection의 LaunchedEffect 트리거
|
||||
completeTradingDecision = decision
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 화면 이탈 시(앱 종료 등): 루프 중단 (리소스 정리)
|
||||
onDispose {
|
||||
AutoTradingManager.stopDiscovery()
|
||||
}
|
||||
}
|
||||
|
||||
// 중앙 관리용 상태들
|
||||
var refreshTrigger by remember { mutableStateOf(0) }
|
||||
|
||||
@@ -70,7 +70,7 @@ fun IntegratedOrderSection(
|
||||
}
|
||||
|
||||
var profitRate by remember(monitoringItem) {
|
||||
mutableStateOf(monitoringItem?.profitRate?.toString() ?: "3.0")
|
||||
mutableStateOf(monitoringItem?.profitRate?.toString() ?: "2.0")
|
||||
}
|
||||
var stopLossRate by remember(monitoringItem) {
|
||||
mutableStateOf(monitoringItem?.stopLossRate?.toString() ?: "-2.0")
|
||||
@@ -114,12 +114,43 @@ fun IntegratedOrderSection(
|
||||
}
|
||||
}
|
||||
LaunchedEffect(completeTradingDecision) {
|
||||
val MIN_CONFIDENCE = 70.0 // 최소 신뢰도
|
||||
val MIN_MID_SCORE = 65.0 // 최소 중기 점수 (주봉/재무)
|
||||
println("completeTradingDecision = $completeTradingDecision")
|
||||
if (completeTradingDecision != null &&
|
||||
completeTradingDecision.stockCode.equals(stockCode)) {
|
||||
println(completeTradingDecision?.decision)
|
||||
fun resultCheck(completeTradingDecision :TradingDecision) {
|
||||
println("""
|
||||
${completeTradingDecision.corpName}
|
||||
${completeTradingDecision.confidence}
|
||||
${completeTradingDecision.profitPossible()}
|
||||
${completeTradingDecision.safePossible()}
|
||||
""".trimIndent())
|
||||
// 2. 조건 검사: 신뢰도 80 이상 AND 중기 점수 70 이상
|
||||
if (completeTradingDecision.confidence >= MIN_CONFIDENCE &&
|
||||
completeTradingDecision.profitPossible() >= MIN_MID_SCORE &&
|
||||
completeTradingDecision.safePossible() > MIN_MID_SCORE) {
|
||||
|
||||
println("🚀 [조건 만족] 강력 매수 시그널 포착 -> 자동 매수 진행 (1주) ${completeTradingDecision.stockCode}")
|
||||
// 3. 매수 실행 (자동 감시 켜기: true, 수량: 1주)
|
||||
// 수량은 필요에 따라 로직으로 계산하여 변경 가능 (예: 자산의 10% 등)
|
||||
excuteTrade(willEnableAutoSell = true, orderQty = "1")
|
||||
|
||||
} else {
|
||||
println("✋ [조건 미달] 매수 의견이나 점수 부족으로 관망")
|
||||
}
|
||||
}
|
||||
when (completeTradingDecision?.decision) {
|
||||
"BUY" -> if (completeTradingDecision.confidence > 70) excuteTrade(true, "1")
|
||||
"BUY" -> {
|
||||
println("[$stockCode] 매수 추천 resultCheck: ${completeTradingDecision?.reason}")
|
||||
resultCheck(completeTradingDecision)
|
||||
}
|
||||
"SELL" -> println("[$stockCode] 매도: ${completeTradingDecision?.reason}")
|
||||
else -> println("[$stockCode] 관망 유지: ${completeTradingDecision?.reason}")
|
||||
else -> {
|
||||
resultCheck(completeTradingDecision)
|
||||
println("[$stockCode] 관망 유지 resultCheck: ${completeTradingDecision?.reason}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,20 +94,20 @@ fun StockDetailSection(
|
||||
launch { tradeService.fetchPeriodChartData(stockCode, "D").onSuccess {
|
||||
daySummary = it.takeLast(7)
|
||||
TechnicalAnalyzer.daily = it
|
||||
println("daySummary ${daySummary.size} total: ${it.size} ${it.firstOrNull()?.toString()}")
|
||||
// println("daySummary ${daySummary.size} total: ${it.size} ${it.firstOrNull()?.toString()}")
|
||||
}
|
||||
} // 최근 7일
|
||||
launch { tradeService.fetchPeriodChartData(stockCode, "W").onSuccess {
|
||||
weekSummary = it.takeLast(4)
|
||||
TechnicalAnalyzer.weekly = it
|
||||
println("weekSummary ${weekSummary.size} total: ${it.size} ${it.firstOrNull()?.toString()}")
|
||||
// println("weekSummary ${weekSummary.size} total: ${it.size} ${it.firstOrNull()?.toString()}")
|
||||
}
|
||||
} // 최근 4주
|
||||
launch { tradeService.fetchPeriodChartData(stockCode, "M").onSuccess {
|
||||
monthSummary = it.takeLast(6) // 최근 6개월
|
||||
yearSummary = it.takeLast(36) // 최근 3년
|
||||
TechnicalAnalyzer.monthly = it
|
||||
println("monthSummary ${monthSummary.size} yearSummary ${yearSummary.size} total: ${it.size} ${it.firstOrNull()?.toString()}")
|
||||
// println("monthSummary ${monthSummary.size} yearSummary ${yearSummary.size} total: ${it.size} ${it.firstOrNull()?.toString()}")
|
||||
}
|
||||
}
|
||||
launch {
|
||||
|
||||
Reference in New Issue
Block a user