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:
@@ -90,4 +90,40 @@ describe('stocks criteriaEval', () => {
|
||||
expect(marketCapEok('1조 2,000억')).toBe(12000);
|
||||
expect(marketCapEok('2조')).toBe(20000);
|
||||
});
|
||||
|
||||
// ── v2.2.212 정밀화 규칙 ──────────────────────────────────────────────
|
||||
|
||||
test('ROE 레버리지 가드 — 부채비율 200% 면 ROE 15% 라도 미통과', () => {
|
||||
const stock: Stock = { 이름: '레버리지주', 심볼: '000010', 'ROE(25E)': '15%' };
|
||||
const evHigh = evaluateCriteria(stock, { symbol: '000010', roe: 15, debtRatio: 200 }, NOW);
|
||||
expect(evHigh.results.find(r => r.keyword === 'ROE')!.state).toBe('fail');
|
||||
const evLow = evaluateCriteria(stock, { symbol: '000010', roe: 15, debtRatio: 80 }, NOW);
|
||||
expect(evLow.results.find(r => r.keyword === 'ROE')!.state).toBe('pass');
|
||||
});
|
||||
|
||||
test('성장성 — 실측 YoY 가 있으면 마진 폴백 대신 YoY 로 판정', () => {
|
||||
const stock: Stock = { 이름: '진짜성장주', 심볼: '000011', '영업이익률(25E)': '5%' };
|
||||
// 마진 5% (폴백이면 fail) 이지만 매출 YoY 25% → pass
|
||||
const grow = evaluateCriteria(stock, { symbol: '000011', operatingMargin: 5, revenueGrowthYoY: 25 }, NOW);
|
||||
expect(grow.results.find(r => r.keyword === '성장성')!.state).toBe('pass');
|
||||
// 마진 18% (폴백이면 pass) 이지만 매출 YoY -5%·영업이익 YoY 3% → 실측 우선으로 fail
|
||||
const noGrow = evaluateCriteria(stock, { symbol: '000011', operatingMargin: 18, revenueGrowthYoY: -5, opProfitGrowthYoY: 3 }, NOW);
|
||||
expect(noGrow.results.find(r => r.keyword === '성장성')!.state).toBe('fail');
|
||||
});
|
||||
|
||||
test('안정성 부채 가드 — 유보율·시총 통과여도 부채비율 150% 면 미통과', () => {
|
||||
const stock: Stock = { 이름: '부채대형주', 심볼: '000012', 유보율: '4,000%', 시가총액: '1조' };
|
||||
const ev = evaluateCriteria(stock, { symbol: '000012', retentionRatio: 4000, marketCapEok: 10000, debtRatio: 150 }, NOW);
|
||||
expect(ev.results.find(r => r.keyword === '안정성')!.state).toBe('fail');
|
||||
});
|
||||
|
||||
test('PER 키워드 — ≤12배 통과, 저평가우량주 우선순위에 포함', () => {
|
||||
const { ev, verdict } = judge({
|
||||
이름: '저PER주', 심볼: '000013', 투자성향: '저평가우량주',
|
||||
'ROE(25E)': '11%', 'PER(25E)': '8', PBR: '0.9', 유보율: '1,200%',
|
||||
});
|
||||
expect(ev.results.find(r => r.keyword === 'PER')!.state).toBe('pass');
|
||||
// 통과: ROE, 유동성, PBR, PER → 우선순위 [PBR, PER, ROE, ...]
|
||||
expect(verdict.text).toBe('충족 (PBR, PER, ROE)');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user