This commit is contained in:
2026-04-02 11:16:53 +09:00
parent 6e7f485988
commit 921e6c7caf
2 changed files with 52 additions and 63 deletions
+44 -11
View File
@@ -852,8 +852,8 @@ object FinancialAnalyzer {
val isDebtSafe = fs.debtRatio < 200.0 // 부채비율 200% 미만
val isLiquiditySafe = fs.quickRatio > 80.0 // 당좌비율 80% 이상
val isNotDeficit = fs.isNetIncomePositive // 당기순이익은 일단 흑자여야 함
return isDebtSafe && isLiquiditySafe && isNotDeficit
val isNotCrashing = fs.netIncomeGrowth > -40.0
return isDebtSafe && isLiquiditySafe && isNotDeficit && isNotCrashing
}
/**
@@ -876,10 +876,12 @@ object FinancialAnalyzer {
val isDebtSafe = fs.debtRatio < 200.0 // 부채비율 200% 미만
val isLiquiditySafe = fs.quickRatio > 80.0 // 당좌비율 80% 이상
val isNotDeficit = fs.isNetIncomePositive // 당기순이익은 일단 흑자여야 함
val isNotCrashing = fs.netIncomeGrowth > -40.0
if ((isDebtSafe && isLiquiditySafe && isNotDeficit) == false) {
if (isDebtSafe)buffer.appendLine( "부채비율 200% 이상")
if (isLiquiditySafe)buffer.appendLine( "당좌비율 80% 미만")
if (isNotDeficit)buffer.appendLine( "당기순이익 적자")
if (!isDebtSafe)buffer.appendLine( "부채비율 200% 이상")
if (!isLiquiditySafe)buffer.appendLine( "당좌비율 80% 미만")
if (!isNotDeficit)buffer.appendLine( "당기순이익 적자")
if (!isNotCrashing) { buffer.appendLine("당기순이익 급감(${String.format("%.1f", fs.netIncomeGrowth)}%)") }
buffer.appendLine("최소 기준 미달")
} else {
buffer.appendLine("최소 기준 충족")
@@ -1009,23 +1011,47 @@ class TechnicalAnalyzer {
): InvestmentScores {
// 1. 초단기 (분봉 + 에너지 지표 위주)
val ultra = (calculateMFI(min30, 14) * 0.4 +
var ultra = (calculateMFI(min30, 14) * 0.4 +
calculateStochastic(min30) * 0.3 +
(if(calculateChange(min30.takeLast(10)) > 0) 30 else 0)).toInt()
// 2. 단기 (일봉 추세 + OBV 에너지)
val short = (calculateRSI(daily) * 0.3 +
var short = (calculateRSI(daily) * 0.3 +
(if(calculateOBV(daily) > 0) 40 else 10) +
(if(calculateChange(daily.takeLast(3)) > 0) 30 else 0)).toInt()
// 3. 중기 (주봉 + 재무 점수 혼합)
val mid = (if(calculateChange(weekly) > 0) 40 else 10) +
var mid = (if(calculateChange(weekly) > 0) 40 else 10) +
(financialScore * 0.6).toInt()
// 4. 장기 (월봉 + 섹터/기업 펀더멘털)
val long = (if(calculateChange(monthly) > 0) 50 else 0) +
var long = (if(calculateChange(monthly) > 0) 50 else 0) +
(financialScore * 0.5).toInt()
// 1. 일봉 이격도 과열 체크 (20일 이평선 기준)
if (daily.size >= 20) {
val ma20Daily = daily.takeLast(20).map { it.stck_prpr.toDouble() }.average()
val currentPrice = daily.last().stck_prpr.toDouble()
val disparityDaily = (currentPrice / ma20Daily) * 100
if (disparityDaily > 115.0) { // 20일선보다 15% 이상 떠 있으면 감점 시작
val penalty = ((disparityDaily - 115.0) * 1).toInt() // 초과분 1%당 2점 감점
short -= penalty
ultra -= (penalty / 2) // 초단기에도 영향
println("⚠️ [과열 감점] 일봉 이격도(${String.format("%.1f", disparityDaily)}%): -${penalty}")
}
}
// 2. 주봉 급등 체크 (최근 3주간의 상승폭)
if (weekly.size >= 3) {
val weeklyChange = calculateChange(weekly.takeLast(3))
if (weeklyChange > 30.0) { // 3주간 30% 이상 급등 시
mid -= 15
short -= 7
println("⚠️ [과열 감점] 주봉 급등(${String.format("%.1f", weeklyChange)}%): -15점")
}
}
return InvestmentScores(
ultraShort = ultra.coerceIn(0, 100),
shortTerm = short.coerceIn(0, 100),
@@ -1296,8 +1322,15 @@ class ScalpingAnalyzer {
val volSurge = volRatioNow > VOL_SURGE_THRESHOLD
val bbGood = bbPos > BB_LOWER_POS && bbPos < BB_UPPER_POS
val maBull = currentClose > sma10Now && sma10Now > sma20Now
val buySignal = maBull && rsiBull && volSurge && bbGood && isBreakout
// val buySignal = maBull && rsiBull && volSurge && bbGood
// val buySignal = maBull && rsiBull && volSurge && bbGood && isBreakout
val ma5Daily = if (candles.size >= 5) candles.takeLast(5).map { it.close.toDouble() }.average() else currentClose
val dailyDisparity = (currentClose / ma5Daily) * 100
// 과열 기준 정의
val isOverheated = dailyDisparity > 110.0 // 일봉 5일선 대비 10% 이상 이격 시 과열로 간주
// 매수 신호 조건에 과열 방지 추가
val buySignal = maBull && rsiBull && volSurge && bbGood && isBreakout && !isOverheated
val score = (if (maBull) 25 else 0) +