본문 바로가기
주식/주식자동매매

주식 자동매매 프로그램 변동성 돌파 전략 단점 업그레이드 하기 (대신증권 크레온 플러스 파이썬 API)

by 날아라키위새 2021. 6. 23.
반응형

주식 프로그램매매 변동성 돌파 전략 단점 업그레이드 (대신증권 크레온플러스 API)

최근 유튜브나 여러 블로그를 보면 증권사 API를 이용하여 자동매매 하는 정보를 공유하고 있다.

(특히 대신증권 크레온플러스 API)

가장 쉽게 접할 수 있는 것이 변동성 돌파 전략 (Volatility Breakout)이다.

따라 하기 간단하기 때문인데 큰 기대는 하지 말자. 

별생각 없이 따라 해서 돈 벌 수 있으면 다 부자 됐을 테다.

그들이 공유하는 코드도 실제로 실행해보면 제한되는 부분도 많고 엉성한 부분도 많다. 

실제로 프로그램매매로 돈을 버는 사람들은 조용히 남 모르게 돈 벌고 있겠지..

내가 생각했던 단점? 한계?를 조금 보완할 수 있는 방법을 공유하려 한다.

기본 변동성 돌파 전략 (Volatility Breakout Strategy)

일반적인 변동성 돌파 전략은

현재가 > 당일 시가 + (전일 고가-전일 저가) * K 를 만족하면 매매하는 전략이다.

이때 많은 사람들이 돌파 계수 K값으로 고정된 0.5를 사용한다. 

자세히 파고 들어가자면 좀 더 논리적인 이유가 있고 (실제로 상당히 타당하다)

0.5를 사용하여 백테스트한 결과 안정적이고 좋은 수익률을 내었기 때문이다.

하지만...

 

K값 0.5는 과거의 데이터를 기반으로 한 것이고 고정된 돌파계수를 사용하기에는 시장의 변화에 잘 따라가지 못할 수 있다. 

예를 들어 특정 종목의 (전일 고가-전일 저가)가 갑자기 크게 증가한 다음날 (상한가를 치거나 주가가 많이 오른 경우) 전날보다는 못하지만 어느 정도 상승장을 이어가고 있을 때 고정된 돌파계수 0.5 때문에 매수 타이밍을 못 잡는 경우가 생길 수도 있고 반대의 경우, 즉 (전일 고가-전일 저가)가 작았던 다음날 작은 주가 상승에도 매수를 시도하는 경우가 생기기도 한다.

 

실제로 온라인에 떠도는 코드를 시험 삼아 며칠 돌려보았을 때 전날 등락률이 작았을 때 장 초반 주가가 얼마 오르지도 않은 상황 (변동성을 돌파하는지 애매한 상황)에서도 매수를 시도하였고 얼마 지나지 않아 주가가 하락하면서 손실을 보게 되는 경우가 종종 생겼다. 

변동성 돌파 전략 단점 업그레이드 하기: 시장 상황에 맞게 돌파 계수 k값 변화시키기

다양한 방법이 있겠지만

그중에서 생각보다 쉽게 적용할 수 있는 방법을 소개한다. 

 

고정된 돌파계수 대신 종목의 평균 추세를 사용하여 과거 x일 동안 추세가 강한 경우 돌파계수를 작게 추세가 약한 경우 돌파계수를 크기 정하여 매수 타이밍을 잡는 방법이다.

 

대신증권 크레온 플러스 API를 사용하여 파이썬 코드를 짜보았는데.

종목의 20일 동안의 ohlc 값을 받아서 추세 평균값을 계산하는 방법이다.

(꼭 20일 아니어도 상관없으니 테스트해보자.)

get_kvalue()에서 받은 값을 매수하는 함수에서 불려 들여 k값 대신 사용하면 된다.

 

import win32com.client
import pandas as pd

cpohlc = win32com.client.Dispatch('CpSysDib.StockChart')


def get_ohlc(code, qty):  # 인자로 받은 종목의 OHLC 가격 정보를 qty 개수만큼 반환한다
    try:
        cpohlc.SetInputValue(0, code)  # 종목코드
        cpohlc.SetInputValue(1, ord('2'))  # 1:기간, 2:개수
        cpohlc.SetInputValue(4, qty)  # 요청개수
        cpohlc.SetInputValue(5, [0, 2, 3, 4, 5])  # 0:날짜, 2~5:OHLC
        cpohlc.SetInputValue(6, ord('D'))  # D:일단위
        cpohlc.SetInputValue(9, ord('1'))  # 0:무수정주가, 1:수정주가
        cpohlc.BlockRequest()
        count = cpohlc.GetHeaderValue(3)  # 3:수신개수
        columns = ['open', 'high', 'low', 'close']
        index = []
        rows = []
        for i in range(count):
            index.append(cpohlc.GetDataValue(0, i))
            rows.append([cpohlc.GetDataValue(1, i), cpohlc.GetDataValue(2, i),
                         cpohlc.GetDataValue(3, i), cpohlc.GetDataValue(4, i)])
        df = pd.DataFrame(rows, columns=columns, index=index)
        return df
    except Exception as ex:
        print('get_ohlc() -> 에러: ' + str(ex))
        return None


def get_kvalue(code):  # 인자로 받은 종목에 대한 20일 average noise ratio.
    try:
        ohlck = get_ohlc(code, 20)
        ohlck['noiseratio'] = 1 - (abs(ohlck['open'] - ohlck['close']) / (ohlck['high'] - ohlck['low']))
        return round(ohlck['noiseratio'].mean(), 2)
    except Exception as ex:
        print('get_kvalue() -> 에러: ' + str(ex))
        return None

 

반응형

댓글