본문 바로가기

파이썬 기초

[파이썬 활용] 주식 등락률 비교해보기

파이썬으로 주식 등락률 비교해보기

오늘은 평소 관심 가지고 있는 주식 종목이 일정 기간 동안 어느 정도 오르고, 내렸는지 확인해보고 여러 개의 주식 종목들을 서로 비교하여 상대적으로 어떤 종목이 많이 오르고 어떤 종목이 많이 떨어지는지 확인할 수 있는 파이썬 코드를 작성해보겠습니다.

 

시가 총액 기준으로 상위 Top 15의 최근 한 달 동안 성적은 어떨까요?

물론 종목마다 네이버에서 검색하여 한 달 전의 주가와 비교하여 계산하는 것도 가능하지만 한 번에 차트로 볼 수 있다면 종목 간의 상호 비교뿐만 아니라 종목이 상승세인지 하락세인지 등 한눈에 확인이 가능합니다.

 

금일 기준으로 시가 총액이 TOP 15 기업을 dictionary로 만들었습니다.

삼성전자, SK하이닉스, 삼성바이로로직스, NAVER, 셀트리온, 삼성전자 우, LG화학, 카카오, 삼성 SDI, 현대차, LG생활건강, 현대모비스, 삼성물산, 엔씨소프트, SK텔레콤

 

company_code_dict = {'삼성전자':'005930',
                     'SK하이닉스': '000660',
                     '삼성바리오로직스': '207940',
                     'NAVER': '035420',
                     '셀트리온': '068270',
                     '삼성전자우': '005935',
                     'LG화학': '051910',
                     '카카오': '035720',
                     '삼성SDI': '006400',
                     '현대차': '005380',
                     'LG생활건강': '051900',
                     '현대모비스': '012330',
                     '삼성물산': '028260',
                     '엔씨소프트': '036570',
                     'SK텔레콤': '017670' }

 

파이썬(Python) 코드 구현 방법을 간단히 정리해보면 다음과 같습니다.

 

위에서 만든 기업명과 주식 코드가 작성된 dictionary를 for문을 사용하여 종목별로 네이버 증권 페이지에서 약 한 달(거래일로는 20일) 동안 종목의 종가 데이터를 크롤링하여 필요한 데이터를 parsing 하고, 획득한 일별 주가를 기준일의 주가로 정규화(Normalization)하여 마지막 결과를 내림차순 정렬하고 차트로 나타내어 보았습니다.

 

우선 웹크롤링을 위해서 requestsBeautifulSoup를 import하고 data의 빠른 처리를 위해 pandas를 아래와 같이 import 하였습니다. 만약 해당 라이브러리가 설치되어 있지 않아서 import 에러가 발생하면 pip install 이용하여 설치하시면 됩니다.

 

import requests
from bs4 import BeautifulSoup
import pandas as pd

 

다음은 입력 받은 종목 코드를 네이버 증권 페이지에서 웹 크롤링하여 종목의 종가를 받아오는 함수, get_daily_close_price()에 대한 설명입니다.

이 함수에서 반환되는 것은 날짜별 종가를 저장한 dictionary입니다.

해당 함수에서 웹 페이지에서 주가를 받아오는 상세 설명은 "파이썬 활용 주식 일봉 데이터 받기 및 차트 그리기 1" 포스팅에 자세히 설명되어 있습니다.

필요하신 분은 참조하세요.( ☞ https://digital-play.tistory.com/18 )

함수에 대해서 간략히 설명하면 url은 네이버 증권 페이지 주소입니다.

페이지 주소 중앙에 count=20이라고 적혀 있는 것을 볼 수 있는데 최근 며칠의 데이터를 받아올지 결정하는 부분입니다. 저는 20일(약 1개월) 데이터 받아오기 위해 20으로 설정하였는데 원하는 수집 데이터 개수를 입력하면 됩니다. 

items_list에는 최근 20일 동안의 웹 페이지에서 parsing 데이터가 저장되고 <item data="날짜|시가|고가|저가|종가|거래량"></item>의 형태로 구성되어 있습니다.

for문을 이용하여 데이터를 split('|') 함수로 구분하였고 구분된 데이터에서 첫 번째 데이터(날짜), data [0]에서는 20200722의 형식으로 날짜가 저장되는데 2020을 제외한 0722만 가져왔습니다. 다섯 번째 데이터(종가), data [4]에서는 주가의 종가가 문자로 저장되어 있는데 정수로 변환하였습니다.

Parsing 하고 가공한 날짜별 주가는 price_dict라는 dictionary에 저장 후 반환합니다.

 

def get_daily_close_price(company_code):
    url = 'http://fchart.stock.naver.com/sise.nhn?timeframe=day&count=20&requestType=0&symbol=' + company_code
    
    price_data = requests.get(url)
    html = BeautifulSoup(price_data.text, "html")
    items_list = html.find_all('item')
    
    price_dict = {}
    for item in items_list:
        data = item['data'].split('|')
        price_dict[ data[0][4: ] ] = int(data[4])
    
    return price_dict

 

하나의 종목에 대해서 날짜별 주가를 받아오는 함수 구현이 다되었으면 본격적으로 시가 총액 TOP 15의 날짜별 주가를 가져와서 dataframe에 저장해보겠습니다.

 

price_df라는 비어 있는 dataframe를 하나 만듭니다.

처음 만들었던 company_dict를 for문은 이용하여 get_daily_close_price(code)를 차례대로 호출하고 반환받은 날짜별 주가를 price_df라는 dataframe에 저장하였습니다.

if price_df.empty는 price_df라는 dataframe이 비어 있으면 확인하기 위한 조건문입니다. 최초 한 번만 수집한 20개의 날짜 데이터를 첫 번째 열에 저장하고 set_index()를 이용하여 인덱스 열로 지정하기 위해서 추가하였습니다.

 

company_dict = {'삼성전자': '005930',
                'SK하이닉스': '000660',
                '삼성바이오로직스': '207940',
                'NAVER': '035420',
                '셀트리온': '068270',
                '삼성전자우': '005935',
                'LG화학': '051910',
                '카카오': '035720',
                '삼성SDI': '006400 ',
                '현대차': '005380',
                'LG생활건강': '051900',
                '현대모비스': '012330',
                '삼성물산': '028260 ',
                '엔씨소프트': '036570',
                'SK텔레콤': '017670'
               }

price_df = pd.DataFrame()

for company, code in company_dict.items():
    
    price_dict = get_daily_close_price(code)
    
    if price_df.empty:
        price_df['날짜'] = list(price_dict.keys())
        price_df.set_index('날짜', inplace=True)
        
    price_df[company] = list(price_dict.values())

 

지금까지의 작성한 파이썬 코드의 결과를 확인해보면 아래와 같습니다. 가로축은 주식 종목이고 세로축은 날짜입니다.

price_df
price_df 출력 결과

price_dftranspose()라는 함수를 이용하여 가로축과 와 세로축을 바꾸어 daily_price_df에 저장합니다.

그러면 세로축은 종목이되고 가로축은 날짜가 됩니다.

 

daily_price_df = price_df.transpose()

 

다음은 주가를 정규화(Normalization)하기 위해서 종목별로 종목의 첫째 날의 주가로 모두 주가에 나누기를 수행합니다.

이렇게 하면 첫째 날은 모두 '1'이 되고 이후 날짜의 주가는 첫째 날의 주가를 기준으로 주가가 어느 정도의 등락이 발생되었는지를 비율로 표현됩니다. 이처럼 주가를 정규화하여 표현하면 종목들 간의 상호 비교가 가능해집니다.

주가를 첫째날의 주가로 나누기할 때 주의할 점은 앞에서부터 나누기하면 첫째 날의 데이터가 1로 변경되기 때문에 첫째 날의 주가정보가 살아지게 됩니다. 이를 해결하기 위해서 마지막 날짜부터 나누기를 수행하였습니다.

daily_price_df의 열 이름은 columns라는 속성을 이용하였으며 마지막 날짜에서부터 나누어주기 위해서 [ : : -1] 이용하였습니다.

round() 함수를 사용하여 결과값에 소수점 셋째 자리에서 반올림하였습니다.

 

for date in daily_price_df.columns[::-1]:
    daily_price_df[date] = round(daily_price_df[date] / daily_price_df[daily_price_df.columns[0]], 3)

 

이렇게 정규화한 주가 데이터를 sort_values() 함수를 이용하여 마지막 열(0722)을 기준으로 내림차순 정렬하여 가장 많이 상승한 종목은 첫 번째 중에 가장 많이 하락한 종목은 마지막 줄에 위치시켰습니다.

ascending에서 False는 내림차순 정렬, True는 오름 차순 정렬이고 inplace는 정렬된 결과를 원본 데이터에 바꾸기를 원할 때 True로 하시면 됩니다.

 

daily_price_df.sort_values(by=[daily_price_df.columns[-1]], ascending=False, inplace=True)

 

실행 결과, TOP 15 종목 중, 11개의 종목이 첫째 날(0625) 대비 상승하였고 4개의 종목은 하락되었네요.

가장 많이 상승한 종목은 현대차이며 상승율은 19.2%인 반면 엔씨소프트는 -5.6%로 가장 많이 하락한 것을 수치로 쉽게 알 수 있습니다.

주가 정규화 및 정렬 결과

 

마지막 단계로, TOP 15 종목에 대한 결과를 차트로 그려 봅시다.

matplotlib라는 라이브러리를 import하고 for문으로 plot() 함수를 실행시켰습니다.

 

from matplotlib import pyplot as plt

plt.figure(figsize=(15, 10))
for company in company_dict.keys():
    plt.plot(daily_price_df.loc[company][:], label=company)
    
plt.legend()
plt.show()

 

아래는 차트 그리기 실행 결과입니다.

plot 수행 결과

 

추가적으로 엑셀로 결과를 저장하여 활용하기 위해서 to_excel() 함수를 사용하였습니다. 파이썬 코드가 있는 폴더에 result_0722.xlsx라는 엑셀 파일이 생성됩니다. 

 

daily_price_df.to_excel('reult_0722.xlsx')

 

엑셀 파일에 저장된 데이터를 이용하여 차트를 그리기를 수행한 결과입니다.

엑셀 파일 차트

 

이상으로 파이썬을 이용하여 시가 총액 TOP 15에 대해서 주가를 정규화하여 등락률을 상호 비교해볼 수 있도록 구현하여보았습니다. 주가 분석에 조금의 도움이라도 되었으면 합니다.