import pandas as pd
from stock.analysis.Common import Common

# 6. Pandas와 Plotly를 이용한 MACD 차트 그리기: https://excelsior-cjh.tistory.com/111
# 스토캐스틱 슬로우(Stochastics Slow)를 이용한 간단한 매매기법: https://bagal.tistory.com/124
# Stochastic Slow, 스토캐스틱을 통한 주식 매매법 정리: https://m.blog.naver.com/PostView.nhn?blogId=kangyh427&logNo=220957146041&proxyReferer=https:%2F%2Fwww.google.com%2F
# 차트분석 2편 스토캐스틱을 활용한 매수타이밍 포착!: https://m.post.naver.com/viewer/postView.nhn?volumeNo=7446693&memberNo=32471429
class Stochastic:

    common = None

    def __init__(self):
        self.common = Common()
        return

    # 일자(n,m,t)에 따른 Stochastic(KDJ)의 값을 구하기 위해 함수형태로 만듬
    # n=15 (%k), m=5 (%d), t=3
    # n=5 (%k), m=3 (%d), t=3
    # n=14 (%k), m=3 (%d), t=3
    def apply(self, df, n=12, m=5, t=5):
        # 입력받은 값이 dataframe이라는 것을 정의해줌
        df = pd.DataFrame(df)

        # n일중 최고가
        ndays_high = df.high.rolling(n).max()
        # n일중 최저가
        ndays_low = df.low.rolling(n).min()

        # Fast%K 계산
        # n(15)일 동안의 최고가(high)와 최저가(low) 사이 중 현재 종가(close)의 상대적 위치를 판단하는 값
        # 가격이 지속적으로 상승하고 있다면 Stochastic 값은 100에 가까워 지며, 반대로 지속적으로 하락하고 있다면 Stochastic 값은 0에 가까워 지는 경향을 나타낸다.
        fast_k = ((df.close - ndays_low) / (ndays_high - ndays_low)) * 100

        # Fast%D (=Slow%K) 계산
        # m(5)일간의 Fast%K의 이동평균 값
        # 기본값으로 5일을 설정하며 Fast%K 값을 일반화하는 역할을 한다.
        #slow_k = fast_k.ewm(span=m).mean()
        slow_k = fast_k.rolling(m).mean()

        # Slow%D 계산
        # t(3)일간의 Slow%K의 이동평균 값
        # 기본값으로 3일을 설정하며 Slow%K 값을 일반화 하는 역할을 한다.
        #slow_d = slow_k.ewm(span=t).mean()
        slow_d = slow_k.rolling(t).mean()

        # dataframe에 컬럼 추가
        #df = df.assign(fast_k=fast_k, slow_k=slow_k, slow_d=slow_d).dropna()
        df = df.assign(fast_k=fast_k, slow_k=slow_k, slow_d=slow_d)

        return df

    """
    def analyze(self, stock):
        df = pd.DataFrame()
        df = df.from_dict(stock['PRICE'])
        df = self.apply(df)

        for i in range(len(df.fast_k)):
            stock['PRICE'][i]['stochastic_buy'] = 0
            if "fast_k" not in stock['PRICE'][i]:
                stock['PRICE'][i]['fast_k'] = -1
                stock['PRICE'][i]['slow_k'] = -1
                stock['PRICE'][i]['slow_d'] = -1

            i_ = i + len(stock['PRICE']) - len(df.fast_k)
            stock['PRICE'][i_]['fast_k'] = df.fast_k.values[i]
            stock['PRICE'][i_]['slow_k'] = df.slow_k.values[i]
            stock['PRICE'][i_]['slow_d'] = df.slow_d.values[i]

            # 0: 중립, 1: 매수, -1: 매도
            stock['PRICE'][i_]['stochastic_buy'] = 0
            stock['PRICE'][i_]['direction'] = ''

            if i_ > 2:
                if ('slow_k' in stock['PRICE'][i_-1] and 'slow_k' in stock['PRICE'][i_]):
                    # %k선이 %d선을 상향 돌파하면 매수 신호
                    if (self.common.checkUpward('slow_k', stock['PRICE'][i_-2:i_+1]) and
                            stock['PRICE'][i_-1]['slow_k'] < stock['PRICE'][i_-1]['slow_d'] and
                            stock['PRICE'][i_]['slow_k'] > stock['PRICE'][i_]['slow_d']):
                        if stock['PRICE'][i_]['slow_k'] < 5:
                            stock['PRICE'][i_]['stochastic_buy'] = 8
                        elif 5 <= stock['PRICE'][i_]['slow_k'] < 10:
                            stock['PRICE'][i_]['stochastic_buy'] = 7
                        elif 10 <= stock['PRICE'][i_]['slow_k'] < 15:
                            stock['PRICE'][i_]['stochastic_buy'] = 6
                        elif 15 <= stock['PRICE'][i_]['slow_k'] < 20:
                            stock['PRICE'][i_]['stochastic_buy'] = 5
                        elif 20 <= stock['PRICE'][i_]['slow_k'] < 30:
                            stock['PRICE'][i_]['stochastic_buy'] = 4
                        elif 30 <= stock['PRICE'][i_]['slow_k'] < 40:
                            stock['PRICE'][i_]['stochastic_buy'] = 3
                        elif 40 <= stock['PRICE'][i_]['slow_k'] < 50:
                            stock['PRICE'][i_]['stochastic_buy'] = 2
                        else:
                            stock['PRICE'][i_]['stochastic_buy'] = 1

                    if self.common.checkUpward('slow_k', stock['PRICE'][i_ - 1:i_ + 1]):
                        stock['PRICE'][i_]['direction'] = 'up'

                    if (self.common.checkDownward('slow_k', stock['PRICE'][i_ - 2:i_ + 1]) and
                            stock['PRICE'][i_-1]['slow_k'] > stock['PRICE'][i_-1]['slow_d'] and
                            stock['PRICE'][i_]['slow_k'] < stock['PRICE'][i_]['slow_d']):
                        if stock['PRICE'][i_]['slow_k'] > 90:
                            stock['PRICE'][i_]['stochastic_buy'] = -6
                        elif 90 >= stock['PRICE'][i_]['slow_k'] > 80:
                            stock['PRICE'][i_]['stochastic_buy'] = -5
                        elif 80 >= stock['PRICE'][i_]['slow_k'] > 70:
                            stock['PRICE'][i_]['stochastic_buy'] = -4
                        elif 70 >= stock['PRICE'][i_]['slow_k'] > 60:
                            stock['PRICE'][i_]['stochastic_buy'] = -3
                        elif 60 >= stock['PRICE'][i_]['slow_k'] > 50:
                            stock['PRICE'][i_]['stochastic_buy'] = -2
                        else:
                            stock['PRICE'][i_]['stochastic_buy'] = -1

                    if self.common.checkDownward('slow_k', stock['PRICE'][i_ - 1:i_ + 1]):
                        stock['PRICE'][i_]['direction'] = 'down'

        results = []
        for day in stock['PRICE']:
            results.append({'DATE': day['DATE'],
                      'fast_k': day['fast_k'],
                      'slow_k': day['slow_k'],
                      'slow_d': day['slow_d'],
                      'stochastic_buy': day['stochastic_buy']})
        return results
    """

    def analyze(self, stock):
        df = pd.DataFrame()
        df = df.from_dict(stock['PRICE'])
        df = self.apply(df)

        for i in range(len(df.fast_k)):
            if "stochastic_fast_k" not in stock['PRICE'][i]:
                stock['PRICE'][i]['stochastic_fast_k'] = -1
                stock['PRICE'][i]['stochastic_slow_k'] = -1
                stock['PRICE'][i]['stochastic_slow_d'] = -1

            stock['PRICE'][i]['stochastic_fast_k'] = df.fast_k.values[i]
            stock['PRICE'][i]['stochastic_slow_k'] = df.slow_k.values[i]
            stock['PRICE'][i]['stochastic_slow_d'] = df.slow_d.values[i]

        return
    
if __name__ == "__main__":
    stochastic = Stochastic()
