Sysmetic trading

[트레이딩] Optuna를 이용한 시스템 트레이딩 전략 최적화

quantoasis 2023. 4. 26. 18:21
반응형

 
 
 
최근 네이버블로거 백석꾼님께서 직장인 트레이딩 전략을 올려주시고 계시는데요.
 
다른 시스템트레이딩 블로거님들도 검증을 해주시고 계시는데, 놀랍게도 백테스팅 하시는 분마다 우상향 그래프를 뽑아내고 계시네요. 전략이 상당히 robustness한 것 같습니다.
 
저도 같은 전략을 백테스팅을 해봤는데요, 파이썬에 Optuna라는 라이브러리를 이용하여 전략의 파라미터를 최적화하는 과정도 추가하였습니다.
 
우선 백석꾼님이 올려주신 로직 그대로 백테스팅을 진행해봤습니다.
 
조건은 아래와 같습니다.

매수 조건 (1 or 2) and (3 or 4)
1번 조건: 당일 저가가 전일 저가보다 높음
2번 조건: 당일 거래량이 최근 3일의 거래량 이동평균보다 낮음
3번 조건: 이동평균선과 현재 가격의 이격도(20일 이동평균 사용)가 98 이하
4번 조건: 이동평균선과 현재 가격의 이격도(20일 이동평균 사용)가 106 이상

매도 조건 
매수조건이 False일때 매도

전략 실행 방법
매수 시: 매수 조건을 충족하는경우 'KODEX 레버리지'를 시장가로 매수주문을 걸어놓음.
매도 시: 매수 조건을 만족하지 않는 경우 매도를 결정

 
결과는 아래와 같습니다. 슬리피지를 0.3%나 제외했는데도 깔끔한 우상향을 그리는군요 ^^
 

 
 
이제 더 나아가 Optuna를 이용하여 파라미터를 최적화하기 전에 ChatGPT를 통해 optuna에 대해 물어봤습니다.
 
 

Optuna는 하이퍼파라미터 튜닝을 자동화하기 위한 오픈소스 프레임워크입니다.

하이퍼파라미터 튜닝은 모델의 성능을 높이기 위해 매우 중요합니다. 그러나 수동으로 튜닝하는 것은 매우 시간이 많이 걸리고 불안정하며 비효율적입니다. Optuna는 이러한 문제를 해결하기 위해 베이즈 최적화 알고리즘을 사용하여 효율적이고 자동화된 하이퍼파라미터 튜닝을 제공합니다.


Optuna를 사용하려면 약간의 코딩이 필요한데요, 우선 직장인 투자전략의 결과를 뽑아내는 함수를 만들어내겠습니다.
 

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

# 종목 코드와 기간 설정
symbol = '122630.KS'
start_date = '2010-01-01'
end_date = '2023-04-20'

df = yf.download(symbol, start=start_date, end=end_date)


def backtest(df, params):
    # 초기 자본금 설정
    initial_capital = 10000000

    final_capital = initial_capital
    final_capital_cur = initial_capital

    price_buy = 0
    price_sell = 0

    df['Asset'] = final_capital
    df['Asset_Cur'] = final_capital_cur

    # 전일, 전전일 저가, 거래량, 이격도 계산
    df['prev_low'] = df['Low'].shift(1)
    df['prev_prev_low'] = df['Low'].shift(2)
    df['prev_volume'] = df['Volume'].shift(1)
    df['avg_volume'] = df['Volume'].rolling(window=params['avg_vol']).mean()
    df['prev_close'] = df['Close'].shift(1)
    df['prev_ma'] = df['prev_close'].rolling(window=params['avg_ma']).mean()
    df['prev_dist'] = (df['prev_close'] - df['prev_ma']) / df['prev_ma'] * 100

    # 매수/매도 조건 설정
    buy_condition = ((df['prev_low'] > df['prev_prev_low']) | (df['prev_volume'] < df['avg_volume'])) & ((df['prev_dist'] < params['buy_dist']) | (df['prev_dist'] > params['sell_dist']))
    sell_condition = ~buy_condition

    # 매수/매도 시점 설정
    for i in range(1, len(df)):

        df['Asset'][i] = final_capital
        df['Asset_Cur'][i] = final_capital_cur

        if price_buy == 0 and buy_condition[i]:

            # 매수 조건을 만족하고 매수한 상태가 아니면 당일 시가에 매수
            price_buy = df['Open'][i]

        elif price_buy != 0 and sell_condition[i]:
            # 매도 조건을 만족하고 매수한 상태이면 당일 시가에 매도

            price_sell = df['Open'][i]
            profit = (price_sell - price_buy)*100/price_buy -0.03

            profit_money = initial_capital*profit/100
            final_capital += profit_money

            final_capital_cur = final_capital_cur*(profit+100)/100

            price_buy = 0


    final_capital = final_capital_cur

    # 남은 자산 계산
    profit = final_capital - initial_capital

    # 수익률 계산
    roi = profit / initial_capital * 100

    
    return roi

 
 
이번에는 옵튜나를 이용한 파라미터 튜닝 코드인데요 아래와 같습니다.
 

def objective(trial):
    # Hyperparameter 범위 설정
    buy_dist = trial.suggest_uniform('buy_dist', -15, 0)
    sell_dist = trial.suggest_uniform('sell_dist',0, 15)
    avg_vol  = trial.suggest_int('avg_vol',2, 10)
    avg_ma = trial.suggest_int('avg_ma',10, 35)
    params = {'buy_dist': buy_dist,
              'sell_dist': sell_dist,
              'avg_vol': avg_vol,
              'avg_ma': avg_ma
             }

    # 전략 수익률 계산
    roi = backtest(df, params)

    # 목적 함수 값 계산 (수익률 최대화)
    return roi

코드를 보면 감이 오시지 않나요?
 
buy_dist가 이격도를 -15부터 0까지 넣을거고,
sell_dist는 0부터 15를 넣을거고,
avg_vol은 2부터 10, avg_ma는 10부터 35를 넣어보면서 결과값을 뽑아내보겠다 이런의미입니다.
 
사람이 하던 노가다를 획기적으로 줄여줄 수 있습니다.
 
실행 코드는 아래와 같습니다.
 

study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=100)

print(f'최적 수익률: {study.best_value:.2f}%')
print(f'최적 하이퍼파라미터: {study.best_params}')

그럼 아래와 같이 열심히 best parameter를 찾습니다.

 
결과적으로 나온 최적 parameter는 아래와 같습니다.

 

최적 하이퍼파라미터: {'buy_dist': -1.146924668869434, 'sell_dist': 3.2638370521144866, 'avg_vol': 10, 'avg_ma': 20}

 
결과는 아래와 같습니다.
 
어떠시나요 이전 전략보다 더 나아보이시나요? ^^
 

 

 여기서 끝나면 안됩니다.

 
시스템트레이딩에 있어 가장 큰 적인 '과최적화'의 저주에 빠져버릴 수 있기 때문입니다.
 
성공적인 시스템트레이딩 전략을 만들기 위해서는 이 전략이 왜 working하는지를 논리적으로 설명할 수 있어야 해요.
 
optuna에서도 이점을 중요하게 생각하여 파라미터들을 분석할 수 있는 기능들도 제공해줍니다.
 
 

optuna.visualization.plot_parallel_coordinate(study)

 

optuna.visualization.plot_param_importances(study)

optuna.visualization.plot_contour(study)

 
꼭 전략의 과최적화 여부를 검증하는 과정을 거쳐 시장에서 통하는 투자전략을 개발하시길 바라겠습니다!
 
읽어주셔서 감사합니다.
 
 
 
 
 
 
 
 
 
ETF 시스템 트레이딩 연구소 : 네이버 블로그 (naver.com)

 

업무로 바쁜 직장인들을 위한 트레이딩 전략(5)

안녕하세요 직장인 전략 다섯번째 시간입니다. 벌써 (5)편이네요. 직장인 전략 이제 좀 지루하신 분도 계실...

blog.naver.com

직장인 투자전략 교차검증 #2 : 네이버 블로그 (naver.com)

 

직장인 투자전략 교차검증 #2

https://blog.naver.com/o2no/223082110529 지난번에 이어 백석꾼님이 올리신 '직장인 투자전략'...

blog.naver.com

https://blog.naver.com/okshin23432/223080021842

 

[퀀트투자전략] 초강추 !! 직장인 투자전략 (이보다 따라하기 쉬운전략은 없다)

안녕하세요~! 퀀스택스 입니다. 오늘은 친애하는 '백석꾼' 님이 개발하신 '직장인 투자전략...

blog.naver.com

 

반응형