본문 바로가기
AyoProject/Ayotera-Trade

[AT] 25. 우량주 종목 자동 예측 및 선정 (3-1)

by 청양호박이 2020. 12. 29.

지난 시간에는, 모든 종목에 대한 고유번호를 저장하고, 각 종목별로 재무제표 정보를 저장하는 로직을 구현해 보았습니다. 재무제표에는 상당히 많은 정보들이 있으며, 이 정보들을 모두 활용하는데는 어마어마한 노력이 필요합니다. 따라서 이번시간에는 나에게 필요한 최소한의 정보에 대해서 추출하고 DB에 저장하여 활용하는 방법에 대해서 생각해 보겠습니다. 

 

  • 우량주 종목 선정을 위한 기반 데이터 수집 방안 (전자공시시스템 활용) - 1개 종목기준
  • 정리된 데이터 수집 방안에 대해서 코스피, 코스닥 전체 종목에 대한 데이터를 DBMS에 적재
  • 우량주 종목 선정 로직을 적용하여 대상 종목 추출
  • 추출된 우량주 종목에 대해서 저평가 종목 추출
  • 추출된 종목에 대해서 실험실 진행

 

우선 생각해 보아야 할 점은, 재무제표의 항목중 어떠한 항목을 활용할 것인지 입니다. 경우에 따라서는 이전에 구성했던 DB의 Table과 프로그램도 모두 변경이 필요할 수 있습니다. 

 

그럼 차근차근 진행해 보겠습니다.

 

 

1. 재무제표 항목 선정


우리가 흔히 들어본 재무제표에는 크게 3가지 항목으로 구성이 되어있습니다. 그 주요 항목으로는 [대차대조표], [손익계산서], [현금흐름표] 가 그것입니다. 여기서 이 3가지에 대해서 자세히 논해보자는 것은 아니고... 3가지 큰 항목이 존재하고 여기서 각 항목별로 필요한 것을 생각해 보자는게 그 취지입니다.

 

[현금흐름표]

 

우선적으로 가장 중점적으로 볼 항목은, 현금흐름표 입니다. 현금흐름표는 손익계산서를 보완하는 목적으로 사용하는데... 실제로 손익계산에서 나오는 매출액, 영업이익 등은 많은 기업들이 해당 매출에 대해서 현금이 아닌 채권으로 처리를 하는 경우가 많기 때문에 투자에 활용하는데 있어서 정확하지 않을 수 있습니다.

 

따라서, 실제 현금이 이동하는 부분에 집중하기 위해서 현금흐름표를 중심으로 판단할 것 입니다. 이러한 현금흐름표에는 또 3가지 항목이 존재합니다. [영업활동 현금흐름], [투자활동 현금흐름], [재무활동 현금흐름] 이 그것인데... 각각 용어에 맞게 해당 활동에 대한 현금흐름을 표현합니다. 

 

각 활동에 대해서 간단하게 확인해보면...

 

  • 영업활동 현금흐름 : 회사의 상품을 파는 과정에서 생기는 현금에 대한 흐름정의
  • 투자활동 현금흐름 : 회사의 기반시설, 기술개발 등에 대한 투자 과정에서 생기는 현금에 대한 흐름정의
  • 재무활동 현금흐름 : 회사가 금융기관에서 돈을 빌리고 갚는 등에 대한 현금 흐름정의

 

[손익계산서]

 

위에서 한참 손익계산서에 대한 단점일 수 있는 부분에 대해서 언급했지만, 그래도 손익계산서의 항목에 대해서도 생각해 보겠습니다. 해당 항목에서는 [매출액], [영업이익]에 대한 지표를 활용할 것 입니다. 실제로 영업이익률에 대한 항목은 해당 종목이 기본적으로 건실한 종목인지 확인할 수 있기 때문입니다.  

 

자 그렇다면, 지금까지 총 6가지 항목을 기준으로 종목을 판단하게 되었습니다. 

 

매출액, 영업이익, 이익률, 영업활동 현금흐름, 투자활동 현금흐름, 재무활동 현금흐름

 

이제 해당 데이터를 가져오기 위해서 DB Table 및 소스 코드를 수정해 보겠습니다. 

 

 

2. 선정항목 DB화 하기 - Table 구성


이전에 설계한 DB의 Table과 완전히 다르게 구성을 하고자 합니다. 종목 / 년 / 분기를 기준으로 위에서 결정한 6개 항목을 한번에 저장하겠습니다. 따라서, 그 Table은 아래와 같이 구성됩니다.

 

[Table 구조]

이름 필드명
종목 stocks_id
년도 bsns_year
분기 bsns_quarter
매출액 revenue
매출액(누적) revenue_add
영업이익 operating_income
영업이익(누적) operating_income_add
영업활동 현금흐름 operating_cashflow
투자활동 현금흐름 investing_cashflow
재무활동 현금흐름 financing_cashflow

 

[Table 생성]

기존에 생성한 Table을 삭제하고 신규 테이블을 생성해줍니다.

DROP TABLE fin_stat_info;

CREATE TABLE fin_stat_info(
	idx int(100) NOT NULL AUTO_INCREMENT PRIMARY KEY,
	stocks_id VARCHAR(10),
	bsns_year VARCHAR(4),
	bsns_quarter VARCHAR(1),
	revenue VARCHAR(30),
	revenue_add VARCHAR(30),
	operating_income VARCHAR(30),
	operating_income_add VARCHAR(30),
	operating_cashflow VARCHAR(30),
	investing_cashflow VARCHAR(30),
	financing_cashflow VARCHAR(30)
);

 

[Table 생성 결과]

기존 데이터가 깔끔하게 지워지고, 새로운 구조의 Table이 생성되었습니다. 

 

 

3. 선정항목 DB화 하기 - 소스 코드 수정


이제 Table까지 정상적으로 생성이 되었으니, DB화를 진행해 보겠습니다. 기존코드에서 수정되는 부분은 몇줄밖에 되지 않습니다. 바뀌는 부분만 확인해보면 아래와 같습니다.

 

  • DB형태가 바뀌었기 때문에 sql_dml 자체가 바뀌어야 합니다. 또한, sql_data도 인자개수가 바뀌어야 합니다.
  • 기존에는 재무제표 항목별로 Table의 행을 생성하여 insert했지만, 원하는 모든 항목을 sql_data로 만들어서 수행합니다. 이때, 해당 항목에 대한 초기화도 진행합니다.
  • API를 통해서 가져돈 response json에 대해서는 원하는 항목을 추가합니다.

 

[sql_dml 변경]

sql_dml = '''
    INSERT INTO fin_stat_info(stocks_id, bsns_year, bsns_quarter, revenue, revenue_add, operating_income, operating_income_add, operating_cashflow, investing_cashflow, financing_cashflow)
    VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
'''

[sql_data 변경]

    revenue = '0'
    revenue_add = '0'
    operating_income = '0'
    operating_income_add = '0'
    operating_cashflow = '0'
    investing_cashflow = '0'
    financing_cashflow = '0'
    
    sql_data = (i[0], this_year, str(quarter_info+1), revenue, revenue_add, operating_income, operating_income_add, operating_cashflow, investing_cashflow, financing_cashflow)

[API 결과 중 항목 추가]

if res.json()['list'][k]['account_nm'] == '수익(매출액)':
    revenue = res.json()['list'][k]['thstrm_amount']
    revenue_add = res.json()['list'][k]['thstrm_add_amount']
if res.json()['list'][k]['account_nm'] == '영업이익' or res.json()['list'][k]['account_nm'] == '영업이익(손실)':
    operating_income = res.json()['list'][k]['thstrm_amount']
    operating_income_add = res.json()['list'][k]['thstrm_add_amount']
if res.json()['list'][k]['account_nm'] == '영업활동 현금흐름' or res.json()['list'][k]['account_nm'] == '영업활동현금흐름':
    operating_cashflow = res.json()['list'][k]['thstrm_amount']
if res.json()['list'][k]['account_nm'] == '투자활동 현금흐름' or res.json()['list'][k]['account_nm'] == '투자활동현금흐름':
    investing_cashflow = res.json()['list'][k]['thstrm_amount']
if res.json()['list'][k]['account_nm'] == '재무활동 현금흐름' or res.json()['list'][k]['account_nm'] == '재무활동현금흐름':
    financing_cashflow = res.json()['list'][k]['thstrm_amount']

이렇게 변경하면, 새로운 로직으로 재무제표 데이터를 가져오게 됩니다.

 

[실행결과]

...
...
도화엔지니어링 2015 4 데이터 없음
('019180', '0', '티에이치엔', '019180', '티에이치엔', '00118965') 2015 4 데이터 존재 DB에 저장시작
에쎈테크 2015 4 데이터 없음
('039130', '0', '하나투어', '039130', '하나투어', '00269940') 2015 4 데이터 존재 DB에 저장시작
('066570', '0', 'LG전자', '066570', 'LG전자', '00401731') 2015 4 데이터 존재 DB에 저장시작
웹케시 2015 4 데이터 없음
('149950', '10', '아바텍', '149950', '아바텍', '00442048') 2015 4 데이터 존재 DB에 저장시작
('049950', '10', '미래컴퍼니', '049950', '미래컴퍼니', '00447760') 2015 4 데이터 존재 DB에 저장시작
미래테크놀로지 2015 4 데이터 없음
('005440', '0', '현대그린푸드', '005440', '현대그린푸드', '00105280') 2015 4 데이터 존재 DB에 저장시작
('048830', '10', '엔피케이', '048830', '엔피케이', '00108490') 2015 4 데이터 존재 DB에 저장시작
('000120', '0', 'CJ대한통운', '000120', 'CJ대한통운', '00113410') 2015 4 데이터 존재 DB에 저장시작
우진아이엔에스 2015 4 데이터 없음
('013360', '0', '일성건설', '013360', '일성건설', '00146232') 2015 4 데이터 존재 DB에 저장시작
('060240', '10', '룽투코리아', '060240', '룽투코리아', '00373571') 2015 4 데이터 존재 DB에 저장시작
('000430', '0', '대원강업', '000430', '대원강업', '00111847') 2015 4 데이터 존재 DB에 저장시작
('065350', '10', '신성델타테크', '065350', '신성델타테크', '00136226') 2015 4 데이터 존재 DB에 저장시작
...
...

작업종료!!

 

[DB Table 결과]

 

이번시간에는 우량주 종목 선정을 위해서, 필요한 데이터를 준비하는 작업을 하였습니다. 그럼 다음시간에 바로 이어서 내가 준비한 재무제표 데이터 중에서 어떤 종목이 우량주인지를 판단하여 선정하는 작업을 해보겠습니다. 

 

이렇게 우량주 종목 판단이 완료된다면... EMA MACD를 통한 해당 종목의 매수타이밍을 조합하여 실험실을 진행해 보도록 하겠습니다. 감사합니다.

 

- Ayotera Lab -

댓글