본문 바로가기
데이터과학/데이터 분석 실습

OBV 거래량 지표를 이용한 알고리즘 투자 전략 (feat. 파이썬)

by 경성현 2020. 12. 25.
주의: 이 글은 교육적인 목적으로 작성되었습니다. 투자 조언으로 받아 들여서는 안되며, 투자는 본인의 재량에 따라 하십시오.

이번 글에서는 On-Balance Volume이라는 거래량 지표와 파이썬 프로그래밍을 사용한 간단한 거래 전략에 대해 설명해 드리겠습니다. 주식 시장의 모멘텀 방향을 예측하는 것은 매우 어려운 일이긴 하지만 한번 시도해 보겠습니다. 통계와 확률에 대해 잘 이해하고있는 사람도 이번에 소개드릴 내용을 이해하고 프로그래밍하는데 어려움을 겼을 수 있습니다. 알고리즘 거래는 가격, 타이밍, 그리고 거래량과 같은 변수를 이용하여 미리 프로그래밍된 자동화 거래 지침을 사용하여 주문을 실행하는 프로세스입니다.

금융 분야에서 가장 인기 있는 프로그래밍 언어 중 하나인 파이썬과 On-Balance Volume (OBV)이라는 지표를 이용하여 주식을 매매 할 시기를 알 수 있는 거래 전략을 만들어 보겠습니다.

OBV (On-Balance Volume) 란 무엇입니까? 

거래량 균형(OBV)은 주식 거래량 흐름을 사용하여 주가의 변화를 예측하는 기술 거래 모멘텀 지표입니다. Joseph Granville은 1963년 저서 New Key to Stock Market Profits에서 처음으로 OBV 지표를 발표했습니다. Granville은 거래량이 시장의 핵심 원동력이라고 믿고 거래량 변화에 따라 시장의 주요 움직임이 발생할 때를 예측 할 수 있도록 OBV를 설계했습니다. Granville는 거의 저서에서 OBV에 의해 생성 된 예측을 "단단하게 감긴 스프링"이라고 설명했습니다. 그는 주가의 큰 변화없이 거래량이 급격히 증가하면 결국 가격이 상승하거나 하락할 것이라고 믿었습니다.

OBV 추세 신호

  • 가격과 OBV 모두 더 높은 정점과 더 높은 저점을 만들면 상승 추세가 계속 될 것입니다. 
  • 가격이 계속해서 저점을 낮추고 OBV가 저점을 낮추지 못하면 하락 추세가 정체되거나 반등 할 가능성이 높습니다.이를 포지티브 다이버전스라고 합니다. 
  • 거래 기간 동안 OBV가 상승하면 누적이 발생할 수 있습니다. 이는 상승 돌파에 대한 경고입니다. 
  • 거래 기간 동안 OBV가 하락하면 분배가 발생할 수 있습니다. 이는 하락 돌파에 대한 경고입니다. 
  • 가격이 계속해서 더 높은 피크를 만들고 OBV가 더 높은 피크를 만들지 못하면 상승 추세가 정체되거나 실패 할 가능성이 있습니다.이를 음의 발산이라고 합니다. 
  • 가격이 계속해서 저점을 낮추고 OBV가 저점을 낮추지 못하면 하락 추세가 정체되거나 실패 할 가능성이 높습니다. 이를 양의 발산이라고 합니다.

OBV 계산 방법

OBV는 다음 공식에 의해서 계산됩니다.    

 

OBV를 이용한 매수/매도 타이밍 전략 

전략 #1 

OBV를 사용하는 거래자는 거래 전략을 세우기 위해 OBV의 변화율에 관심을 가지는 경우가 있습니다. OBV가 상승 방향으로 움직이고 있다면 큰 주가 상승이 올 수 있다고 생각 할 수 있고, OBV가 하락 방향으로 움직이고 있다면 큰 주가 하락을 생각할 수 있습니다. 예를 들어, OBV가 해당 가격 변동보다 빠르게 하락하면 조만간 엄청나게 큰 가격 하락이 올 가능성이 있음을 알 수 있습니다.

전략 #2

OBV에 이동 평균을 추가하여 주식을 매매 할 시기를 결정하고 교차점(Cross-over)을 신호로 거래할 수도 있습니다. 이것이 이번에 소개해 드릴 내용입니다.

OBV가 지수 이동 평균 (EMA) 이상에서 거래를 시작하면 주식을 매수할 타이밍을 의미합니다.
OBV가 지수 이동 평균 (EMA) 아래에서 거래를 시작하면 주식을 매도할 타이밍을 의미합니다.

참고 : OBV의 장기 이동 평균으로 100일 기간 지수 이동 평균을 추가하면 단기 이동 평균보다 더 효과적입니다. 200 지수 이동 평균은 매수/매도 타이밍을 조금 더 적게 산출해 줍니다. OBV에서 매수/매도 타이밍을 Whipsaw라고 하는데, 이는 특정 시간에 유가 증권의 가격이 한 방향으로 움직이다가 반대 방향으로 빠르게 움직일 때를 의미하며 주식의 매수와 매도에 대한 거래량의 움직임을 설명해 줍니다.

OBV 전략의 요점 

OBV는 거래량이 늘어난 날과 내려간날의 단순 누적 합계입니다. OBV가 가격과 함께 움직이면 현재 추세와 동행하고 있음을 알 수 있습니다. OBV와 가격 사이의 차이가 발생한다면 주가 흐림이 반전 될 수 있음을 의미합니다. 추세선을 사용하면 OBV와 가격 흐림에 차이가 발생하는지 파악하여 거래 기회를 획득하는데 도움이 될 수 있습니다. OBV는 가격 변화 방향을 예측하는데도 도움이 됩니다. OBV를 이용함에 있어 주의해야 할 점이 있습니다. 가령, 어떤 특별한 이유 없이 거래량이 급증하는 경우가 있는데, 이런 경우에는 지표가 왜곡되어 객관적인 해석을 더 어려워 지기도 합니다. 또한 OBV가 종종 가격을 선도하는 것처럼 보일 수 있지만, 이것은 종종 우리가 찾고자 하는 증거를 검색하는 경우입니다. 따라서 OBV는 가격 분석과 함께 활용될 수 있는 지표지만 전적으로 OBV에 의존해서 투자전략을 세우기에는 한계가 있습니다.

  • OBV는 가격 예측을 위해 거래량의 변화를 사용하는 기술적 지표입니다. 
  • OBV는 해당 종목에 반영된 강세 또는 약세에 대한 군중 심리를 보여줍니다. 
  • 가격과 OBV 간의 상대적인 추세 흐름을 비교하면, 주식 차트 하단에서 띄워놓고 보는 (빨간색 또는 초록색으로 표시되는) 거래량 히스토그램 보다 더 많은 정보를 알 수 있습니다.

파이썬을 이용한 OBV 투자 전략

파이썬을 이용해서 OBV를 계산하고, 이를 기반으로 투자 전략을 세워보겠습니다. 우선 분석이 필요한 라이브러리를 Import 하겠습니다.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')

 

주식 데이터 불러오기

실습에 사용하게될 예제로 코로나19 백신 개발 업체로 잘 알려진 아스트라제네카(NYSE: AZN) 데이터를 사용하겠습니다. 야후 파이낸스에서 데이터를 가져오려면 yfinance 라이브러리가 필요합니다. yfinance 라이브러리가 없다면, '!pip install yfinance'를 통해서 설치해주세요.

import yfinance as yf
df = yf.download('AZN', start="2018-12-01", end="2020-11-30")
df['Date'] = df.index
df.head()

 

주가 데이터 시각화

아래 파이썬 코드를 이용하여 yfinance에서 불러온 주가 데이터를 시각화 해보겠습니다.

# Create and plot the graph
plt.figure(figsize=(12.2,4.5)) #width = 12.2in, height = 4.5
plt.plot( df['Close'],  label='Close')#plt.plot( X-Axis , Y-Axis, line_width, alpha_for_blending,  label)
plt.xticks(rotation=45) 
plt.title('Close Price History')
plt.xlabel('Date',fontsize=18)
plt.ylabel('Price USD ($)',fontsize=18)
plt.show()

 

OBV 계산하기

#Calculate the On Balance Volume
OBV = []
OBV.append(0)
for i in range(1, len(df.Close)):
    #If the closing price is above the prior close price 
    if df.Close[i] > df.Close[i-1]: 
        #then: Current OBV = Previous OBV + Current Volume
        OBV.append(OBV[-1] + df.Volume[i]) 
    elif df.Close[i] < df.Close[i-1]:
        OBV.append( OBV[-1] - df.Volume[i])
    else:
       OBV.append(OBV[-1])

 

OBV와 지수 이동 평균을 새로운 컬럼에 추가하기

# OBV값을 pd.DataFrame의 새로운 컬럼에 추가 
df['OBV'] = OBV

# 지수 평균 이동값 계산
df['OBV_EMA'] = df['OBV'].ewm(com=20).mean()

# 데이터 출력
df

 

 

OBV와 OBV의 지수 이동 평균값 시각화

#Create and plot the graph
plt.figure(figsize=(12.2,4.5)) #width = 12.2in, height = 4.5
plt.plot( df['OBV'],  label='OBV', color= 'orange')
plt.plot( df['OBV_EMA'],  label='OBV_EMA', color= 'purple')
plt.xticks(rotation=45) 
plt.title('OBV/OBV_EMA')
plt.xlabel('Date',fontsize=18)
plt.ylabel('Price USD ($)',fontsize=18)
plt.show()

 

매수/매도 타이밍 신호 찾는 함수 생성

  • 매수 신호: OBV > OBV_EMA
  • 매도 신호: OBV < OBV_EMA
def buy_sell(signal, col1, col2):
  sigPriceBuy = []
  sigPriceSell = []
  flag = -1 #A flag for the trend upward/downward

  #Loop through the length of the data set
  for i in range(0,len(signal)):

    #if OBV > OBV_EMA  and flag != 1 then buy else sell
      if signal[col1][i] > signal[col2][i] and flag != 1:
          sigPriceBuy.append(signal['Close'][i])
          sigPriceSell.append(np.nan)
          flag = 1

      #else  if OBV < OBV_EMA  and flag != 0 then sell else buy
      elif signal[col1][i] < signal[col2][i] and flag != 0:    
          sigPriceSell.append(signal['Close'][i])
          sigPriceBuy.append(np.nan)
          flag = 0

      #else   OBV == OBV_EMA  so append NaN 
      else: 
        sigPriceBuy.append(np.nan)
        sigPriceSell.append(np.nan)

  return (sigPriceBuy, sigPriceSell)

 

매수/매도 신호값을 새로운 컬럼에 추가

x = buy_sell(df, 'OBV','OBV_EMA' )
df['Buy_Signal_Price'] = x[0]
df['Sell_Signal_Price'] = x[1]
#Show the data frame
df

매도/매도 신호 시각화

# Create and plot the graph
plt.figure(figsize=(12.2,4.5)) #width = 12.2in, height = 4.5
plt.scatter(df.index, df['Buy_Signal_Price'], color = 'green', 
                    label='Buy Signal',  marker = '^', alpha = 1)
plt.scatter(df.index, df['Sell_Signal_Price'], color = 'red',
                    label='Sell Signal', marker = 'v', alpha = 1)
plt.plot( df['Close'],  label='Close Price', alpha = 0.35)
plt.xticks(rotation=45)
plt.title('The Stock Buy / Sell Signals')
plt.xlabel('Date',fontsize=18)
plt.ylabel('Close Price USD ($)',fontsize=18)
plt.legend( loc='upper left')
plt.show()

그래프를 살펴보면 OBV를 이용한 투자 전략이 어느정도 잘 작동하는 것 같습니다. 즉, 이 데이터 세트에 이 전략을 사용했다면, 이 기간 내에 수익을 올렸을 것입니다. 그러나 이 지표가 완벽하지 않으며 전략이 성공을 보장하지 않는다는 점을 명심하십시오. 이 전략을 사용하기 전에 더 많은 테스트를 수행해야하며 주식을 매매 할시기에 대한 자세한 정보를 위해 OBV 전략과 함께 다른 지표를 함께 사용하시길 권장드립니다.

참고) 이 글은 randerson112358의 Know When To Buy and Sell Stock Using A Trading Strategy With On-Balance Volume (OBV) and Python을 각색하여 한글로 번역한 글입을 밝힙니다. 원문은 링크를 통해서 확인하실 수 있습니다.