ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [비트코인] 가상화폐 자동투자 프로그램 개발하기(4) - 변동성 돌파 전략 보완(version 2)
    프로젝트/가상화폐 자동투자 2021. 4. 27. 18:59
    반응형

    지난 2장에서는 변동성 돌파 전략의 설명과 백테스팅을 진행하여 보았다. 아직 읽어보지 않았다면 아래 이전 2장 포스트를 먼저 읽고 오는 것을 추천한다.

     

    [비트코인] 가상화폐 자동투자 프로그램 개발하기(2) - 변동성 돌파 전략 및 백테스팅

    이번 시간에는 가상화폐 자동투자를 실행할 '전략'에 대해 포스팅한다. 사람이 직접 하는 투자가 아니라 프로그램이 자동으로 진행하는 투자이기 때문에, 최대한 체계적이고 일률적인 투자전략

    poalim.tistory.com

    백테스팅 결과는 가상화폐를 처음부터 끝까지 그냥 들고있었을 때보다 수익률과 MDD 모두 우수했다. 오늘(2021/04/27 17:00) 기준 백테스팅 결과를 다시 한 번 확인해 보자.

    무려 2배 가까운 수익률을 얻을 수 있었다. 하지만 변동성 돌파 전략의 장점은 수익률 뿐 아니라 최대 손실률(MDD) 가 낮아서 안정적으로 우상향 한다는 데 있다. 백테스팅 결과를 그래프로 확인해 보면 이 점이 더욱 명확해진다.

    2017-10-06 - 2021-04-27 기간의 비트코인 가격 변동 차트
    같은 기간 변동성 돌파 전략을 적용하였을 때의 수익률 차트

     

    위의 두 그래프를 비교하여 보면, 변동성 돌파 전략을 적용하였을 때 가격의 급락을 피하면서 어느정도 안정적으로 우상향 하는 모습을 확인할 수 있다.

     

    하지만, 여전히 아쉬움은 존재한다. 가상화폐의 가격이 오르기만 하는 상승장에서는 돌파신호, 즉 targetPrice 를 만나기까지의 수익률을 포기하여야 하고 그렇다고 K 의 값을 낮추면 리스크 관리 측면에서 좋지 않다. 이러한 아쉬움을 해결하기 위하여 한 가지 전략을 추가하여 보았다.

     

    최적의 K 구하기

    현재 우리의 전략은 전체 기간의 백테스팅을 통하여 가장 좋은 결과를 낸 K = 0.5 값을 모든 구간에서 적용하고 있다. 하지만, 어느 구간이냐에 따라 가장 좋은 결과를 내는 K 의 값은 달라지기 때문에 구간별로 최적의 K 값을 적용한 targetPrice 를 적용하면 더 좋은 수익률을 얻을 수 있을 것이라 생각했다. 예를 들어, 지속되는 상승장에서는 K 값을 최대한 낮게 가져가야 모든 상승분을 얻을 수 있고, 지속되는 하락장에서는 높은 K 값을 적용하여 매수를 최대한 신중하게 진행하도록 할 수 있다. 그렇다면 백테스팅을 통하여 이를 검증하여 보도록 하자.

     

    변동성 돌파 전략은 자산 가격의 변동이 추세적 흐름을 따른다는 데 기반한다. 즉 최근의 흐름이 상승장이면 오늘도 상승할 확률이 높고 최근 흐름이 하락장이면 오늘도 하락할 확률이 높을 것이라 예상하는 것이다.  이에 따르면 오늘의 가격 변동은 가장 최근 가격 변동에 영향을 받기 때문에 특정한 날에 적용할 최적의 K 값은 최근 20일간의 데이터에서 가장 좋은 수익률을 보인 K 값으로 선정한다.

    def get_crr(df, fees, K) :
        df['range'] = df['high'].shift(1) - df['low'].shift(1)
        df['targetPrice'] = df['open'] + df['range'] * K
        df['drr'] = np.where(df['high'] > df['targetPrice'], 
        		(df['close'] / (1 + fees)) / (df['targetPrice'] * (1 + fees)), 1)
        return df['drr'].cumprod()[-2]
    
    def get_best_K(coin, fees, to) :
        df = pyupbit.get_ohlcv(coin, to = to, interval = "day", count = 21)
        time.sleep(0.1)
        max_crr = 0
        best_K = 0.5
        for k in np.arange(0.0, 1.0, 0.1) :
            crr = get_crr(df, fees, k)
            if crr > max_crr :
                max_crr = crr
                best_K = k
        return best_K

    get_crr() 함수는 입력받은 데이터에서 수익률을 계산하여 기간동안의 누적 수익률을 반환하는 함수이다. 세부 내용은 2장에서 설명하였으니 넘어가도록 하고, 마지막 반환값 return df['drr'].cumprod()[-2] 에서 [-1] 값이 아닌 [-2] 를 해 준 이유는 [-1] 은 입력받은 데이터에서의 가장 마지막 날까지의 누적 수익률인데, 데이터의 가장 마지막 날은 매매를 진행하여야 하는 당일로 아직 매매를 진행하지 않았으므로 하루 전날까지의 누적 수익률을 받아오기 위함이다.

    get_best_K() 함수는 특정 날을 기준으로 지난 20일간의 데이터로 최적의 K 값을 찾아 반환하는 함수이다. to 파라미터에 날짜가 들어오면 업비트 API 에서 해당 날짜까지 최근 21일간의 차트 데이터를 받아온다. 가장 최근일을 제외하고 20일간의 데이터를 사용하여야 하므로 21 개의 데이터를 받아와야 한다. 그 후 k 의 값에 0.0 ~ 0.9 까지의 값을 각각 적용하여 누적 수익률을 계산한 후 가장 높은 수익률을 보이는 K 값을 반환한다.

     

    이제 새로 구한 best_K 값을 적용하여 targetPrice 를 구한다.

    df['best_K'] = 0.5
    for i in range(1, day_count) :
        print(i)
        df['best_K'][i] = get_best_K(coin, fees, df.index[i])
    df['targetPrice'] = df['open'] + df['range'] * df['best_K']

    2장에서 만들었던 백테스팅 코드의 targetPrice 를 계산하는 부분을 이렇게 바꾸었다. df.index[i] 는 해당일의 날짜를 반환한다. 전체 코드는 github.com/poArlim/crypto-auto 의 backtesting_v3.py 에서 확인 가능하다. 

    반응형

    백테스팅 결과

    API 요청이 많아서 그런지 생각보다 실행시간이 오래 걸려서 2~3분 가량 걸린 것 같다. 우선 1300일간의 데이터에 일괄 K = 0.5 값을 적용했을 때의 결과는 아래와 같았다.

    시작일인 2017-10-06 일 시가에 비트코인을 매수하여 현재 시간인 2021-04-27 까지 보유하였을 때의 수익률은 1198.32% 였지만, K = 0.5 의 변동성 돌파 전략을 적용하였을 때에는 같은 기간 2098.43% 의 수익률과 -20% 의 MDD 가 나왔다. 다음은 기간에 따른 최적의 K 를 적용한 변동성 돌파 전략의 백테스팅 결과를 보자.

    같은 기간 수익률이 무려 8185.77% 로 나타난다! 생각보다 높은 수치에 놀라서 모든 날짜에 적용된 best_K 값을 확인해보니 best_K 값이 최소치인 0 으로 적용된 날과 최대치인 0.9 로 적용된 날이 생각보다 많다는 것이 눈에 띄었다. 상승 추세가 강할수록 모든 상승분을 챙기고 하락 추세가 강할수록 매수를 최대한으로 자제하여 놀라운 결과를 얻은 것이다. 다만 갑작스러운 추세의 전환에는 약하여 꽤 높은 MDD(-39%) 를 보인 것은 아쉽게 느껴진다.

     

     

    이제 오늘 다룬 version 2 전략을 구현하여 실제 자동매매를 일정 기간 진행해 본 후 결과와 필요하다면 새로운 기능을 추가하여 다음 포스트로 찾아와 보려고 한다. 기다려주세요~!

    반응형
Designed by Tistory.