feat: 기업정보 종합 판단에 추정ROE·추정EPS 리비전 반영
- ROE: trailing 낮아도 추정ROE 급증(≥15% & 현재의 1.5배↑) 전망이면 좋은 점으로 표시 - PBR≥3: 추정ROE≥20%면 고평가 단정 대신 '실현 여부 관건'으로 완화 (PER/추정PER과 동일 패턴) - 추정EPS 리비전(est_change_pct)을 전망 개선/악화 판단에 추가 (목표가 리비전보다 직접적 신호) - synthNote: pbrJustified로 valHigh 제외 + EPS 리비전을 grPos/grNeg에 포함 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7911,7 +7911,14 @@ def render_html() -> str:
|
||||
'function companyGC(j){'
|
||||
'var good=[],caution=[],per=_gnum(j.per),pbr=_gnum(j.pbr),roe=_gnum(j.roe);'
|
||||
'var fwd=_gnum((j.fundamentals&&j.fundamentals.consensus)?j.fundamentals.consensus.per:null);'
|
||||
'if(roe!=null){if(roe<0)caution.push("ROE "+roe.toFixed(1)+"% — 자기자본이 손실(수익성 부진)");else if(roe>=15)good.push("ROE "+roe.toFixed(1)+"% — 자본 수익성 우수");else if(roe<8)caution.push("ROE "+roe.toFixed(1)+"% — 자본 수익성 다소 낮음");}'
|
||||
'var estRoe=_gnum((j.consensus&&j.consensus.this_year)?j.consensus.this_year.roe:null);'
|
||||
# ROE: trailing 낮아도 추정ROE 급증 전망이면 그쪽을 우선 표시 (PER/추정PER과 동일 패턴).
|
||||
'if(roe!=null){'
|
||||
'if(roe<0)caution.push("ROE "+roe.toFixed(1)+"% — 자기자본이 손실(수익성 부진)");'
|
||||
'else if(roe>=15)good.push("ROE "+roe.toFixed(1)+"% — 자본 수익성 우수");'
|
||||
'else if(estRoe!=null&&estRoe>=15&&estRoe>=roe*1.5)good.push("추정ROE "+estRoe.toFixed(1)+"% — 올해 수익성 급증 전망(현재 "+roe.toFixed(1)+"%)");'
|
||||
'else if(roe<8)caution.push("ROE "+roe.toFixed(1)+"% — 자본 수익성 다소 낮음");'
|
||||
'}'
|
||||
# PER: trailing 높아도 추정(forward) PER이 크게 낮으면 이익 급증 기대 반영 → 고평가로 단정 X, 다만 추정치 미달 위험 경고.
|
||||
'if(per!=null){'
|
||||
'if(per<=0)caution.push("PER 산정 불가 — 적자 또는 이익 미미");'
|
||||
@@ -7921,7 +7928,14 @@ def render_html() -> str:
|
||||
'}'
|
||||
'else if(per<=10)good.push("PER "+per.toFixed(1)+"배 — 밸류에이션 부담이 작음");'
|
||||
'}'
|
||||
'if(pbr!=null){if(pbr>=3)caution.push("PBR "+pbr.toFixed(1)+"배 — 자산가치 대비 비싼 편");else if(pbr>0&&pbr<1)good.push("PBR "+pbr.toFixed(1)+"배 — 자산가치(청산가치) 이하");}'
|
||||
# PBR: 높아도 추정ROE가 충분히 높으면 정당화 가능 → 단정 대신 실현 여부 관건으로 표현.
|
||||
'if(pbr!=null){'
|
||||
'if(pbr>=3){'
|
||||
'if(estRoe!=null&&estRoe>=20)caution.push("PBR "+pbr.toFixed(1)+"배 — 자산가치 대비 높지만, 추정ROE "+estRoe.toFixed(1)+"% 실현 여부가 관건");'
|
||||
'else caution.push("PBR "+pbr.toFixed(1)+"배 — 자산가치 대비 비싼 편");'
|
||||
'}'
|
||||
'else if(pbr>0&&pbr<1)good.push("PBR "+pbr.toFixed(1)+"배 — 자산가치(청산가치) 이하");'
|
||||
'}'
|
||||
'return {good:good,caution:caution};'
|
||||
'}'
|
||||
'function growthGC(j){'
|
||||
@@ -7934,6 +7948,9 @@ def render_html() -> str:
|
||||
'if(p&&tp){var up=(tp/p-1)*100;if(up>=15)good.push("목표주가까지 상승여력 +"+up.toFixed(0)+"%");else if(up<0)caution.push("현재가가 목표주가를 "+(-up).toFixed(0)+"% 웃돔 — 추가 상승여력 제한");}'
|
||||
'if(fc.opinion_label){if(fc.opinion_label.indexOf("매수")>=0)good.push("증권사 투자의견 "+escHtml(fc.opinion_label));else if(fc.opinion_label.indexOf("매도")>=0||fc.opinion_label.indexOf("중립")>=0||fc.opinion_label.indexOf("보유")>=0)caution.push("투자의견 "+escHtml(fc.opinion_label)+" — 적극 매수는 아님");}'
|
||||
'var tr=_gnum(cn.target_change_pct);if(tr!=null){if(tr>0)good.push("최근 3개월 목표가 상향(+"+tr.toFixed(1)+"%) — 전망 개선");else if(tr<0)caution.push("최근 3개월 목표가 하향("+tr.toFixed(1)+"%) — 전망 악화");}'
|
||||
# 추정EPS 리비전 — 목표가 리비전보다 직접적인 이익 전망 신호.
|
||||
'var er=_gnum(cn.est_change_pct);var ri=cn.rev_item||"EPS";'
|
||||
'if(er!=null){if(er>0)good.push("최근 추정"+escHtml(ri)+" 상향(+"+er.toFixed(1)+"%) — 이익 전망 개선");else if(er<0)caution.push("최근 추정"+escHtml(ri)+" 하향("+er.toFixed(1)+"%) — 이익 전망 악화");}'
|
||||
'var so=_gnum(cn.surprise_op);if(so!=null){if(so>0)good.push("최근 영업이익 어닝 서프라이즈(+"+so.toFixed(1)+"%)");else if(so<0)caution.push("최근 영업이익이 컨센서스 하회("+so.toFixed(1)+"%)");}'
|
||||
'return {good:good,caution:caution};'
|
||||
'}'
|
||||
@@ -7943,13 +7960,16 @@ def render_html() -> str:
|
||||
'var gr=(j.fundamentals&&j.fundamentals.growth)||{},fc=(j.fundamentals&&j.fundamentals.consensus)||{},cn=j.consensus||{};'
|
||||
'var oy=_gnum(gr.oper_profit_yoy),sy=_gnum(gr.sales_yoy),tr=_gnum(cn.target_change_pct);'
|
||||
'var p=_gnum(j.price),tp=_gnum(fc.target_price),up=(p&&tp)?(tp/p-1)*100:null;'
|
||||
'var fwd=_gnum(fc.per);'
|
||||
'var fwd=_gnum(fc.per);var er=_gnum(cn.est_change_pct);'
|
||||
'var estRoe=_gnum((cn&&cn.this_year)?cn.this_year.roe:null);'
|
||||
'var growthPriced=(per!=null&&per>=30&&fwd!=null&&fwd>0&&fwd<per*0.6&&fwd<20);'
|
||||
'var valHigh=(per!=null&&per>=30&&!growthPriced)||(pbr!=null&&pbr>=3);'
|
||||
# 추정ROE가 충분히 높으면 높은 PBR을 고평가로 단정하지 않음 (companyGC와 동일 기준).
|
||||
'var pbrJustified=(pbr!=null&&pbr>=3&&estRoe!=null&&estRoe>=20);'
|
||||
'var valHigh=(per!=null&&per>=30&&!growthPriced)||(pbr!=null&&pbr>=3&&!pbrJustified);'
|
||||
'var valCheap=(per!=null&&per>0&&per<=10)||(pbr!=null&&pbr>0&&pbr<1);'
|
||||
'var buy=fc.opinion_label&&fc.opinion_label.indexOf("매수")>=0;'
|
||||
'var grPos=(oy!=null&&oy>=20)||(up!=null&&up>=15)||buy||(tr!=null&&tr>0);'
|
||||
'var grNeg=(oy!=null&&oy<0)||(sy!=null&&sy<0)||(up!=null&&up<0)||(tr!=null&&tr<0);'
|
||||
'var grPos=(oy!=null&&oy>=20)||(up!=null&&up>=15)||buy||(tr!=null&&tr>0)||(er!=null&&er>0);'
|
||||
'var grNeg=(oy!=null&&oy<0)||(sy!=null&&sy<0)||(up!=null&&up<0)||(tr!=null&&tr<0)||(er!=null&&er<0);'
|
||||
'if(growthPriced)return "현재 PER은 "+per.toFixed(0)+"배로 높지만 추정이익이 급증해 추정(forward) PER은 "+fwd.toFixed(1)+"배로 낮아요. 시장이 가파른 이익 성장을 기대하는 구간으로, 성장이 실현되면 밸류가 정당화되지만 추정치에 못 미치면 조정 위험이 큽니다.";'
|
||||
'if(valHigh&&grPos)return "성장·실적 기대는 좋지만 현재 밸류에이션이 높아 그 기대가 주가에 이미 상당 부분 반영돼 있어요. 성장이 기대만큼 이어지는지가 관건입니다.";'
|
||||
'if(valCheap&&grNeg)return "밸류에이션은 저평가 구간이나 성장·전망이 부진해요. 싸다는 이유만으로 접근하기보다 실적 반등 신호를 함께 봐야 합니다.";'
|
||||
|
||||
Reference in New Issue
Block a user