본문 바로가기
퀀트 분석/퀀트 활용(통계, 머신러닝)

Pivot Point로 주가 추세 구하기

by 쿼카퀀트 2022. 2. 13.
728x90

안녕하세요, 바쁘다보니 점점 블로그에 글 쓰는 빈도가 줄어들고 있군요..

오늘은 오랜만에 글 쓰는 김에, 원래 자주 다루고 싶었던 주가 데이터 관련 내용을 다뤄보고자 합니다.

 

시작하기 전에, 이번 블로그 내용 및 예시 출처는 위 Adam Grimes의 The Art and Science of Technical Analysis 책을 참고했습니다.

 

Pivot Point란?

오늘은 Pivot Point 지표를 계산해 볼 건데요, Pivot Point란, 단어에서도 알 수 있듯이 주가의 방향이 꺾이는(Pivot) 시점을 의미합니다.

즉, 주가가 상승하다가 하락으로 변하는 시점, 혹은 하락하다가 상승으로 변하는 시점을 의미합니다. 추세가 바뀐다고도 표현하죠?

 

이 '변하는 시점'은 주변 날짜보다 고가(High)/저가(Low)가 높은/낮은 시점으로 정의합니다.

예를 들어, 어제의 고가가 $15, 오늘 고가가 16$, 내일 고가가 $14라면, 오늘이 주변 날짜보다 고가가 높기 때문에 Pivot Point가 되는 것이죠. 이처럼 주변과 비교해 가장 높은 시점을 Pivot High라고 부릅니다.

반대로, 어제의 저가가 $10, 오늘 저가가 $8, 내일 저가가 $9라면, 오늘은 Pivot Low가 됩니다.

 

First, Second, Third order Pivot Point

First-order Pivot Point

위 예시처럼 어제, 내일 시점과 비교한 점을 First-order Pivot Point라고 합니다.

First-order Pivot Point

설명을 돕기 위해, 책에서 예시 하나를 발췌해 왔습니다. 위 차트에서 진한 동그라미가 Pivot High, 연한 동그라미가 Pivot Low입니다. 어제/내일 고가보다 오늘 고가가 높다면 Pivot High, 저가보다 오늘 저가가 낮다면 Pivot Low라는 것이 이해가 되시나요?

 

이해가 되셨다면, 다시 위 차트를 자세히 봐 볼까요?

분명 추세를 구하기 위해 만든 지표인데, 찍힌 점 모양으로 봐선 추세가 전혀 보이지 않습니다. 눈으로 대충 봐도 상당한 상승장인데, Pivot Point는 중구난방으로 찍혀있군요. 이래선 어디에도 써먹지 못하는 지표가 될 것 같습니다.

 

따라서, 이 Pivot Point 중에서 더 의미있는 점들만 뽑아보도록 합시다.

 

Second-order Pivot Point

이번에 구할 값은 Second-order Pivot Point입니다.

First-order Pivot Point에선 앞/뒤 날짜와 비교를 했다면, Second-order Pivot Pointd에선 각 Pivot Point마다 인접한 Pivot Point 끼리 비교합니다.

앞/뒤 Pivot Point의 고가보다 지금 고가가 더 높다면 이를 Second Pivot High, 저가보다 지금 저가가 더 낮다면 Second Pivot Low라고 부릅니다.

 

이것도 아래 예시를 보면서 이해해보세요.

Second-order Pivot Point

위 차트의 진한 화살표가 Second Pivot High, 연한 화살표가 Second Pivot Low를 의미합니다(작은 점은 First Pivot Point입니다). 인접한 Pivot Point보다 높은/낮은 값이라는 것이 이해가 되시나요?

 

Third-order Pivot Point

Second-order Pivot Point는 처음보단 나아지긴 했지만, 그래도 뭔가 석연치 않습니다. 생각보다 시그널도 자주 나오고, 신뢰도도 그렇게 높지는 않아 보입니다.

 

때문에, 또 다시 Pivot Point를 구해봅니다. 앞서 구한 방식과 마찬가지로, 인접한 Second-order Pivot Point끼리 고가/저가를 비교해 Third-order Pivot Point를 구합니다. 구하는 방식은 이제 이해가 가실테니, 생략하겠습니다.

 

다행히 예시는 있습니다.

Third-order Pivot Point

마찬가지로 화살표가 Third-order Pivot Point를 의미합니다. 작은 점은 First-order Pivot Point를 의미합니다. 실제 계산에 필요한 시점은 Second-order인데, 예시엔 First-order만 찍혀있어 보기 좀 힘드실텐데요, 그래프는 Second-order 예시와 동일하니 불편하시더라도 왔다갔다하면서 봐 주시길 바랍니다ㅎㅎ

 

이렇게 구한 Third-order Pivot Point는 확실히 추세가 좀 더 잘 보이는군요!

하락하는 두 시점에서 정확히 Pivot High가 보이고, 상승장에선 Pivot Low가 찍혀있는 모습입니다.

 

Pivot Point 활용 방법

"아니 그럼 이제 이걸로 투자하면 되는거 아닌가요? Pivot Low 시그널에 매수, Pivot High 시그널에 매도하면 되잖아요?"

라는 생각을 하셨다면, 슬픈 소식이 있습니다.

 

Pivot Point는 실전 투자에서 효용이 매우 떨어집니다.

왜냐면, Third-order Pivot Point를 구하기 위해선 미래 시점의 Second-order Pivot Point를 알아야하고, 이를 구하려면 또 다시 그보다 더 미래 시점의 First-order Pivot Point를 알아야하기 때문입니다.

따라서 우리가 원하는 Pivot Point 시그널이 나타났을땐 이미 진입 타이밍을 한참 놓친 후일겁니다.

 

"아니 그럼 이건 대체 왜 알려준거죠? 죄송한데 주린이신가요?"

라는 생각을 또 하셨다면, 다행히 Pivot Point도 다 쓸모가 있습니다.

 

Pivot Point 활용의 한 가지 예시로, 학습 데이터 생성이 있습니다.

머신러닝 등, 학습을 기반으로 하는 기법에는 학습 데이터셋이 꼭 필요합니다. 많은 경우, 이 학습 데이터셋에는 정답 값(Y)도 필요합니다.

그렇다면, 현재 추세가 상승/하락인지 예측하는 모델을 만든다면 추세의 상승/하락 여부를 Y값으로 만들어야 하는데, 이 Y값을 어떻게 계산할 수 있을까요?

이때 Pivot Point를 활용할 수 있습니다. Pivot High 이후 시점은 모두 하락기, Pivot Low 이후 시점은 모두 상승기로 나누는 등 말이죠!

참고한 책에 나와있는 활용 용도는 아니지만, 제가 생각하기에 가장 유용하게 활용할 수 있는 방법은 이건 것 같습니다.

 

Pivot Point 계산 코드

그럼 파이썬으로 Pivot Point를 직접 계산해볼까요?

사용한 데이터는 비트코인 4시간봉입니다.

 

바로 코드 보시죠.

def get_pivot(data):
    # PIVOT ORDER1
    v = data.copy()

    past_diff = v['high'].pct_change(1).values # +면 어제보다 오늘 가격이 더 높다는 뜻
    future_diff = v['high'].pct_change(-1).values # +면 오늘보다 내일 가격이 더 낮다는 뜻
    pivot_high_order1 = np.array([1 if past_diff[i] > 0 and past_diff[i] * future_diff[i] > 0 else 0 for i in range(len(past_diff))])

    past_diff = v['low'].pct_change(1).values # +면 어제보다 오늘 가격이 더 높다는 뜻
    future_diff = v['low'].pct_change(-1).values # +면 오늘보다 내일 가격이 더 낮다는 뜻
    pivot_low_order1 = np.array([-1 if past_diff[i] < 0 and past_diff[i] * future_diff[i] > 0 else 0 for i in range(len(past_diff))])

    v['pivot_order1'] = pivot_high_order1 + pivot_low_order1

    # PIVOT ORDER2
    v2 = v[v['pivot_order1'] > 0]

    past_diff = v2['high'].pct_change(1).values # +면 어제보다 오늘 가격이 더 높다는 뜻
    future_diff = v2['high'].pct_change(-1).values # +면 오늘보다 내일 가격이 더 낮다는 뜻
    pivot_high_order2 = np.array([1 if past_diff[i] > 0 and past_diff[i] * future_diff[i] > 0 else 0 for i in range(len(past_diff))])
    pivot_order2 = pd.DataFrame(pivot_high_order2,index=v2.index,columns=['pivot_order2_high'])
    v = v.join(pivot_order2)

    v2 = v[v['pivot_order1'] < 0]
    past_diff = v2['low'].pct_change(1).values # +면 어제보다 오늘 가격이 더 높다는 뜻
    future_diff = v2['low'].pct_change(-1).values # +면 오늘보다 내일 가격이 더 낮다는 뜻
    pivot_low_order2 = np.array([-1 if past_diff[i] < 0 and past_diff[i] * future_diff[i] > 0 else 0 for i in range(len(past_diff))])
    pivot_order2 = pd.DataFrame(pivot_low_order2,index=v2.index,columns=['pivot_order2_low'])
    v = v.join(pivot_order2)
    v.fillna(0,inplace=True)

    v['pivot_order2'] = v['pivot_order2_high'] + v['pivot_order2_low']
    del v['pivot_order2_high']
    del v['pivot_order2_low']

    # PIVOT ORDER3
    v2 = v[v['pivot_order2'] > 0]
    past_diff = v2['high'].pct_change(1).values # +면 어제보다 오늘 가격이 더 높다는 뜻
    future_diff = v2['high'].pct_change(-1).values # +면 오늘보다 내일 가격이 더 낮다는 뜻
    pivot_high_order3 = np.array([1 if past_diff[i] > 0 and past_diff[i] * future_diff[i] > 0 else 0 for i in range(len(past_diff))])
    pivot_order3 = pd.DataFrame(pivot_high_order3,index=v2.index,columns=['pivot_order3_high'])
    v = v.join(pivot_order3)

    v2 = v[v['pivot_order2'] < 0]
    past_diff = v2['low'].pct_change(1).values # +면 어제보다 오늘 가격이 더 높다는 뜻
    future_diff = v2['low'].pct_change(-1).values # +면 오늘보다 내일 가격이 더 낮다는 뜻
    pivot_low_order3 = np.array([-1 if past_diff[i] < 0 and past_diff[i] * future_diff[i] > 0 else 0 for i in range(len(past_diff))])
    pivot_order3 = pd.DataFrame(pivot_low_order3,index=v2.index,columns=['pivot_order3_low'])
    v = v.join(pivot_order3)
    v.fillna(0,inplace=True)

    v['pivot_order3'] = v['pivot_order3_high'] + v['pivot_order3_low']
    del v['pivot_order3_high']
    del v['pivot_order3_low']

    return v

def draw_pivot(data):
    v2 = data.copy()

    plt.plot(v2['low'],linewidth=0.5,c='k')
    plt.plot(v2['high'],linewidth=0.5,c='k')

    plt.scatter(v2[v2['pivot_order1'] > 0].index,v2[v2['pivot_order1'] > 0]['high'],s=10,c='k')
    plt.scatter(v2[v2['pivot_order1'] < 0].index,v2[v2['pivot_order1'] < 0]['low'],s=10,c='k')

    plt.scatter(v2[v2['pivot_order2'] > 0].index,v2[v2['pivot_order2'] > 0]['high'],s=50,c='b')
    plt.scatter(v2[v2['pivot_order2'] < 0].index,v2[v2['pivot_order2'] < 0]['low'],s=50,c='r')

    plt.scatter(v2[v2['pivot_order3'] > 0].index,v2[v2['pivot_order3'] > 0]['high'],s=200,c='b',marker='s')
    plt.scatter(v2[v2['pivot_order3'] < 0].index,v2[v2['pivot_order3'] < 0]['low'],s=200,c='r',marker='s')
    plt.show()

 

코드를 막 적었더니 유난히 반복이 심하지만, 그래도 길진 않고 내용도 쉬우니 쉽게 이해할 수 있을 것 같습니다. 이해되지 않는 부분이 있다면, 댓글로 알려주세요.

 

위 코드로 Pivot Point를 구해보면 아래와 같습니다.

draw_pivot(get_pivot(data['KRW-BTC']))

두 개의 검은 선은 각각 고가, 저가를 의미합니다.

또, 검은 점은 First-order Pivot Point,

작은 파랑/빨강 점은 Second-order Pivot Point,

큰 파랑/빨강 네모는 Third-order Pivot Pont를 의미합니다.

(파랑은 Pivot High, 빨강은 Pivot Low)

 

Third-order만 보면, 꽤 추세를 잘 구분하고 있다는 생각이 들지 않나요?

 

 

결론

지금까지 Pivot Point 구하는 방법과 활용 방법, 그리고 실제 구하는 코드를 살펴봤습니다.

 

Pivot Ponit는 추세가 명확할 경우, 꽤 정확한 모습을 보입니다. 하지만, 횡보장처럼 명확한 추세가 없는 경우엔 오히려 없는 추세를 가져와 오묘한 결과물을 가져올 수 있습니다.

때문에, 앞서 설명한대로 Pivot Point를 머신러닝의 학습 데이터셋을 만드는 등으로 활용할 시, 현재 추세에 대해 정확히 파악하기 위해선 다른 지표를 함께 섞어가며 사용하면 좋을 것 같습니다.

 

지금까지 Pivot Point에 대해 간단히 설명해 보았습니다.

그럼 모두 성투하세요!

728x90

댓글