This commit is contained in:
lunaticbum 2026-06-19 15:17:20 +09:00
parent fd8283c507
commit c55b089fcd
3 changed files with 42 additions and 4 deletions

View File

@ -264,6 +264,9 @@ class TradeConfig {
var autoSellOrderMin : Double = -15.0 var autoSellOrderMin : Double = -15.0
var autoSellOrderMax : Double = -29.0 var autoSellOrderMax : Double = -29.0
var autoSellOrderAppend : Int = 3 var autoSellOrderAppend : Int = 3
var minExpectedProfitRate: Double = 2.0 // 필터링 기준 최소 기대 수익률 (%)
var maxExpectedReboundDays: Double = 10.0 // 필터링 기준 최대 허용 반등 주기 (일)
var minExpectedReboundDays: Double = 1.5
} }

View File

@ -1169,19 +1169,20 @@ object AutoTradingManager {
) )
val isSteadyUptrend = tempAnalyzer.checkSteadyUptrend(dailyData) val isSteadyUptrend = tempAnalyzer.checkSteadyUptrend(dailyData)
// 🌟 [수정] 조건 통합 (OR 조건) // 🌟 [수정] 조건 통합 (OR 조건)
val isProfitable = expectedProfitRate >= 2.0 || dailyStats.avgReboundAmplitude >= 2.0 val isProfitable = expectedProfitRate >= KisSession.tradeConfig.minExpectedProfitRate || dailyStats.avgReboundAmplitude >= KisSession.tradeConfig.minExpectedProfitRate
// 반등 주기에 도달했거나(Mean Reversion), 안정적으로 뻗어나가는 우상향 종목(Trend Following)이면 통과 // 반등 주기에 도달했거나(Mean Reversion), 안정적으로 뻗어나가는 우상향 종목(Trend Following)이면 통과
val isValidEntryTiming = (dailyStats.isValid && isApproaching && dailyStats.avgReboundPeriod <= 10.0 && dailyStats.avgReboundPeriod >= 1.5) || isSteadyUptrend val isValidEntryTiming = (dailyStats.isValid && isApproaching && dailyStats.avgReboundPeriod <= KisSession.tradeConfig.maxExpectedReboundDays && dailyStats.avgReboundPeriod >= KisSession.tradeConfig.minExpectedReboundDays) || isSteadyUptrend
if (!isProfitable || !isValidEntryTiming) { if (!isProfitable || !isValidEntryTiming) {
print("-> [${stock.name}] 조건 미달 필터링 (예측수익: ${"%.1f".format(expectedProfitRate)}%, 주기: ${"%.1f".format(dailyStats.avgReboundPeriod)}일, 진입권: $isApproaching) | ") print("-> [${stock.name}] 조건 미달 필터링 (예측수익: ${"%.1f".format(expectedProfitRate)}%, 주기: ${"%.1f".format(dailyStats.avgReboundPeriod)}일, 진입권: $isValidEntryTiming) | ")
return@withTimeout // 조건에 맞지 않으면 주봉/월봉 API 호출 및 LLM 분석 없이 즉시 다음 종목으로 넘어감 return@withTimeout // 조건에 맞지 않으면 주봉/월봉 API 호출 및 LLM 분석 없이 즉시 다음 종목으로 넘어감
} }
println("🔍 [분석 진입] ${stock.name} (${LocalTime.now()})") println("🔍 [분석 진입] ${stock.name} (${LocalTime.now()}) (예측수익: ${"%.1f".format(expectedProfitRate)}%, 주기: ${"%.1f".format(dailyStats.avgReboundPeriod)}일, 진입권: $isValidEntryTiming)")
if (!isSafetyBeltStockCodes.contains(stock.code)) { if (!isSafetyBeltStockCodes.contains(stock.code)) {
val analyzer = coroutineScope { val analyzer = coroutineScope {
val min30 = async { tradeService.fetchChartData(stock.code, true).getOrDefault(emptyList()) } val min30 = async { tradeService.fetchChartData(stock.code, true).getOrDefault(emptyList()) }

View File

@ -681,6 +681,40 @@ fun TradingDecisionLog() {
helperText = "위의 수치 만큼 호가 위로 주문함." helperText = "위의 수치 만큼 호가 위로 주문함."
) )
} }
Row(horizontalArrangement = Arrangement.SpaceEvenly) {
SettingInputField(
modifier = Modifier.weight(1.0f, true),
label = "예상 수익율",
initialValue = (tradeConfig.minExpectedProfitRate).toString(),
onSave = {
tradeConfig.minExpectedProfitRate = it.toDouble()
KisSession.saveTradeConfig()
},
helperText = "현제가 기준 예상 수익율이 더커야 삼"
)
SettingInputField(
modifier = Modifier.weight(1.0f, true),
label = "예상 매도 기준일",
initialValue = (tradeConfig.maxExpectedReboundDays).toString(),
onSave = {
tradeConfig.maxExpectedReboundDays = it.toDouble()
KisSession.saveTradeConfig()
},
helperText = "이정도 일수 전에는 팔릴거라 예상"
)
SettingInputField(
modifier = Modifier.weight(1.0f, true),
label = "주식 널뛰기 기준(예상 매도 기준일)",
initialValue = (tradeConfig.minExpectedReboundDays).toString(),
onSave = {
tradeConfig.minExpectedReboundDays = it.toDouble()
KisSession.saveTradeConfig()
},
helperText = "너무 작으면 초단타,널뛰기, 이 보다 커야 분석함"
)
}
} }
} }
} }