파이썬으로 주식 분석 프로그램 툴 만들기(시가배당률 이용)
본문 바로가기
파이썬으로 만든 것들/퀀트투자

파이썬으로 주식 분석 프로그램 툴 만들기(시가배당률 이용)

by Squat Lee 2022. 10. 25.

 

 

주식은 싸게 사서 비싸게 팔면 된다.

 

아주 간단한 원리다. 하지만 싸다는 기준과 비싸다는 기준은 너무나 모호하다. 아무도 알려주지 않는다. 책에서 나름 똑똑하다는 사람이 여러 기준을 알려주었지만, 실제로 테스트를 해 보지 않아서 잘 모르겠다.

 

나는 개인적으로 PER 밴드, PBR 밴드로 주가가 저가임을 판단한다. 하지만, 이것도 그렇게 완벽하지는 않은 것 같은 느낌이다.(아래는 파이썬으로 PER 밴드차트를 그려본 포스트다.)

 

2022.09.19 - [취미로 하는 파이썬/투자 실험실 with 파이썬] - 파이썬으로 PER 밴드 차트 그리기 3 - qt designer로 UI 만들기

 

파이썬으로 PER 밴드 차트 그리기 3 - qt designer로 UI 만들기

2022.09.07 - [취미로 하는 파이썬/투자 실험실 with 파이썬] - 파이썬으로 PER 밴드 차트 그리기 2 - 수정주가 가져와서 선형으로 그래프 그리기 파이썬으로 PER 밴드 차트 그리기 2 - 수정주가 가져와서

dotsnlines.tistory.com

 

비록 내가 PER 밴드차트를 파이썬으로 구현해 보았지만, 증권사 사이트가 더 신뢰가 가서 그것을 이용한다.

 


개인적인 경험으로는 시가배당률을 이용하는 방법이 항상 이익을 가져다 주었다.

 

시가 배당률을 이용하는 원리는 간단하다. 배당률은 "배당/주가X100" 으로 구한다. 배당률이 높을 수록 주가가 낮다. 그리고 배당률이 높을 때 사면 비록 주가가 오르지 않더라도 배당 자체가 높으니깐 수익이 날때까지 기다릴 수 있다.

 

qtdesinger를 이용해서 UI를 만들어 보았다. 자주 사용할거라 UI를 만드는 것이 훨씬 편리하고, 효율적이다.

 

종목명은 기본적으로 '삼성전기'가 표시 되도록 했다. 당연히 다른 종목명으로 수정 가능하다. 이 상태에서 '배당분석하기' 버튼을 누르면 삼성전기의 5년치 배당수익률이 분석된 결과가 나온다.

 

시작일은 입력을 하지 않으면 5년전 날짜로 자동 입력이 된다. 종료일은 영업일로 최근 날짜가 표시된다.

 

결과는 위와 같이 나온다.

 

분석 기간동안의 최고가와 최저가가 나오고, 최근주가는 영업일 기준으로 최근의 종가를 나타낸다.

 

배당수익률도 분석기간 동안 최저, 최고, 최근을 표시하였다.

 

여기서 중요한 포인트 하나는 연도별 배당금이다. 이렇게 시가배당률로 주식을 분석 하기 위해서는 기본적으로 매년 배당을 일정하게 주거나 배당금이 늘어나야 한다. 

 

위에서 분석한 삼성전기는 2016년부터 배당금이 매년 늘었다. 아주 좋은 조건이다.

 

 

그래프로 그려보면 위와 같이 나온다.

 

아내와 아들에게 이걸 보여주니 '데칼코마니' 같다고 얘기했다. 주가와 시가배당률을 완전히 반대로 움직인다.

 

혹시나 이게 당연한거 아닌가 하는 사람도 있을 것이다. 그 말은 반은 틀리고 반은 맞다. 

 

배당을 꾸준히 주지 않은 회사는 그래프가 이렇게 나오지 않는다.  

 

삼성전자는 배당이 들쭉날쭉하다. 

 

그래프 모양이 좀 이상하지 않은가? 그리고 이런 주식은 시가배당률을 기준으로 배당률이 가장 높을 때 사더라도 주가가 더 떨어 질 수 있다는 Risk가 있다.(위에 삼성전기 같이 배당이 일정한 주식은 배당률이 높으면 거의 저가라고 판단 할 수 있다. 당연히 거기서 더 떨어질 수 있지만, 대부분 저가에 근접하고 무조건 수익을 볼 확률이 높다.)

 

 


이 방법으로 내가 보유하고 있는 주식을 살펴보니, 손실을 기록하는 주식들은 모두 배당률이 낮을때 샀는 것이다. 한마디로 묻지마 투자를 한 것은 수익률이 다 좋지 않다.

 

최근 몇 달전에 산 하이트진로 배당수익률x주가 그래프다. 지금 -20% 기록하고 있다.

 

최근 폭락장에서도 수익을 기록하는 기업은행을 살펴보자.

 

그래프가 좀 이상하지 않은가? 

 

연도별 배당금일 일정하지 않아서 그래프가 이상하게 나온다.

 

어쨌든 배당수익률이 나름 높을때 사서 수익을 보고 있는 주식이다.

 

최근에 악재가 겹친 건설주를 마지막으로 보도록 하자

 

2015년에는 배당이 없어서 왼쪽 아래에 그래프가 직선으로 표시된다.

 

이 그래프를 보면 지금이 주식이 정말 싸다는게 보여지지 않은가?

2016년부터 배당금도 꾸준히 지급이 되었다.

 

내가 만든 그래프는 일별 종가 기준이라 최고 배당수익률은 13% 정도로 표시되었다. 하지만, 지난주에 한창 주가가 빠질때 15%까지 기록한 것으로 기억하고 있다.

 

이 포스트는 종목 리딩방이 아니다. 종목 추천을 하는 곳이 절대 아님을 알려둔다. 투자는 본인이 알아서 하고 이익이나 손실도 본인이 알아서 감내해라. 나는 책임을 지지 않는다.

 

 


이 프로그램을 만든 코드는 아래와 같다. 코드를 포스트하지 않으니, 다음 프로그램을 만들때 참고할게 없고 금방 잊어버린다. 그래서 항상 포스트 하려고 한다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
from pykrx import stock
from datetime import datetime
import matplotlib.pyplot as plt
import pandas as pd
 
ui = '배당수익률.ui'
 
class MainDialog(QDialog):
    def __init__(self):
        QDialog.__init__(selfNone)
        uic.loadUi(ui, self)
 
        self.btn.clicked.connect(self.input_data)
 
 
    def input_data(self):
 
        end = str(datetime.today()).split('-')
        end = end[0+ end[1+ end[2][:2]  # 날짜를 'yyyymmdd' str 형태로 변환
        print(end)
 
        # 이름을 받아서 code 입력
        def code_by_name(name, date):
            codes = stock.get_market_ticker_list(date, market='ALL')
 
            li_code = []
            for code in codes:
                company = stock.get_market_ticker_name(code)
                li_code.append(company)
 
            dic_code = dict(zip(li_code, codes))
 
            if name in dic_code:
                code = dic_code[name]
                return code
 
        name = self.le_name.text()
        code = code_by_name(name, end)
        self.textEdit.clear()
        self.lbl_code.setText(code)
 
        if not self.le_start.text(): #le_start 가 비었으면
            start = int(end[:4])-5 #5년 전부터 시작
            start = str(start) + '0101'
        else:
            start = self.le_start.text() #아니면 원하는 날짜에 시작
 
        df_f = stock.get_market_fundamental(start[:4+ '1230', end, code, freq='y')  # BPS, PER, PBR, EPS, DIV, DPS
        df_f = df_f['DPS']
 
        # 년도별 배당금 표시하기
        dps_li = []
        try:
            for y in range(int(start[:4]), int(end[:4]) + 1):
                day = stock.get_nearest_business_day_in_a_week(str(y) + '0530')
                df_f = stock.get_market_fundamental_by_ticker(date=day, market='ALL')  # BPS, PER, PBR, EPS, DIV, DPS
                df_f = df_f.loc[code]  # 원하는 종목의 코드에 해당하는 데이터만 필터
                dps = int(df_f['DPS'])  # 배당금을 dps 변수에 저장
                dps_li.append([y - 1, dps])  # 년도와 배당금을 리스트로 저장(년도는 전년도로 저장)
        except:
            pass
        print(dps_li)
 
        for data in dps_li:
            exist = self.textEdit.toPlainText()
            self.textEdit.setText(exist + '연도 : ' + str(data[0]) + ' / 배당금 : ' + str(format(data[1], ",")) + '\n')
 
 
        # 주가, 배당수익률 비교 그래프
        df_f = stock.get_market_fundamental(start, end, code, freq='d')  # BPS, PER, PBR, EPS, DIV, DPS
        name = stock.get_market_ticker_name(code)
        df_f = df_f['DIV']
 
        df_p = stock.get_market_ohlcv(start, end, code)
        df_p = df_p['종가']
 
        df_t = pd.merge(df_p, df_f, left_index=True, right_index=True)
        df_t.columns = ['price''DIV']
        p_max = str(format(df_t['price'].max(),","))
        p_min = str(format(df_t['price'].min(),","))
        d_max = str(round(df_t['DIV'].max(), 3))
        d_min = str(round(df_t['DIV'].min(), 3))
        price = str(format(df_t['price'].iloc[-1],","))
        div = str(round(df_t['DIV'].iloc[-1], 3))
 
        self.lbl_pmax.setText(p_max)
        self.lbl_pmin.setText(p_min)
        self.lbl_dmax.setText(d_max)
        self.lbl_dmin.setText(d_min)
        self.lbl_price.setText(price)
        self.lbl_div.setText(div)
        self.le_start.setText(start)
 
        plt.rcParams['figure.figsize'= (169)
 
        fig, ax1 = plt.subplots()
        ax1.set_xlabel('Date')
        ax1.set_ylabel('price')
        ax1.plot(df_t.index, df_t['price'], color='red', label='Price')
        ax1.legend(loc='upper left')
 
        ax2 = ax1.twinx()
        ax2.set_ylabel('DIV')
        ax2.plot(df_t.index, df_t['DIV'], color='blue', label='DIV')
        ax2.legend(loc='upper right')
        plt.title(name)
        plt.show()
 
if __name__ == '__main__':
    app = QApplication(sys.argv)
    Dialog = MainDialog()
    Dialog.show()
    app.exec_()
cs

 

나중에 시간나면 집구석 강의 코너에서 코드를 만드는 순서를 좀 더 자세히 설명해야겠다.

728x90
반응형

댓글