우선주와 보통주의 괴리율 계산하기¶
1. 우선주란?¶
주식은 의결권 여부에 따라 보통주와 우선주로 나눌 수 있음
보통주(본주)는 주주총회에 참석하여 기업의 주요 경영사항에 대해 의결권을 행사하고 배당을 받는 등 주주로서의 권리를 행사할 수 있는 주식을 말함
우선주는 의결권이 제한되지만 보통주보다 이익, 배당, 잔여재산 분배 등에 있어서 우선적 지위기 인정되는 주식
1996년 상법개정 전 발행된 우선주는 본주명 뒤에 '-우', 이후 발행된 우선주는 '-우B'가 붙어 있음. B가 붙는 이유는 배당 자체를 보장해주는 채권(Bond)의 성격이 들어있기 때문임
1우B, 2우B, 3우B에서 숫자는 발행 순서를 의미함
[출처]: 주린이가 가장 알고 싶은 최다질문 TOP 77
2. 우선주와 보통주의 괴리율¶
- 우선주와 보통주의 괴리율은 다음과 같이 계산
- 괴리율이 높을수록 우선주가 보통주에 비해 저평가된 것으로 볼 수 있음
3. FinanceDataReader 패키지를 이용하여 우선주와 본주의 괴리율 계산¶
In [1]:
import FinanceDataReader as fdr
df_krx = fdr.StockListing('KRX')
df_krx['Name'] = df_krx['Name'].str.strip()
df_krx.head()
Out[1]:
In [2]:
# 우선주 목록
ps_list = [s for s in df_krx['Name'] if s.endswith('우') | s.endswith('우B')]
print(ps_list)
- '미래에셋대우' 같이 본주의 마지막 글자가 '우'로 끝나는 종목을 따로 골라줌
In [3]:
exception = ['미래에셋대우', '연우', '이오플로우']
In [4]:
ps_list = [s for s in df_krx['Name'] if (s.endswith('우') | s.endswith('우B')) & (s not in exception)]
len(ps_list)
Out[4]:
In [5]:
df_ps = df_krx.loc[df_krx['Name'].isin(ps_list), ['Symbol', 'Market', 'Name']]
df_ps.head()
Out[5]:
In [6]:
import re
# '~우'로 끝나는 종목은 '우' 앞자리 까지만 가져옴
df_ps.loc[df_ps['Name'].str.endswith('우'), 'CS_Name'] = df_ps['Name'].str[:-1]
# '~우B'로 끝나는 종목은 '우B' 앞자리 까지만 가져옴
df_ps.loc[df_ps['Name'].str.endswith('우B'), 'CS_Name'] = df_ps['Name'].str[:-2]
# 정규표현식으로 숫자만 제거
df_ps['CS_Name'] = df_ps['CS_Name'].map(lambda s: re.sub('\d+', '', s)).str.strip()
df_ps.head()
Out[6]:
In [7]:
import pandas as pd
df_krx = df_krx[['Symbol', 'Name', 'Sector']].rename(columns={'Symbol':'CS_Symbol', 'Name':'CS_Name'})
df_ps = pd.merge(df_ps, df_krx, how='left', on='CS_Name')
df_ps.head()
Out[7]:
In [9]:
fdr.DataReader(symbol='005930', start='20210122', end='20210122')
Out[9]:
In [40]:
for idx in range(len(df_ps)):
try:
df_ps.loc[idx, 'PS_price'] = fdr.DataReader(symbol=df_ps.loc[idx, 'Symbol'], start='20210122', end='20210122')['Close'].iat[0]
except:
df_ps.loc[idx, 'PS_price'] = 0
try:
df_ps.loc[idx, 'CS_price'] = fdr.DataReader(symbol=df_ps.loc[idx, 'CS_Symbol'], start='20210122', end='20210122')['Close'].iat[0]
except:
df_ps.loc[idx, 'CS_price'] = 0
In [42]:
df_ps[(df_ps['PS_price']==0) | (df_ps['CS_price']==0)]
Out[42]:
남선알미늄, 삼성중공업, 코리아써키트는 우선주에서 이름이 축약되어 있어서 본주 이름이 제대로 들어가지 않았다.
수정 후 다시 작업
In [43]:
df_ps.loc[df_ps['CS_Name']=='남선알미', 'CS_Name'] = '남선알미늄'
df_ps.loc[df_ps['CS_Name']=='삼성중공', 'CS_Name'] = '삼성중공업'
df_ps.loc[df_ps['CS_Name']=='코리아써', 'CS_Name'] = '코리아써키트'
In [47]:
df_ps = pd.merge(df_ps[['Symbol', 'Market', 'Name', 'CS_Name']], df_krx, how='left', on='CS_Name')
df_ps.head()
Out[47]:
In [48]:
for idx in range(len(df_ps)):
try:
df_ps.loc[idx, 'PS_price'] = fdr.DataReader(symbol=df_ps.loc[idx, 'Symbol'], start='20210122', end='20210122')['Close'].iat[0]
except:
df_ps.loc[idx, 'PS_price'] = 0
try:
df_ps.loc[idx, 'CS_price'] = fdr.DataReader(symbol=df_ps.loc[idx, 'CS_Symbol'], start='20210122', end='20210122')['Close'].iat[0]
except:
df_ps.loc[idx, 'CS_price'] = 0
In [49]:
df_ps[(df_ps['PS_price']==0) | (df_ps['CS_price']==0)]
Out[49]:
In [50]:
df_ps.head()
Out[50]:
In [53]:
# 괴리율 = 1 - 우선주가격/보통주가격
df_ps['diff'] = 1 - df_ps['PS_price']/df_ps['CS_price']
df_ps.head()
Out[53]:
In [57]:
df_ps.sort_values(['diff'], ascending=False)
Out[57]:
In [58]:
df_ps[df_ps['CS_Name']=='삼성전자']
Out[58]:
삼성전자처럼 보통주와 우선주의 괴리율이 작은 종목이 있는가하면 두산퓨얼셀처럼 보통주와 우선주의 괴리율이 큰 종목도 있음
일반적으로 우선주는 보통주에 비해 가격이 저렴하지만 삼성중공업우 같이 우선주의 가격이 보통주에 비해 비정상적으로 높은 주식도 있음
이는 우선주의 총발행주식수가 매우 적어 발생할 수 있는 현상임
In [59]:
# 괴리율 상위 20개 종목
df_ps.sort_values(['diff'], ascending=False).head(20)
Out[59]: