<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>alpha-pulse on ICE-ICE-BEAR-BLOG</title><link>https://ice-ice-bear.github.io/ko/tags/alpha-pulse/</link><description>Recent content in alpha-pulse on ICE-ICE-BEAR-BLOG</description><generator>Hugo -- gohugo.io</generator><language>ko</language><lastBuildDate>Thu, 02 Apr 2026 00:00:00 +0900</lastBuildDate><atom:link href="https://ice-ice-bear.github.io/ko/tags/alpha-pulse/index.xml" rel="self" type="application/rss+xml"/><item><title>Trading Agent 개발기 #8 — 다중 팩터 가중치 시스템과 합성 스코어 마이그레이션</title><link>https://ice-ice-bear.github.io/ko/posts/2026-04-02-trading-agent-dev8/</link><pubDate>Thu, 02 Apr 2026 00:00:00 +0900</pubDate><guid>https://ice-ice-bear.github.io/ko/posts/2026-04-02-trading-agent-dev8/</guid><description>&lt;img src="https://ice-ice-bear.github.io/" alt="Featured image of post Trading Agent 개발기 #8 — 다중 팩터 가중치 시스템과 합성 스코어 마이그레이션" /&gt;&lt;h2 id="개요"&gt;개요
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://ice-ice-bear.github.io/ko/posts/2026-03-30-trading-agent-dev7/" &gt;이전 글: Trading Agent 개발기 #7&lt;/a&gt;에서는 에이전트 설정 UI와 시그널 카드 개선을 다뤘다. 이번 #8에서는 단일 &lt;code&gt;min_rr_score&lt;/code&gt; 게이트를 &lt;strong&gt;5개 팩터 합성 스코어(Composite Score)&lt;/strong&gt; 시스템으로 교체하고, 종목 리서치 페이지 신규 구축, 매도 검증 로직, 그리고 프로젝트 리브랜딩까지 41개 커밋에 걸친 대규모 개선을 정리한다.&lt;/p&gt;
&lt;h2 id="1-종목-리서치-페이지-stock-info"&gt;1. 종목 리서치 페이지 (Stock Info)
&lt;/h2&gt;&lt;h3 id="문제"&gt;문제
&lt;/h3&gt;&lt;p&gt;시그널이 발생해도 해당 종목의 기본적 분석, 기술적 지표, 수급 동향 등을 한눈에 볼 수 있는 페이지가 없었다. 매번 외부 증권사 HTS를 열어야 했고, 이는 의사결정 지연의 원인이 됐다.&lt;/p&gt;
&lt;h3 id="구현"&gt;구현
&lt;/h3&gt;&lt;p&gt;백엔드에 &lt;code&gt;/api/research&lt;/code&gt; 라우터를 추가하고 5개 엔드포인트(기본 정보, 재무, 기술적 지표, 수급, 뉴스/공시)를 구성했다. 프론트엔드는 9개 섹션 컴포넌트로 분리했다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// frontend/src/components/stockinfo/ 구조
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;DiscoverySidebar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt; &lt;span class="c1"&gt;// 종목 검색 사이드바
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;ResearchHeader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt; &lt;span class="c1"&gt;// 종목 기본 정보 헤더
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;PriceChartSection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt; &lt;span class="c1"&gt;// 캔들스틱 차트 + 기술적 지표
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;FundamentalsSection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt; &lt;span class="c1"&gt;// 재무제표 핵심 지표
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;ValuationSection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt; &lt;span class="c1"&gt;// 밸류에이션 비교
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;InvestorFlowSection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt; &lt;span class="c1"&gt;// 외국인/기관 수급
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;PeerSection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt; &lt;span class="c1"&gt;// 동종업계 비교
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;InsiderSection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt; &lt;span class="c1"&gt;// 내부자 거래
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;SignalHistorySection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tsx&lt;/span&gt; &lt;span class="c1"&gt;// 과거 시그널 이력
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;차트는 기존 라인 차트에서 &lt;strong&gt;캔들스틱 + 거래량 + 이동평균선(MA) + 볼린저 밴드(BB)&lt;/strong&gt; 오버레이로 업그레이드했으며, 기술적 지표는 RSI, MACD, 볼린저 밴드, 거래량 추세를 각각 미니 차트가 포함된 2x2 그리드 카드로 표시한다.&lt;/p&gt;
&lt;h2 id="2-시그널-파이프라인-개선--선형-신뢰도와-매도-검증"&gt;2. 시그널 파이프라인 개선 — 선형 신뢰도와 매도 검증
&lt;/h2&gt;&lt;h3 id="sigmoid에서-linear-매핑으로"&gt;Sigmoid에서 Linear 매핑으로
&lt;/h3&gt;&lt;p&gt;기존 sigmoid 기반 &lt;code&gt;compute_confidence&lt;/code&gt;는 R/R 스코어가 0.5~1.5 구간에서 거의 동일한 신뢰도를 출력하는 &amp;ldquo;사각지대&amp;quot;가 있었다. 이를 선형 매핑으로 교체하고 &lt;code&gt;min_rr_score&lt;/code&gt; 임계값을 0.3으로 낮춰 더 넓은 범위의 시그널을 포착하도록 했다.&lt;/p&gt;
&lt;h3 id="매도sell-검증-로직"&gt;매도(SELL) 검증 로직
&lt;/h3&gt;&lt;p&gt;보유하지 않은 종목에 대해 SELL 시그널이 발생하는 문제를 발견했다. 두 단계의 하드 게이트를 추가했다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Risk Manager&lt;/strong&gt;: 미보유 종목 SELL 거부 + 최소 보유 기간(min hold time) 검증&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Market Scanner&lt;/strong&gt;: 미보유 종목의 SELL을 HOLD로 강제 전환&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;전문가 패널 프롬프트에도 SELL/HOLD 방향 규칙을 명시적으로 추가하여, Chief Analyst가 보유 현황을 인지한 상태에서 의견을 내도록 개선했다.&lt;/p&gt;
&lt;h2 id="3-다중-팩터-합성-스코어-시스템"&gt;3. 다중 팩터 합성 스코어 시스템
&lt;/h2&gt;&lt;p&gt;이번 시리즈의 핵심 변경이다. 단일 R/R 스코어에 의존하던 시그널 필터링을 &lt;strong&gt;5개 독립 팩터의 가중합&lt;/strong&gt;으로 전면 교체했다.&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart LR
 subgraph 5-Factors["5개 서브 스코어"]
 A["R/R Ratio&amp;lt;br/&amp;gt;(리스크 대비 수익)"]
 B["Expert Consensus&amp;lt;br/&amp;gt;(전문가 합의도)"]
 C["Fundamental&amp;lt;br/&amp;gt;(PER, ROE 등)"]
 D["Technical Momentum&amp;lt;br/&amp;gt;(RSI, MACD, 거래량)"]
 E["Institutional Flow&amp;lt;br/&amp;gt;(외국인/기관 수급)"]
 end

 subgraph Weights["가중치 정규화"]
 W["normalize_weights()"]
 end

 subgraph Quality["데이터 품질"]
 Q["confidence_grades&amp;lt;br/&amp;gt;A=1.0 B=0.85 C=0.6 D=0.3"]
 end

 A --&gt; W
 B --&gt; W
 C --&gt; W
 D --&gt; W
 E --&gt; W
 W --&gt;|"weighted sum"| R["raw score"]
 R --&gt;|"x quality"| F["Composite Score&amp;lt;br/&amp;gt;(0~100)"]
 Q --&gt; F&lt;/pre&gt;&lt;h3 id="서브-스코어-설계"&gt;서브 스코어 설계
&lt;/h3&gt;&lt;p&gt;각 팩터는 0~1 범위로 정규화되며, 데이터가 없으면 기본값 0.5(중립)를 반환한다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# backend/app/models/composite_score.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;score_fundamental&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;per&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;roe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;debt_ratio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;operating_margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;각 지표를 독립적으로 0~1로 정규화하고 평균을 반환한다.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; 누락된 지표는 계산에서 제외.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;40.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;roe&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;roe&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;30.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ... debt_ratio, operating_margin 동일 패턴&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;기관/외국인 수급 스코어는 sigmoid 정규화를 사용한다. 순매수 합계를 기준금액(기본 10억원)으로 나눠 -1~1 범위로 매핑한다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;score_institutional_flow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;foreign_net&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;institution_net&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1_000_000_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# 10억원&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;combined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;foreign_net&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;institution_net&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;combined&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="가중치-정규화와-합산"&gt;가중치 정규화와 합산
&lt;/h3&gt;&lt;p&gt;사용자가 설정한 가중치는 합이 1.0이 되도록 자동 정규화된다. 최종 점수는 가중합에 데이터 품질 멀티플라이어를 곱한 뒤 0~100 스케일로 변환한다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute_composite_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rr_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;calibration_ceiling&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;expert_analyses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dart_financials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;technicals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;investor_trend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;confidence_grades&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;normalize_weights&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;weights&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DEFAULT_WEIGHTS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ... 5개 서브 스코어 계산 ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;rr_ratio&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rr_sub&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;expert_consensus&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;expert_sub&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;fundamental&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;fundamental_sub&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;technical&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;technical_sub&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;institutional&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;institutional_sub&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;quality&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute_data_quality_multiplier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;confidence_grades&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;quality&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="데이터-품질-멀티플라이어"&gt;데이터 품질 멀티플라이어
&lt;/h3&gt;&lt;p&gt;전문가별로 데이터 신뢰도 등급(A/B/C/D)을 부여하고, 등급 평균을 멀티플라이어로 적용한다. 데이터 품질이 낮으면 합성 스코어가 자동으로 할인된다.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;등급&lt;/th&gt;
 &lt;th&gt;멀티플라이어&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;A&lt;/td&gt;
 &lt;td&gt;1.00&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;B&lt;/td&gt;
 &lt;td&gt;0.85&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;C&lt;/td&gt;
 &lt;td&gt;0.60&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;D&lt;/td&gt;
 &lt;td&gt;0.30&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="4-ui-슬라이더와-db-마이그레이션"&gt;4. UI 슬라이더와 DB 마이그레이션
&lt;/h2&gt;&lt;h3 id="가중치-조절-ui"&gt;가중치 조절 UI
&lt;/h3&gt;&lt;p&gt;Settings 페이지에 5개 팩터별 가중치 슬라이더를 추가했다. 사용자가 슬라이더를 움직이면 실시간으로 정규화된 비율이 표시된다. 기존 &lt;code&gt;min_rr_score&lt;/code&gt; 슬라이더는 &lt;code&gt;min_composite_score&lt;/code&gt;로 교체되었고, 기본 임계값은 15%로 설정했다.&lt;/p&gt;
&lt;h3 id="전체-스택-마이그레이션"&gt;전체 스택 마이그레이션
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;min_rr_score&lt;/code&gt;에서 &lt;code&gt;min_composite_score&lt;/code&gt;로의 변경은 다음 레이어를 모두 수정해야 했다.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;레이어&lt;/th&gt;
 &lt;th&gt;파일&lt;/th&gt;
 &lt;th&gt;변경 내용&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;스코어링 모듈&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;composite_score.py&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;5개 서브 스코어 + 합산 함수 신규&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;스캐너&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;market_scanner.py&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;compute_confidence&lt;/code&gt; 제거, composite score 연결&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;리스크 매니저&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;risk_manager.py&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;게이트 기준 변경&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;API 라우터&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;agents.py&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;가중치 필드 추가, 필드명 변경&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;프론트엔드 타입&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;types.ts&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;가중치 필드 5개 추가&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;설정 UI&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;SettingsView.tsx&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;슬라이더 5개 추가&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;DB&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;trading.db&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;컬럼 rename + 가중치 기본값 insert&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="5-기타-개선사항"&gt;5. 기타 개선사항
&lt;/h2&gt;&lt;h3 id="alpha-pulse-리브랜딩"&gt;Alpha Pulse 리브랜딩
&lt;/h3&gt;&lt;p&gt;프로젝트명을 &amp;ldquo;KIS Trading&amp;quot;에서 &lt;strong&gt;Alpha Pulse&lt;/strong&gt;로 변경했다. 파비콘, 매니페스트, 헤더바, 앱 타이틀 등 전체 브랜딩 에셋을 교체했다.&lt;/p&gt;
&lt;h3 id="인프라-수정"&gt;인프라 수정
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;APScheduler cron 요일 변환&lt;/strong&gt;: 표준 cron(0=Sun)과 APScheduler(0=Mon) 간 요일 인덱스 차이를 변환하여 스케줄 태스크가 정확한 요일에 실행되도록 수정&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;uvicorn WebSocket&lt;/strong&gt;: &lt;code&gt;websockets&lt;/code&gt; 패키지의 DeprecationWarning을 해결하기 위해 &lt;code&gt;wsproto&lt;/code&gt;로 구현체 변경&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;스케줄 정렬&lt;/strong&gt;: 스케줄 태스크 목록을 cron 시간(시:분) 기준 오름차순으로 정렬&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="전문가-패널-강화"&gt;전문가 패널 강화
&lt;/h3&gt;&lt;p&gt;각 전문가에게 투자자 수급 동향, DART 공시 요약, 전문 분야별 신뢰도 등급을 추가로 제공하여 분석 품질을 향상시켰다.&lt;/p&gt;
&lt;h2 id="커밋-로그"&gt;커밋 로그
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;날짜&lt;/th&gt;
 &lt;th&gt;설명&lt;/th&gt;
 &lt;th&gt;카테고리&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;03-24&lt;/td&gt;
 &lt;td&gt;스케줄 태스크 cron 시간순 정렬&lt;/td&gt;
 &lt;td&gt;UI&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-25&lt;/td&gt;
 &lt;td&gt;에이전트 설정 구성 가능화 + 시그널 카드 UI 개선&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-25&lt;/td&gt;
 &lt;td&gt;CLAUDE.md 멀티 에이전트 시스템 문서 업데이트&lt;/td&gt;
 &lt;td&gt;docs&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-30&lt;/td&gt;
 &lt;td&gt;uvicorn WebSocket을 wsproto로 전환&lt;/td&gt;
 &lt;td&gt;fix&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-30&lt;/td&gt;
 &lt;td&gt;APScheduler cron 요일 변환 수정&lt;/td&gt;
 &lt;td&gt;fix&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-30&lt;/td&gt;
 &lt;td&gt;Stock Info 페이지 설계 문서 + 구현 계획&lt;/td&gt;
 &lt;td&gt;docs&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;technical_service 모듈 추가 (재사용 가능 지표 계산)&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;research 타입 + API 함수 추가&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;/api/research 라우터 (5개 엔드포인트)&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;stockinfo 섹션 컴포넌트 9개 + DiscoverySidebar&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;InsiderSection, SignalHistorySection 컴포넌트&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;ResearchPanel, StockInfoView, CSS 완성&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;StockInfoView를 앱 내비게이션에 연결&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;lint 에러 해결 및 stockinfo 컴포넌트 완성&lt;/td&gt;
 &lt;td&gt;fix&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;verbatimModuleSyntax 호환 import type 수정&lt;/td&gt;
 &lt;td&gt;fix&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;검색 결과 반환 + 종목 전환 시 stale state 방지&lt;/td&gt;
 &lt;td&gt;fix&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;시그널 파이프라인 수정 설계 문서&lt;/td&gt;
 &lt;td&gt;docs&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;캔들스틱 차트 + 거래량, MA, BB 오버레이&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;기술적 지표 미니 차트 카드 분리&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;compute_confidence 선형 매핑 함수 추가&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;sigmoid를 linear confidence로 교체, min_rr_score 0.3&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;기술적 지표 카드 2x2 그리드 레이아웃&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;SELL 검증 — 미보유 종목 거부 + 최소 보유 기간&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;미보유 종목 SELL을 HOLD로 강제 전환&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;Chief Analyst 프롬프트에 SELL/HOLD 방향 규칙 추가&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;전문가 데이터 강화 — 수급, DART, 신뢰도 등급&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;가격/거래량 차트 영역 간격 조정&lt;/td&gt;
 &lt;td&gt;fix&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;calibration ceiling 슬라이더, min hold time 입력&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;RSI 게이지 CSS 누락분 반영&lt;/td&gt;
 &lt;td&gt;fix&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;다중 팩터 합성 스코어 설계 문서 (Approach C)&lt;/td&gt;
 &lt;td&gt;docs&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;다중 팩터 합성 스코어 구현 계획&lt;/td&gt;
 &lt;td&gt;docs&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;03-31&lt;/td&gt;
 &lt;td&gt;KIS Trading에서 Alpha Pulse로 리브랜딩&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;04-01&lt;/td&gt;
 &lt;td&gt;5개 서브 스코어 함수 + 데이터 품질 멀티플라이어&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;04-01&lt;/td&gt;
 &lt;td&gt;compute_composite_score + 가중치 정규화&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;04-01&lt;/td&gt;
 &lt;td&gt;합성 스코어를 파이프라인에 연결, compute_confidence 제거&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;04-01&lt;/td&gt;
 &lt;td&gt;min_rr_score 게이트를 min_composite_score로 변경 (15%)&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;04-01&lt;/td&gt;
 &lt;td&gt;API 라우터에 가중치 필드 추가&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;04-01&lt;/td&gt;
 &lt;td&gt;프론트엔드 타입에 가중치 필드 추가&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;04-01&lt;/td&gt;
 &lt;td&gt;가중치 슬라이더 UI, min_composite_score 교체&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;04-01&lt;/td&gt;
 &lt;td&gt;DB 마이그레이션 — 컬럼 rename + 가중치 기본값&lt;/td&gt;
 &lt;td&gt;feat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="인사이트"&gt;인사이트
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;단일 지표의 한계&lt;/strong&gt;: &lt;code&gt;min_rr_score&lt;/code&gt; 하나로 매매 신호를 필터링하면, R/R이 높지만 기본적 분석이 취약한 종목이나, 수급이 좋지만 기술적 지표가 부정적인 종목을 구분할 수 없다. 다중 팩터 시스템으로 전환하면서 각 차원을 독립적으로 평가하고 가중합으로 결합할 수 있게 됐다. 사용자가 슬라이더로 가중치를 조절할 수 있어 투자 성향(기본적 분석 중심 vs 모멘텀 중심)에 맞는 튜닝이 가능하다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;데이터 품질을 점수에 반영하는 것의 가치&lt;/strong&gt;: 모든 팩터의 데이터가 동일한 품질은 아니다. DART 공시가 오래된 종목, 거래량이 적어 기술적 지표가 불안정한 종목 등에서는 높은 합성 스코어가 나오더라도 실제 신뢰도는 낮다. 데이터 품질 멀티플라이어를 도입하여 &amp;ldquo;좋은 데이터로 계산된 70점&amp;quot;과 &amp;ldquo;나쁜 데이터로 계산된 70점&amp;quot;을 구분할 수 있게 한 것이 이번 설계의 핵심이었다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;전체 스택을 관통하는 필드명 변경의 비용&lt;/strong&gt;: &lt;code&gt;min_rr_score&lt;/code&gt; 하나를 &lt;code&gt;min_composite_score&lt;/code&gt;로 바꾸는 데 DB, 백엔드 모델, API 라우터, 프론트엔드 타입, UI 컴포넌트까지 7개 레이어를 수정해야 했다. 초기 설계 시 범용적인 네이밍을 사용했다면 이 비용을 줄일 수 있었을 것이다.&lt;/p&gt;</description></item></channel></rss>