[Data] #1 yfinance로 삼성전자 주가 데이터 수집하기

2026. 2. 4. 21:42·Data
이번 포스트에서는 yfinance를 이용해서 주가 데이터를 직접 수집하는 방법을 다룹니다.

 

들어가며

그동안 포트폴리오는 구글 스프레드시트로 관리해왔는데, 일부 종목은 가격 데이터가 누락되거나 업데이트가 늦어 전체 포트폴리오를 일관된 기준으로 관리하기 어렵다는 문제가 있었다.

 

이 문제를 해결하기 위해, 외부 도구에 의존하기보다는 주가 데이터를 직접 수집하고 관리하는 방식을 시도해보기로 했다. 이번 글에서는 "일단 가장 간단한 형태"로, 주가 데이터를 직접 수집하고 1/3/6/12개월 수익률을 계산하는 스크립트를 만들어본다.

 

주가 데이터 수집 방식 선택

주가 데이터를 수집하는 방법은 다양하다. 가장 대표적인 방법은 증권사 API를 사용하는 것인데, 안정성과 정확성 면에서는 장점이 있다. 다만, 인증 절차, 초기 설정 등 진입 비용이 비교적 큰 편이다.

 

우선 초기 단계인만큼 빠르게 실험하고 전체 흐름을 파악하는 것이 더 중요하기 때문에 Yahoo Finance 데이터를 SDK 형태로 제공하는 yfinance를 사용하기로 했다. 별도의 인증 없이도 원하는 기간의 데이터를 쉽게 가져올 수 있고, Pandas 기반 분석도 간편하다는 점에서 프로토타이핑 하는 데 가장 적합한 선택이라고 판단했다.

 

스크립트 구성: "데이터 수집 -> 수익률 계산 -> 결과 출력"

스크립트는 다음 세 단계로 구성되어 있다.

  1. fetch_price_data: 지정한 기간의 가격 데이터 수집
  2. calculate_returns: 종가(Close) 기준으로 기간 수익률 계산
  3. main: 실행 흐름 및 출력

yfinance로 1년치 데이터 수집

yfinance에서는 종목 코드(ticker)와 조회 기간을 지정하는 방식으로 데이터를 가져올 수 있다. 종목 코드는 네이버 증권에서 종목명을 검색하면 확인할 수 있고, 삼성전자의 종목 코드는 "005930"이다. 이를 yfinance에서 사용할 때는 한국거래소를 나타내는 ".KS"를 붙여야 한다.

df = yf.download("005930.KS", start="2025-01-01", end="2026-01-01")

 

 

수집된 데이터는 날짜를 인덱스로 하며, 시가(Open), 고가(High), 저가(Low), 종가(Close), 거래량(Volume) 등이 포함된다.

Price              Close          High           Low          Open    Volume
Ticker         005930.KS     005930.KS     005930.KS     005930.KS 005930.KS
Date                                                                        
2025-01-02  52272.527344  52468.304600  51195.752436  51587.306948  16630538
2025-01-03  53251.414062  53936.634464  51685.196002  51685.196002  19318046
2025-01-06  54719.746094  55013.411994  53153.527959  53251.416592  19034284
2025-01-07  54230.304688  56090.188783  54230.304688  55600.745600  17030235
2025-01-08  56090.187500  56285.964769  53545.083006  53642.971640  26593553

 

기간 수익률 계산에서 중요한 포인트: "정확히 n개월 전 데이터는 없을 수 있다"

수익률 계산식 자체는 간단하다. 

(현재 가격 / 과거 가격) - 1

 

하지만 실제 주가 데이터를 다루다 보면, 이 "과거 가격"을 정확히 찾는 것이 생각보다 까다롭다. 대표적인 이유는 다음과 같다.

1) 주말이나 공휴일로 거래가 없다

2) 신규 상장 종목이라면 특정 시점 이전 데이터가 존재하지 않을 수 있다.

 

즉, "정확히 N개월 전" 날짜의 주가 데이터가 없을 수 있다는 것이다. 이번 포스트에서는 삼성전자를 대상으로 하기 때문에 상장일 문제는 제외하고, 휴장일 문제만 고려해보자.

 

예제 데이터

import pandas as pd

data = {
    "Close": {
        "2026-01-01": 101,
        "2026-01-02": 102,
        # 2026-01-03: 없음 (휴일)
        "2026-01-06": 106,
        "2026-02-03": 203,
    }
}
df = pd.DataFrame(data)
df.index = pd.to_datetime(df.index)

 

수익률을 계산하기 위해 "2026-02-03"의 1개월 전 가격, 즉 "2026-01-03" 가격을 조회한다고 하자. 이때 .loc[]으로 접근하면 다음과 같이 KeyError가 발생한다.

past_price = df["Close"].loc["2026-01-03"]
# → KeyError: '2026-01-03'

 

이럴 때 .asof()를 사용하면 지정한 날짜 이전 중 가장 가까운 날짜의 값을 반환해준다. 이 기능 덕분에 휴일, 주말 등으로 인한 결측에도 에러 없이 수익률을 계산할 수 있다.

past_price = df["Close"].asof("2026-01-03")
print(past_price)  # 출력: 102.0 (2026-01-02의 종가)

 

최종 코드

import pandas as pd
import yfinance as yf


def fetch_price_data(ticker, start_date, end_date):
    return yf.download(tickers=ticker, start=start_date, end=end_date)


def calculate_returns(df, periods):
    close = df["Close"]

    latest_date = close.index.max()
    latest_price = close.loc[latest_date]
    earliest_date = close.dropna().index.min()

    returns = {}

    for label, offset in periods.items():
        past_date = latest_date - offset

        if past_date < earliest_date:
            returns[label] = float("nan")
            continue

        past_price = close.asof(past_date)
        returns[label] = (latest_price / past_price - 1) * 100

    return pd.DataFrame(returns)


def main():
    ticker = "005930.KS"
    start_date = "2025-01-01"
    end_date = "2026-02-03"

    periods = {
        "1m": pd.DateOffset(months=1),
        "3m": pd.DateOffset(months=3),
        "6m": pd.DateOffset(months=6),
        "12m": pd.DateOffset(months=12),
    }

    df = fetch_price_data(ticker, start_date, end_date)
    returns_df = calculate_returns(df, periods)

    print("\n📈 Period Returns (%)")
    print("-" * 30)
    print(returns_df.round(2).to_string())
    print("-" * 30)


if __name__ == "__main__":
    main()

 

실행 결과

📈 Period Returns (%)
------------------------------
              1m     3m      6m     12m
Ticker                                 
005930.KS  17.04  40.59  120.33  193.21
------------------------------

 

나가며

이번 포스트에서는 yfinance를 이용해 주가 데이터를 수집하고, 기간별 수익률을 계산하는 흐름을 살펴보았다. 다음 포스트에서는 이 스크립트를 기반으로, 여러 종목에 대한 수익률을 한번에 계산하고 비교할 수 있는 구조로 확장해볼 예정이다.

'Data' 카테고리의 다른 글

[Data] Data Engineering Zoomcamp 2주차  (0) 2026.02.03
[Data] Data Engineering Zoomcamp 1주차  (0) 2026.01.27
[Data] DE #100일챌린지 - Day 0: 시작  (0) 2025.10.31
'Data' 카테고리의 다른 글
  • [Data] Data Engineering Zoomcamp 2주차
  • [Data] Data Engineering Zoomcamp 1주차
  • [Data] DE #100일챌린지 - Day 0: 시작
cloudndata
cloudndata
cloudndata 님의 블로그 입니다.
  • 전체
    오늘
    어제
    • 분류 전체보기 (16)
      • Cloud (0)
      • Data (4)
        • Databricks (1)
        • Curation (3)
        • Spark (3)
        • Project (0)
      • CS (0)
      • PS (4)
      • Reading (0)
  • 태그

    데이터브릭스에서SQL
    데이터엔지니어링프로젝트
    PySpark
    데이터엔지니어
    DatabricksSQL
    데이터브릭스
    AI시대
    데이터엔지니어링
    100일챌린지
    leetcode
    de
    스파크
    Data Engineering Zoomcamp
    PS
    코딩테스트
    DataEngineering
    줌캠프
    문제풀이
    무료부트캠프
    DataEngineer
    dezoomcamp
    ProblemSolving
    알고리즘
    Zoomcamp
    ETL파이프라인
    코테준비
    데이터엔지니어미래
    AI미래
    Spark
    데엔
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
cloudndata
[Data] #1 yfinance로 삼성전자 주가 데이터 수집하기
상단으로

티스토리툴바