115 lines
5.7 KiB
Kotlin
115 lines
5.7 KiB
Kotlin
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 -> "🚨 [부실] 재무 구조 악화 지속"
|
|
}
|
|
}
|
|
}
|
|
|