Python Pandas와 yfinance로 주식 데이터 분석하기

Python

금융 데이터 분석에 있어서 Python은 강력한 도구입니다. 특히 pandasyfinance 라이브러리를 조합하면 주식 시장 데이터를 손쉽게 가져와서 분석할 수 있습니다. 이번 포스트에서는 이 도구들을 활용하여 삼성전자와 마이크로소프트의 주가 데이터를 가져오고 분석하는 방법에 대해 알아보겠습니다.

필요한 라이브러리 설치하기

시작하기 전에 필요한 라이브러리를 설치해야 합니다:

pip install pandas pandas-datareader yfinance matplotlib

yfinance 라이브러리 소개

yfinance는 Yahoo Finance에서 금융 데이터를 쉽게 다운로드할 수 있게 해주는 라이브러리입니다. 이전에는 pandas-datareader가 Yahoo Finance API를 직접 사용했지만, API 변경으로 인해 이제는 yfinance를 통해 데이터를 가져오는 것이 더 안정적입니다.

yfinance의 주요 기능

  1. 주식 기본 데이터 조회: 주가, 거래량, 배당금 등
  2. 기업 재무제표 데이터: 수익, 자산, 부채 등
  3. 주식 분할 및 배당금 정보
  4. 옵션 체인 데이터
  5. 기업 기본 정보

기본 주가 데이터 가져오기

yfinancepandas-datareader를 사용하여 삼성전자(005930.KS)와 마이크로소프트(MSFT)의 주가 데이터를 가져오는 코드부터 시작해 보겠습니다:

from pandas_datareader import data as pdr
import yfinance as yf
yf.pdr_override()

# 삼성전자(005930) 2018년 5월 4일부터 현재까지의 데이터 가져오기
sec = pdr.get_data_yahoo('005930.KS', start='2018-05-04')
msft = pdr.get_data_yahoo('MSFT', start='2018-05-04')

Upgrade (2025.05.11)

import yfinance as yf

# Get data directly using yf.download
sec = yf.download('005930.KS', start='2018-05-04')
msft = yf.download('MSFT', start='2018-05-04')

실행하면 다음과 같은 진행 상황이 표시됩니다:

[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed

데이터 구조 살펴보기

yfinance로 가져온 데이터의 구조

yfinance를 통해 가져온 데이터는 pandas DataFrame 형태로 제공됩니다. 이 DataFrame은 다음과 같은 열로 구성됩니다:

  1. Open: 시가
  2. High: 고가
  3. Low: 저가
  4. Close: 종가
  5. Adj Close: 수정 종가 (배당금, 주식 분할 등을 반영)
  6. Volume: 거래량

아래 코드로 삼성전자의 처음 10개 행을 확인해 봅시다:

print(sec.head(10))

출력 결과:

                Open     High      Low    Close     Adj Close    Volume
Date
2018-05-04  53000.0  53900.0  51800.0  51900.0  46191.074219  39565391
2018-05-08  52600.0  53200.0  51900.0  52600.0  46814.070312  23104720
2018-05-09  52600.0  52800.0  50900.0  50900.0  45301.074219  16128305
2018-05-10  51700.0  51700.0  50600.0  51600.0  45924.066406  13905263
2018-05-11  52000.0  52200.0  51200.0  51300.0  45657.078125  10314997
2018-05-14  51000.0  51100.0  49900.0  50100.0  44589.066406  14909272
2018-05-15  50200.0  50400.0  49100.0  49200.0  43788.066406  18709146
2018-05-16  49200.0  50200.0  49150.0  49850.0  44366.574219  15918683
2018-05-17  50300.0  50500.0  49400.0  49400.0  43966.070312  10365440
2018-05-18  49900.0  49900.0  49350.0  49500.0  44055.070312   6706570

마이크로소프트의 마지막 5개 행을 확인해 보겠습니다 (거래량 제외):

tmp_msft = msft.drop(columns='Volume')
print(tmp_msft.tail())

출력 결과:

                   Open        High         Low       Close   Adj Close
Date
2022-02-14  293.769989  296.760010  291.350006  295.000000  294.391296
2022-02-15  300.010010  300.799988  297.019989  300.470001  299.850006
2022-02-16  298.369995  300.869995  293.679993  299.500000  299.500000
2022-02-17  296.359985  296.799988  290.000000  290.730011  290.730011
2022-02-18  293.049988  293.859985  286.309998  287.929993  287.929993

DataFrame의 기본 구조 탐색

DataFrame의 인덱스와 컬럼 정보를 확인해 봅시다:

print(sec.index)

출력 결과:

DatetimeIndex(['2018-05-04', '2018-05-08', '2018-05-09', '2018-05-10',
               '2018-05-11', '2018-05-14', '2018-05-15', '2018-05-16',
               '2018-05-17', '2018-05-18',
               ...
               '2022-02-09', '2022-02-10', '2022-02-11', '2022-02-14',
               '2022-02-15', '2022-02-16', '2022-02-17', '2022-02-18',
               '2022-02-21', '2022-02-22'],
              dtype='datetime64[ns]', name='Date', length=935, freq=None)
print(sec.columns)

출력 결과:

Index(['Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume'], dtype='object')

데이터 분석과 가공

yfinance로 가져온 데이터는 표준 pandas DataFrame이므로, pandas의 모든 기능을 활용하여 다양한 분석과 가공이 가능합니다.

기본 통계 정보 확인하기

# 기본 통계 정보
print(sec.describe())

출력 결과:

              Open         High          Low        Close    Adj Close         Volume
count   935.000000   935.000000   935.000000   935.000000   935.000000  9.350000e+02
mean  62272.486631  62991.168984  61518.237433  62257.593583  59424.953440  1.862924e+07
std   14584.926127  14672.183335  14504.968421  14614.022756  15599.916985  1.061837e+07
min   41550.000000  42300.000000  41000.000000  41800.000000  41800.000000  3.157900e+06
25%   51300.000000  51900.000000  50800.000000  51400.000000  48127.427734  1.197267e+07
50%   58000.000000  58600.000000  57400.000000  58000.000000  54653.832031  1.573842e+07
75%   73800.000000  74500.000000  72900.000000  73500.000000  70732.031250  2.211126e+07
max   92000.000000  92800.000000  90100.000000  91000.000000  91000.000000  1.188622e+08

이동평균 계산하기

주가 분석에서 자주 사용되는 이동평균을 계산해 봅시다:

# 20일, 60일 이동평균 계산하기
sec['MA20'] = sec['Close'].rolling(window=20).mean()
sec['MA60'] = sec['Close'].rolling(window=60).mean()

print(sec[['Close', 'MA20', 'MA60']].tail(10))

출력 결과:

                Close        MA20        MA60
Date                                         
2022-02-09  75200.0  75675.0000  74991.6667
2022-02-10  75300.0  75455.0000  74893.3333
2022-02-11  74800.0  75240.0000  74788.3333
2022-02-14  73900.0  74975.0000  74670.0000
2022-02-15  74500.0  74755.0000  74605.0000
2022-02-16  73500.0  74490.0000  74513.3333
2022-02-17  72300.0  74160.0000  74386.6667
2022-02-18  72300.0  73875.0000  74286.6667
2022-02-21  72300.0  73625.0000  74193.3333
2022-02-22  71700.0  73360.0000  74080.0000

일별 수익률 계산하기

# 일별 수익률 계산하기
sec['Daily Return'] = sec['Close'].pct_change() * 100
print(sec[['Close', 'Daily Return']].tail())

출력 결과:

                Close  Daily Return
Date                               
2022-02-16  73500.0      -1.342282
2022-02-17  72300.0      -1.632653
2022-02-18  72300.0       0.000000
2022-02-21  72300.0       0.000000
2022-02-22  71700.0      -0.829876

데이터 시각화하기

matplotlib을 사용하여 주가 데이터를 시각화해 봅시다:

import matplotlib.pyplot as plt
import yfinance as yf

# Get data directly using yf.download
sec = yf.download('005930.KS', start='2018-05-04')
msft = yf.download('MSFT', start='2018-05-04')

plt.figure(figsize=(12, 6))
plt.plot(sec.index, sec.Close, 'b', label='Samsung Electronics')
plt.plot(msft.index, msft.Close, 'r--', label='Microsoft')
plt.title('Stock Price Comparison: Samsung vs Microsoft')
plt.xlabel('Date')
plt.ylabel('Price (Local Currency)')
plt.legend(loc='best')
plt.grid(True)
plt.show()
Stock Price Comparison

위 그래프는 2018년 5월부터 현재까지 삼성전자와 마이크로소프트의 종가를 비교한 것입니다. 삼성전자는 원화로, 마이크로소프트는 달러로 표시되어 있어 직접적인 비교는 어렵지만, 각 회사의 가격 추세를 확인할 수 있습니다.

좀 더 의미 있는 비교를 위해 두 회사의 주가를 첫 날 가격 대비 상대적 변화로 정규화해 봅시다:

import matplotlib.pyplot as plt
import yfinance as yf

# Get data directly using yf.download
sec = yf.download('005930.KS', start='2018-05-04')
msft = yf.download('MSFT', start='2018-05-04')

sec_norm = sec.Close / sec.Close.iloc[0] * 100
msft_norm = msft.Close / msft.Close.iloc[0] * 100

plt.figure(figsize=(12, 6))
plt.plot(sec.index, sec_norm, 'b', label='Samsung Electronics')
plt.plot(msft.index, msft_norm, 'r--', label='Microsoft')
plt.title('Normalized Stock Performance (First day = 100)')
plt.xlabel('Date')
plt.ylabel('Normalized Price')
plt.legend(loc='best')
plt.grid(True)
plt.show()
Normalized Stock Performance

이제 두 회사의 상대적 성과를 더 명확하게 비교할 수 있습니다. 마이크로소프트가 해당 기간 동안 삼성전자보다 더 높은 성장률을 보인 것을 확인할 수 있습니다.

거래량 분석하기

거래량도 중요한 지표입니다. 삼성전자의 거래량을 시각화해 봅시다:

import matplotlib.pyplot as plt
import yfinance as yf
import pandas as pd

# 데이터 다운로드
sec = yf.download('005930.KS', start='2025-04-01')

# 그래프 생성
fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, figsize=(12, 10))

# 종가 그래프
sec['Close'].plot(ax=ax1)
ax1.set_title('Samsung Electronics Stock Price')
ax1.set_ylabel('Price (KRW)')
ax1.grid(True)

# 거래량 그래프 - width 파라미터 추가
sec['Volume'].plot(kind='bar', ax=ax2, color='g', alpha=0.5, width=1.0)
ax2.set_title('Trading Volume')
ax2.set_ylabel('Volume')
ax2.grid(True)

# x축 레이블 조정
ax2.set_xticklabels(sec.index.strftime('%Y-%m-%d'), rotation=45)
# 바 그래프의 x축 범위 조정
ax2.set_xlim(-1, len(sec))

plt.tight_layout()
plt.show()
Trading Volume

이 그래프에서 주가 변동과 거래량 사이의 관계를 볼 수 있습니다. 일반적으로 중요한 가격 변동은 높은 거래량과 함께 나타나는 경향이 있습니다.

yfinance를 사용한 추가 정보 수집

yfinance는 주가 데이터 외에도 회사의 기본 정보, 재무제표 등 다양한 정보를 제공합니다. 삼성전자에 대한 추가 정보를 살펴봅시다:

# Ticker 객체 생성
samsung = yf.Ticker('005930.KS')

# 회사 기본 정보
print(samsung.info['longName'])  # 회사명
print(samsung.info['sector'])    # 섹터
print(samsung.info['industry'])  # 산업

# 최근 뉴스
print(samsung.news)

# 주요 주주 정보
print(samsung.institutional_holders)

# 재무제표 요약
print(samsung.financials)

기술적 분석 지표 계산하기

투자 분석에 자주 사용되는 몇 가지 기술적 분석 지표를 계산해 봅시다:

import matplotlib.pyplot as plt
import yfinance as yf
import pandas as pd

# 데이터 다운로드
sec = yf.download('005930.KS', start='2018-05-04')
msft = yf.download('MSFT', start='2018-05-04')


# RSI(Relative Strength Index) 계산 함수
def compute_rsi(data, window=14):
    diff = data.diff()
    up = diff.clip(lower=0)
    down = -1 * diff.clip(upper=0)

    ma_up = up.rolling(window=window).mean()
    ma_down = down.rolling(window=window).mean()

    rsi = ma_up / (ma_up + ma_down) * 100
    return rsi


# 볼린저 밴드 계산
sec['MA20'] = sec['Close'].rolling(window=20).mean()  # 20일 이동평균
sec['Std20'] = sec['Close'].rolling(window=20).std()  # 20일 표준편차
sec['Upper'] = sec['MA20'] + (sec['Std20'] * 2)  # 상단 밴드
sec['Lower'] = sec['MA20'] - (sec['Std20'] * 2)  # 하단 밴드

# RSI 계산
sec['RSI'] = compute_rsi(sec['Close'])

# 볼린저 밴드 시각화
plt.figure(figsize=(12, 6))
plt.plot(sec.index, sec.Close, 'b', label='Close')
plt.plot(sec.index, sec.MA20, 'k--', label='MA20')
plt.plot(sec.index, sec.Upper, 'r-', label='Upper Band')
plt.plot(sec.index, sec.Lower, 'g-', label='Lower Band')
plt.fill_between(sec.index, sec.Upper, sec.Lower, color='lightgray', alpha=0.4)
plt.title('Bollinger Bands for Samsung Electronics')
plt.legend(loc='best')
plt.grid(True)
plt.show()
Bollinger Bands

여러 회사 한번에 데이터 가져오기

여러 회사의 데이터를 한 번에 가져오려면 다음과 같이 할 수 있습니다:

import matplotlib.pyplot as plt
import yfinance as yf
import pandas as pd

# 여러 회사의 티커 리스트
tickers = ['005930.KS', 'MSFT', 'GOOG', 'AAPL']

# 데이터 가져오기
data = yf.download(tickers, start='2020-01-01')

# 종가 데이터만 선택
close_data = data['Close']

# 시각화
plt.figure(figsize=(14, 7))
for ticker in tickers:
    plt.plot(close_data.index, close_data[ticker]/close_data[ticker].iloc[0]*100, label=ticker)

plt.title('Stock Performance Comparison (2020-01-01 = 100)')
plt.xlabel('Date')
plt.ylabel('Normalized Price (%)')
plt.legend()
plt.grid(True)
plt.show()
Stock Performance Comparison

결론

이 포스트에서는 pandasyfinance를 사용하여 주식 데이터를 가져오고 분석하는 기본적인 방법을 살펴보았습니다. 이러한 도구들을 통해 주가 데이터를 다양한 방식으로 시각화하고 분석할 수 있습니다.

Python의 강력한 데이터 분석 라이브러리를 활용하면, 복잡한 금융 분석도 몇 줄의 코드로 쉽게 수행할 수 있습니다. 더 나아가 머신러닝 기법을 접목하여 주가 예측 모델을 만들거나, 포트폴리오 최적화 알고리즘을 구현할 수도 있습니다.

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤