본문 바로가기
파이썬/주식

Python으로 보통주, 우선주 괴리율을 이용한 투자전략 - 1

by 행복론자 2020. 6. 6.

최근 주식시장이 강세입니다.

많이 오른 종목도 있고 상대적으로 안 오른 종목들도 있는데 이번에 살펴볼 방법은 제 짧은 지식으로 생각해본

보통주, 우선주 괴리율 투자법입니다.

 

먼저 보통주와 우선주가 무엇이고 이 둘의 차이에 대해서는 아래 치킨요정님의 블로그에 잘 정리되어있습니다.

https://md2biz.tistory.com/374

 

주식 보통주 우선주 차이 비교

우리나라를 대표하는 주식 종목을 꼽으라 하면, 누구나 다 삼성전자를 꼽을 것입니다. 삼성전자 종목 하나가 우리나라 코스피+코스닥시장 총 시가총액의 10%가 넘는 비중을 차지하기 때문이죠. �

md2biz.tistory.com

 

 

간단히 설명하면 우리가 흔히 거래하는 보통주는 한주라도 소유하면 의결권을 행사할 수 있는 주주가 됩니다.

하지만 우선주는 의결권은 없는대신 이익 배당, 기업 청산시 재산에 대한 우선권을 얻습니다.

 

이 우선주의 이름은 보통 규칙적인데 주로 보통주 이름 + 우라는 형태로 지어집니다. (아닌 경우도 있습니다.)

예를 들면 삼성전자의 우선주는 삼성전자우입니다.

 

 

 

이렇게 보통주와 우선주는 각각 가격이 다른 상황에서 제가 생각한 가정과 이를 바탕으로한 전략은 이렇습니다.

 

코로나 폭락장 이전 보통주와 우선주의 가격차이인 괴리율이 어느정도 일정하게 유지되어 왔는데 
이번 폭락장에서 보통주, 우선주 모두 가격이 하락했다가 다시 회복하게 된 속도는 보통주가 빠르다.
따라서 이 둘의 가격차이가 평소보다 더 크게 벌어진 경우는 우선주를 사서 가격 상승을 기대한다.

 

 

다시 말하자면 보통주와 우선주의 괴리율이 다시 회복할 것이라는 가정을 바탕으로 

가격이 상대적으로 덜 오른 우선주를 사서 가격이 오르길 기대하겠다는 것입니다.

 

그런데 이를 확인하기 위해 우선주가 있는 보통주 목록을 구하려니 어디서 구해야할지 몰랐습니다.

Naver Finance를 크롤링하면 우선주명은 알 수 있으나 또 종목코드와 연결시켜 가격정보를 가져오려니 쉽지 않았습니다.

 

이를 해결하기 위해 Kiwoom Open API를 사용했습니다.

이 과정에서 API 연결, 로그인, 데이터 가져 오기 부분은 class101 주식자동 프로그램 개발에서 첨부한 소스 및 다른 블로그를 참조했습니다. (참조한 블로그들 링크는 다 날려버렸습니다 ㅠㅜ)

 

증권사 API를 사용하니 우선주를 포함한 모든 종목코드가 나오고 여기서 우선주만 추출하는 방식을 사용했습니다.

 

먼저 일부분만 첨부하면 다음과 같습니다.

    def get_all_codes_names(self):
        ret = self.dynamicCall("GetCodeListByMarket(QString)", ["0"])  # 맨뒤 인자는 시장구분, 모든 코드들을 가져옴
        kospi_code_list = ret.split(';')

        for code in kospi_code_list:
            name = self.dynamicCall("GetMasterCodeName(QString)", [code])  # 맨뒤는 종목코드, 코드에 따른 종목명을 가져옴

            regex = re.compile('[우][a-zA-Z]{0,1}$')
            match = regex.search(name)
            self.code_dict[name] = code

            if match:
                # 우선주 이름
                preferred_stock_name = name

                # 우선주에서 보통주 이름 구하기
                common_stock_name = re.sub('\d{0,1}[우]{0,1}[a-zA-Z]{0,1}$', '', name)

                # 우선주 이름 <> 보통주 매핑
                self.stock_map[preferred_stock_name] = common_stock_name

        # 네이밍 검증 전 출력
        print(len(self.stock_map), self.stock_map)

        # 네이밍 검증, '보통주 + 우' 형태가 아닌 경우는 걸러냄
        del_list = []
        for code in self.stock_map.keys():
            common_stock_name = self.stock_map[code]
            if common_stock_name not in self.code_dict.keys():
                del_list.append(code)
            
        for del_code in del_list:
            print( self.stock_map[del_code])
            del self.stock_map[del_code]

        # 네이밍 검증 이후 출력
        print(len(self.stock_map), self.stock_map)

 

 

이름이 단순히 보통주 + 우와 같은 경우도 많지만 아닌 경우 (미래에셋대우2우B)도 많아서 따로 정규식을 사용해 이름을 걸렀습니다.

또 반대로 이렇게 걸러낸 우선주에서 다시 보통주를 찾기 위해 re.sub()을 이용했습니다.

 

이렇게 걸러내면 총 116세트의 우선주-보통주 매핑이 찾아집니다. 하지만 몇가지 예외 사항이 있습니다

예를 들면 미래에셋대우의 경우 보통주임에도 우선주로 저장하고 미래에셋대는 보통주로 저장했습니다.

 

이런 경우 나중에 가격정보를 가져오면 존재하지 않는 주식이라고 에러가 발생할 것입니다.

이를 방지하기 위해 이렇게 추출한 이름이 전체 매핑(self.code_dict)에 있는지 확인해보고 없으면 잘못됐겠거니 하고 삭제했습니다.

 

이렇게 잘못된 케이스는 5건이 있습니다.

(CJ제일제당이 걸린 이유는 이름이 CJ제일제당 우이기 때문입니다.. 정규식을 바꾸면 거르지 않을 수 있습니다.)

 

 

아무튼 try-except 처리를 한다면 위 검증을 안해도 프로그램 동작에는 문제가 없으나 

5건을 삭제하고 전체 목록을 뽑아보면 다음과 같이 111건이 나옵니다

유가증권시장에서 우선주 발행한 기업이 100개 정도라는 얘기인데.. 제대로 나온게 맞나는 잘 모르겠습니다. 

 

{'하이트진로홀딩스우': '하이트진로홀딩스', '남양유업우': '남양유업', '대신증권우': '대신증권', '신원우': '신원', '계양전기우': '계양전기', '현대건설우': '현대건설', '동양2우B': '동양', 'SK이노베이션우': 'SK이노베이션', '한양증권우': '한양증권', '한진칼우': '한진칼', '대상홀딩스우': '대상홀딩스', 'KG동부제철우': 'KG동부제철', '크라운제과우': '크라운제과', 'GS우': 'GS', '한화3우B': '한화', '동양3우B': '동양', '두산2우B': '두산', '유화증권우': '유화증권', '코오롱인더우': '코오롱인더', '대교우B': '대교', '대원전선우': '대원전선', '신풍제약우': '신풍제약', 'JW중외제약우': 'JW중외제약', '금강공업우': '금강공업', '두산퓨얼셀2우B': '두산퓨얼셀', '코오롱글로벌우': '코오롱글로벌', '대상우': '대상', '동부건설우': '동부건설', '넥센타이어1우B': '넥센타이어', '롯데지주우': '롯데지주', '하이트진로2우B': '하이트진로', '유유제약1우': '유유제약', '태영건설우': '태영건설', '진흥기업2우B': '진흥기업', '대한제당우': '대한제당', 'DB하이텍1우': 'DB하이텍', '동원시스템즈우': '동원시스템즈', '대덕1우': '대덕', '두산솔루스2우B': '두산솔루스', '대신증권2우B': '대신증권', 'CJ우': 'CJ', '금호석유우': '금호석유', 'SK디스커버리우': 'SK디스커버리', 'JW중외제약2우B': 'JW중외제약', '대림산업우': '대림산업', '한화우': '한화', '성문전자우': '성문전자', '녹십자홀딩스2우': '녹십자홀딩스', '삼성전기우': '삼성전기', '미래에셋대우우': '미래에셋대우', '미래에셋대우2우B': '미래에셋대우', '넥센우': '넥센', '깨끗한나라우': '깨끗한나라', 'CJ씨푸드1우': 'CJ씨푸드', 'LG화학우': 'LG화학', '서울식품우': '서울식품', '노루홀딩스우': '노루홀딩스', '유안타증권우': '유안타증권', '호텔신라우': '호텔신라', '세방우': '세방', '덕성우': '덕성', '유유제약2우B': '유유제약', '삼성전자우': '삼성전자', '두산퓨얼셀1우': '두산퓨얼셀', '아모레퍼시픽우': '아모레퍼시픽', 'SK우': 'SK', '태양금속우': '태양금속', 'S-Oil우': 'S-Oil', '한화솔루션우': '한화솔루션', '흥국화재우': '흥국화재', 'NH투자증권우': 'NH투자증권', '진흥기업우B': '진흥기업', '금호산업우': '금호산업', '현대차우': '현대차', '현대비앤지스틸우': '현대비앤지스틸', '현대차2우B': '현대차', '한국금융지주우': '한국금융지주', '삼성물산우B': '삼성물산', '두산솔루스1우': '두산솔루스', '대덕전자1우': '대덕전자', '코오롱우': '코오롱', '삼양홀딩스우': '삼양홀딩스', 'LG하우시스우': 'LG하우시스', '대한항공우': '대한항공', 'NPC우': 'NPC', 'SK케미칼우': 'SK케미칼', '롯데칠성우': '롯데칠성', 'LG전자우': 'LG전자', '성신양회우': '성신양회', 'BYC우': 'BYC', '노루페인트우': '노루페인트', 'LG우': 'LG', 'SK증권우': 'SK증권', '흥국화재2우B': '흥국화재', '크라운해태홀딩스우': '크라운해태홀딩스', '유한양행우': '유한양행', '삼성SDI우': '삼성SDI', '코리아써키트2우B': '코리아써키트', '두산우': '두산', '한화투자증권우': '한화투자증권', '부국증권우': '부국증권', 'LG생활건강우': 'LG생활건강', '아모레G우': '아모레G', '삼성화재우': '삼성화재', 'SK네트웍스우': 'SK네트웍스', '동양우': '동양', '쌍용양회우': '쌍용양회', '현대차3우B': '현대차', '신영증권우': '신영증권', '삼양사우': '삼양사', '일양약품우': '일양약품'}

 

 

다음 포스팅에서는 이들을 가지고 전략을 수행해보겠습니다. 

 

다음 이야기

2020/06/06 - [파이썬/주식] - Python으로 보통주, 우선주 괴리율을 이용한 투자전략 - 2

 

Python으로 보통주, 우선주 괴리율을 이용한 투자전략 - 2

2020/06/06 - [Python/Stock] - Python으로 보통주, 우선주 괴리율을 이용한 투자전략 - 1 Python으로 보통주, 우선주 괴리율을 이용한 투자전략 - 1 최근 주식시장이 강세입니다. 많이 오른 종목도 있고 상대

jsp-dev.tistory.com

 

 

제 블로그에 방문해주셔서 감사합니다.
좋아요, 댓글은 제가 글을 쓰는데 큰 힘이 됩니다.
아래는 쿠팡 링크이고 쿠팡 파트너스 활동을 통해 일정 수익이 발생할 수 있음을 알려 드립니다.

반응형
이 포스팅은 쿠팡파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

댓글