From dab3ab79932ad3cc06f49af6a348f16640105317 Mon Sep 17 00:00:00 2001 From: lunaticbum Date: Tue, 6 Oct 2026 17:18:49 +0900 Subject: [PATCH] .... --- src/main/kotlin/service/AutoTradingManager.kt | 42 +++++++++---------- src/main/kotlin/ui/TradingDecisionLog.kt | 42 ++++++++----------- 2 files changed, 38 insertions(+), 46 deletions(-) diff --git a/src/main/kotlin/service/AutoTradingManager.kt b/src/main/kotlin/service/AutoTradingManager.kt index d09b229..ed63674 100644 --- a/src/main/kotlin/service/AutoTradingManager.kt +++ b/src/main/kotlin/service/AutoTradingManager.kt @@ -196,7 +196,7 @@ object AutoTradingManager { ts: TradingDecision, totalScore: Double, confidence: Double, - finScore100: Double // ๐Ÿ’ก [์ˆ˜์ •1] ์ปดํŒŒ์ผ ์—๋Ÿฌ ๋ฐฉ์ง€์šฉ ํŒŒ๋ผ๋ฏธํ„ฐ ์ถ”๊ฐ€ + finScore100: Double ): InvestmentGrade { val minScore = KisSession.config.getValues(ConfigIndex.MIN_PURCHASE_SCORE_INDEX) val minConfidence = minScore @@ -209,51 +209,52 @@ object AutoTradingManager { val midLongAvg = (ts.midTermScore + ts.longTermScore) / 2.0 val isOverheated = ts.analyzer?.isOverheatedStock() ?: true - // 1. ๊ธฐ๋ณธ ๋“ฑ๊ธ‰ ์‚ฐ์ • + // ๐ŸŒŸ 1. ๊ธฐ๋ณธ ๋“ฑ๊ธ‰ ์‚ฐ์ • (ํ˜„์‹ค์ ์ธ ํ†ต๊ณ„ ๋ฒ”์œ„๋กœ ์ปท์˜คํ”„ ํ•˜ํ–ฅ ์กฐ์ •) var rawGrade = when { - midLongAvg >= 70.0 -> { - if (shortAvg >= 75.0) InvestmentGrade.LEVEL_5_STRONG_RECOMMEND - else if (shortAvg >= 65.0) InvestmentGrade.LEVEL_4_BALANCED_RECOMMEND - else InvestmentGrade.LEVEL_3_CAUTIOUS_RECOMMEND + midLongAvg >= 65.0 -> { // ์šฐ๋Ÿ‰ํ•œ ์ค‘์žฅ๊ธฐ ํ๋ฆ„ (๊ธฐ์กด 70 -> 65 ์™„ํ™”) + if (shortAvg >= 65.0) InvestmentGrade.LEVEL_5_STRONG_RECOMMEND // ๊ฐ•ํ•œ ํ„ด์–ด๋ผ์šด๋“œ/์ˆ˜๊ธ‰ (๊ธฐ์กด 75 -> 65 ์™„ํ™”) + else if (shortAvg >= 50.0) InvestmentGrade.LEVEL_4_BALANCED_RECOMMEND + else InvestmentGrade.LEVEL_3_CAUTIOUS_RECOMMEND // ๋ˆŒ๋ฆผ๋ชฉ ์ง„์ž… ์ดˆ๊ธฐ } - midLongAvg >= 60.0 -> { - if (shortAvg >= 70.0) InvestmentGrade.LEVEL_4_BALANCED_RECOMMEND - else if (shortAvg >= 60.0) InvestmentGrade.LEVEL_3_CAUTIOUS_RECOMMEND + midLongAvg >= 55.0 -> { // ๋ฌด๋‚œํ•œ ํ๋ฆ„ + if (shortAvg >= 65.0) InvestmentGrade.LEVEL_4_BALANCED_RECOMMEND + else if (shortAvg >= 50.0) InvestmentGrade.LEVEL_3_CAUTIOUS_RECOMMEND else InvestmentGrade.LEVEL_2_HIGH_RISK } - else -> { - if (shortAvg >= 70.0) InvestmentGrade.LEVEL_2_HIGH_RISK + else -> { // ์—ญ๋ฐฐ์—ด ๋˜๋Š” ์žฌ๋ฌด ํ•˜์œ„ + if (shortAvg >= 65.0) InvestmentGrade.LEVEL_2_HIGH_RISK else InvestmentGrade.LEVEL_1_SPECULATIVE } } - // ๐Ÿ’ก [์ˆ˜์ •2] ๋ˆ„๋ฝ๋˜์—ˆ๋˜ ์šฐ๋Ÿ‰์ฃผ ๋ˆŒ๋ฆผ๋ชฉ ํ”„๋ฆฌ๋ฏธ์—„ & ์žก์ฃผ ํˆฌ๋งค ํšŒํ”ผ ๋กœ์ง ์ถ”๊ฐ€ - val isHealthy = finScore100 >= 70.0 - val isPullback = midLongAvg >= 75.0 && shortAvg <= 45.0 + // ๐ŸŒŸ 2. [ํ•ต์‹ฌ] ์šฐ๋Ÿ‰์ฃผ ํ™ฉ๊ธˆ ๋ˆŒ๋ฆผ๋ชฉ ํ”„๋ฆฌ๋ฏธ์—„ (Premium) + // ์žฌ๋ฌด๊ฐ€ ํ›Œ๋ฅญ(75์  ์ด์ƒ)ํ•˜๊ณ  ์ค‘์žฅ๊ธฐ ์ถ”์„ธ๊ฐ€ ์‚ด์•„์žˆ๋Š”๋ฐ, ๋‹จ๊ธฐ ์ง€ํ‘œ๊ฐ€ ๋ฐ”๋‹ฅ์„ ์ฐ๊ณ  ๋ง‰ ๊ณ ๊ฐœ๋ฅผ ๋“œ๋Š”(30~55์ ) ํƒ€์  + val isHealthy = finScore100 >= 75.0 + val isPullback = midLongAvg >= 70.0 && shortAvg in 30.0..55.0 if (isHealthy && isPullback) { rawGrade = when (rawGrade) { - InvestmentGrade.LEVEL_1_SPECULATIVE, - InvestmentGrade.LEVEL_2_HIGH_RISK -> InvestmentGrade.LEVEL_3_CAUTIOUS_RECOMMEND - + // ๐Ÿ’ก ์šฐ๋Ÿ‰์ฃผ๊ฐ€ ์™„๋ฒฝํ•œ ๋ˆŒ๋ฆผ๋ชฉ์—์„œ ๋ฐ˜๋“ฑ์„ ์‹œ์ž‘ํ•˜๋ฉด ์ตœ๊ณ  ๋“ฑ๊ธ‰(5๋“ฑ๊ธ‰)์œผ๋กœ ์Šน๊ฒฉ! + InvestmentGrade.LEVEL_4_BALANCED_RECOMMEND -> InvestmentGrade.LEVEL_5_STRONG_RECOMMEND InvestmentGrade.LEVEL_3_CAUTIOUS_RECOMMEND -> InvestmentGrade.LEVEL_4_BALANCED_RECOMMEND + InvestmentGrade.LEVEL_2_HIGH_RISK -> InvestmentGrade.LEVEL_3_CAUTIOUS_RECOMMEND else -> rawGrade } } else if (!isHealthy && isPullback) { + // ์žก์ฃผ์ธ๋ฐ ์ฐจํŠธ๊ฐ€ ๋ˆŒ๋Ÿฌ์•‰์€ ๊ฒฝ์šฐ (์ง€ํ•˜์‹ค ์œ„ํ—˜์œผ๋กœ ๊ฐ•๋“ฑ) rawGrade = when (rawGrade) { InvestmentGrade.LEVEL_5_STRONG_RECOMMEND, InvestmentGrade.LEVEL_4_BALANCED_RECOMMEND, InvestmentGrade.LEVEL_3_CAUTIOUS_RECOMMEND -> InvestmentGrade.LEVEL_1_SPECULATIVE - InvestmentGrade.LEVEL_2_HIGH_RISK, InvestmentGrade.LEVEL_1_SPECULATIVE -> InvestmentGrade.LEVEL_0_SPECULATIVE - else -> InvestmentGrade.LEVEL_0_SPECULATIVE } } + // 3. ๊ณผ์—ด ๊ฐ•๋“ฑ ๋กœ์ง (๊ธ‰๋“ฑ์ฃผ๋Š” ํ•œ ๋‹จ๊ณ„์”ฉ ๋‚ฎ์ถค) val finalGrade = if (isOverheated) { when (rawGrade) { InvestmentGrade.LEVEL_5_STRONG_RECOMMEND -> InvestmentGrade.LEVEL_4_BALANCED_RECOMMEND @@ -265,7 +266,7 @@ object AutoTradingManager { rawGrade } - // ๐ŸŒŸ [์ถ”๊ฐ€] ์‚ฌ์šฉ์ž๊ฐ€ ๋น„ํ™œ์„ฑํ™”ํ•œ ๋“ฑ๊ธ‰์ธ์ง€ ์ฒดํฌํ•˜์—ฌ ๋งค์ˆ˜ ์›์ฒœ ์ฐจ๋‹จ + // 4. ์‚ฌ์šฉ์ž๊ฐ€ UI์—์„œ ์Šค์œ„์น˜๋กœ ๊บผ๋‘”(๋น„ํ™œ์„ฑํ™”) ๋“ฑ๊ธ‰์ธ์ง€ ์ฒดํฌํ•˜์—ฌ ๋งค์ˆ˜ ์ฐจ๋‹จ val isEnabled = when (finalGrade) { InvestmentGrade.LEVEL_5_STRONG_RECOMMEND -> KisSession.tradeConfig.useGrade5 InvestmentGrade.LEVEL_4_BALANCED_RECOMMEND -> KisSession.tradeConfig.useGrade4 @@ -275,7 +276,6 @@ object AutoTradingManager { else -> false } - // ๋น„ํ™œ์„ฑํ™”๋œ ๋“ฑ๊ธ‰์ด๋ผ๋ฉด LEVEL_0_SPECULATIVE(๊ด€๋ง) ๋ฐ˜ํ™˜ return if (isEnabled) finalGrade else InvestmentGrade.LEVEL_0_SPECULATIVE } diff --git a/src/main/kotlin/ui/TradingDecisionLog.kt b/src/main/kotlin/ui/TradingDecisionLog.kt index f3b1156..cd78704 100644 --- a/src/main/kotlin/ui/TradingDecisionLog.kt +++ b/src/main/kotlin/ui/TradingDecisionLog.kt @@ -288,7 +288,7 @@ fun TradingDecisionLog() { modifier = Modifier.fillMaxSize().background(Color.White) // fillMaxWidth() ๋Œ€์‹  ์ „์ฒด ์ฑ„์šฐ๊ธฐ ) { // ========================================== - // 1๏ธโƒฃ ์ฒซ ๋ฒˆ์งธ ์„น์…˜: 2์—ด ๋ฐฐ์น˜ ๊ตฌ๊ฐ„ (span = 3) + // 1๏ธโƒฃ ์ฒซ ๋ฒˆ์งธ ์„น์…˜: 3์—ด ๋ฐฐ์น˜ ๊ตฌ๊ฐ„ (span = 2๋กœ ์ˆ˜์ •) // ========================================== item(span = { GridItemSpan(maxLineSpan) }) { // 6์นธ ๋ชจ๋‘ ์ฐจ์ง€ @@ -298,16 +298,15 @@ fun TradingDecisionLog() { modifier = Modifier.padding(top = 10.dp, bottom = 8.dp) ) } -// ConfigIndex.BUY_WEIGHT_INDEX, + var defaults = arrayOf( - ConfigIndex.TAX_INDEX, ConfigIndex.PROFIT_INDEX, + ConfigIndex.TAX_INDEX, ConfigIndex.PROFIT_INDEX,ConfigIndex.MIN_PURCHASE_SCORE_INDEX, ConfigIndex.MAX_BUDGET_INDEX, ConfigIndex.MAX_PRICE_INDEX, ConfigIndex.MIN_PRICE_INDEX, - ConfigIndex.MIN_PURCHASE_SCORE_INDEX, ConfigIndex.SELL_PROFIT, - ConfigIndex.MAX_COUNT_INDEX, ConfigIndex.MAX_HOLDING_COUNT, + ConfigIndex.SELL_PROFIT, ConfigIndex.MAX_COUNT_INDEX, ConfigIndex.MAX_HOLDING_COUNT, ) - // ๐Ÿ’ก items์— span์„ ์ฃผ์–ด 3์นธ์”ฉ ์ฐจ์ง€ํ•˜๊ฒŒ ๋งŒ๋“ฆ (๊ฒฐ๊ณผ์ ์œผ๋กœ 2์—ด ๋ฐฐ์น˜) - items(defaults.size, span = { GridItemSpan(3) }) { index -> + // ๐ŸŒŸ [์ˆ˜์ •] GridItemSpan(3) -> GridItemSpan(2)๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ 3์—ด ๋ฐฐ์น˜ + items(defaults.size, span = { GridItemSpan(2) }) { index -> val configKey = defaults.get(index) var localText by remember(configKey) { mutableStateOf(KisSession.config.getValues(configKey)?.toString() ?: "") } @@ -355,28 +354,28 @@ fun TradingDecisionLog() { } } - // ๐Ÿ’ก 2์—ด ๋ฐฐ์น˜๋‹ˆ๊นŒ ๊ฐ๊ฐ span = 3 - item(span = { GridItemSpan(3) }) { + // ๐ŸŒŸ [์ˆ˜์ •] ๋ชจ๋“  ๋ฆฌ์Šคํฌ ๊ด€๋ฆฌ ์•„์ดํ…œ๋“ค๋„ GridItemSpan(3) ๋ฐ maxLineSpan -> GridItemSpan(2)๋กœ ํ†ต์ผ + item(span = { GridItemSpan(2) }) { SettingSwitchField( label = "๋ณด์œ  ์ฃผ์‹ ์ž๋™ ๋งค๋„ ํ™œ์„ฑํ™”", initialChecked = KisSession.config.getValues(ConfigIndex.TAKE_PROFIT) > 0.0, onCheckedChange = { KisSession.config.setValues(ConfigIndex.TAKE_PROFIT, if (it) 1.0 else 0.0) }, - helperText = "๋ชฉํ‘œ ์ˆ˜์ต๋ฅ  ${KisSession.config.SELL_PROFIT} ๋„๋‹ฌ ์‹œ ๊ธฐ๊ณ„์  ๋งค๋„" + helperText = "์ˆ˜์ต ${KisSession.config.SELL_PROFIT} ๋„๋‹ฌ ๋งค๋„" // ํ…์ŠคํŠธ ๊ฐ„์†Œํ™” ) } - item(span = { GridItemSpan(3) }) { + item(span = { GridItemSpan(2) }) { SettingSwitchField( label = "์ž๋™ ์†์ ˆ ํ™œ์„ฑํ™”", initialChecked = KisSession.config.getValues(ConfigIndex.STOP_LOSS) > 0.0, onCheckedChange = { KisSession.config.setValues(ConfigIndex.STOP_LOSS, if (it) 1.0 else 0.0) }, - helperText = "์†์‹ค ๋ฐฉ์–ด์„  ๋„๋‹ฌ ์‹œ ๊ธฐ๊ณ„์  ์†์ ˆ" + helperText = "๋ฐฉ์–ด์„  ๋„๋‹ฌ ์‹œ ๊ธฐ๊ณ„์  ์†์ ˆ" ) } - item(span = { GridItemSpan(3) }) { + item(span = { GridItemSpan(2) }) { SettingInputField( label = "์ตœ์†Œ ์†์ ˆ ๋ผ์ธ (%)", initialValue = KisSession.config.getValues(ConfigIndex.LOSS_MINRATE).toString(), @@ -386,7 +385,7 @@ fun TradingDecisionLog() { ) } - item(span = { GridItemSpan(3) }) { + item(span = { GridItemSpan(2) }) { SettingInputField( label = "์ตœ๋Œ€ ํ—ˆ์šฉ ์†์ ˆ๋ฅ  (%)", initialValue = KisSession.config.getValues(ConfigIndex.LOSS_MAXRATE).toString(), @@ -396,27 +395,20 @@ fun TradingDecisionLog() { ) } - // ๐Ÿ’ก ๊ธˆ์•ก์€ ๊ธธ๊ฒŒ ๋ป—์–ด์•ผ ํ•˜๋‹ˆ maxLineSpan - item(span = { GridItemSpan(maxLineSpan) }) { + // ๐ŸŒŸ ๊ธˆ์•ก ์ž…๋ ฅ์นธ๋„ ํ•œ ์ค„์— 3๊ฐœ ๋‚˜๋ž€ํžˆ ๋ฐฐ์น˜๋˜๋„๋ก ๋ณ€๊ฒฝ + item(span = { GridItemSpan(2) }) { SettingInputField( label = "์ตœ๋Œ€ ํ—ˆ์šฉ ์†์‹ค ๊ธˆ์•ก (์›)", initialValue = KisSession.config.getValues(ConfigIndex.LOSS_MAX_MONEY).toLong().toString(), placeholder = "50000", onSave = { KisSession.config.setValues(ConfigIndex.LOSS_MAX_MONEY, it.toDoubleOrNull() ?: 0.0) }, - helperText = "1์ข…๋ชฉ๋‹น ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ์†์‹ค์•ก (์› ๋‹จ์œ„)" + helperText = "1์ข…๋ชฉ๋‹น ์ตœ๋Œ€ ์†์‹ค์•ก" // ํ…์ŠคํŠธ ๊ฐ„์†Œํ™” ) } - item(span = { GridItemSpan(maxLineSpan) }) { - Column { - Spacer(modifier = Modifier.height(10.dp)) - Divider(color = Color.LightGray, thickness = 1.dp) - Spacer(modifier = Modifier.height(20.dp)) - } - } // ========================================== - // 2๏ธโƒฃ ๋‘ ๋ฒˆ์งธ ์„น์…˜: 3์—ด ๋ฐฐ์น˜ ๊ตฌ๊ฐ„ (span = 2) + // 2๏ธโƒฃ ๋‘ ๋ฒˆ์งธ ์„น์…˜: 3์—ด ๋ฐฐ์น˜ ๊ตฌ๊ฐ„ (๊ธฐ์กด ์ฝ”๋“œ ๊ทธ๋Œ€๋กœ ์œ ์ง€) // ========================================== item(span = { GridItemSpan(maxLineSpan) }) { // 6์นธ ๋ชจ๋‘ ์ฐจ์ง€ Text(