파이썬 바이낸스 API로 차트 분석. 판다스 스토캐스틱

파이썬 바이낸스 API로 차트 분석. 판다스 스토캐스틱

파이썬 바이낸스 API로 코인 가격에 대한 시계열 데이터 분석을 쉽게 할 수 있습니다. 이번 포스팅에서도 캔들 차트를 이용합니다. 파이썬 바이낸스 API의 get_historical_klines() 함수로 시간, 시가, 고가, 저가, 종가 데이터를 가져온 후 판다스 데이터프레임을 이용하여 차트 보조지표 중 스토캐스틱 구하는 방법과 스토캐스틱의 활용법에 대해 알아보겠습니다.


글의 순서

스토캐스틱 오실레이터 (Stochastic Oscillator) 개념
스토캐스틱이 보여주는 과매수, 과매도 상태
스토캐스틱 종류
스토캐스틱 이용 방법
파이썬 코드 : 바이낸스 API, 판다스 데이터프레임을 이용한 스토캐스틱


스토캐스틱 오실레이터 (Stochastic Oscillator) 개념

스토캐스틱은 주가의 마감 가격(종가)가 어떤 기간 내에서 어느 곳에 있었는지를 나타내주는 보조지표입니다. 최근 n일간의 최고가와 최저가의 범위 내에서 현재 가격의 위치를 표시해 줍니다. 물론 지난 포스팅의 이동평균선처럼 코인 가격에도 적용 가능합니다. 스토캐스틱은 매수세가 강할 때 높은 위치에, 매도세가 강할 때는 낮은 위치에 형성됩니다.

예를 들어, 어떤 주식의 최근 5일간 최고가가 10000원, 최저가가 5000원이었고, 현재가가 9000원이라면 매수세가 강하며, 오르는 추세라는 것을 알 수 있습니다. 반대로 현재가가 6000원이라면 매도세가 강하고 내리는 추세인 것입니다.

이제는 현재가를 스토캐스틱으로 환산해 보겠습니다. 현재가 9000원은 80%입니다. 최고가와 최저가의 차이, 그러니까 가격 변동폭이 5000원이고, 현재가는 최저가로부터 4000원이 높은 위치이므로, 변동폭 대비 80%가 됩니다. 4000/5000 × 100(%) = 80%로부터 구할 수 있습니다. 만약 현재가가 6000원이라면 최저가로부터 1000원이 높은 위치이며, 1000/5000 × 100(%) = 20%가 됩니다.



스토캐스틱이 보여주는 과매수, 과매도 상태

현재가가 5일간의 구간에서 최고가인 10000원이라면, 스토캐스틱은 100%이니까 매수세가 가장 강한 경우입니다. 100%에 가까울수록 과매수 상태, 0%에 가까울수록 과매도 상태라고 판단할 수 있습니다. 그러니까 현재 가격이 어느 정도 위치에 있는지를 알 수 있게 해주는 지표입니다.


스토캐스틱 종류

2가지 종류가 있습니다. 하나는 Fast Stochastic, 다른 하나는 Slow Stochastic입니다. 패스트스토캐스틱은 주가의 변동이 자주 발생해서 단기매매, 빠른 매매에 유리한 지표입니다. 그런데, 패스트 스토캐스틱은 변동이 잦아서 투자 판단에 어려움이 있습니다. 이를 느리게 만든 것이 슬로 스토캐스틱입니다. 위의 ‘스토캐스틱 오실레이터 개념’ 에서 계산했던 스토캐스틱이 바로 Fast 스토캐스틱입니다.

▶스토캐스틱 %K = (현재가 – n일 중 최저가)/(n일 중 최고가 – n일 중 최저가) × 100
▶스토캐스틱 %D = m일 동안 %K의 평균
▶Slow %K = 스토캐스틱 %D
▶Slow %D = t 일 동안의 Slow %K 평균

여기서, n, m, t라는 날짜가 나왔는데요, 보통 (n, m, t) = (5, 3, 3), (10, 6, 6), (14, 3, 3), (20, 12, 12)의 4가지를 주로 사용합니다. (n-m-t) = (5-3-3)의 의미를 살펴보면, 먼저 최근 5일간의 최고점과 최저점을 이용하여 스토캐스틱 %K를 구합니다. 이렇게 구한 %K의 3일 동안의 평균으로 스토캐스틱 %D를, 3일 동안의 스토캐스틱 %D(=Slow %K) 평균으로 Slow %D를 구한다는 의미입니다.


스토캐스틱 이용 방법

차트 보조지표 스토캐스틱은 일정한 방향이 없는 박스권의 구간에서 효과적입니다. 보통 Slow %K선이 20이하의 과매도 구간까지 하락했다가, 다시 상승할 때를 매수 시점으로 보고, 80 이상의 과매수 구간까지 상승했다가 다시 하락할 때를 매도 신호로 봅니다.

좀 더 구체적으로 정리해보면 다음과 같습니다.
▶ 매수 : 스토캐스틱 20 이하, %K 선이 %D를 상향돌파
▶ 매도 : 스토캐스틱 80 이상, %K 선이 %D를 하향돌파

판다스 데이터프레임과 넘파이(numpy) 라는 파이썬 패키지를 함께 사용하면, 상향 또는 하향 돌파할 때의 교차점을 쉽게 찾아낼 수 있습니다.

아래는 numpy의 where 함수를 사용해서 두 스토캐스틱의 교차지점을 찾아내는 코드입니다. np.where(조건, 1, 0) 함수는 조건이 참일 때 1, 거짓일 때 0을 출력합니다. 그러니까 아래 코드는 %K가 %D 보다 위에 있을 때 1을 출력하게 합니다. 따라서 df[‘cross’] 열이 0이었다가 1로 바뀌는 시점이 바로 %K가 %D를 교차한 후 위로 올라가는 시점입니다.

df['cross'] = np.where(df['slow_k'] > df['slow_d'], 1, 0)
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 == '1h':
        timestamp_stt = timestamp_now - nbar*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

#02-0) simple moving average
def get_sma(close, n):
    sma = close.rolling(n).mean()
    return sma

#02-1) 스토캐스틱 Fast %K = ((현재가 - n기간 중 최저가) / (n기간 중 최고가 - n기간 중 최저가)) * 100
def get_stochastic_fast_k(high, low, close, n):
  fast_k = ((close - low.rolling(n).min()) / (high.rolling(n).max() - low.rolling(n).min())) * 100
  return fast_k

#02-2) 스토캐스틱 Slow %K = Fast %K의 m기간 이동평균(SMA)
def get_stochastic_slow_k(fast_k, m):
  slow_k = fast_k.rolling(m).mean()
  return slow_k

#02-3) Slow %D = Slow %K의 t기간 이동평균(SMA)
def get_stochastic_slow_d(slow_k, t):
  slow_d = slow_k.rolling(t).mean()
  return slow_d

#03) 현재시간
timestamp_now = time.time()
utc_now = datetime.fromtimestamp(timestamp_now)

#04) 바이낸스 API 시계열 데이터 수집 시점부터 현재까지의 bar 데이터(ohlcv 데이터) 획득 
nbar = 30d
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) 스토캐스틱 기간 
n = 5
m = 3
t = 3 

#11-1) 스토캐스틱 Fast %K 
df['fast_k'] = get_stochastic_fast_k(df['high'], df['low'], df['close'], n)

#11-2) 스토캐스틱 Slow %K = Fast %K의 m기간 이동평균(SMA)
df['slow_k'] = get_stochastic_slow_k(df['fast_k'], m)

#11-3) Slow %D = Slow %K의 t기간 이동평균(SMA)
df['slow_d'] = get_stochastic_slow_d(df['slow_k'], t)

#11-4) Slow %K와 Slow %D의 교차점
df['cross_sto'] = np.where(df['slow_k'] > df['slow_d'], 1, 0)

print(df)

 [ BINANCE ACCOUNT ACCESSED ]

         time_open_utc      time_open      open      high       low  ...          time_close_utc     fast_k     slow_k     slow_d  cross_sto
0  2023-01-26 05:30:00  1674711000000  23171.00  23179.16  23130.69  ... 2023-01-26 05:44:59.999        NaN        NaN        NaN          0      
1  2023-01-26 05:45:00  1674711900000  23136.10  23172.07  23130.55  ... 2023-01-26 05:59:59.999        NaN        NaN        NaN          0      
2  2023-01-26 06:00:00  1674712800000  23148.26  23164.11  23120.01  ... 2023-01-26 06:14:59.999        NaN        NaN        NaN          0      
3  2023-01-26 06:15:00  1674713700000  23153.17  23155.38  22897.17  ... 2023-01-26 06:29:59.999        NaN        NaN        NaN          0      
4  2023-01-26 06:30:00  1674714600000  23001.67  23061.63  22979.59  ... 2023-01-26 06:44:59.999  53.494805        NaN        NaN          0      
5  2023-01-26 06:45:00  1674715500000  23049.23  23091.24  23045.17  ... 2023-01-26 06:59:59.999  69.370680        NaN        NaN          0      
6  2023-01-26 07:00:00  1674716400000  23088.63  23096.78  23032.19  ... 2023-01-26 07:14:59.999  57.548513  60.137999        NaN          0      
7  2023-01-26 07:15:00  1674717300000  23050.79  23057.79  23004.12  ... 2023-01-26 07:29:59.999  51.403896  59.441030        NaN          0      
8  2023-01-26 07:30:00  1674718200000  23029.35  23046.79  22951.27  ... 2023-01-26 07:44:59.999  19.957391  42.969933  54.182987          0      
9  2023-01-26 07:45:00  1674719100000  22979.58  23014.74  22957.10  ... 2023-01-26 07:59:59.999  10.624699  27.328662  43.246542          0      
10 2023-01-26 08:00:00  1674720000000  22965.81  23026.36  22964.02  ... 2023-01-26 08:14:59.999  43.900763  24.827618  31.708738          0      
11 2023-01-26 08:15:00  1674720900000  23014.48  23031.07  22944.30  ... 2023-01-26 08:29:59.999  30.575381  28.366948  26.841076          1      
12 2023-01-26 08:30:00  1674721800000  22979.00  23028.00  22923.56  ... 2023-01-26 08:44:59.999  82.910006  52.462050  35.218872          1      
13 2023-01-26 08:45:00  1674722700000  23025.90  23048.49  22999.10  ... 2023-01-26 08:59:59.999  64.283999  59.256462  46.695153          1      
14 2023-01-26 09:00:00  1674723600000  23003.11  23036.69  23000.04  ... 2023-01-26 09:14:59.999  84.583367  77.259124  62.992545          1      
15 2023-01-26 09:15:00  1674724500000  23028.55  23029.33  22945.64  ... 2023-01-26 09:29:59.999  35.788041  61.551802  66.022463          0      
16 2023-01-26 09:30:00  1674725400000  22968.26  22981.23  22900.00  ... 2023-01-26 09:44:59.999  50.952926  57.108111  65.306346          0      
17 2023-01-26 09:45:00  1674726300000  22976.68  23007.06  22955.26  ... 2023-01-26 09:59:59.999  47.612634  44.784534  54.481482          0      
18 2023-01-26 10:00:00  1674727200000  22970.70  22988.65  22915.19  ... 2023-01-26 10:14:59.999  20.528203  39.697921  47.196855          0      
19 2023-01-26 10:15:00  1674728100000  22927.21  22981.96  22879.39  ... 2023-01-26 10:29:59.999  65.586234  44.575690  43.019382          1      
20 2023-01-26 10:30:00  1674729000000  22977.31  22995.72  22926.83  ... 2023-01-26 10:44:59.999  47.364299  44.492912  42.922174          1      
21 2023-01-26 10:45:00  1674729900000  22939.86  22957.51  22850.01  ... 2023-01-26 10:59:59.999  56.829035  56.593189  48.553931          1      
22 2023-01-26 11:00:00  1674730800000  22939.26  22946.82  22895.48  ... 2023-01-26 11:14:59.999  44.602292  49.598542  50.228214          0      
23 2023-01-26 11:15:00  1674731700000  22915.55  22975.60  22909.12  ... 2023-01-26 11:29:59.999  75.080640  58.837322  55.009685          1      
24 2023-01-26 11:30:00  1674732600000  22959.57  22980.41  22952.10  ... 2023-01-26 11:44:59.999  83.350491  67.677808  58.704557          1      
25 2023-01-26 11:45:00  1674733500000  22970.86  22993.90  22947.31  ... 2023-01-26 11:59:59.999  99.332824  85.921318  70.812149          1      
26 2023-01-26 12:00:00  1674734400000  22992.09  23033.00  22966.56  ... 2023-01-26 12:14:59.999  56.057301  79.580205  77.726444          1      
27 2023-01-26 12:15:00  1674735300000  22972.57  23065.45  22962.20  ... 2023-01-26 12:29:59.999  84.072155  79.820760  81.774094          0      
28 2023-01-26 12:30:00  1674736200000  23042.09  23132.99  23038.36  ... 2023-01-26 12:44:59.999  76.610297  72.246584  77.215850          0      
29 2023-01-26 12:45:00  1674737100000  23089.56  23097.07  23081.03  ... 2023-01-26 12:59:59.999  78.258294  79.646915  77.238087          1      

[30 rows x 13 columns]

댓글 남기기