본문 바로가기

Project

01-4. 비트코인 자동 매매 트레이딩 봇: 샘플 코드 분석을 해보아요!

반응형

01-4. 비트코인 자동 매매 트레이딩 봇 만들기

 

자동 매매 샘플 코드 분석하기

 

 

비트코인 자동매매 트레이딩 봇 시리즈의 4번째 포스팅입니다!

이번에는 실제 매매에 사용할 샘플 코드를 자세히 살펴보고, 내가 원하는 조건으로 어떻게 수정하면 좋을지 알아보겠습니다.

샘플 코드는 유튜버 조코딩님께서 깃허브에 올려놓으신 자료를 사용하였습니다.

 

 

# 조코딩님의 github 바로가기

 

# 조코딩님의 유튜브 채널 바로가기

 

 

이번 포스팅 내용은 API, pyupbit 라이브러리, 데이터 프레임(dataframe), 티커(ticker) 등에 대한
기본 이해가 있다면 훨씬 읽기 편하실 거예요.
이러한 단어를 처음 들어 보신다면 이전 포스팅을 참고해주세요.

 

# 01-1. 비트코인 자동 매매 트레이딩 봇: API Key 발급받기

# 01-2. 비트코인 자동 매매 트레이딩 봇: 너무 쉬운 API, 이해하고 사용해요

# 01-3. 비트코인 자동 매매 트레이딩 봇: API 데이터, 어떻게 사용할까요?

 

 

비트코인 자동 매매 코드의 전체적인 순서는 "로그인 → 매수 실행 → 매도 실행"으로 아주 단순합니다.

로그인 이후의 매수/매도 단계무한 반복으로 진행되므로, 수동으로 프로그램을 종료하지 전까지 계속 실행됩니다.

이러한 동작을 수행하기 위한 비트코인 자동 매매 전체 코드 구성을 자세히 살펴보고자 합니다.

 

 

# 포스팅 내용

  • 필요 라이브러리 호출
  • 자동 매매를 위한 함수 정의
  • 매수 가격, 시작 시간, 잔고 조회, 현재 가격
  • 로그인
  • 자동 매매 무한 루프
  • 특정 시간 기준으로 자동 매매 시작
  • 설정 전략에 따른 매수 실행
  • 특정 시간 기준으로 매도 실행
  • 코드 수정 계획

 


 

Step 1. 라이브러리 호출

가장 먼저, 라이브러리는 업비트 API 사용을 위한 pyupbit와 함께
날짜와 시간을 다루기 위한 time 및 datatime 라이브러리를 불러옵니다.

import time
import pyupbit
import datetime

 

 

 

Step 2. 함수 정의

다음으로는 자동 매매 동작을 위해 필요한 몇 가지 기능을 함수로 만들어줍니다.
반복적으로 사용하는 변수를 함수로 묶어 정의함으로써, 효율적이고 간결한 코드가 만들어지고
전체 흐름 파악하기 쉬워집니다. 또한, 추후 전략 변경에 따른 코드 수정 시에도 빠른 작업이 가능합니다.

매수 가격 설정하기: get_target_price( )

변동성 돌파 전략에 따른 오늘의 매수 가격을 계산하고 target_price로 반환하는 함수입니다.

# 매수가 정하기, ticker와 k를 파라미터로 가지는 함수 정의

def get_target_price(ticker, k):        
    df = pyupbit.get_ohlcv(ticker, interval="day", count=2)     
    target_price = df.iloc[0]['close'] + (df.iloc[0]['high'] - df.iloc[0]['low']) * k       
    return target_price

 

위 함수에서 df = pyupbit.get_ohlcv( ) 부분만 출력하면, 해당 ticker에 대한 오늘과 어제의 가격 정보를 불러옵니다. 

df = pyupbit.get_ohlcv("KRW-BTC", interval="day", count=2)

print (df) 

 

interval = "day"가격 정보를 1일 기준으로 불러오는 조건이고, count=2는 불러오는 데이터의 개수입니다.
따라서 아래 표를 참고하여 intervalcount 조건을 수정하면
각자가 원하는 시간 단위 기준으로 필요한 만큼의 가격 데이터를 사용할 수 있습니다.

 

interval 지정 가능 값 month
week
day
minute1, minute3, minute5, minute10, minute15, minute30, minute60, minute240
count 지정 가능 값 숫자 integer (default 값: 200)

 

그다음 줄의 target_price매수 가격을 계산하는 코드입니다.

매수 가격 계산을 위해서 래리 윌리엄스(Larry R. Williams)의 변동성 돌파 전략을 사용하며
변동성 돌파 전략에 따른 매수가를 식으로 표현하면 전일 종료 가격 + (전일 최고가 - 전일 최저가)*K입니다.

target_price = df.iloc[0]['close'] + (df.iloc[0]['high'] - df.iloc[0]['low']) * k

return target_price

 

df는 pyupbit.get_ohlcv( )로 저장한 가격 데이터이고
df.iloc[0]['close']는 데이터 프레임(df)첫 번째 행(row)에 있는 close 필드 값을 가져옵니다.
이러한 방식으로 원하는 연산을 수행 한 뒤, 변수 target_price로 저장하고 반환(return)함으로써 매수가를 설정합니다.

 

# 변동성 돌파 전략이란?

더보기

기술 투자의 대가인 래리 윌리엄스의 전략으로, 일일 단기 매매에서 큰 수익률을 자랑합니다.

이는, 전날의 종가(=당일 시작 가격)에서 전날의 변동 폭(=최고가-최저가)의 K배만큼 상승했을 때 매수하고
다음날 종가에 전량 매도하는 방법입니다.

 

변동성 돌파 전략 개념

 

 

시작 시간 정하기: get_start_time( )

자동 매수/매도가 발생하는 기준"시간"으로 잡아 주기 위해, 특정 시간을 strart_time으로 저장하는 함수입니다.

# 시작 시간 정의 하기, 1일 매매 기준

def get_start_time(ticker):             
    df = pyupbit.get_ohlcv(ticker, interval="day", count=1)
    start_time = df.index[0]
    return start_time

 

위 함수를 한 줄씩 실행 후, 출력하면 다음과 같습니다.

df = pyupbit.get_ohlcv("KRW-BTC", interval="day", count=1) 
print (df) 

start_time = df.index[0] 
print (start_time) 

 

start_time = df.index[0]은 df의 가장 첫 번째 부분인 index를 저장한 것으로,
오늘의 날짜와 시작 시간 "yyyy-mm-dd 09:00:00"임을 알 수 있습니다.
이 값을 마지막에 반환(return)하여 자동 매매의 "기준 시간"으로 사용합니다.

 

만약, 자동 매매의 시작 기준을 당일 오전 9:00이 아닌 다른 시간을 사용하고 싶다면,
df = pyupbit.get_ohlcv( )에서 interval 조건을 변경해서 사용하면 됩니다.
예를 들어, 4시간 기준으로 매매를 진행한다고 가정하면 아래와 같이 수정합니다(interval = "minute240").

# 시작 시간 정의하기, 4시간 매매 기준! 

def get_start_time(ticker): 
	df = pyupbit.get_ohlcv(ticker, interval="minute240", count=1) 
	start_time = df.index[0] 
	return start_time

 

interval 조건을 4시간 기준으로 변경 후, start_time 값을 확인해 보니 오늘의 날짜와 함께 13:00이 나왔습니다.
이러한 조건으로 자동 매매를 한다면, 당일 13:00에 매수/매도 진행 한 뒤,
4시간 이후에 start_time이 17:00이 되면서 매수/매도가 계속 반복될 것임을 알 수 있습니다.

df = pyupbit.get_ohlcv("KRW-BTC", interval="minute240", count=1) 
start_time = df.index[0] 

print (start_time)

 

 

잔고 조회 및 가져오기: get_balance( )

업비트 어플에 있는 개인 잔고를 조회하고, 가지고 있는 보유 자산 중 매매에 사용할 자산을 가져오는 함수입니다.

# 잔고 조회 및 매매 할 자산 가져오기

def get_balance(ticker):                
    balances = upbit.get_balances()
    for b in balances:
        if b['currency'] == ticker:
            if b['balance'] is not None:
                return float(b['balance'])
            else:
                return 0

 

balances = upbit.get_balances( ) 부분을 데이터 프레임으로 출력하면 아래와 같습니다.

# 개인 잔고 조회에 대한 자세한 내용은 01-3. 비트코인 자동 매매 트레이딩 봇: API 데이터, 어떻게 사용 할까요? Step.2를 참고해 주세요.

개인 잔고 조회 결과

 

balances = upbit.get_balances( )for 문 내용을 해석해 보면 간단합니다.
balances의 "currency" 필드에 있는 값이 함수의 파라미터로 넣은 ticker와 일치할 때,
ticker(currnecy)의 balance 값을 float 타입의 숫자로 반환(return) 하고,
그 이외의 경우에는 모두 '0'을 반환(return)합니다.

 

따라서, get_balance( ) 함수의 파라미터로 들어갈 ticker
"currency" 필드에 있는 값 중 하나가 되어야 합니다 (마켓 코드 아님).
예를 들어, 이더리움을 매수/매도한다면 매수할 때는 get_balane(KRW), 매도할 때는 get_balane(ETH)를 사용합니다.

 

 

현재 가격 가져오기: get_current_price( )

매도/매수를 진행할 코인의 현재 가격을 가져옵니다.

# 현재 가격 가져오기

def get_current_price(ticker):          
    return pyupbit.get_orderbook(tickers=ticker)[0]["orderbook_units"][0]["ask_price"]

 

함수의 return 부분에서 앞부분만 출력해 보겠습니다. (주피터 노트북, 데이터 프레임 사용)

# 현재 가격 가져오기

pd.DataFrame(pyupbit.get_orderbook(tickers="KRW-BTC")[0]["orderbook_units"])

매수/매도 호가 호출

 

위 결과는 호가 정보를 가져온 것으로, ask_price와 bid_price는 각각 매도 및 매수 호가이며
가장 첫 번째 값(index 0번의 ask_price 값)이 현재 시장 가격입니다.
따라서 함수의 return 부분 전체를 출력하면 표의 가장 첫 번째 값이 나옵니다.

pyupbit.get_orderbook(tickers="KRW-BTC")[0]["orderbook_units"][0]["ask_price"]

현재 가격 호출

 

이렇게 가져온 코인의 현재 가격get_target_price( ) 함수에 따른 매수 가격을 비교해서 실제 자동 매수가 실행됩니다.

 

 

 

Step 3. 로그인

로그인에 대한 설명은 01-3. 비트코인 자동 매매 트레이딩 봇: API 데이터, 어떻게 사용 할까요? Step.2 내용을 참고해 주세요.

# 현재 가격 가져오기

access = "your access key"
secret = "your secret key"

upbit = pyupbit.Upbit(access, secret)

 

 

 

Step 4. 자동 매매 무한 루프

드디어 실제 자동 매매를 수행하는 구간입니다!
이 구간에서는 위에서 정의해 놓은 함수들을 이용해서 코드가 작성되어있습니다.
그러므로 위에 있는 함수들의 기능이 이해가 되셨다면, 자동 매매가 이루어지는 코드는 훨씬 쉽게 느껴지실 거예요!

 

가장 먼저, 특정 시간을 기준으로 매매를 실행하기 위해 현재 시간, 시작 시간, 종료 시간을 정의합니다.
현재 시간은 파이썬의 datatime 라이브러리를 이용하고, 시작 시간은 미리 정의한 get_start_time( ) 함수를 사용합니다.

 

# 현재 시간, 매매 시작 및 종료 시간 

now = datetime.datetime.now()
print (now)

start_time = get_start_time("KRW-BTC")
print (start_time)

end_time = start_time + datetime.timedelta(days=1)
print (end_time)

 

 

# datatime 사용 가이드

 

datetime — 기본 날짜와 시간 형 — Python 3.9.5 문서

datetime — 기본 날짜와 시간 형 소스 코드: Lib/datetime.py datetime 모듈은 날짜와 시간을 조작하는 클래스를 제공합니다. 날짜와 시간 산술이 지원되지만, 구현의 초점은 출력 포매팅과 조작을 위한

docs.python.org

 

 

다음으로, 매수/매도 전략을 설정하고 이를 수행하는 샘플 코드입니다.

if start_time < now < end_time - datetime.timedelta(seconds=10):
    target_price = get_target_price("KRW-BTC", 0.5)
    current_price = get_current_price("KRW-BTC")
        
        if target_price < current_price:
            krw = get_balance("KRW")
            if krw > 5000:
                upbit.buy_market_order("KRW-BTC", krw*0.9995)

else:
    btc = get_balance("BTC")
    if btc > 0.00008:
        upbit.sell_market_order("KRW-BTC", btc*0.9995)

 

첫 번째 if)

  • 현재 시간이 yyyy-mm-dd 09:00:00 ~ yyyy-mm-dd(+1) 08:59:50 조건을 만족하는 순간 첫 번째 코드가 실행됩니다.
  • get_target_price( ) 함수에 입력한 티커(ticker)와 k 값 (예; 0.5)에 따라 오늘의 매수 가격을 정합니다. → target_price
  • get_current_price( ) 함수에 입력한 티커(ticker)의 현재 가격을 가져옵니다. → current_price

 

두 번째, 세 번째 if )

  • 티커에 해당하는 코인의 현재 가격(current_price)오늘의 매수 가격(target_price)에 도달할 때, (즉, 현재 가격이 매수 가격을 넘어서는 시점) 매수를 위한 원화(KRW)를 가져옵니다.
  • 이때, 원화(KRW)가 최소 거래금액(5,000) 이상이면, 해당 코인을 시장가에 즉시 매수합니다.

첫 번째 else, 네 번째 if )

  • 현재 시간이 yyyy-mm-dd 09:00:00 ~ yyyy-mm-dd(+1) 08:59:50 조건을 불만족할 때, (즉, 09:00:00 전 10초 동안) else 아래 코드가 실행됩니다.
  • 전날 매수했던 코인을 가져옵니다. → 예; BTC
  • 그리고 최소 거래 금액 이상이면, 해당 코인을 시장가에 모두 매도합니다

 

마지막으로, 시간 설정부터 매매 수행까지 전체 코드while True: 로 묶어서 무한 루프를 만들어 주면 완성입니다!!😆

 

 

 

Step 5. 코드 수정 계획

다 왔습니다!

기본적인 함수와 샘플 코드가 모두 정리되었으니 본인만의 전략을 적용하고 실행하는 단계만 남았어요.😏

 

가장 쉬운 방법은 위 샘플 코드를 그대로 사용하면서,

함수와 While 문의 파라미터들(ticker, K 값 등)만 변경하는 방법입니다.

 

자동 매매를 수행하고 싶은 가상 화폐 코인(ticker)을 하나 정한 뒤, 최적의 K값을 찾아 입력하면 됩니다.

이렇게 하면 코드 자체는 거의 수정할 부분이 없어 보입니다.

그렇다면, 최적의 K값은 어떻게 찾느냐? 바로 백테스트(BackTest)를 통해 찾을 수 있습니다.

 

백테스트(BackTest)는 과거 데이터를 바탕으로 전략을 시뮬레이션해 보는 것입니다.

백테스트 코드 또한 조코딩님께서 github에 올려놓으신 자료가 있어 비트코인 기준으로 과거 7일, 30일, 100일에 대해

간략하게 테스트해 보니 대략 0.3 정도의 K 값이 적절해 보이네요.

 

이 값을 바로 사용하기보다는 좀 더 다양한 가상 화폐 코인을 대상으로 4시간, 1일, 1주 등의 기준으로 테스트를 진행 한 뒤 적용하는 것을 권해드립니다. 그리고 변동성 돌파 전략 외에 본인만의 다른 전략을 구상하여 적용시켜 좀 더 안전한 투자가 이루어지길 바랍니다.

 

우선은 변동성 돌파 전략을 기준으로 여러 조건으로 테스트 한 뒤, 실전 적용해 보아야겠습니다.

그리고 다른 몇 가지 아이디어에 대해 앞으로 테스트 및 실전 적용하며 응용해보려고 합니다! (후후.. 설레네요🥰)

 

 


 

 

 

여기까지 오시느라 수고하셨습니다!

안전하고 성공적인 투자에 조금이라도 도움이 되시길 바랍니다.

그리고 좋은 강의와 자료를 제공해 주신 조코딩님께도 감사드립니다!

 

✋ 백테스트 및 자동 매매 프로그램으로 무조건적인 수익을 보장하지 않습니다.

✋ 모든 투자의 책임은 투자자 본인에게 있습니다.

 

 

 

# 다음 포스팅에서는

  • 다양한 조건으로 백테스킹을 진행하고 그 결과에 대해 알아볼 계획입니다.
  • 분석한 샘플코드를 바탕으로, 원하는 전략으로 코드 수정 후 자동 매매 트레이딩 프로그램을 1차 완성하는 것이 목표입니다.
  • 가능하면 클라우드 서비스까지 적용시켜 볼 예정입니다.

 

 

 

# 참고 자료

 

 

 

반응형