상세 컨텐츠

본문 제목

비트코인 가격예측3

프로그래밍/경진대회(데이콘, 캐글)

by 아싸호랑나비 2022. 10. 12. 14:30

본문

2편

https://nanke.tistory.com/134

데이터구하기

처음부터 다시시작하는 마음으로 데이터를 구해보자

이번엔 btc/usd를 가져오자 (모델이 잘나오면 바이낸스 선물을 해보려고한다ㅎ)

야후 파이낸스를 이용했다 

reference: https://medium.com/analytics-vidhya/python-how-to-get-bitcoin-data-in-real-time-less-than-1-second-lag-38772da43740

 

처음에 보자마자 조금 당황스러웠던 이유는 volume(거래량)부분이 결측값이 많았기때문이다 아무래도 제거를 해야할것같다

찝찝하긴하지만 2편에서 feature importance구해봤을때도 거래량은 상대적으로 importance가 낮았으니 불행중 다행인것같다

adj close에대해서도 처음 보는 부분이라 찾아보았는데 회사측의 영향을 받아 계산되는 종가라하니

비트코인에서는 중요하지 않은부분인것같아 그냥 제거하면 될것같다 

모든 데이터는 상대적인값

절대적인값을 이용하지 않을생각이다 내일 오르는지 내리는지를 맞추는 문제에서 매일매일의 절대적인 가격데이터를 활용하는것은

의미가 없다고 판단하였다 

오늘 종가는 어제종가보다 13% 올랐습니다 내일은 오를까요 내릴까요? (O)

오늘 종가는 37000원입니다 내일은 오를까요 내릴까요? (X)

이격도를 구하자

이격도=(주가 / N일 이동평균지수) * 100이다

일단 이동평균선을 먼저구해보자

reference: https://wendys.tistory.com/178

 

바이낸스 이평선: 7, 25, 99

키움 이평선 5, 10, 20, 60, 120

그외 사람들이 많이쓰는것같은 50, 100, 200

btc['ma7'] = btc['Close'].rolling(7).mean()

이평선을 만들어서 생긴 결측값들은 제거를 해주었다

그후 간단한 코드로 이격도를 만들어주었다

btc['dp7'] = btc['Close']/btc['ma7']

이격도를 보고 현재 추세가 어떻게되는지를 알수있을것이다

각종지표들 추가

예전에 머신러닝을 시도해봤을때 어디선가 퍼온 코드들이 있었고 

그대로 이용해봤다 정확한지는 모른다 귀찮으니까 그냥 바로 이용해주었다

ADX

def get_adx(high, low, close, lookback):
    plus_dm = high.diff()
    minus_dm = low.diff()
    plus_dm[plus_dm < 0] = 0
    minus_dm[minus_dm > 0] = 0
    
    tr1 = pd.DataFrame(high - low)
    tr2 = pd.DataFrame(abs(high - close.shift(1)))
    tr3 = pd.DataFrame(abs(low - close.shift(1)))
    frames = [tr1, tr2, tr3]
    tr = pd.concat(frames, axis = 1, join = 'inner').max(axis = 1)
    atr = tr.rolling(lookback).mean()
    
    plus_di = 100 * (plus_dm.ewm(alpha = 1/lookback).mean() / atr)
    minus_di = abs(100 * (minus_dm.ewm(alpha = 1/lookback).mean() / atr))
    dx = (abs(plus_di - minus_di) / abs(plus_di + minus_di)) * 100
    adx = ((dx.shift(1) * (lookback - 1)) + dx) / lookback
    adx_smooth = adx.ewm(alpha = 1/lookback).mean()
    return plus_di, minus_di, adx_smooth

btc['plus_di'] = pd.DataFrame(get_adx(btc['High'], btc['Low'], btc['Close'], 14)[0]).rename(columns = {0:'plus_di'})
btc['minus_di'] = pd.DataFrame(get_adx(btc['High'], btc['Low'], btc['Close'], 14)[1]).rename(columns = {0:'minus_di'})
btc['adx'] = pd.DataFrame(get_adx(btc['High'], btc['Low'], btc['Close'], 14)[2]).rename(columns = {0:'adx'})

RSI

def computeRSI (data, time_window):
    diff = data.diff(1).dropna()        # diff in one field(one day)

    #this preservers dimensions off diff values
    up_chg = 0 * diff
    down_chg = 0 * diff
    
    # up change is equal to the positive difference, otherwise equal to zero
    up_chg[diff > 0] = diff[ diff>0 ]
    
    # down change is equal to negative deifference, otherwise equal to zero
    down_chg[diff < 0] = diff[ diff < 0 ]
    
    # check pandas documentation for ewm
    # https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.ewm.html
    # values are related to exponential decay
    # we set com=time_window-1 so we get decay alpha=1/time_window
    up_chg_avg   = up_chg.ewm(com=time_window-1 , min_periods=time_window).mean()
    down_chg_avg = down_chg.ewm(com=time_window-1 , min_periods=time_window).mean()
    
    rs = abs(up_chg_avg/down_chg_avg)
    rsi = 100 - 100/(1+rs)
    return rsi

btc['RSI'] = computeRSI(btc['Close'], 14)

 

STOCHASTIC

def stochastic(data, k_window, d_window, window):
    
    # input to function is one column from df
    # containing closing price or whatever value we want to extract K and D from
    
    min_val  = data.rolling(window=window, center=False).min()
    max_val = data.rolling(window=window, center=False).max()
    
    stoch = ( (data - min_val) / (max_val - min_val) ) * 100
    
    K = stoch.rolling(window=k_window, center=False).mean() 
    #K = stoch
    
    D = K.rolling(window=d_window, center=False).mean() 


    return K, D

btc['K'], btc['D'] = stochastic(btc['RSI'], 3, 3, 14)

보조지표는 이정도추가하면 될것같다

 

결과는 좋아졌을까

프로세스중간마다 저장하는 습관

프로세스 중간마다 결과를 확인하여 나아지고 있는지를 확인하는것은

 

옳은길을가고있는지 틈틈히 지도를 보는것과 같다

 

보조지표를 추가하고 결과는 좋아졌는지 확인해보자 기대가 된다

생각보다 훨씬 형편없는 결과가 나왔다

 

결국 중요한것은 데이터의 양?

결과를 믿을수가 없어서 upbit데이터로 같은 과정을 진행하였다

아 업비트는 value와 volume이 추가되어있고, 데이터의 양이 4만건으로 야후 파이낸스보다 2~3배 더많다

왼쪽이 보조지표 추가전 오른쪽이 추가후이다 진짜 쪼오오오금 올랐다(안떨어진게 다행이라 생각하긴한다)

 

feature importance는 다음과같다

sigmoid를 잘못이해한사람

이진분류를 할때 마지막레이어로 sigmoid를 쓰면 이진분류가 된다고해서 그렇게했는데

1과0으로 분리되는것이아닌 1과0사이 숫자들만 나와서 이게 아닌가 하다가

softmax함수를 써보게 되었고 1과0으로 분리가 되었으나 모두 1로 예측하는바람에 골치가 아팠었다

softmax는 세개이상으로 분류하는 다중클래스 분류에 사용되는 활성화 함수였다

 

정리해서 말하자면

  • sigmoid: 0과1사이의 값반환 특정숫자에 더 가까운것으로 이진분류가능
  • softmax: 3개이상 다중분류에 쓰임

따라서 다시 딥러닝을 도전하기로 한다

 

다음편에서 계속..

 

 

관련글 더보기