본문 바로가기

Python 개발일지

스파르타 코딩 클럽 : [왕초보] 주식 데이터를 활용한 파이썬 데이터분석 2주차 개발일지

저번 주에 이어 Python을 활용한 데이터분석에 대해 배웠다.

이번 주차의 강의는 개인 사정이 너무 바빠 끊어끊어 듣다보니 들을 때마다 새로워 조금 어려웠다.

기본적으로 처음 들어보는 라이브러리와 처음 들어보는 명령문들이 어려워지는데에 한 몫 했는데, 그 덕분에 중간에 Python에 대한 수강을 포기하고 싶어지는 생각도 들었다.

하지만 꾸역꾸역 해나가서 마지막 숙제까지 해냈다.

 

이 글엔 스파르타 코딩 클럽에서 수강중인 Python, 2주차에 배운 것에 대한 개발일지를 작성하였다.

 

강의의 2주차 수업 목표는 이러했다.

[수업 목표]
1. Pandas 의 DataFrame을 활용할 수 있다.
2. yfinance 라이브러리를 활용할 수 있다.
3. 해외주식 정보를 다룰 수 있다.

아래부터는 수업을 요약한 내용이다.


1. 서론

Pandas란 무엇일까?

Pandas 라이브러리는 데이터 분석하는 사람들에게 매우 익숙한 라이브러리이다.

한 번 배우고 익히면 실제로 어떤 데이터 분석을 하던지 무조건 유용하게 사용할 것이다.

Pandas의 DataFrame을 사용하면, 복잡한 데이터를 깔끔하게 표 형태로 볼 수 있다.

더불어 열 추가, 혹은 특정 행 추출 같은 것들을 데이터의 크기에 상관 없이 자유자재로 다룰 수 있게 해준다.

 

그렇다면 yfinance는 무엇일까?

yfinance는 yahoo finance의 정보를 활용할 수 있는 라이브러리이다.

yahoo finance 페이지는 다양한 해외주식 정보를 모아놓은 사이트로, 종목코드를 검색하면 해당 종목에 대해 여러가지 데이터를 제공하고 그 데이터를 활용할 수 있게 해 주는 yfinance라이브러리로 데이터 분석을 할 수 있다.

 

먼저, pandas를 활용하기 위해선 라이브러리를 설치해야 할 것이다.

더불어 pandas를 조금 더 유용하게 활용하기 위해 numpy 라이브러리 또한 설치할 것이다.

!pip install pandas numpy

라이브러리를 설치했다면, 프로그램을 불러와야 할 것이다.

import pandas as pd # pandas 라이브러리를 별칭 pd로 사용
import numpy as np # numpy 라이브러리를 별칭 np로 사용

2. 본론

1) Pandas 기초

- 기본 DataFrame 만들어보기

Pandas에 들어가는 데이터들은 기본적으로 아래와 같이 생겼다.

# DataFrame을 만들 딕셔너리 data 생성
data = {
    'name' : ['철수','영희','동희','영수'],
    'age' : [15,12,20,35]
}

# 딕셔너리 data를 pandas의 DataFrame으로 만들고 이를 변수 df에 저장
df = pd.DataFrame(data)

print(df)

위의 코드를 실행하면 이렇게 생긴 DataFrame이 나온다.

- DataFrmae 다루기 : 기초

DataFrame을 생성했다면 기초적인 기능들을 알아볼 시간이다.

 

1) 행 추가하기

# df에 추가할 데이터 딕셔너리 doc 생성
doc = {
    'name' : '세종',
    'age' : 23
}

# df에 doc을 추가해서 다시 만들기
df = df.append(doc, ignore_index = True) # ignore_index : 따로 index를 만들지 않고 이어 붙이겠다!

2) 열 추가하기

df['city'] = ['서울','부산','서울','부산','부산']

3) 특정 열만 추출

df[['name','city']]		# 대괄호 두번 해주기!

4) 원하는 조건에 맞는 행만 추출

# 조건 생성
cond = df['age'] < 20

# 조건에 맞추어 df 추출
df[cond]

# 보통 조건이 짧을 때는 따로 변수로 조건을 만들지 않고 바로 써준다.

5) 특정 행에서 뽑기

print(df.iloc[-1])   # 마지막 줄 (뒤에서 첫번째 줄) 가져오기
print(df.iloc[-1,0]) # 마지막 줄의 첫번째 정보인 이름 가져오기
print(df.iloc[-1,1]) # 마지막 줄의 두번째 정보인 나이 가져오기
print(df.iloc[-1,2]) # 마지막 줄의 세번째 정보인 도시 가져오기
print(df.iloc[-2,0]) # 뒤에서 두번째 줄의 첫번째 정보 가져오기
데이터 분석을 할 때 주로 마지막 줄을 자주 볼 것이다.
그 이유는 DataFrame은 맨 끝 결과를 정렬하여 보는 경우가 많다.
예를 들어 가격이 높은 순서로 정렬하여 맨 위 정보와 맨 마지막 정보를 보는 경우가 많은 것이다.

- DataFrame 다루기 : 연산

DataFrame의 기초적인 기능들을 알아봤다면 조금 더 알아볼 시간이다.

 

1) 열 정렬하기

print(df.sort_values(by='age',ascending=False))   # df의 값을 age에 관해 내림차순으로 정렬
print(df.sort_values(by='age',ascending=False).iloc[0,1])
                                                  # 내림차순으로 정렬했을 때 첫번째 줄의 첫번째 정보 추출

2) 조건에 맞는 열 추가하기

# df에 나이가 20보다 적으면 청소년, 많으면 성인으로 표시하는 열 추가
df['is_adult'] = np.where(df['age'] < 20, '청소년', '성인') 


df

3) 평균, 최대값, 최소값, 개수 구하기

# df의 나이 열에 대한 정보들 추출
# 순서대로 개수, 평균, 표준편차, 최소값, 25%값, 50%값, 75%값, 최대값
print(df['age'].describe())
# df의 나이 열에 대한 평균
print(df['age'].mean())
# df의 나이 열에 대한 최대값
print(df['age'].max())
# df의 나이 열에 대한 최소값
print(df['age'].min())
# df의 나이 열에 대한 정보 개수
print(df['age'].count())

※ 퀴즈

서울에 사는 사람 중 나이가 가장 많은 사람이 몇 살인지 구하기

1) 최대값으로 구하기

cond = df['city'] == '서울'

print(df[cond])                    # 조건 cond에 맞는 행 추출
print(df[cond]['age'])             # 조건 cond에 맞는 행의 'age' 정보 추출
print(df[cond]['age'].max())       # 조건 cond에 맞는 행의 'age' 정보들의 최대값값 추출

2) 내림차순으로 정렬하여 맨 위의 정보 추출

# 'city'가 '서울'인 행 추출
print(df[df['city'] == '서울'])
# 'city'가 '서울'인 행들을 나이에 관해 내림차순으로 정렬
print(df[df['city'] == '서울'].sort_values('age',ascending = False))
# 'city'가 '서울'인 행들을 나이에 관해 내림차순으로 정렬했을 때 첫번째 행 두번째 정보 추출
print(df[df['city'] == '서울'].sort_values('age',ascending = False).iloc[0,1])

 

2) 엑셀 가져오기

대부분의 데이터 분석가들은 대체로 엑셀보다 Pandas를 선호한다.

따라서 기존의 엑셀파일을 DataFrame으로 변환할 필요가 있다.

본 강의에서는 종목데이터가 담긴 엑셀파일을 활용할 것이다.

파일명은 '종목데이터.xlsx'로 Colab에 업로드 한 후 사용한다.

 

파일을 Colab에 업로드했다면 이제 Colab에서 Pandas를 사용해 읽어내면 된다.

df = pd.read_excel('종목데이터.xlsx')

df          # 엑셀 파일 Pandas로 열기
df.head()   # 데이터 처음 5개 정보 추출
df.tail()   # 데이터 마지막 5개 정보 추출
df.tail(10) # 데이터 마지막 10개 정보 추출

이렇게 엑셀을 읽어오면 읽어온 데이터의 소수점 아래 자리가 꽤 긴 것을 볼 수 있다.

따라서 아래와 같은 코드를 실행하여 소수점을 소수점 둘째 자리까지만 보도록 하겠다.

pd.options.display.float_format = '{:.2f}'.format

 

3) Pandas 실전

위의 엑셀에서 가져온 데이터를 활용하여 Pandas에 대해 실전 응용을 배워보겠다.

 

- 어제 오른 종목들만 골라보기

어제 오른 종목들을 고르라는 것은 변화율, 즉 change_rate가 0보다 큰 종목들을 고르라는 것이다.

(change_rate : 어제보다 오늘 얼마나 올랐는가?)

cond = df['change_rate'] > 0      # change_rate가 0보다 크다는 조건을 변수 cond로 설정

df[cond]                          # df(종목데이터)에서 cond에 맞는 항목들을 추출출

- per가 0인 종목들을 제거하기

cond = df['change_rate'] > 0

df = df[cond]                     # 위의 데이터프레임을 새로운 데이터프레임으로 저장

cond = df['per'] > 0              # per가 0보다 크다는 조건을 변수 cond에 다시 저장
df = df[cond]                     # 조건에 맞는 항목들만 추출하여 다시 저장장

df

- 순이익, 종가 추가하기

per = 시가총액 / 순이익 = 주가 / 주당순이익 이다.

(시가총액 = marketcap)  (주당순이익 = eps)  (주가 = 종가)

따라서

순이익 = marketcap / per이고,

종가 = per * eps이다.

 

따라서 순이익과 종가를 추가한다면 아래와 같이 하면 된다.

df['earning'] = df['marketcap'] / df['per']   	# 새로운 열 'earning'의 항목들 설정하여 추가

df['close'] = df['per'] * df['eps']       	# 새로운 열 'close'의 항목들 설정하여 추가

df

- date 칼럼을 없애기

del df['date']

df

- 'pbr< 1' & ' 시총 1조 이상' & 'per < 20'을 추려보기

 

cond = (df['pbr'] <1) & (df['marketcap'] > 1000000000000) & (df['per'] < 20)      # 변수 cond에 조건 저장
df = df[cond]                  

df

+ 정렬하기

df.sort_values(by = 'marketcap', ascending = False)

+ 수에 대한 정보 한 번에 보기

df.describe()
# 결과는 데이터 개수, 평균, 표준편차, 최소값, 최대값, 25%, 50%, 75% 값이 나온다.

 

4) 해외주식 다루기 - yfinance

이제 본격적으로 yfinance 라이브러리를 사용하여 해외주식을 분석하기 전에

yfinance를 기본적으로 사용해보려 한다.

 

- yfinance 라이브러리 설치하기

당연하게도 yfinance 라이브러리를 사용하기 위해선 설치해야 한다.

!pip install yfinance

해당 코드를 실행시키면 런타임을 재실행할 것을 요구한다.

그 때는 런타임을 다시 시작하기만 하면 된다.

 

- yfinance 실행해보기

yfinance 라이브러리의 설치가 끝났다면, yfinance 라이브러리를 불러와야 할 것이다.

import yfinance as yf			# yfinance 라이브러리를 별칭 yf로 불러오기

yfinance 라이브러리를 불러왔다면, 이제 기본적인 내용들부터 살펴보겠다.

company = yf.Ticker('TSLA')     # 종목코드 'TSLA'의 주식정보를 모아서 변수 company에 저장

company				# 'TSLA'의 정보를 저장한 변수
company.info      		# 'TSLA'의 정보들을 추출한다. (사이트와 항목 이름이 같진 않음)

전체적인 사용방법은 아래 링크에서 볼 수 있다.

https://pypi.org/project/yfinance/

 

- 기본 정보 얻기

위의 결과로 나온 정보들에서 기본 정보들을 얻어보겠다.

(ex_ 회사명, 산업, 시가총액, 매출)

# 회사명
name = company.info['shortName']
# 산업
industry = company.info['industry']
# 시가총액
marketcap = company.info['marketCap']
# 매출
revenue = company.info['totalRevenue']

print(name)
print(industry)
print(marketcap)
print(revenue)

- 재무제표에서 3년치 데이터 얻기

기본 정보들을 얻었다면 대차대조표, 현금흐름표, 기업 실적의 정보를 얻어보겠다.

# 대차 대조표
company.balance_sheet                 # 연도별 자료가 있는 것이 특징
company.balance_sheet.loc[['Cash']]   # Cash 인덱스의 자료만 추출 (꺾쇠 두개로 하면 예쁘게 나옴)

# 현금흐름표
company.cashflow

# 기업 실적
company.earnings

- 그 외 정보들

yfinance 라이브러리를 사용하면 위에서 알아본 정보들 외에도 여러 정보들을 얻어낼 수 있다.

아래는 그 예시다.

# 증권사 추천 : recommendations
company.recommendations

# 만약 'JP Morgan'의 정보만 보고 싶다면?
df = company.recommendations

cond = df['Firm'] == 'JP Morgan'
df[cond]
# 뉴스 : news
news = company.news

print(news)              # 뉴스 전체 불러오기
print(news[0])           # 첫번째 뉴스 불러오기
print(news[0]['title'])  # 첫번째 뉴스 제목 불러오기

 

5) 분석하기(1) : 전략 세우기, 데이터 모으기

[전략세우기]

- 종목 별로 보고 싶은 정보 고르기

ex) 종목코드, 회사명, 산업, 짧은 설명, 시가총액, 현재 주가, 1년 후 예상 주가 등등

- 보고 싶은 정보 모으기

company = yf.Ticker('TSLA')

name = company.info['shortName']                  # 회사명
code = 'TSLA'                                     # 종목코드
industry = company.info['industry']               # 산업
marketcap = company.info['marketCap']             # 시가총액
summary = company.info['longBusinessSummary']     # 짧은 설명
currentprice = company.info['currentPrice']       # 현재 주가
targetprice = company.info['targetMeanPrice']     # 1년 후 예상 주가
per = company.info['trailingPE']                  # PER
eps = company.info['trailingEps']                 # EPS
pbr = company.info['priceToBook']                 # PBR

- 모은 정보에 매출, 순이익 추가하기

rev2021 = company.earnings.iloc[-1,0]
rev2020 = company.earnings.iloc[-2,0]
rev2019 = company.earnings.iloc[-3,0]             # 연도별 매출

ear2021 = company.earnings.iloc[-1,1]
ear2020 = company.earnings.iloc[-2,1]
ear2019 = company.earnings.iloc[-3,1]             # 연도별 순이익

 

[데이터 모으기]

- 빈 DataFrame 만들기

데이터를 모으려면 데이터를 모을 빈 DataFrame이 필요할 것이다.

df = pd.DataFrame()

- 리마인드 : DataFrame에 데이터 넣기

우리는 DataFrame에 모은 데이터들을 넣어야 하기 때문에 데이터를 넣는 방법을 복습해보겠다.

doc = {
    'name' : '철수',
    'age' : 19
}

df.append(doc, ignore_index = True)

- 데이터 모으기

우선, 데이터를 모아서 딕셔너리를 생성하겠다.

doc = {
      'name' : name,
      'industry' : industry,
      'code' = code
      'marketcap' : marketcap,
      'summary' : summary,
      'currentprice' : currentprice,
      'targetprice' : targetprice,
      'per' : per,
      'eps' : eps,
      'pbr' : pbr,
      'rev2021' : rev2021,
      'rev2020' : rev2020,
      'rev2019' : rev2019,
      'ear2021' : ear2021,
      'ear2020' : ear2020,
      'ear2019' : ear2019,
  }

- 전체 데이터 모으기

딕셔너리를 생성했다면, 위의 딕셔너리를 code값에 대해서 한 번에 모아서 정리해주는 함수를 생성하겠다.

이 때, 코드에 관련된 항목은 함수의 변수로 사용하기에 제외해도 된다.

def add_company(code) : 
  company = yf.Ticker(code)

  name = company.info['shortName']                  # 회사명
  industry = company.info['industry']               # 산업
  marketcap = company.info['marketCap']             # 시가총액
  summary = company.info['longBusinessSummary']     # 짧은 설명
  currentprice = company.info['currentPrice']       # 현재 주가
  targetprice = company.info['targetMeanPrice']     # 1년 후 예상 주가
 
  per = company.info['trailingPE']                  # PER
  eps = company.info['trailingEps']                 # EPS
  pbr = company.info['priceToBook']                 # PBR

  rev2021 = company.earnings.iloc[-1,0]
  rev2020 = company.earnings.iloc[-2,0]
  rev2019 = company.earnings.iloc[-3,0]             # 연도별 매출

  ear2021 = company.earnings.iloc[-1,1]
  ear2020 = company.earnings.iloc[-2,1]
  ear2019 = company.earnings.iloc[-3,1]             # 연도별 순이익

  doc = {
      'name' : name,
      'industry' : industry,
      'marketcap' : marketcap,
      'summary' : summary,
      'currentprice' : currentprice,
      'targetprice' : targetprice,
      'per' : per,
      'eps' : eps,
      'pbr' : pbr,
      'rev2021' : rev2021,
      'rev2020' : rev2020,
      'rev2019' : rev2019,
      'ear2021' : ear2021,
      'ear2020' : ear2020,
      'ear2019' : ear2019,
  }

  return doc

함수를 생성했다면, 함수를 사용하여 코드에 대한 전체 데이터를 모을 수 있다.

df = pd.DataFrame()               # 빈 DataFrame 생성

row = add_company('TSLA')         # 종목코드 TSLA에 대한 주식 정보들을 변수 row에 저장

df.append(row, ignore_index=True) # 변수 row를 데이터 프레임 df 에 추가

- 전체 데이터 모으기(10개 회사)

한 가지 회사의 주식정보를 가져서는 분석다운 분석을 할 수 없을 것이다.

우리는 함수를 생성하여 작업이 한 결 간편해졌으니, 리스트와 반복문을 사용하여 여러 회사에 대해 정보를 모을 수 있다.

codes = ['AAPL','ABNB','BIDU','FB','GOOG','MSFT','TSLA','PYPL','NFLX','NVDA']
                                              # 주식 정보를 모을 종목코드들을 리스트 codes로 저장
df = pd.DataFrame()                           # 빈 데이터 프레임 생성

for code in codes :                           # 리스트 codes의 원소들에 대해 변수 code로 반복
  print(code)                                 # 진행상황을 알기 위해 code 출력
  try :                                       # 모으고자 하는 주식 정보가 없을 경우를 대비해 try-except문 작성성
    row = add_company(code)                   # code에 대해 주식 정보 모아서 변수 row에 저장
    df = df.append(row, ignore_index=True)    # 데이터프레임에 변수 row 추가하여 새로이 저장
                                              # 이후 반복하며 code들에 대하여 데이터프레임에 정보가 쌓임임
  except : 
    print(f'error - {code}')                  # 오류가 발생할 경우 'error - {코드명}' 출력

df

 

6) 분석하기(2) : 분석하기

- eps 순서대로 정렬해보기

df.sort_values(by = 'eps',ascending=False)			
df.sort_values(by = 'eps',ascending=False).head(5)	# 상위 5개 항목만 보기

- 특정 per 이하만 보기

cond = df['per'] < 30

df[cond]
df[cond].sort_values(by='per',ascending = False)

- '현재가격 - 1년 후 가격'의 비율 차이가 큰 종목들을 추려내기

#new_df = df[['name','currentprice','targetprice']]         # 원본에 영향이 감
new_df = df[['name','currentprice','targetprice']].copy()   # 원본에 영향 안 감

new_df['gap'] = new_df['targetprice'] / new_df['currentprice'] -1

new_df.sort_values(by='gap',ascending=False)

- 3년 연속 순수익이 오른 기업을 표기하기

new_df = df[['name','ear2021','ear2020','ear2019']].copy()

cond = (new_df['ear2021']>new_df['ear2020']) & (new_df['ear2020']>new_df['ear2019'])
 
new_df['is_target'] = np.where(cond, 'O','X')

new_df

3. 숙제

# yfinance를 이용해서 Balace Sheet의 cash를 사진과 같이 표기하기

아래는 나의 풀이이다.

!pip install pandas numpy
!pip install yfinance

import pandas as pd
import numpy as np
import yfinance as yf

company = yf.Ticker('TSLA')

df = company.balance_sheet.loc[['Cash']].copy()

shortname = company.info['shortName']

df = df.reset_index(drop=True)
df.insert(0,'name',shortname)
df.columns = ['name', '2021', '2020','2019','2018']
df = df.drop([df.columns[3],df.columns[4]],axis=1)
df['diff'] = df['2021'] - df['2020']
df

아래는 강의에서 제공한 정답이다.

!pip install pandas numpy
!pip install yfinance

import pandas as pd
import numpy as np
import yfinance as yf

company = yf.Ticker('TSLA')

df = company.balance_sheet.loc[['Cash']]
df.columns = ['2021','2020','2019','2018']

df['name'] = company.info['shortName']

new_df = df[['name','2021','2020']].copy()

new_df['diff'] = new_df['2021'] - new_df['2020']

new_df.reset_index(drop=True)