Quant

Backtest를 위한 python sample code

gt.kim28 2023. 5. 9. 10:24
반응형

backtest는 특정 거래 전략이 과거의 주가 데이터에서 어떻게 작동했는지를 시뮬레이션하는 과정입니다. 글에서는 Python 사용하여 backtest 수행하는 간단한 방법을 소개합니다. 예제에서는 이동평균 전략(Moving Average Strategy) 기반으로 backtest 진행합니다.

 

데이터 가져오기

Yahoo Finance에서 주가 데이터를 가져옵니다.

import yfinance as yf

def get_data(ticker, start_date, end_date):
    stock_data = yf.download(ticker, start=start_date, end=end_date)
    return stock_data

이동평균 전략 구현

이동평균 전략을 구현한 함수를 작성합니다.

이동평균 전략(Moving Average Strategy) 함수는 주식 데이터를 사용하여 이동평균에 기반한 거래 신호를 생성하는 역할을 합니다. 다음은 이동평균 전략 함수의 코드와 각 부분에 대한 설명입니다.

이번 포스트에서는 short_window는 40, long_window는 100을 사용할 예정이고,

short_window 이평선이 long_window 넘어설 경우 매수 signal = 1 설정, 반대의 경우에는 signal = 0으로 설정합니다.

import pandas as pd

def moving_average_strategy(data, short_window, long_window):
    signals = pd.DataFrame(index=data.index)
    signals['signal'] = 0.0

    signals['short_mavg'] = data['Close'].rolling(window=short_window, min_periods=1, center=False).mean()
    signals['long_mavg'] = data['Close'].rolling(window=long_window, min_periods=1, center=False).mean()

    signals['signal'][short_window:] = np.where(signals['short_mavg'][short_window:] > signals['long_mavg'][short_window:], 1.0, 0.0)
    signals['positions'] = signals['signal'].diff()

    return signals

backtest 실행

def backtest(data, signals, initial_capital):
    positions = pd.DataFrame(index=signals.index).fillna(0.0)
    portfolio = pd.DataFrame(index=signals.index).fillna(0.0)

    # 포지션 계산
    positions['stock'] = 100 * signals['signal']

    # 포트폴리오 가치 계산
    portfolio['positions'] = (positions.multiply(data['Close'], axis=0))
    portfolio['cash'] = initial_capital - (positions.diff().multiply(data['Close'], axis=0)).cumsum()
    portfolio['total'] = portfolio['positions'] + portfolio['cash']

    return portfolio

시각화

import matplotlib.pyplot as plt

def plot_backtest_result(portfolio, initial_capital):
    fig, ax = plt.subplots(figsize=(12, 6))

    portfolio['total'].plot(ax=ax, label='Portfolio Total Value')
    ax.axhline(y=initial_capital, color='r', linestyle='--', label='Initial Capital')

    ax.set(title='Backtest Result', ylabel='Portfolio Value')
    ax.legend(loc='best')

    plt.show()

결과 출력

def print_return_percentage(data, portfolio, initial_capital):
    final_portfolio_value = portfolio['total'].iloc[-1]
    profit_percentage = ((final_portfolio_value - initial_capital) / initial_capital) * 100

    print(f"Backtest Period: {start_date} to {end_date}")
    print(f"Initial Capital: {initial_capital}")
    print(f"Final Portfolio Value: {final_portfolio_value}")
    print(f"Return Percentage: {profit_percentage:.2f}%")

실행

## 백테스트 실행 및 결과 확인

ticker = 'AAPL'
start_date = '2020-01-01'
end_date = '2023-04-30'
short_window = 40
long_window = 100
#initial_capital은 초기자본이고, 여기는 주식 데이터의 통화와 맞게 10만달러로 설정합니다.
initial_capital = 100000.0

data = get_data(ticker, start_date, end_date)
signals = moving_average_strategy(data, short_window, long_window)
portfolio = backtest(data, signals, initial_capital)

plot_backtest_result(portfolio, initial_capital)
print_return_percentage(data, portfolio, initial_capital)

결과

[*********************100%***********************]  1 of 1 completed
Backtest Period: 2021-01-01 to 2023-04-30
Initial Capital: 100000.0
Final Portfolio Value: 102855.99899291992
Return Percentage: 2.86%

시각화 결과

반응형