파이썬 코인 자동매매 프로그램 만들기 : 청산기법 및 매수 매도 구현
토이 프로젝트/암호화폐 자동거래 봇(Bot) 만들기

파이썬 코인 자동매매 프로그램 만들기 : 청산기법 및 매수 매도 구현

by TechNyang 2024. 10. 25.
반응형

지난 포스팅에서는 스토캐스틱, 이동편균선, 일목균형표를 구현하는 방법에 대해 말씀드렸습니다.

 

파이썬 코인 자동매매 프로그램 만들기 : 스토캐스틱, 이동평균선, 일목균형표 구현하기

지난 시간에는 파이썬으로 기술적 분석을 통해 어떤 라이브러리를 설치해야 하는지 알아보았고, 볼린저 밴드와 MFI, RSI를 구현하는 법을 알아보았습니다.이번에는 기술적 분석 방법 중 스토캐스

technyang.tistory.com

이런 기술적 지표를 이용하여 좋은 타이밍에 진입해서 수익을 얻는 것은 매우 중요합니다. 하지만 좋은 위치에서 매도를 하지 않는다면 결고 진정한 수익을 얻었다고 말할 수 없습니다.

 

매도는 참 어려운 영역입니다. 너무 일찍 매도를 하면 충분한 수익을 얻을 수 없고, 너무 늦게 매도를 해도 만족할 만한 수익을 얻기 힘듭니다. 오히려 손해를 볼 수도 있습니다.

 

 

파라볼릭 SAR(Parabolic SAR)

내가 매수한 코인이 상승추세를 타고 잘 오르다가 추세가 반전될 때 매도를 하면 참 좋겠다.라는 생각에 조사를 진행했고, 파이썬으로 구현이 쉽게 가능한 전략 2가지를 발견했습니다.

 

그 중 첫 번째인 파라볼릭 SAR을 말씀드리고자 합니다.

파라볼릭 SAR은 1970년대 후반 기술적 분석가인 웰스 와일더에 의해 개발된 지표입니다.

 

파라볼릭 SAR 지표는 시장가격 위나 아래에 찍힌 점 들로 이루어집니다. 즉, 상승 추세 동안에는 점들이 시장 가격보다 아래에 표시되며, 하락 추세 동안에는 점들이 시장가격 위에 표시됩니다.

 

그래서 일부 트레이더들은 스톱-로스 가격을 지정하기 위해 이 파라볼릭 SAR을 사용하기도 합니다.

하지만 이 파라볼릭 SAR도 한계점을 가지고 있는데요.

 

그것은 바로 횡보장에서는 거짓 신호를 제공할 가능성이 높다는 것입니다. 이는 앞으로 상승이 더 될 수 있음에도 불구하고 일찍 청산을 하게 만들 수 있습니다.

 

그렇기 때문에 항상 말씀드리는 것이지만 보조지표는 보조지표일 뿐 한가지만 너무 맹신해서는 안되겠습니다. 파라볼릭 SAR은 다음과 같이 구할 수 있습니다.

sar = talib.SAR(df['high'], df['low'], acceleration=0.02, maximum=0.2)

 

acceleration은 가속변수라고 불리는데요. 새로운 고점을 형성하거나(상승추세) 새로운 저점(하락 추세)을 형성할 때마다 증가하는 값으로서 위 값으로 보자면 가속변수는 0.02부터 시작하여  0.02씩 증가합니다.

 

그러다가 maximum값인 0.2에 도달하면 추세가 진행되는 동안에는 해당 값은 동일하게 유지됩니다.

이 가속변수를 0.02보다 크게 설정하면 추세를 보다 민감하게 반영한다는 것이고, 0.02보다 낮게 설정하면 추세에 보다 둔감하게 반영한다는 뜻입니다.

 

지표를 개발한 웰스 와일더는 가속변수를 0.02로 설정하는 것을 추천했습니다. 그럼 파라볼릭 SAR을 이용한 매매기법은 어떤것이 있을까요?

 

가장 간단하고 유명한 방법은 현재의 주가가 파라볼릭 SAR보다 밑에 있으면 매도하고, 위에 있으면 매수하는 방법입니다. 아래 그림을 보겠습니다.

 

파라볼릭-SAR-차트화면
파라볼릭 SAR 차트화면

 

빨간색으로 표기한 부분을 보시면 주가가 SAR보다 밑에 있을 경우 하락추세를, 주가가 SAR보다 이에 있으면 상승추세임을 나타냅니다. 이를 청산을 위한 지표로 사용한다고 할 경우 함수구현은 아래와 같이 할 수 있습니다.

 

def getPSAR(ticker):
    df = getCandleStick(ticker, '3m')
    sar = talib.SAR(df['high'], df['low'], acceleration=0.02, maximum=0.2)
    nowSAR = sar.iloc[-1]
    curPirce = getCurrPrice(ticker)
    if float(curPirce) < float(nowSAR): #현재 가격이 SAR보다 아래에 있으면 매도
        return -1
    else:
        return 0

 

샹들리에 출구전략

샹들리에 출구전략은 ATR(Average True Range)를 사용하는 전략입니다.

ATR은 TR이라는 변동성의 값을 평균화한 지표입니다.

ATR을 구하는 방법은 아래와 같습니다.

atr = talib.ATR(df['high'], df['low'], df['close'], timeperiod = 20).iloc[-1]

 

ART을 이용한 샹들리에 출구전략은 매수 후 고가에서 ART에서 일정한수를 곱한 값을 뺀가격보다 현재가가 낮으면 매도하는 전략입니다.

 

즉, 현재가격 >  매수 후 최고가 - K * ATR이 되는 것입니다. 이때 K는 2.5 ~ 4의 값을 사용합니다. 이를 함수로 나타내면 다음과 같습니다.

def getChandelierExit(ticker):
    df = getCandleStick(ticker, '3m')
    df20 = df.iloc[-21:-1] # 3분봉기준이므로 1시간의 차틎어보가 되겠다.
    maxPrice = df20['high'].max() #최근 1시간동안의 최고가를 변수에 지정
    atr = talib.ATR(df['high'], df['low'], df['close'], timeperiod = 20).iloc[-1]
    stopPrice = maxPrice - 2.5 * atr #청산가격 설정
    curPirce = getCurrPrice(ticker)
    if float(curPirce) < float(stopPrice): 
        return -1
    else:
        return 0

 

 

매수하기

지금까지 인기있는 몇가지의 기술적 지표를 구하는 방법을 알아보았습니다.

그렇다면 이제 남은 것은 매수 및 매도하는 방법이겠지요.

 

그중 먼저 매수하는 방법을 알아보겠습니다.

매수와 매도는 업비트와 빗썸의 코드가 서로 다르므로 나누어서 말씀드리겠습니다.

 

업비트

#시장가 매수
exchange.options = {'createMarketBuyOrderRequiresPrice': False} # 업비트는 이 옵션을 넣어줘야 한다.
buy_order = exchange.create_market_buy_order(ticker, price)  # 시장가 매수 업비트는 금액을 넣는다.

#지정가 매수
buy_order = exchange.create_limit_buy_order(ticker, unit, price) #암호화폐, 구매수량, 가격

 

빗썸

#시장가 매수
buy_order = exchange.create_market_buy_order(ticker, unit)  # 시장가 매수

#지정가 매수
buy_order = exchange.create_limit_buy_order(ticker, unit, price) #암호화폐, 구매수량, 가격

 

보시는 바와 같이 업비트와 빗썸의 시장가 매수 방법이 다름을 알 수 있습니다. 

그럼 매수를 하는 메소드를 업비트 버전과 빗썸 버전을 구현해보겠습니다.

 

업비트 시장가 매수 코드

def market_buy_upbit(ticker, invest_price):
    try:
        krw = invest_price
        exchange.options = {'createMarketBuyOrderRequiresPrice': False}
        buy_order = exchange.create_market_buy_order(ticker, krw)  
        return buy_order
    except Exception as e:
        print(e)
        pass

 

업비트 시장가 매수는 간단합니다.

투자금액과 암호화폐 티커만 입력하면, 시장가를 반영하여 자동적으로 수량이 계산되어지고 매수가 됩니다.

 

업비트 지정가 매수 코드

def limit_buy_upbit(ticker, unit, order_price):
    try:
        buy_order = exchange.create_limit_buy_order(ticker, unit, order_price)
        return buy_order
    except Exception as e:
        print(e)
        pass

 

지정가 매수는 더 간단합니다. 암호화폐 티커, 매수 하고자 하는 수량, 그리고 매수하고자 하는 금액을 넣어주시면 됩니다.

 

빗썸 시장가 매수 코드

def market_buy_bithumb(ticker, invest_price):
    try:
        krw = invest_price
        orderbook = exchange.fetch_order_book(ticker) # 호가정보 조회
        sell_price = orderbook['asks'][0][0]
        unit = round(krw / sell_price,4)
        buy_order = exchange.create_market_buy_order(ticker, unit) 
        return buy_order
    except Exception as e:
        print(e)
        pass

 

빗썸은 앞서 보신 업비트보다는 코드가 조금더 복잡합니다. 이유는 빗썸의 경우 구매수량을 입력해야 하는데요.

투자하고자 하는 금액에 맞는 수량을 계산하기 위해서는 호가정보를 이용해야하기 때문입니다.

 

호가정보는 ccxt의 fetch_order_book을 이용하여 확인할 수 있습니다.

호가정보를 불러오면 아래와 같이 bids(매수)와 asks(매도)의 호가를 알 수 있습니다.

호가정보들은 List의 형태로 구성되어 있는데요 앞은 호가, 뒤는 수량입니다.

bids-결과화면
bids(매수) 결과 화면

 

시장가로 매수를 하기 위해서는 최우선 순위의 매도호가를 알아야겠지요?

그리고 우리가 원하는 것은 호가이기 때문에 아래와 같은 코드로 최우선 매도호가를 가져올 수 있습니다.

orderbook = exchange.fetch_order_book(ticker) # 호가정보 조회
sell_price = orderbook['asks'][0][0] # 최우선 매도 호가
unit = krw / sell_price

 

투자금액을 조회해온 매도호가로 나누면 구매 가능한 수량을 구할 수가 있습니다. 

빗썸 지정가 매수는 앞서보신 업비트와 동일합니다.

 

빗썸 지정가 매수 코드

def limit_buy_bithumb(ticker, unit, invest_price):
    try:
        buy_order = exchange.create_limit_buy_order(ticker, unit, invest_price)
        return buy_order
    except Exception as e:
        print(e)
        pass

 

매도하기

다음은 매도하는 방법입니다. 지정가 매도와 시장가 매도는 업비트와 빗썸 동일합니다.

 

업비트/빗썸 매도 코드

#시장가 매도
sell_order = exchange.create_market_sell_order(ticker, unit)

#지정가 매도
sell_order = exchange.create_limit_sell_order(ticker, unit, price)

 

하지만 매도시 주문수량은 업비트와 빗썸이 다릅니다.

그 이유는 빗썸의 경우 암호화폐의 가격에 따라 호가단위가 다르기 때문입니다.

 

업비트 시장가 매도 코드

def market_sell_upbit(ticker, unit):
    try:
        sell_order = exchange.create_market_sell_order(ticker, unit)
        return sell_order
    except Exception as e:
        print(e)
        pass

 

업비트 지정가 매도 코드

def limit_sell_upbit(ticker, unit, price):
    try:
        sell_order = exchange.create_limit_sell_order(ticker, unit, price)
        return sell_order
    except Exception as e:
        print(e)
        pass

 

빗썸 시장가 매도 코드

def market_sell_bithumb(ticker, unit):
    try:
        sellUnit = math.floor(unit*10000)/10000 #빗썸은 소수점 4째자리까지만 매도수량을 받는다.
        if sellUnit > 0.0:
            sell_order = exchange.create_market_sell_order(ticker, sellUnit)
            return sell_order
    except Exception as e:
        print(e)
        pass

 

빗썸 지정가 매도 코드

def limit_sell_bithumb(ticker, unit, price):
    try:
        sellUnit = math.floor(unit*10000)/10000 #빗썸은 소수점 4째자리까지만 매도수량을 받는다.
        if sellUnit > 0.0:
            sell_order = exchange.create_limit_sell_order(ticker, sellUnit, price)
            return sell_order
    except Exception as e:
        print(e)
        pass

 

빗썸의 매도부분을 보시면 math.floor라는 함수가 보이실 것입니다.

math.floor를 쓰게 되면 소수점은 버리게 됩니다.

 

만약 unit이 0.00001이라고 한다면 0.00001 * 10000은 0.1이 됩니다.

math.floor는 소수점을 버리므로 math.floor(0.1) = 0이 되게 됩니다.

 

0을 10000으로 나누면 0이기 때문에 매도주문을 하지 않습니다.

만약 unit이 0.0001(가장 작은 호가단위)이라고 하면 0.0001 * 10000은 1이 되고, math.floor(1)은 1입니다.

거기에 10000을 나누면 0.0001이 되는데, 이때는 0보다 크므로 매도주문이 들어가게 됩니다.

 

매수 평단가 구하기(업비트만 해당)

자동매매를 하다보면 내가 보유한 코인들을 얼마주고 구매했는지.

즉 매수평균단가가 얼마인지 알아야 할 때가 있을 수 있습니다.

아래는 코인별로 내가 구매한 매수평균 단가가 얼마인지 계산하는 함수입니다.

def getAvgBuyPrice(ticker):
    bal = exchange.fetch_balance()
    hasList = {}
    for i in range(1, len(bal['info'])):
        hasList[bal['info'][i]['currency']] = bal['info'][i]['avg_buy_price']
    charPosition = ticker.find('/')
    tickerName = ticker[0:charPosition]
    if tickerName in hasList:
        return hasList[tickerName] #매수 평균가
    else:
        return 0

 

에필로그

지금까지 읽어주셔서 감사합니다.

여기에 소개드린 기술적 분석기법은 유명하고 많이 사용하고 있는 기법들입니다.

 

그렇다고 해서 지표들만 맹신하시면 안됩니다.

그리고 지표들에 적용된 옵션 값들은 기본적인 값들이지, 절대적인 수치가 아니라는 점 꼭 명심해주셨으면 좋겠습니다.

 

주제 넘게 몇 가지 팁을 드리자면, 한번에 너무 많은 돈을 투자하지 마십시오.

처음에는 정말 소액만 넣어보시고 프로그램을 구동시킨 후에 자신이 원하는 전략에 맞게 여러가지 지표들도 혼합해 보고, 지표들의 설정값도 바꿔보시길 권해드립니다.

 

또한 각 지표들이 어떤 원리로 만들어졌는지 이해하시면 전략을 세우시는데에 많은 도움이 되실 것 입니다.

그러다 안정적이고 만족할만한 수익률이 나오면 그때 투자금을 늘리시는 것을 추천드립니다.

 

암호화폐시장은 영향력 있는 사람의 한마디 한마디에 출렁거릴 만큼 변동성도 크고, 1년 365일 장이 열려있는, 어떻게 보면 투자하기 쉽지않은 시장입니다.

 

그러다 보니 낮에 핸드폰을 손에서 놓기도 어렵고, 심지어 밤에 잠도 잘 안오실 것 입니다.

이 포스팅이 조금이나마 여러분들께서 편안한 밤을 보내시는데 도움이 되었으면 좋겠습니다. 감사합니다.

반응형

TOP

Designed by 티스토리

loading