-
[4장]ISL with R : 로지스틱회귀 LDA QDA 실습 in R(재무지표를 통한 상승주 분류)기초지식/ISL with R(통계학) 2024. 3. 14. 07:59반응형
재무지표를 통한 부도 예측
로지스틱회귀, LDA, QDA라는 툴을 투자에 적용하면 내가 찍은 주식이 오를지 떨어질지 예측하는데 쓸 수 있다. ISL with R 4장에서 살펴본 로지스틱회귀, LDA, QDA 모두 다양한 투입변수를 통해서 어떤 결과로 분류할 수 있는지 예측하는 모델이라는 점에서 다양한 투입변수를 통해서 상승할 종목인지, 하락할 종목인지 판단할 수 있는 것이다. 이때 유용한 투입변수가 될 수 있는 것이 각종 재무지표이다.( 주요 재무비율 통한 기업 분석 참조) 이번 분석에서는 2023년 3분기 매출원가율, 부채비율, 순이익증가율 이라는 세 가지 요소가 2024년 2월 말 주식의 상승 여부와 어떻게 작용하는지를 볼 것이다. 회사별 재무비율은 금융감독원에서 제공하는 전자공시시스템인 다트(https://dart.fss.or.kr/)를 통해서 아래와 같이 회사를 검색해서 확인할 수 있다.
주가가 상승했는지 하락했는지에 대한 정보는 아래와 같이 KRX정보데이터시스템(http://data.krx.co.kr/contents/MDC/MAIN/main/index.cmd)을 통해서 확인할 수 있다. 코스피 전 종목에 대해서 2023년 3분기 종가와 2024년 2월말 종가를 아래 그림 2와 같이 조회해서 엑셀파일로 만들었다.
2023년 3분기 코스피지수대비 2024년 2월 코스피 지수가 7% 정도 상승했다는 점을 감안해서 10% 상승한 종목을 A종목, 그 외의 종목을 B종목으로 분류한다면, 위와 같이 조회한 자료를 바탕으로 각 기업의 2023년 3분기 재무비율 자료를 붙인 데이터를 아래 첨부파일과 같이 만들어 낼 수 있다.(편의상 매출원가율, 부채비율, 순이익증가율 중 하나라도 안 나왔다면 분석 대상에서 제외했다.)
Logistic 회귀분석
output 엑셀파일 입수
R의 readxl 패키지를 사용하면 쉽게 엑셀데이터를 읽어올 수 있는데, 아래와 같이 먼저 엑셀 패키지를 설치한 뒤
install.packages("readxl")
read_excel 함수를 사용해서 data 라는 변수에 위의 output 파일의 데이터를 저장할 수 있다.
data <- read_excel("엑셀파일의 경로")
R Studio 로 작업한다면 변수에 저장된 데이터가 아래 그림 3과 같이 우측 상단 칸에 표시가 되고, 이 변수를 클릭하면 좌측상단칸과 같이 변수에 저장된 실제 데이터를 확인할 수 있다.
data의 컬럼은 names(data)라는 명령어로 살펴볼 수 있는데 아래와 같은 결과가 나타날 것이다. (한 줄짜리 코드는 좌측하단 콘솔창에 바로 입력하면 된다.)
> names(data) [1] "종목코드" "종목명" "종가_x" "종가_y" "비율" [6] "분류" "기관코드" "매출원가율" "매출총이익률" "금융비용부담률" [11] "부채비율" "총자산증가율" "순이익증가율"
그림 3에서 확인할 수 있는 것처럼 output.xlsx 데이터는 2023년 3분기 대비 2024년 2월 10% 이상 상승한 종목을 A종목, 그 외의 종목을 B종목으로 설정했다. 이를 코드화하기 위해서 아래와 같이 data에 "분류코드"컬럼을 추가하고 "분류"컬럼 데이터가 "A종목"이면 1 그 외의 경우 0 값을 부여해서 최종 데이터를 완성한다.
data$분류코드 <- ifelse(data$분류 == "A종목", 1, 0)
Logistic 회귀분석 결과 분석하기
데이터만 제대로 입수되었으면 분석 모델을 만드는 것은 간단하다. 아래와 같이 glm 이라는 R의 함수를 사용해서 glm 클래스의 fits라는 객체를 만들면 된다.
# 라이브러리 참조 > library(MASS) # ex) # glm.fits = glm(결과값(종속변수)~투입값(독립변수), data=데이터명, family=로지스틱 회귀 모델에서는 # 이항분포(binomial) 사용) > glm.fits = glm(분류코드~매출원가율+부채비율+순이익증가율, data=data, family=binomial) > summary(glm.fits) Call: glm(formula = 분류코드 ~ 매출원가율 + 부채비율 + 순이익증가율, family = binomial, data = data) Coefficients: Estimate Std. Error z value Pr(>|z|) (Intercept) -0.3209685 0.4585976 -0.700 0.4840 매출원가율 -0.0106507 0.0057440 -1.854 0.0637 . 부채비율 0.0004756 0.0003714 1.281 0.2003 순이익증가율 0.0003681 0.0002491 1.478 0.1394 --- Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 (Dispersion parameter for binomial family taken to be 1) Null deviance: 709.75 on 637 degrees of freedom Residual deviance: 701.87 on 634 degrees of freedom AIC: 709.87 Number of Fisher Scoring iterations: 4
로지스틱 회귀분석은 결국 아래 식에서( [4장]ISL with R : 로지스틱 회귀(로지스틱 함수) 참조)
b0, b1 ... bp까지의 계수들을 찾아내는 하나의 과정이다. glm.fits = glm(분류코드~매출원가율+부채비율+순이익증가율, data=data, family=binomial)를 통해서 모델을 완성할 수 있고, summary(glm.fits)를 통해서 완성된 모델의 요약을 볼 수 있다. summary(glm.fits)을 통해서 알 수 있는 모델의 계수들의 값은 매출원가율: -0.0106507, 부채비율: 0.0004756, 순이익증가율: 0.0003681이다.각 계수들의 유의수준인 p 값은 각각 매출원가율: 0.0637, 부채비율: 0.2003, 순이익증가율: 0.1394을 보이는데, 보통 95% 신뢰 수준을 보통 가정한다면 유의 수준인 p는 5%보다는 낮아야 하므로 각 계수들의 신뢰 수준은 낮은 편이라고 할 수 있다.
Deviance 값은 관찰된 결과와 예측한 결과 간의 편차를 의미한다. Null deviance 는 아무런 입력변수 없이 절편값만 있는 상태와 실제 결과값의 차이로 계산한 편차이고, Residual deviance는 독립변수까지 모델에 넣었을 때 도출된 종속 변수와 실제 결과값의 차이로 계산한 편차이다. 모델이 유의미하려면 당연히 편차만 적용된 Null deviance 보다(여기서 709.75) 모델이 제대로 적용된 Residual deviance 값이(여기서 701.87) 더 작을 것이다.
AIC는(Akaike Information Criterion) 모델의 적합도와 복잡성을 동시에 고려해서 나타내는 지표이다. 절대적인 값은 크게 의미가 없고 모델간 비교를 가능하게 하는데, 작을수록 모델이 더 적합하다고 한다.
LDA(Linear Discriminant Analysis)
그림 3의 output.xlsx 데이터는 주어진 기간동안 주가가 10% 이상 오른 A그룹 주식과 그 외의 B그룹 주식으로 나뉜다. LDA에서는 "특정 기업(매출원가율, 부채비율, 순이익증가율의 재무비율)이 주어졌을 때 A그룹에 혹은 B그룹에 속할 사후확률을 구하는 것"이 목적이다. 하지만 사후확률로 바로 접근하는 것은 어려우므로 베이즈 정리를 통해서 사후확률을 구하는 식을 "A(또는 B) 그룹이 나올 확률 * A(또는 B) 그룹 일 때 특정 기업 데이터일 확률 / 특정 기업이 A그룹 혹은 B그룹에 속할 확률"을 구하는 식으로 변형한다. 이를 바탕으로 도출한 판별함수를 통해서 특정 기업(매출원가율, 부채비율, 순이익증가율) 재무비율로 A그룹인지 B그룹인지 판별할 수 있게 되는 것이다.( [4장]ISL with R : LDA(선형판별분석) 참조)
R 에서 LDA 자체는 아래와 같은 코드로 간단하게 수행할 수 있다.
# 라이브러리 참조 > library(MASS) # ex) # lda.fits = lda(결과값(종속변수)~투입값(독립변수), data=데이터명) > lda.fits = lda(분류코드~매출원가율+부채비율+순이익증가율, data=data) > lda.fits Call: lda(분류코드 ~ 매출원가율 + 부채비율 + 순이익증가율, data = data) Prior probabilities of groups: 0 1 0.7554859 0.2445141 Group means: 매출원가율 부채비율 순이익증가율 0 80.98230 110.7157 -95.23615 1 78.28655 140.7248 -17.93937 Coefficients of linear discriminants: LD1 매출원가율 -0.043845044 부채비율 0.001516735 순이익증가율 0.001069575
lda.fits = lda(분류코드~매출원가율+부채비율+순이익증가율, data=data)를 통해서 lda의 결과를 lda 클래스의 fits 객체에 만들 수 있다. summary 함수는 사용하지 않고 단순히 lda.fits라는 새로운 객체를 다시 입력하면 (> lda.fits) 분석 결과를 볼 수 있다. Prior probabilities of groups는 각 그룹의 사전확률을 의미한다. 즉, 실제 데이터 상에서 A그룹(=1)은 24.45% 만큼 존재하고 B그룹(=2)은 75.55%만큼 존재한다는 의미이다. Group meanss는 각 그룹에서 매출원가율, 부채비율, 순이익증가율이라는 독립변수들의 평균을 의미한다. Group meanss 를 통해서 A그룹에 속한 기업이 매출원가는 낮고, 부채비율은 높고, 순이익증가율은 - 값이 더 작다는 것을 알 수 있다. Coefficients of linear discriminants는 [4장]ISL with R : LDA(선형판별분석) 참조에서 구해본 선형판별식의 각 계수들을 의미한다.
QDA(Quadratic Discriminant Analysis)
QDA는 LDA와 기본적으로 같은데 A그룹과 B그룹의 각 독립변수들(매출원가율, 부채비율, 순이익증가율)의 분산(엄밀하게 공분산 행렬) 이 다르다는 가정을 추가한다. 그 결과 판별함수도 비선형적인 형태를 띠게 된다.( [4장]ISL with R : QDA(이차판별분석) 참조) 아래와 같이 R을 이용한 분석을 하면, 이런 QDA의 특징으로 인해서 Coefficients of linear discriminants 값은 나오지 않는다.
# 라이브러리 참조 > library(MASS) # ex) # qda.fits = qda(결과값(종속변수)~투입값(독립변수), data=데이터명) > qda.fits = qda(분류코드~매출원가율+부채비율+순이익증가율, data=data) > qda.fits Call: qda(분류코드 ~ 매출원가율 + 부채비율 + 순이익증가율, data = data) Prior probabilities of groups: 0 1 0.7554859 0.2445141 Group means: 매출원가율 부채비율 순이익증가율 0 80.98230 110.7157 -95.23615 1 78.28655 140.7248 -17.93937
그 외에 Prior probabilities of groups, Group means 값은 데이터가 동일하기 때문에 LDA와 동일하게 나오지만 새로운 데이터로 qda.fits를 이용한 결과 예측을 수행하면, lda.fits와 다른 값을 나타낼 것이다.
반응형'기초지식 > ISL with R(통계학)' 카테고리의 다른 글
[4장]ISL with R : QDA(이차판별분석) (0) 2023.07.20 [4장]ISL with R : LDA(선형판별분석) (0) 2023.07.08 [4장]ISL with R : 로지스틱 회귀(회귀계수의 계산2: 최적해 도출) (1) 2023.04.09 [4장]ISL with R : 로지스틱 회귀(회귀계수의 계산1: 우도함수와 경사하강법) (0) 2023.04.05 [4장]ISL with R : 로지스틱 회귀(로지스틱 함수) (0) 2023.04.04