파이썬 주식 데이터 분석, CSV 불러오기부터 수익률 계산까지
파이썬으로 주식 데이터를 분석하려면 CSV 파일을 불러온 뒤 날짜를 정렬하고, 중복 데이터와 빈칸을 확인한 다음 수익률을 계산하면 됩니다. pandas를 사용하면 이 과정을 순서대로 처리할 수 있습니다. 이 글에서는 단일 종목의 일별 주가 CSV를 기준으로 설명합니다. 파일을 불러오는 방법부터 데이터 점검, 하루 수익률과 누적수익률 계산까지 따라 할 수 있도록 구성했습니다.
준비물은 파이썬 실행 환경과 주가 CSV 파일입니다. pandas와 numpy가 설치되어 있어야 하며, 아래 코드는 같은 노트북이나 실행 세션에서 순서대로 실행하세요.
1. pandas로 주가 CSV 파일 불러오기
CSV는 데이터를 쉼표로 구분해 저장한 파일입니다. 엑셀로도 열 수 있고, 파이썬에서는 pandas의 read_csv()로 불러올 수 있습니다.
먼저 파일에 어떤 열이 있는지 확인하세요. 아래 실습은 다음 열 이름을 기준으로 합니다.
| 열 이름 | 의미 | 분석 전 확인할 내용 |
|---|---|---|
| Date | 거래일 | 날짜 형식 |
| Open | 시가 | 가격 단위와 숫자 형식 |
| High | 고가 | 저가와의 관계 |
| Low | 저가 | 고가와의 관계 |
| Close | 종가 | 빈칸과 비정상적인 가격 |
| Volume | 거래량 | 빈칸과 음수 |
데이터 제공처에 따라 열 이름이 날짜, 종가, 거래량 등으로 표시될 수 있습니다. 아래 코드를 적용하려면 Date와 Close라는 열이 있어야 합니다.
pandas가 설치되어 있지 않다면 터미널에서 다음 명령을 실행합니다.
python -m pip install pandas numpy
이제 CSV 파일을 불러옵니다.
import pandas as pd
import numpy as np
csv_path = input()
df = pd.read_csv(csv_path)
print(df.head())
print(df.columns)
print(df.dtypes)
입력창이 나타나면 CSV 파일의 경로를 입력하세요. 예를 들어 실행 위치에 파일이 있다면 stock_data.csv를 입력하면 됩니다.
df.head()는 처음 5개 행을 보여줍니다. df.columns는 열 이름, df.dtypes는 각 열의 데이터 형식을 보여줍니다.
파일을 찾을 수 없다는 오류가 발생하면 파일명과 경로를 확인하세요. 한글이 깨지거나 인코딩 오류가 발생하면 원본 파일의 인코딩을 확인해야 합니다. 이 예시는 UTF-8로 읽을 수 있는 CSV를 기준으로 합니다.
파일을 정상적으로 읽었다면 분석 전에 원본을 복사해둡니다.
original_df = df.copy()
원본 CSV도 그대로 보관하세요. 처리 후 값이 달라졌을 때 비교할 기준이 됩니다.
2. 날짜 정렬과 중복 데이터 확인하기
수익률은 이전 가격과 현재 가격을 비교해 계산합니다. 따라서 날짜가 뒤섞여 있으면 계산 결과도 잘못될 수 있습니다.
예를 들어 수요일, 월요일, 화요일 순으로 저장된 주가를 그대로 계산하면 시간 흐름에 맞는 수익률이 나오지 않습니다.
날짜 열을 날짜 형식으로 바꾸고, 날짜를 기준으로 정렬하세요.
df.Date = pd.to_datetime(df.Date)
if df.Date.isna().any():
raise ValueError
df = df.set_index(df.Date)
df = df.sort_index()
print(df.head())
print(df.index.is_monotonic_increasing)
마지막 결과가 True이면 날짜가 오름차순으로 정렬됐다는 뜻입니다.
날짜 변환 과정에서 오류가 발생하거나 빈 날짜 때문에 실행이 멈추면, 원본 파일에서 날짜 표기를 확인하세요. 날짜를 임의로 추정해 넣기보다 원본 제공처와 비교하는 것이 우선입니다.
다음은 같은 날짜가 여러 번 들어 있는지 확인하는 코드입니다.
duplicate_rows = df.loc[
df.index.duplicated(keep=False)
]
print(duplicate_rows)
단일 종목의 일별 데이터라면 일반적으로 거래일마다 한 행이 있어야 합니다. 중복된 날짜가 출력되면 가격과 거래량이 같은지 확인하세요.
| 중복 상황 | 처리 방향 |
|---|---|
| 같은 행이 반복 수집됨 | 원본과 비교 후 중복 제거 |
| 같은 날짜인데 가격이 다름 | 제공처에서 올바른 값 확인 |
| 여러 종목이 섞여 있음 | 종목별로 분리해 분석 |
| 분봉 데이터가 들어 있음 | 날짜와 시간을 함께 구분 |
중복의 원인을 해결한 뒤 다음 조건을 확인합니다.
if df.index.duplicated().any():
raise ValueError
이 코드가 멈춘다면 중복 거래일이 아직 남아 있다는 뜻입니다. 확인 없이 첫 번째 행만 남기는 방식으로 처리하지 마세요.
3. 빈칸과 급등락한 가격 점검하기
데이터의 빈칸을 결측치라고 합니다. pandas에서는 주로 NaN으로 표시됩니다.
어느 열에 빈칸이 있는지 확인하세요.
print(df.isna().sum())
종가를 숫자로 변환하고, 0 이하의 값이 있는지도 확인합니다.
df.Close = pd.to_numeric(df.Close)
invalid_prices = df.loc[
df.Close.le(0)
]
print(invalid_prices)
if not invalid_prices.empty:
raise ValueError
숫자 변환 오류가 발생하면 종가 열에 쉼표, 통화 기호, 문자 등이 섞여 있는지 확인해야 합니다. 해당 제공처의 표기 규칙에 맞춰 정리하세요.
빈칸이 있다고 이전 값으로 무조건 채우면 안 됩니다.
| 데이터 상태 | 권장 확인 방법 |
|---|---|
| 주말·휴장일의 행이 없음 | 거래일 기준 데이터라면 그대로 유지 |
| 정상 거래일의 종가가 비어 있음 | 원본에서 재확인하거나 재수집 |
| 거래량이 비어 있음 | 이전 거래량을 복사하지 말고 원인 확인 |
| 거래정지 기간의 행이 없음 | 거래정지 여부와 제공처 처리 방식 확인 |
거래일 기준 데이터에는 주말 행이 없는 것이 자연스럽습니다. 금요일과 월요일 사이에 임의의 가격을 만들어 넣을 필요는 없습니다.
반면 화요일 종가가 누락된 상황에서 수요일 종가로 화요일을 채우면, 화요일에는 알 수 없었던 미래 가격을 사용하게 됩니다. 예측모델이나 백테스트에서는 이런 미래 정보 누수를 피해야 합니다.
pandas의 ffill()은 이전 값을 전달하고, bfill()은 뒤에 있는 값을 앞의 빈칸에 전달합니다. 기능을 사용할 수 있다는 것과 해당 데이터에 적절하다는 것은 별개의 판단입니다. pandas.pydata.org
급등락한 가격도 원인을 확인해야 합니다. 주식분할 때문에 주당 가격이 낮아진 상황을 실제 투자 손실로 계산하면 분석이 왜곡됩니다.
예를 들어 1주를 2주로 나누는 주식분할이 발생하면 주당 가격이 대략 절반으로 낮아질 수 있습니다. 보유 주식 수의 변화까지 함께 봐야 합니다.
수익률을 계산하기 전에 가격의 조정 기준을 확인하세요.
데이터 제공처의 수정주가가 주식분할과 배당을 어떻게 반영하는지 확인하고, 분석 기간 전체에 일관된 기준을 적용해야 합니다. 아래 실습에서는 Close 열이 분석 목적에 맞는 가격이라고 가정합니다.
4. 하루 수익률과 누적수익률 계산하기
단순수익률은 이전 가격보다 현재 가격이 얼마나 변했는지 나타냅니다.
단순수익률 = 현재 가격 ÷ 이전 가격 − 1
가격이 100에서 105로 올랐다면 수익률은 0.05, 즉 5%입니다.
pandas에서는 pct_change()로 계산합니다.
df = df.assign(
simple_return=df.Close.pct_change(
fill_method=None
)
)
print(df.simple_return.mul(100).head())
pct_change()는 퍼센트로 표시된 숫자가 아닌 상대적인 변화량을 반환합니다. 따라서 0.05를 5로 표시하려면 100을 곱합니다. pandas.pydata.org
fill_method=None은 수익률 계산 과정에서 빈 가격을 임의로 채우지 않도록 설정한 것입니다.
첫 행에는 비교할 이전 가격이 없으므로 수익률이 비어 있는 것이 정상입니다. 종가가 누락됐다면 그 날짜와 다음 관측값의 수익률도 계산되지 않을 수 있습니다.

또한 여기서 계산되는 것은 이전 행과 현재 행 사이의 수익률입니다. 중간 거래일이 누락됐다면 반드시 하루 수익률이라고 볼 수는 없습니다.
다음은 계산을 이해하기 위한 가상의 가격 예시입니다.
| 거래일 | 종가 | 직전 거래일 대비 수익률 | 첫째 날 대비 누적수익률 |
|---|---|---|---|
| 첫째 날 | 100 | 계산 불가 | 0% |
| 둘째 날 | 110 | 10% | 10% |
| 셋째 날 | 99 | −10% | −1% |
100이 110으로 올랐다가 99로 떨어졌으므로 전체 기간의 수익률은 −1%입니다.
10%와 −10%를 단순히 더하면 0%가 되지만, 올바른 누적 계산은 다음과 같습니다.
누적수익률 = 1.10 × 0.90 − 1 = −1%
단일 종목을 처음부터 끝까지 보유한 가격 기준 누적수익률은 첫 가격과 현재 가격을 비교해 계산할 수 있습니다.
if df.Close.iloc[:1].isna().any():
raise ValueError
df = df.assign(
cumulative_return=(
df.Close / df.Close.iloc[0] - 1
)
)
print(
df.cumulative_return.mul(100).head()
)
이 코드는 첫 행의 가격을 기준으로 합니다. 첫 가격이 비어 있다면 기준 가격을 확인해야 하므로 실행을 멈추도록 했습니다.
결측치가 있는 구간의 수익률을 임의로 0으로 바꾼 뒤 누적하지 마세요. 누락 구간의 가격 변화를 없었던 것으로 처리할 수 있습니다.
로그수익률도 계산할 수 있습니다.
로그수익률 = ln(현재 가격 ÷ 이전 가격)
df = df.assign(
log_return=np.log(
df.Close / df.Close.shift(1)
)
)
result = pd.concat(
[
df.Close,
df.simple_return,
df.cumulative_return,
df.log_return
],
axis=1
)
print(result.head())
단순수익률과 로그수익률의 차이는 다음과 같습니다.
| 구분 | 단순수익률 | 로그수익률 |
|---|---|---|
| 계산 | 현재 가격 ÷ 이전 가격 − 1 | 가격 비율에 자연로그 적용 |
| 기간 누적 | 1에 수익률을 더한 값을 곱함 | 기간별 값을 더함 |
| 해석 | 투자금의 상대적 증감 | 가격 비율의 로그 변화 |
| 활용 | 투자 성과 설명 등에 활용 | 통계모형의 목적에 따라 활용 |
로그수익률을 더한 값은 누적 로그수익률입니다. 일반적인 누적수익률로 바꾸려면 지수함수를 적용한 뒤 1을 빼야 합니다.
로그수익률이 항상 더 정확하거나 유리한 것은 아닙니다. 독자에게 투자 성과를 설명할 때는 단순수익률이 직관적이고, 통계 분석에서는 모델 목적에 따라 로그수익률을 선택할 수 있습니다.
마지막으로 가격 기준 수익률과 실제 계좌 수익률을 구분하세요. 배당을 반영하지 않은 가격으로 계산하면 배당수익이 빠질 수 있으며, 수수료와 세금도 위 계산에 자동으로 포함되지 않습니다.
파이썬 주식 데이터 분석, CSV 불러오기부터 수익률 계산까지
5. 주식 데이터 분석에서 자주 묻는 질문
질문 1. CSV를 불러왔는데 Close 관련 오류가 발생합니다.
먼저 df.columns로 실제 열 이름을 확인하세요. 종가 열이 Close가 아니라 종가 또는 다른 이름으로 저장됐을 수 있습니다.
열 이름 앞뒤에 공백이 들어간 경우도 확인해야 합니다. 이 글의 코드는 Date와 Close 열이 존재하는 파일을 기준으로 합니다.
질문 2. 급락한 날짜를 삭제하면 분석 결과가 좋아지지 않나요?
실제 급락을 삭제하면 수익률과 위험이 현실보다 좋게 보일 수 있습니다. 급락은 투자자가 실제로 겪을 수 있는 시장 상황이므로 오류가 확인되지 않았다면 임의로 지우지 마세요.
입력 오류나 주식분할에 따른 가격 변화라면 원본과 가격 조정 기준을 확인해 수정합니다. 변동이 크다는 이유만으로 삭제하지 않는 것이 핵심입니다.
질문 3. 계산한 누적수익률을 백테스트 성과로 봐도 되나요?
이 글의 누적수익률은 첫 가격에서 매수해 계속 보유했다고 가정한 가격 변화입니다. 매매 신호에 따라 사고파는 전략의 백테스트 성과와는 다릅니다.
전략을 평가하려면 매수·매도 시점, 실제 체결 가능한 가격, 거래비용 등을 반영해야 합니다. 당일 종가를 확인해 만든 신호로 같은 종가에 거래할 수 있다고 가정하는 경우에도 실행 가능성을 점검해야 합니다.
분석 결과를 활용하기 전에는 다음 사항을 확인하세요.
- 단일 종목의 일별 데이터인지 확인했는가
- 날짜 순서와 중복 거래일을 점검했는가
- 빈칸과 0 이하의 가격을 확인했는가
- 누락된 거래일 때문에 관측 간격이 달라지지 않았는가
- 주식분할·배당과 가격 조정 기준을 확인했는가
- 누적수익률을 올바른 방식으로 계산했는가
- 원본 데이터와 처리 내역을 보관했는가
파이썬 주식 데이터 분석의 첫 단계는 복잡한 예측모델을 만드는 일이 아닙니다. CSV의 날짜와 가격을 확인하고, 계산한 수익률이 무엇을 반영하는지 이해하는 것부터 시작하세요.
금알남




댓글 0
첫 댓글을 남겨보세요.