feat(stocks): 판정 기준 정밀화 — 레버리지 가드·실측 YoY·PER 기둥 (v2.2.212)

퀀트 실증 근거(F-Score 류 품질+가격 결합) 기반 기준 강화:
- ROE: 부채비율 ≤150% 레버리지 가드 — 빚으로 부풀린 ROE 배제 (듀폰분해).
- 성장성: Naver 연간 다년치에서 매출/영업이익 YoY 실측 계산을 1순위로
  (매출 ≥10% 또는 영업이익 ≥15%). 마진 수준·상장연차는 YoY 미확보 시 폴백.
- 안정성: 부채비율 ≤100% 가드 추가 — 유보율은 자본금 왜곡되는 약한 지표.
- PER ≤12배 키워드 신설(보유 데이터인데 미사용이던 가격 매력 축),
  저평가우량주 우선순위에 PBR 다음으로 편입.
- naverFundamentals: revenueGrowthYoY/opProfitGrowthYoY 추출 추가.
- 테스트 12건 (기존 사용자 패턴 8건 유지 + 신규 규칙 4건).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 19:15:21 +09:00
parent ef3628c6eb
commit cbc2558550
5 changed files with 110 additions and 22 deletions
+20 -3
View File
@@ -22,6 +22,9 @@ export interface Fundamentals {
operatingMargin?: number; // % (영업이익률)
retentionRatio?: number; // % (유보율)
debtRatio?: number; // % (부채비율)
/** 최근 확정 2개 연도 기준 YoY 성장률 (%). '성장성' 기준의 실측치 — 마진 수준이 아닌 진짜 성장. */
revenueGrowthYoY?: number; // 매출액 YoY %
opProfitGrowthYoY?: number; // 영업이익 YoY %
/** integration API 의 현재가 + 평가지표. */
per?: number;
pbr?: number;
@@ -125,18 +128,32 @@ export async function fetchFundamentals(symbol: string, timeoutMs = 10000): Prom
// finance/annual — rowList 에서 최근 확정 연도 컬럼 값.
if (fin?.financeInfo?.rowList && fin.financeInfo.rowList.length > 0) {
const latestKey = pickLatestConfirmedKey(fin.financeInfo.trTitleList);
const confirmedKeys = (fin.financeInfo.trTitleList || [])
.filter(t => t.isConsensus === 'N').map(t => t.key).sort().reverse();
const latestKey = confirmedKeys[0] ?? null;
const prevKey = confirmedKeys[1] ?? null;
if (latestKey) {
const rowByTitle = new Map(fin.financeInfo.rowList.map(r => [r.title, r]));
const valueOf = (title: string): number | undefined => {
const valueOf = (title: string, key: string = latestKey): number | undefined => {
const row = rowByTitle.get(title);
if (!row) return undefined;
return parseNumber(row.columns[latestKey]?.value);
return parseNumber(row.columns[key]?.value);
};
out.roe = valueOf('ROE');
out.operatingMargin = valueOf('영업이익률');
out.retentionRatio = valueOf('유보율');
out.debtRatio = valueOf('부채비율');
// YoY 성장률 — 최근 확정 2개 연도. '성장성'을 마진 수준이 아닌 실측 성장으로 판정.
if (prevKey) {
const yoy = (title: string): number | undefined => {
const a = valueOf(title, latestKey);
const b = valueOf(title, prevKey);
if (a === undefined || b === undefined || b === 0) return undefined;
return ((a - b) / Math.abs(b)) * 100;
};
out.revenueGrowthYoY = yoy('매출액');
out.opProfitGrowthYoY = yoy('영업이익');
}
}
}
return out;