파이썬 바이낸스 API로 차트 분석 : 판다스 이동평균선
파이썬 바이낸스 API로 코인 가격에 대한 시계열 데이터 분석을 쉽게 할 수 있습니다. 이번 포스팅에서도 캔들 차트를 이용합니다. 파이썬 바이낸스 API의 get_historical_klines() 함수로 시간, 시가, 고가, 저가, 종가 데이터를 가져온 후 판다스 데이터프레임을 이용하여 이동평균선을 구하는 방법과 이동평균선의 활용법에 대해 알아보겠습니다.
글의 순서
이동평균선 (moving average line)
파이썬 바이낸스 API로 가져온 ohlcv 데이터와 이동평균선
판다스 데이터프레임에서 단순 이동평균선을 구하는 방법
단기, 장기 이동평균선 교차 시점으로 예측하는 추세 전환
파이썬 코드 : 판다스 데이터프레임을 이용한 이동평균선
이동평균선 (moving average line)
이동평균선은 주가나 외환의 기술적 분석에서 사용되는 지표입니다. 물론 코인 가격에도 적용할 수 있습니다. 이동평균선은 종가를 기준으로 계산하며, 짧은 시간 동안에 발생한 극심한 가격 변동을 보다 긴 시간에서의 변화로 바꿔주는 역할을 합니다. 그래서 추세를 확인할 수 있습니다. 주가 차트에서의 이동평균선은 일정기간의 주가를 합한 후 해당 기간으로 나눠서 구합니다.
예를 들어, 10일 이동평균선은 과거 10일 동안의 주가를 평균내서 표시하는 방법입니다. 주가는 예측할 수 없이 움직이지만, 평균을 내보면 방향성이 보이지 않을까?라는 가정으로부터 이동평균선이 나왔습니다.
이동평균선은 크게 3가지 정도로 나눌 수 있습니다. 각각 단순 이동평균 SMA(simple moving average), 지수 이동평균 EMA(exponetial moving average), 가중 이동평균 WMA(weighted moving average)입니다. 이번 포스팅에서는 단순 이동평균 SMA을 구해보겠습니다.
파이썬 바이낸스 API로 가져온 ohlcv 데이터와 이동평균선
파이썬 바이낸스 API는 코인 가격을 시계열 데이터로 쉽게 가져올 수 있도록 get_historical_klines() 함수를 제공합니다. get_historical_klines() 함수에 시작점, 끝점을 인자로 넘겨주면서 시계열 데이터 수집 구간을 정할 수 있는데, 만약 끝점을 넘겨주지 않으면 현재까지의 데이터를 가져옵니다. 인자로 넘겨 줄 시간 간격(시작점, 끝점)은 아래처럼 분(m, minute), 시간(h, hour), 일(d, day), 주(w, week), 월(M, month)로 구분할 수 있습니다.
# valid intervals – 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M
get_historical_klines() 함수의 출력값은 ohlcv라는 캔들 데이터 형태입니다. 여기서, o는 시작가(open), h는 최고가(high), l은 최저가(low), c는 종료가(close), 그리고 v는 총 거래량(volume)을 의미합니다. 캔들 차트로부터 특정 시간 간격에서 가격이 어떻게 변화했는지를 알 수 있고, 각 구간별로 이동평균선도 구할 수 있습니다.
판다스 데이터프레임에서 단순 이동평균선을 구하는 방법
시간 간격을 정해서 나온 ohlcv 데이터, 즉 캔들 데이터로 평균을 구합니다. 주식시장에서처럼 시간 간격을 1일이라고 가정해 보겠습니다. 각 날짜에서 종가가 아래의 리스트처럼 수집되었습니다.
prices = [10, 15, 13, 17, 12, 13, 14, …. ]
5일 이동평균선은 위 리스트에서 5개의 엘리먼트를 이용하여 구합니다. 그러니까 5일 이동평균선의 엘리먼트는 다음과 같이 5개의 엘리먼트를 평균하여 구합니다.
1번째 엘리먼트 : 없음
2번째 엘리먼트 : 없음
3번째 엘리먼트 : 없음
4번째 엘리먼트 : 없음
5번째 엘리먼트 : (10+15+13+17+12)/5
6번째 엘리먼트 : (15+13+17+12+13)/5
7번째 엘리먼트 : (13+17+12+13+14)/5
…
1 2 |
df['sma5'] = df['close'].rolling(5).mean() df['sma10'] = df['close'].rolling(10).mean() |
단기, 장기 이동평균선 교차 시점으로 예측하는 추세 전환
이동평균선은 시장의 추세를 보여줍니다. 5일 이동평균선과 10일 이동평균선이 있다면, 말 그대로 5일이 단기, 10일이 장기가 됩니다. 두 이동평균선이 교차하는 지점이 중요한 의미를 지니며, 이 시점을 거래에 참고합니다. 보통 단기 이동평균선이 장기 이동평균선 아래에 있다가 교차해서 위로 올라가는 시점을 매수 시점으로 봅니다.
판다스 데이터프레임과 넘파이(numpy) 라는 파이썬 패키지를 함께 사용하면, 단기 이동평균선과 장기 이동평균선의 교차점을 쉽게 찾아낼 수 있습니다. 참고로, 넘파이(numpy)는 행렬이나 수치 계산에 최적화되어 있어 데이터 분석에 유용하게 사용할 수 있는 라이브러리입니다.
아래는 numpy의 where 함수를 사용해서 두 이동평균선의 교차지점을 찾아내는 코드입니다. np.where(조건, 1, 0) 함수는 조건이 참일 때 1, 거짓일 때 0을 출력합니다. 그러니까 아래 코드는 단기 이동평균선이 장기 이동평균선보다 위에 있을 때 1을 출력하게 합니다. 따라서 df[‘cross’] 열이 0이었다가 1로 바뀌는 시점이 바로 5일 이동평균선이 10일 이동 평균선을 교차해서 위로 올라가는 시점입니다.
1 |
df['cross'] = np.where(df['sma5'] > df['sma10'], 1, 0) |
파이썬 코드 : 판다스 데이터프레임을 이용한 이동평균선
지금까지의 과정을 ‘판다스 데이터프레임을 이용한 이동평균선’ 파이썬 코드에 나타내었습니다. 지난 포스팅 파이썬 바이낸스 API 시계열 데이터분석. 판다스 시간 처리의 판다스로 시계열데이터 전처리 (바이낸스 차트 분석)라는 파이썬 코드에 이동평균선 부분을 덧붙인 코드입니다. 이동평균선 부분만 출력하도록 했습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
import os import time import pandas as pd import numpy as np from binance.client import Client import datetime from datetime import datetime, timezone, timedelta #01) 바이낸스 계정 접속 api_key = os.getenv('Binan_API_KEY') api_secret = os.getenv('Binan_SECRET_KEY') client = Client(api_key, api_secret) print('\n','[ BINANCE ACCOUNT ACCESSED ]') #02) 시계열 데이터 수집 시작 시점 def get_time_stt(timestamp_now, interval, nbar): interval = str(interval) if interval == '1d': timestamp_stt = timestamp_now - nbar*24*60*60 utc_stt = datetime.fromtimestamp(int(timestamp_stt)) elif interval == '4h': timestamp_stt = timestamp_now - nbar*4*60*60 utc_stt = datetime.fromtimestamp(int(timestamp_stt)) elif interval == '15m': timestamp_stt = timestamp_now - nbar*15*60 utc_stt = datetime.fromtimestamp(int(timestamp_stt)) return utc_stt #03) 현재시간 timestamp_now = time.time() utc_now = datetime.fromtimestamp(timestamp_now) #04) 시계열 데이터 수집 시점부터 현재까지의 bar 데이터(ohlcv 데이터) 획득 nbar = 30 utc_ref = get_time_stt(timestamp_now, '15m', nbar) utc_ref_str = datetime.strftime(utc_ref, '%Y-%m-%d %H:%M:%S') bars = client.get_historical_klines('BTCUSDT', '15m', utc_ref_str, limit=1000) #04-1) ohlcv 데이터를 판다스 데이터프레임에 저장 후 출력 df_core = pd.DataFrame(bars) #05) ohlcv 데이터만 추출 for i in bars: del i[7:] df_core = pd.DataFrame(bars) #06) 데이터프레임 열 이름 붙여주기 df_core = pd.DataFrame(bars, columns=['time_open','open','high','low','close','volume','time_close']) #07) 데이터프레임 열 type을 실수형으로 변환 df_core = df_core.astype({'open' : 'float', 'high' : 'float', 'low' : 'float', 'close' : 'float', 'volume' : 'float'}) #08) timestamp를 UTC로 변환 후 리스트로 저장 t_stt = [] t_end = [] for i in bars: t_stt.append(datetime.fromtimestamp(i[0]/1000)) t_end.append(datetime.fromtimestamp(i[6]/1000)) #09) UTC 리스트를 pandas DataFrame으로 저장 df_t_stt = pd.DataFrame(t_stt, columns=['time_open_utc']) df_t_end = pd.DataFrame(t_end, columns=['time_close_utc']) #10) UTC 데이터를 추가하여 pandas DataFrame 완성 df1 = df_t_stt.join(df_core) df = df1.join(df_t_end) #11) 5일, 10일 이동평균선 df['sma5'] = df['close'].rolling(5).mean() df['sma10'] = df['close'].rolling(10).mean() #12) 이동평균선 교차점 df['cross'] = np.where(df['sma5'] > df['sma10'], 1, 0) print(df) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
[ BINANCE ACCOUNT ACCESSED ] time_open_utc time_open open high low ... time_close time_close_utc sma5 sma10 cross 0 2023-01-24 07:45:00 1674546300000 23059.83 23066.37 23006.98 ... 1674547199999 2023-01-24 07:59:59.999 NaN NaN 0 1 2023-01-24 08:00:00 1674547200000 23054.70 23069.00 23033.80 ... 1674548099999 2023-01-24 08:14:59.999 NaN NaN 0 2 2023-01-24 08:15:00 1674548100000 23042.69 23090.25 23042.24 ... 1674548999999 2023-01-24 08:29:59.999 NaN NaN 0 3 2023-01-24 08:30:00 1674549000000 23072.93 23089.11 23042.29 ... 1674549899999 2023-01-24 08:44:59.999 NaN NaN 0 4 2023-01-24 08:45:00 1674549900000 23078.19 23081.64 23045.00 ... 1674550799999 2023-01-24 08:59:59.999 23060.540 NaN 0 5 2023-01-24 09:00:00 1674550800000 23052.67 23058.29 22825.00 ... 1674551699999 2023-01-24 09:14:59.999 23033.610 NaN 0 6 2023-01-24 09:15:00 1674551700000 22920.56 22958.00 22886.87 ... 1674552599999 2023-01-24 09:29:59.999 23008.380 NaN 0 7 2023-01-24 09:30:00 1674552600000 22918.25 22926.46 22770.00 ... 1674553499999 2023-01-24 09:44:59.999 22955.614 NaN 0 8 2023-01-24 09:45:00 1674553500000 22809.93 22889.41 22801.86 ... 1674554399999 2023-01-24 09:59:59.999 22910.534 NaN 0 9 2023-01-24 10:00:00 1674554400000 22852.21 22906.93 22846.12 ... 1674555299999 2023-01-24 10:14:59.999 22876.822 22968.681 0 10 2023-01-24 10:15:00 1674555300000 22884.56 22924.88 22859.52 ... 1674556199999 2023-01-24 10:29:59.999 22875.984 22954.797 0 11 2023-01-24 10:30:00 1674556200000 22915.24 22942.70 22897.81 ... 1674557099999 2023-01-24 10:44:59.999 22878.802 22943.591 0 12 2023-01-24 10:45:00 1674557100000 22931.49 22941.08 22901.01 ... 1674557999999 2023-01-24 10:59:59.999 22897.318 22926.466 0 13 2023-01-24 11:00:00 1674558000000 22902.51 22920.00 22870.00 ... 1674558899999 2023-01-24 11:14:59.999 22907.682 22909.108 0 14 2023-01-24 11:15:00 1674558900000 22904.17 22930.38 22885.73 ... 1674559799999 2023-01-24 11:29:59.999 22915.280 22896.051 1 15 2023-01-24 11:30:00 1674559800000 22923.22 22933.32 22900.00 ... 1674560699999 2023-01-24 11:44:59.999 22912.578 22894.281 1 16 2023-01-24 11:45:00 1674560700000 22902.47 22926.75 22866.23 ... 1674561599999 2023-01-24 11:59:59.999 22909.812 22894.307 1 17 2023-01-24 12:00:00 1674561600000 22917.11 22931.65 22882.09 ... 1674562499999 2023-01-24 12:14:59.999 22907.312 22902.315 1 18 2023-01-24 12:15:00 1674562500000 22891.01 22999.72 22885.62 ... 1674563399999 2023-01-24 12:29:59.999 22925.616 22916.649 1 19 2023-01-24 12:30:00 1674563400000 22994.94 23035.31 22966.31 ... 1674564299999 2023-01-24 12:44:59.999 22938.592 22926.936 1 20 2023-01-24 12:45:00 1674564300000 22988.01 22990.13 22957.60 ... 1674565199999 2023-01-24 12:59:59.999 22951.072 22931.825 1 21 2023-01-24 13:00:00 1674565200000 22963.20 23016.80 22958.22 ... 1674566099999 2023-01-24 13:14:59.999 22967.584 22938.698 1 22 2023-01-24 13:15:00 1674566100000 23000.97 23012.68 22942.36 ... 1674566999999 2023-01-24 13:29:59.999 22980.808 22944.060 1 23 2023-01-24 13:30:00 1674567000000 22957.52 22975.00 22785.01 ... 1674567899999 2023-01-24 13:44:59.999 22946.818 22936.217 1 24 2023-01-24 13:45:00 1674567900000 22827.04 22883.00 22816.79 ... 1674568799999 2023-01-24 13:59:59.999 22921.318 22929.955 0 25 2023-01-24 14:00:00 1674568800000 22860.37 22946.55 22803.74 ... 1674569699999 2023-01-24 14:14:59.999 22915.900 22933.486 0 26 2023-01-24 14:15:00 1674569700000 22937.04 22939.69 22800.01 ... 1674570599999 2023-01-24 14:29:59.999 22886.210 22926.897 0 27 2023-01-24 14:30:00 1674570600000 22853.65 22886.40 22711.00 ... 1674571499999 2023-01-24 14:44:59.999 22863.616 22922.212 0 28 2023-01-24 14:45:00 1674571500000 22843.16 22961.18 22803.40 ... 1674572399999 2023-01-24 14:59:59.999 22870.200 22908.509 0 29 2023-01-24 15:00:00 1674572400000 22859.10 22880.52 22750.01 ... 1674573299999 2023-01-24 15:14:59.999 22862.280 22891.799 0 |
마치며 …
이번 포스팅에서는 파이썬 바이낸스 API의 get_historical_klines() 함수로 시간, 시가, 고가, 저가, 종가 데이터를 가져온 후 판다스 데이터프레임을 이용하여 이동평균선을 구해 보았습니다.
pandas DataFrame의 rolling().mean() 함수로 이동평균선을 쉽게 구했고, 넘파이의 where 함수를 이용해서 장, 단기 이동평균선의 교차지점을 알아내는 방법도 확인하였습니다. 이동평균선을 구할 때 썼던 판다스 데이터프레임 함수 2개를 기억해주시기 바랍니다.
함께 참고하면 좋은 글 :
1. 바이낸스 코인거래소 API Key로 계좌에 접속하는 파이썬 프로그래밍
2. 파이썬 바이낸스 API로 시계열 데이터를 가져오는 파이썬 프로그래밍
3. 바이낸스 API 보안을 위한 환경 변수 설정 : 윈도우 10
4. 파이썬 바이낸스 API 시계열 데이터분석. 판다스 시간 처리
5. 파이썬 IDE 설정. 비주얼 스튜디오 코드(Visual Studio Code, VS code)
6. 파이썬 프로그래밍 time 이해 : timestamp, UTC, KST
7. API와 파이썬 데이터 분석
8. 파이썬 바이낸스 비트코인 투자 백테스팅 : 이동평균선 매매 기법
9. 시계열 데이터 전처리 결과 확인 : pandas DataFrame
10. 파이썬 프로그래밍 시작 (8) 자료구조(Data Structure) : 리스트
11. 파이썬 프로그래밍 시작
참고자료
python-binance Docs >> get_historical_klines