package analyzer import kotlin.compareTo object FinancialAnalyzer { /** * [매수 고려] 우량 기업 요건 확인 * 모든 조건 충족 시 적극적인 분석(AI/차트) 단계로 진입합니다. */ fun isSafetyBeltMet(fs: FinancialStatement): Boolean { // 1. 유동성 위기 체크 (이건 유지하는 것이 좋습니다) val isDebtSafe = fs.debtRatio < 300.0 // 200% -> 300%로 완화 val isLiquiditySafe = fs.quickRatio > 60.0 // 80% -> 60%로 완화 (급전이 필요한 수준만 차단) // 2. 턴어라운드 허용 (적자여도 개선 중이면 통과) val isTurningAround = !fs.isNetIncomePositive && fs.operatingProfitGrowth > 50.0 val isNotFatalDeficit = fs.isNetIncomePositive || isTurningAround // 3. 상장폐지 요건 중심 필터 val isNotCapitalImpaired = fs.capitalImpairmentRate < 50.0 // 자본잠식 50% 이상 차단 val isNotLossExploding = fs.lossToSalesRatio < 150.0 // 매출보다 손실이 너무 크면 차단 // 최종: 정말 위험한 경우가 아니면 분석 단계(AI/뉴스)로 보냄 return isDebtSafe && isLiquiditySafe && isNotFatalDeficit && isNotCapitalImpaired } fun toString(fs : FinancialStatement): String { var buffer = StringBuffer() 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 (!isNotCrashing) { buffer.appendLine("당기순이익 급감(${String.format("%.1f", fs.netIncomeGrowth)}%)") } buffer.appendLine("최소 기준 미달") } else { buffer.appendLine("최소 기준 충족") } val highProfitability = fs.roe >= 10.0 // ROE 10% 이상 val strongGrowth = fs.netIncomeGrowth >= 15.0 // 이익 성장률 15% 이상 val verySafeDebt = fs.debtRatio <= 100.0 // 부채비율 100% 이하 (안전) val goodLiquidity = fs.quickRatio >= 120.0 // 당좌비율 120% 이상 (여유) val businessHealthy = fs.isOperatingProfitPositive // 본업(영업이익)이 흑자 if ((highProfitability && strongGrowth && verySafeDebt && goodLiquidity && businessHealthy) == false) { if(!highProfitability) buffer.appendLine( "ROE 10% 미만") if(!strongGrowth) buffer.appendLine( "이익 성장률 15% 미만") if(!verySafeDebt) buffer.appendLine( "부채비율 100% 이상 (안전성 미달)") if(!goodLiquidity) buffer.appendLine( "당좌비율 120% 이하 (여유 없음)") if(!businessHealthy) buffer.appendLine( "본업(영업이익)이 적자") buffer.appendLine("재무 건전성 및 성장성 미달") } else { buffer.appendLine("재무 건전성 및 성장성 충족") } return buffer.toString() } fun isBuyConsiderationMet(fs: FinancialStatement): Boolean { val highProfitability = fs.roe >= 10.0 // ROE 10% 이상 val strongGrowth = fs.netIncomeGrowth >= 15.0 // 이익 성장률 15% 이상 val verySafeDebt = fs.debtRatio <= 100.0 // 부채비율 100% 이하 (안전) val goodLiquidity = fs.quickRatio >= 120.0 // 당좌비율 120% 이상 (여유) val businessHealthy = fs.isOperatingProfitPositive // 본업(영업이익)이 흑자 return highProfitability && strongGrowth && verySafeDebt && goodLiquidity && businessHealthy } fun calculateScore(fs: FinancialStatement): Int { var score = 50.0 // 중립 시작 // 1. 수익성 및 성장 추세 (Max 50) score += when { fs.isOperatingProfitPositive && fs.operatingProfitGrowth > 20.0 -> 30.0 // 우량 성장 fs.isOperatingProfitPositive && fs.operatingProfitGrowth < -30.0 -> -20.0 // 쇠퇴 위험 !fs.isOperatingProfitPositive && fs.operatingProfitGrowth > 50.0 -> 20.0 // 턴어라운드 신호 !fs.isOperatingProfitPositive && fs.operatingProfitGrowth < -20.0 -> -30.0 // 적자 심화 else -> 0.0 } // 2. 수익 효율 ROE (Max 30) score += (fs.roe.coerceIn(-20.0, 20.0) * 1.5) // 3. 안정성 (Max 20) if (fs.debtRatio <= 100.0) score += 20.0 else if (fs.debtRatio <= 150.0) score += 10.0 // 4. 감점 페널티 (위험 징후 시 최대 -50) if (fs.capitalImpairmentRate > 20.0) score -= 30.0 if (fs.debtAccelerationRate > 100.0) score -= 20.0 return score.coerceIn(0.0, 100.0).toInt() } /** * 상황별 상태 메시지 정교화 */ fun getInvestmentStatus(fs: FinancialStatement): String { return when { fs.isOperatingProfitPositive && fs.operatingProfitGrowth > 10.0 -> "🚀 [성장중] 실적 개선세 뚜렷" !fs.isOperatingProfitPositive && fs.operatingProfitGrowth > 40.0 -> "☀️ [회복중] 적자폭 급감, 턴어라운드 가시화" fs.isOperatingProfitPositive && fs.operatingProfitGrowth < -40.0 -> "⚠️ [쇠퇴중] 이익 급감, 적자전환 유의" else -> "🚨 [부실] 재무 구조 악화 지속" } } }