1- // services/metricsService.js
21const FinancialSummary = require ( "../models/FinancialSummary" ) ;
32const { fetchStockPrice } = require ( "./fetchStockPrice" ) ;
43
@@ -28,49 +27,48 @@ async function computeMetrics(stockCode, dateStr) {
2827
2928 // 기준일자 파싱
3029 const baseDate = new Date ( dateStr . replace ( / \. / g, "-" ) ) ;
31- // console.log(baseDate);
3230 if ( isNaN ( baseDate ) ) throw new Error ( "잘못된 날짜 형식: " + dateStr ) ;
3331
34- // entries 에 periodDate 부착 & 기준 이전만 필터링
35- const withDate = doc . entries . map ( ( e ) => ( {
36- ...e ,
37- periodDate : getPeriodDate ( e ) ,
38- } ) ) ;
39- const valid = withDate
32+ // entries에 periodDate 부착 & 기준 이전만 필터
33+ const valid = doc . entries
34+ . map ( ( e ) => ( { ...e , periodDate : getPeriodDate ( e ) } ) )
4035 . filter ( ( e ) => e . periodDate <= baseDate )
4136 . sort ( ( a , b ) => a . periodDate - b . periodDate ) ;
4237
43- if ( valid . length < 2 ) throw new Error ( "조회일자 이전에 분기가 부족합니다" ) ;
38+ // 최소 4분기 데이터 확보
39+ if ( valid . length < 4 ) {
40+ throw new Error ( "4분기 이상 데이터가 필요합니다." ) ;
41+ }
4442
45- // TTM 합산 및 평균자본
43+ // 최신 분기 데이터
44+ const last = valid [ valid . length - 1 ] ;
45+
46+ // TTM 합산값과 주식수
47+ const profit = last . profit ;
48+ const ttmRevenue = last . revenue_ttm ;
49+ const equityTTM = last . equity_ttm ;
50+ const shareCount = last . istc_totqy ;
51+
52+ if ( ! profit || ! ttmRevenue || ! shareCount ) {
53+ throw new Error ( "TTM 데이터가 부족하여 EPS/BPS/PSR 계산이 불가능합니다." ) ;
54+ }
55+
56+ // EPS/BPS 보정 계산
57+ const eps = last . eps != null ? last . eps : profit / shareCount ;
58+ const bps = last . bps != null ? last . bps : last . equity / shareCount ;
59+
60+ // 주가 가져오기
4661 const { price : stockPrice , date : priceDate } = await fetchStockPrice (
4762 stockCode ,
4863 dateStr
4964 ) ;
5065
51- const ttmProfit = valid [ valid . length - 1 ] . profit ; //당기 순이익
52- const ttmRevenue = valid [ valid . length - 1 ] . revenue_ttm ; //매출액
53- const ttmequity = valid [ valid . length - 1 ] . equity_ttm ; // 순자산
54- const shareCount = valid [ valid . length - 1 ] . istc_totqy ; // 총 발행 주식수
55- const profit_diff = valid [ valid . length - 1 ] . profit_diff ; // 증감액
56- const profit_diff_rate = valid [ valid . length - 1 ] . profit_diff_rate ; // 증감률
57- // const revenue = valid[valid.length - 1].revenue;
58- // const netProfit_govern = valid[valid.length - 1].net_profit_govern; // 순이익
59- // const profitMargin = valid[valid.length - 1].profit_margin; // 순 이익률
60- // const growthRate = valid[valid.length - 1].growth_rate; //순 이익 성장률
61- // const operatingProfit = valid[valid.length - 1].operating_profit; // 영업 이익
62- // const operatingMargin = valid[valid.length - 1].operating_margin; // 영업 이익률
63- // const operatingGrowthRate = valid[valid.length - 1].operating_growth_rate; // 영업 이익 성장률
64-
6566 // 지표 계산
66- const eps = valid [ valid . length - 1 ] . eps ;
67- const bps = valid [ valid . length - 1 ] . bps ;
68- const roe = valid [ valid . length - 1 ] . roe ;
69-
70- // const pbr = bps ? stockPrice / bps : null;
71- // const per = eps ? stockPrice / eps : null;
72- // const psr = ttmRevenue ? (stockPrice * shareCount) / ttmRevenue : null;
67+ const per = eps ? stockPrice / eps : null ;
68+ const pbr = bps ? stockPrice / bps : null ;
69+ const psr = ttmRevenue ? ( stockPrice * shareCount ) / ttmRevenue : null ;
7370
71+ // 시계열 데이터
7472 const series = {
7573 period : valid . map ( ( e ) => `${ e . bsns_year } .${ e . reprt_code } ` ) ,
7674 revenue : valid . map ( ( e ) => e . revenue ) ,
@@ -84,19 +82,22 @@ async function computeMetrics(stockCode, dateStr) {
8482
8583 return {
8684 price : { price : stockPrice , date : priceDate } ,
85+ per,
86+ pbr,
87+ psr,
8788 stockPrice,
8889 shareCount,
8990 // per,
9091 // psr,
9192 // pbr,
9293 eps,
9394 bps,
94- roe,
95- ttmProfit,
95+ roe : last . roe ,
96+ ttmProfit : profit ,
9697 ttmRevenue,
97- ttmequity ,
98- profit_diff,
99- profit_diff_rate,
98+ equityTTM ,
99+ profit_diff : last . profit_diff ,
100+ profit_diff_rate : last . profit_diff_rate ,
100101 series,
101102 } ;
102103}
0 commit comments