본문 바로가기
파이썬(Python)으로 데이터 기반 주식 퀀트 투자하기/chapter4 백테스팅 알고리즘 트레이딩 정복하기 전략

chapter4 알고리즘 트레이딩 정복하기-백테스팅 이유/기초백테스팅 모델 개발-(슬리피지 적용x)

by ohsungjun 2026. 1. 27.

매매 시그널과 정량 지표만 계산해선
실제 “돈을 벌었는지 / 얼마나 위험했는지”를 알 수 없어서
그걸 계산하려고 백테스팅을 하는 거다.

 

왜 정량 지표만으로는 부족하냐면

네가 지금 한 것:

  • 이동평균
  • n일 최저가
  • 매수 시그널 (buy_sample)

이건 전부 👇
“언제 살까?”에 대한 조건이야.

하지만 아직 모르는 게 많아 ❌

❌ 알 수 없는 것들

  • 실제로 수익이 났는지
  • 총 수익률이 얼마인지
  • 중간에 얼마나 크게 빠졌는지 (리스크)
  • 몇 번 사고팔았는지
  • 운이 좋은 건지, 전략이 좋은 건지

그래서 필요한 게 백테스팅 🔁

백테스팅이 해주는 것

과거 데이터로 실제 매매를 흉내

“이 날 사고 → 이 조건에서 팔았으면
계좌가 어떻게 변했을까?”

백테스팅을 하면 계산 가능한 것들 📊

1️⃣ 수익률

  • 누적 수익률
  • 연평균 수익률 (CAGR)

2️⃣ 리스크

  • 최대 낙폭 (MDD)
  • 변동성
  • 손실 구간 길이

3️⃣ 전략 품질

  • 승률
  • 손익비
  • Sharpe Ratio

👉 이게 정량 지표만으로는 절대 안 나오는 것들

 

이번에 단일 종목 백체스팅을 할거임 왜냐면 속도가 빠르고 구조가 간단해서, 지금은 퀀트 트레이딩 기초다지기 이기에

깃허브에 상용 백테스팅 툴이 다수 존재함 backTEST 파이썬 ,c++ 등 문서화가 많이 되어있음 

최적화, 실거래 바로 다룰 수 있는 것도 많음 

하지만, 개인이 직접 백테스팅 툴을 만들어봐야함

나에게 맞춘 디테일한 기능을 개발이 필요함

 

벡매 시그널과 정량 지표만 계산해선

실제 “돈을 벌었는지 / 얼마나 위험했는지”를 알 수 없어서

그걸 계산하려고 백테스팅을 하는 거다.

 

 

 



왜 정량 지표만으로는 부족하냐면

네가 지금 한 것:

 

이동평균

n일 최저가

매수 시그널 (buy_sample)

이건 전부 👇

“언제 살까?”에 대한 조건이야.

 

하지만 아직 모르는 게 많아 ❌

 

❌ 알 수 없는 것들

실제로 수익이 났는지

총 수익률이 얼마인지

중간에 얼마나 크게 빠졌는지 (리스크)

몇 번 사고팔았는지

운이 좋은 건지, 전략이 좋은 건지

그래서 필요한 게 백테스팅 🔁

백테스팅이 해주는 것

과거 데이터로 실제 매매를 흉내 냄

 

“이 날 사고 → 이 조건에서 팔았으면

계좌가 어떻게 변했을까?”

 

백테스팅을 하면 계산 가능한 것들 📊

1️⃣ 수익률

누적 수익률

연평균 수익률 (CAGR)

2️⃣ 리스크

최대 낙폭 (MDD)

변동성

손실 구간 길이

3️⃣ 전략 품질

승률

손익비

Sharpe Ratio

👉 이게 정량 지표만으로는 절대 안 나오는 것들

 

 

 

이번에 단일 종목 백체스팅을 할거임 왜냐면 속도가 빠르고 구조가 간단해서, 지금은 퀀트 트레이딩 기초다지기 이기에

 

깃허브에 상용 백테스팅 툴이 다수 존재함 backTEST 파이썬 ,c++ 등 문서화가 많이 되어있음 

 

최적화, 실거래 바로 다룰 수 있는 것도 많음 

 

하지만, 개인이 직접 백테스팅 툴을 만들어봐야함

 

나에게 맞춘 디테일한 기능을 개발이 필요함

 

 

📈 백테스팅 모듈 구축 5단계 프로세스

1. 데이터 로드 (Data Ingestion)

  • 실습 데이터셋 불러오기: 과거 가격 데이터(Open, High, Low, Close, Volume)를 준비합니다.
  • 데이터 무결성 확인: 결측치나 오류 데이터가 있는지 확인하여 분석의 정확도를 높입니다.

2. 피처 엔지니어링 (Feature Engineering)

  • 변수 생성: 백테스팅의 판단 근거가 될 지표를 계산합니다.
    • 예: 이동평균선(MA), RSI, 볼린저 밴드 등.
  • 데이터 구조 변경: 매 시점(Row)마다 지표를 참조할 수 있도록 데이터프레임에 열(Column) 형태로 추가합니다.

3. 반복문 기반 시뮬레이션 (Loop Simulation)

  • 시점 이동: for 반복문을 사용하여 시간 순서대로 한 시점(Time-step)씩 이동하며 장을 시뮬레이션합니다.
  • Look-ahead Bias 방지: 현재 시점에서는 '미래의 데이터'를 알 수 없도록 엄격히 통제하며 진행합니다.

4. 매매 로직 및 계좌 관리 (Execution Logic)

  • 상태 변수 업데이트: Holding(보유 수량), Cash(현금 잔고) 변수를 실시간으로 갱신합니다.
  • 수익률 기록: 매수/매도 시그널에 따라 거래를 체결하고, 매일매일의 **일별 수익률(Daily Return)**을 리스트에 저장합니다.

5. 결과 분석 및 시각화 (Reporting)

  • 최종 모듈 완성: 전체 과정을 하나의 함수나 클래스로 캡슐화합니다.
  • 성과 지표 계산: 누적 수익률, MDD(최대 낙폭), 샤프 지수 등을 산출합니다.
  • 그래프 출력: 시간에 따른 자산 곡선(Equity Curve)을 시각화하여 전략의 유효성을 최종 판단합니다.

Tip: 백테스팅 시 **슬리피지(Slippage)**나 거래 수수료 변수를 추가하면 훨씬 더 현실적이고 냉정한 결과를 얻으실 수 있습니다.

백테스팅 코드

이번엔 슬리피지 설정하지않고, 3가지 변수만

holding_cash = 1_000_000 # 보유 현금 100만원
position = 0 # 현재 보유 포지션 지금 갖고있는 주식곗수 
avg_price = 0 # 평단가 보유하고있는 포지션없다면 0
 
daily_total_value = [] # 일별 총 포트폴리오 가치 일별 수익률 포트폴리오 라고 보면
 
#백테스팅 관계없이 항상 사용됨

 

for idx,data in d.iterrows(): #iterrows()함수는 

0과 1의 로우로 이루어진 튜플형태로 바꿔짐 0은 인덱스 값,

 

  • idx (Index): 튜플의 첫 번째 요소입니다. 해당 행의 이름(날짜 등)이나 번호가 들어갑니다. 
  • data (Series): 튜플의 두 번째 요소입니다. 해당 행의 모든 컬럼 값들이 Pandas Series 형태로 들어있습니다.

 

holding_cash = 1_000_000 # 보유 현금
position = 0 # 현재 보유 포지션
avg_price = 0 # 평단가
daily_total_value = [] # 일별 총 포트폴리오 가치

for idx,data in d.iterrows():
    daily_total_value.append(0) #첫번째

#매수조건 확인 및 매수 전략: 종가20일 포지션이없을때 매수를 하는거임olding_cash = 1_000_000 # 보유 현금
position = 0 # 현재 보유 포지션
avg_price = 0 # 평단가
daily_total_value = [] # 일별 총 포트폴리오 가치

for idx,data in d.iterrows():
  # 작성하신 for idx, data in d.iterrows():에서 각각의 역할은 이렇습니다.

# idx (Index): 튜플의 첫 번째 요소입니다. 해당 행의 이름(날짜 등)이나 번호가 들어갑니다.

# data (Series): 튜플의 두 번째 요소입니다. 해당 행의 모든 컬럼 값들이 Pandas Series 형태로 들어있습니다.

# 사용할 때는 data['Close'] 처럼 컬럼명으로 값을 꺼내 쓰면 됩니다.
    daily_total_value.append(0)
    #append(0)
# 백테스팅을 시작하는 **'첫 번째 시점(Day 0)'**에는 아직 거래가 일어나지 않았거나, 수익률을 계산할 "어제의 데이터"가 없기 때문입니다. 구체적으로는 다음과 같은 이유들 때문입니다.

# 1. 초기값 설정 (Placeholder)
# 백테스팅을 시작하는 바로 그 순간, 계좌의 총 가치 변화량이나 수익률은 0에서 시작합니다.

# 리스트의 인덱스를 날짜와 맞추기 위해 **"0일 차의 수익률은 0이다"**라는 기준점을 먼저 찍어두는 것입니다.

# 2. 수익률 계산의 기준점
# 수익률은 보통 (오늘 가치 - 어제 가치) / 어제 가치로 계산합니다.

# 하지만 첫 번째 루프(Day 1)에서는 비교할 **'어제의 가치'**가 리스트에 들어있지 않으면 에러가 발생할 수 있습니다.

# 미리 0을 넣어둠으로써, 다음 날부터 계산되는 수익률 데이터들과 리스트 길이를 맞추는(Alignment) 역할을 합니다.
    #매수조건 확인 및 매수 전략: 종가20일 포지션이없을때 매수를 하는거임
    if data['close'] < data['20d_mean'] and position == 0: #포지션이 0인경우 매수하겠다
        holding_cash -= 1 * data['close'] #한주의 가격만큼 보유현금에서 빠짐
        position += 1
        avg_price = data['close'] #오늘 종가를샀으니, 평단가가 됨

    elif position > 0: #어제 산 경우, 매도 경우 청산할때
        holding_cash += position * data['close']  #청산하니까 돈이 들어겠지 보유현금holding_cash= position현재 보유 포지션 내가 가진주식 *에다가 종가를 곱한 값이 매도한 금액임

        position = 0 #포지션은 다 매도해서(다 팔아서 0임)
        avg_price = 0 #다팔아서 0

    daily_total_value[-1] += holding_cash + position * data['close']  #장마감 끝날때를 말함 장마감 후 작업
    #포트폴리오 총평가치 =내가가진 돈+내가가진 주식포지션+당일 종가가격

 

daily_total_value #백스테스킹이완료된 후  daily_total_value 실행하면 일별 수익률 값이다->이걸을 플러팅 해야함

백테스팅을 통해 얻은 daily_total_value 데이터를 시각화(Plotting)하는 가장 대중적인 방법은 파이썬의 Matplotlib 라이브러리를 사용하는 것입니다.

질문하신 내용처럼 **일별 수익률(또는 총 자산의 변화)**을 그래프로 그리면 내 전략이 우상향하는지 한눈에 확인할 수 있습니다.

19.4.33.2진짜 간단한 백테스팅 툴 개발=벡테스팅 결과_일별 수익률 값.mp4
6.55MB