From f8d17f4437de4f126d5a3b01c6c2b1771c822ea9 Mon Sep 17 00:00:00 2001 From: hyowons Date: Thu, 11 Jun 2026 12:09:45 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EA=B8=B0=EC=97=85=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EB=AA=A8=EB=8B=AC=20=E2=80=94=20=EA=B0=80=EC=B9=98+=EC=84=B1?= =?UTF-8?q?=EC=9E=A5=20=EC=A2=85=ED=95=A9=20=ED=95=B4=EC=84=9D=EC=9D=84=20?= =?UTF-8?q?=EC=9A=94=EC=95=BD=ED=83=AD=EC=97=90=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 각 탭의 개별 판단 박스 제거. 요약탭 최상단에 📌종합(가치 vs 성장·컨센서스 상충을 한 문장으로 화해: 고평가+긍정/저평가+부진/고평가+부진/저평가+긍정 4분기) + ✅좋은 점 / ⚠️주의할 점(두 영역 합산) 표시. companyJudge/growthJudge → companyGC/growthGC({good,caution}) + synthNote 추가. Co-Authored-By: Claude Opus 4.8 --- agents/stock/workspace/scripts/behive_web.py | 44 ++++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/agents/stock/workspace/scripts/behive_web.py b/agents/stock/workspace/scripts/behive_web.py index 311c4f7..202cbc1 100644 --- a/agents/stock/workspace/scripts/behive_web.py +++ b/agents/stock/workspace/scripts/behive_web.py @@ -4443,6 +4443,8 @@ dl.pending-detail .pending-line-meta { margin-top: 2px; } .info-summary { background: #11161f; border: 1px solid #232a36; border-radius: 8px; padding: 10px 12px; margin: 0 0 12px; } .info-jd + .info-jd { margin-top: 8px; } .info-jd > b { display: block; font-size: 12px; margin-bottom: 3px; } +.info-jd-s > b { color: #8ab4f8; } +.info-jd-s-b { font-size: 12.5px; color: #d6d8dd; line-height: 1.65; } .info-jd-g > b { color: #34d399; } .info-jd-c > b { color: #fbbf24; } .info-summary ul { margin: 0; padding-left: 17px; } @@ -7880,7 +7882,10 @@ def render_html() -> str: 'var fg=j.fundamentals||{},gr=fg.growth||{},fc=fg.consensus||{},cn=j.consensus||{};' 'var chg=(j.change>0?"#ef4444":(j.change<0?"#3b82f6":"#9ca3af"));' 'var pc=(j.change_pct!=null?(\' (\'+(j.change_pct>0?"+":"")+fmtNum(j.change_pct,2)+\'%)\'):"");' - 'var h=\'
\';' + # 가치 + 성장·컨센서스 종합 해석 박스 (요약탭 최상단). + 'var _cg=companyGC(j),_gg=growthGC(j);' + 'var h=judgeBox(synthNote(j),_cg.good.concat(_gg.good),_cg.caution.concat(_gg.caution));' + 'h+=\'
\';' 'h+=row("현재가",\'\'+infoWon(j.price)+\'\'+pc,"현재가");' 'h+=row("시가총액",capDisp(j.market_cap),"시가총액");' 'if(fc.target_price!=null)h+=row("목표주가",\'\'+infoWon(fc.target_price)+\'\'+(fc.opinion_label?\' \'+escHtml(fc.opinion_label)+\'\':""),"목표주가");' @@ -7894,21 +7899,23 @@ def render_html() -> str: '}' # 탭 상단 해석 박스 — 지표를 ✅좋은 점 / ⚠️주의할 점으로 판단(규칙 기반). 특이점 없으면 미표시. 'function _gnum(v){var n=Number(v);return (v==null||v===""||isNaN(n))?null:n;}' - 'function judgeBox(good,caution){' - 'if(!good.length&&!caution.length)return "";' + 'function judgeBox(synth,good,caution){' + 'if(!synth&&!good.length&&!caution.length)return "";' 'var h="";' + 'if(synth)h+=\'
📌 종합
\'+synth+\'
\';' 'if(good.length)h+=\'
✅ 좋은 점
    \'+good.map(function(x){return "
  • "+x+"
  • ";}).join("")+\'
\';' 'if(caution.length)h+=\'
⚠️ 주의할 점
    \'+caution.map(function(x){return "
  • "+x+"
  • ";}).join("")+\'
\';' 'return \'
\'+h+\'
\';' '}' - 'function companyJudge(j){' + # 가치/성장 지표를 {good,caution} 으로 분류 (요약탭에서 합쳐 표시). + 'function companyGC(j){' 'var good=[],caution=[],per=_gnum(j.per),pbr=_gnum(j.pbr),roe=_gnum(j.roe);' '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)+"% — 자본 수익성 다소 낮음");}' 'if(per!=null){if(per<=0)caution.push("PER 산정 불가 — 적자 또는 이익 미미");else if(per>=30)caution.push("PER "+per.toFixed(1)+"배 — 기대가 선반영된 고평가 부담");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)+"배 — 자산가치(청산가치) 이하");}' - 'return judgeBox(good,caution);' + 'return {good:good,caution:caution};' '}' - 'function growthJudge(j){' + 'function growthGC(j){' 'var gr=(j.fundamentals&&j.fundamentals.growth)||{},fc=(j.fundamentals&&j.fundamentals.consensus)||{},cn=j.consensus||{},good=[],caution=[];' 'var sy=_gnum(gr.sales_yoy),oy=_gnum(gr.oper_profit_yoy),ey=_gnum(gr.eps_yoy);' 'if(oy!=null){if(oy>=20)good.push("영업이익 +"+oy.toFixed(0)+"% — 이익 고성장");else if(oy<0)caution.push("영업이익 "+oy.toFixed(0)+"% — 이익 역성장");}' @@ -7919,10 +7926,29 @@ def render_html() -> str: '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)+"%) — 전망 악화");}' '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 judgeBox(good,caution);' + 'return {good:good,caution:caution};' '}' - 'var companyInner=companyJudge(j)+titled("가치지표",secGrid("가치지표"))+titled("기본정보",secGrid("기본정보"));' - 'var growthInner=growthJudge(j)+secGrid("성장성·컨센서스");' + # 가치(고평가 등) vs 성장·컨센서스(긍정 등) 상충을 한 문장으로 종합. + 'function synthNote(j){' + 'var per=_gnum(j.per),pbr=_gnum(j.pbr);' + '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 valHigh=(per!=null&&per>=30)||(pbr!=null&&pbr>=3);' + '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);' + 'if(valHigh&&grPos)return "성장·실적 기대는 좋지만 현재 밸류에이션이 높아 그 기대가 주가에 이미 상당 부분 반영돼 있어요. 성장이 기대만큼 이어지는지가 관건입니다.";' + 'if(valCheap&&grNeg)return "밸류에이션은 저평가 구간이나 성장·전망이 부진해요. 싸다는 이유만으로 접근하기보다 실적 반등 신호를 함께 봐야 합니다.";' + 'if(valHigh&&grNeg)return "밸류에이션이 높은데 성장·전망도 약한 부담스러운 조합이에요. 신중히 접근하세요.";' + 'if(valCheap&&grPos)return "저평가 구간에 성장·전망까지 양호한 긍정적 조합이에요.";' + 'if(grPos)return "밸류 부담은 크지 않은 수준에서 성장·전망이 양호한 편이에요.";' + 'if(grNeg)return "성장·전망이 다소 부진한 편이에요.";' + 'return "";' + '}' + 'var companyInner=titled("가치지표",secGrid("가치지표"))+titled("기본정보",secGrid("기본정보"));' + 'var growthInner=secGrid("성장성·컨센서스");' 'var repInner=infoReportsHtml(j);' 'var TB=[["summary","요약",sumPanel()],["company","기업정보·가치",companyInner],["growth","성장성·컨센서스",growthInner],["reports","투자리포트",repInner]];' 'var bar=\'
\';var pans="";'