EXCELSIOR

7. Pandas와 Plotly를 이용한 Stochastic 차트 그리기 본문

Python/주식 분석

7. Pandas와 Plotly를 이용한 Stochastic 차트 그리기

Excelsior-JH 2017. 12. 3. 23:42

Pandas와 Plotly를 이용한 Stochastic 차트 그리기

이전에 포스팅한 6. Pandas와 Plotly를 이용한 MACD 차트 그리기에서는 pandasplotly 모듈을 이용하여 주식분석 중 하나의 지표인 MACD 차트를 그려보았다.이번 포스팅에서는 수집한 주식 데이터를 가지고 Stochastic 차트를 Python의 pandas 모듈을 이용하여 구현해 보도록 한다.

1. Stochastic(스토캐스틱) 이란?

Stochastic은 주식분석에서 MACD와 같이 기술적 분석에 사용되는 보조지표로써, 공식 명칭은 Stochastic Oscillator이다. Stochastic은 1950년대 William Dunnigun이 고안하고 George Lane이 널리 보급하였다고 한다.(출처: Wikipedia) Stochastic은 현재주가가 일정 기간의 주가 변동폭 중 어디에 위치하는지를 백분율 로 나타낸 지표이다.

  • Stochastic은 최근 N일 간의 최고가와 최저가의 범위 내에서 현재 가격의 위치를 표시할 때 매수세가 매도세 보다 강할 때는 그 위치가 높게 형성되고, 매도세가 매수세 보다 강할 떄는 그 위치가 낮게 형성된다는 것을 이용한 것이다.예를 들어, 최근 5일간 최고가가 15,000원이고 최저가가 10,000원인 주식이 있을때, 현재가가 14,000원이라면 매수세가 강하여 오르는 추세임을 알 수 있다. 만일 현재가가 11,000원이라면 매도세가 강하여 내리는 추세임을 알 수 있다.

1) Stochastic 공식

  • Fast%K (K): n(15)일 동안의 최고가(high)와 최저가(low) 사이 중 현재 종가(close)의 상대적 위치를 판단하는 값

    • 가격이 지속적으로 상승하고 있다면 Stochastic 값은 100에 가까워 지며, 반대로 지속적으로 하락하고 있다면 Stochastic 값은 0에 가까워 지는 경향을 나타낸다.

  • Slow%K (D): Fast%D라고도 하며 m(5)일간의 Fast%K의 이동평균 값

    • 기본값으로 5일을 설정하며 Fast%K 값을 일반화하는 역할을 한다.

  • Slow%D (J): t(3)일간의 Slow%K의 이동평균 값

    • 기본값으로 3일을 설정하며 Slow%K 값을 일반화 하는 역할을 한다.

  • Fast%K, Slow%K, Slow%D를 각각 라고하며 Stochastic을 KDJ Stochastic 지표라고 부르기도 한다.

2) Stochastic을 이용한 주식분석 - 참고 : 앤트하우스

Stochastic을 이용해 주식분석을 할때는 Fast%K보다는 Slow%KSlow%D를 주로 이용한다. 그 이유는 실제 주식시장에서의 Fast%K는 변화가 잦고 속임수가 많아 정확하지 않기 때문이다.

  • Slow%K선이 20값을 상향돌파 할 경우: Slow%K값이 20아래에 있다는 것은 지속적인 하락으로 인한 초과매도를 의미한다. 매수포지션(과매도로 인한 상승 전환)

  • Slow%K선이 80값을 하향돌파 할 경우: Slow%K값이 80위에 있다는 것은 지속적인 상승으로 인한 초과매수를 의미한다. 매도포지션(과매수로 인한 하락 전환)

  • Slow%K선이 Slow%D선을 상향돌파 할 경우: 매수 포지션

  • Slow%K선이 Slow%D선을 하향돌파할 경우: 매도 포지션

2. pandas를 이용한 Stochastic 구현하기

위의 내용에서 Stochastic이 무엇이며 어떻게 분석하는지에 대해 알아보았다. 이제부터는 pythonpandas모듈을 이요하여 Stochastic 지표를 직접 구현해 보도록 한다.

1) pandas.read_html()을 이용해 krx에서 종목코드 가져오기

네이버금융에서 원하는 종목의 주식데이터를 가져오기 위해 먼저 코스피(KOSPI)과 코스닥(KOSDAQ)의 종목코드가 필요하다. 한국거래소(krx)에서는 주식시장에 상장된 기업들에 대해 종목코드를 제공한다. pandas모듈의 pandas.read_html()을 이용해 종목코드를 가져올 수 있다. pandas.read_html()은 HTML에서 <table></table>태그를 찾아 자동으로 DataFrame형식으로 만들어준다. 아래의 소스코드를 통해 주식의 종목코드를 가져올 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
import pandas as pd
 
code_df = pd.read_html('http://kind.krx.co.kr/corpgeneral/corpList.do?method=download&searchType=13', header=0)[0]
 
# 종목코드가 6자리이기 때문에 6자리를 맞춰주기 위해 설정해줌
code_df.종목코드 = code_df.종목코드.map('{:06d}'.format)
 
# 우리가 필요한 것은 회사명과 종목코드이기 때문에 필요없는 column들은 제외해준다.
code_df = code_df[['회사명''종목코드']]
 
# 한글로된 컬럼명을 영어로 바꿔준다.
code_df = code_df.rename(columns={'회사명''name''종목코드''code'})
code_df.head()
cs

head() 함수를 통해 상위 5개의 코드를 확인할 수 있다.



2) Naver금융에서 일자별 주식데이터 가져오기

이제 네이버금융에서 원하는 종목의 일자 데이터를 가져와 보도록 하자. 여기서는 신라젠(215600) 의 일자 데이터를 가져온다. 아래의 소스코드는 특정 종목뿐만 아니라 사용자가 원하는 종목의 일자데이터를 가져올 수 있도록 get_url이라는 함수를 만들어 줬다. Naver금융에서 주식데이터를 가져오는 방법에 대해 자세히 알고 싶다면 5. Pandas를 이용한 Naver금융에서 주식데이터 가져오기를 참고하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 종목 이름을 입력하면 종목에 해당하는 코드를 불러와
# 네이버 금융(http://finance.naver.com)에 넣어줌
def get_url(item_name, code_df):
    code = code_df.query("name=='{}'".format(item_name))['code'].to_string(index=False)
    url = 'http://finance.naver.com/item/sise_day.nhn?code={code}'.format(code=code)
    
    print("요청 URL = {}".format(url))
    return url
    
 
# 신라젠의 일자데이터 url 가져오기
item_name='신라젠'
url = get_url(item_name, code_df)
 
# 일자 데이터를 담을 df라는 DataFrame 정의
df = pd.DataFrame()
 
# 1페이지에서 20페이지의 데이터만 가져오기
for page in range(121):
    pg_url = '{url}&page={page}'.format(url=url, page=page)
    df = df.append(pd.read_html(pg_url, header=0)[0], ignore_index=True)
 
# df.dropna()를 이용해 결측값 있는 행 제거
df = df.dropna()
 
# 상위 5개 데이터 확인하기
df.head()
cs

아래의 소스코드는 추후에 데이터 분석에서 편하게 하기위해 추가적으로 처리해 준 코드이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 한글로 된 컬럼명을 영어로 바꿔줌
df = df.rename(columns= {'날짜''date''종가''close''전일비''diff'
                         '시가''open''고가''high''저가''low''거래량''volume'})
 
# 데이터의 타입을 int형으로 바꿔줌
df[['close''diff''open''high''low''volume']] \
    = df[['close''diff''open''high''low''volume']].astype(int)
 
# 컬럼명 'date'의 타입을 date로 바꿔줌
df['date'= pd.to_datetime(df['date'])
 
# 일자(date)를 기준으로 오름차순 정렬
df = df.sort_values(by=['date'], ascending=True)
 
# 상위 5개 데이터 확인
df.head()
cs



3) KDJ Stochastic 지표 구현하기

Stochastic을 구현하기 위해 필요한 데이터 들을 수집하였으면, 이제 Stochastic을 구현해 보도록 한다. 아래의 소스코드는 Stochastic을 get_stochastic()이라는 함수로 구현하였다. 입력값으로는 DataFrame , n=15, m=5, n=3을 입력받아 KDJ Stochastic 지표를 계산한 다음 DataFrame에 추가해준 뒤 리턴해 준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 일자(n,m,t)에 따른 Stochastic(KDJ)의 값을 구하기 위해 함수형태로 만듬 
def get_stochastic(df, n=15, m=5, t=3):
    
    # 입력받은 값이 dataframe이라는 것을 정의해줌
    df = pd.DataFrame(df)
    
    # n일중 최고가
    ndays_high = df.high.rolling(window=n, min_periods=1).max()
    # n일중 최저가
    ndays_low = df.low.rolling(window=n, min_periods=1).min()
 
    # Fast%K 계산
    kdj_k = ((df.close - ndays_low) / (ndays_high - ndays_low))*100
    # Fast%D (=Slow%K) 계산
    kdj_d = kdj_k.ewm(span=m).mean()
    # Slow%D 계산
    kdj_j = kdj_d.ewm(span=t).mean()
 
    # dataframe에 컬럼 추가
    df = df.assign(kdj_k=kdj_k, kdj_d=kdj_d, kdj_j=kdj_j).dropna()
    
    return df
cs


아래의 소스코드를 통해 DataFrame df에 Stochastic 지표가 추가된 것을 확인할 수 있다.

1
2
df = get_stochastic(df)
df.head()
cs


3. plotly를 이용한 Stochastic 차트 그리기

마지막으로 plotly를 이용하여 Stochastic차트를 그려보도록 한다. plotly에 대한 설명은 이전 포스팅인 4. Plotly를 이용한 캔들차트-Candlestick chart 그리기를 참고하면 된다. 아래의 소스코드를 통해 Stochastic 차트를 그릴 수 있다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import plotly.offline as offline 
import plotly.graph_objs as go
from plotly import tools
 
# jupyter notebook 에서 출력 
offline.init_notebook_mode(connected=True)
 
kdj_k = go.Scatter(
                x=df.date,
                y=df['kdj_k'],
                name="Fast%K")
 
kdj_d = go.Scatter(
                x=df.date,
                y=df['kdj_d'],
                name="Fast%D")
 
kdj_d2 = go.Scatter(
                x=df.date,
                y=df['kdj_d'],
                name="Slow%K")
 
kdj_j = go.Scatter(
                x=df.date,
                y=df['kdj_j'],
                name="Slow%D")
 
 
trade_volume = go.Bar(
                x=df.date,
                y=df['volume'],
                name="volume")
 
 
# data = [kdj_k, kdj_d]
data1 = [kdj_d2, kdj_j]
data2 = [trade_volume]
 
# data = [celltrion]
# layout = go.Layout(yaxis=dict(
#         autotick=False,
#         ticks='outside',
#         tick0=0,
#         dtick=10,
#         ticklen=8,
#         tickwidth=4,
#         tickcolor='#000'
#     ))
 
fig = tools.make_subplots(rows=2, cols=1, shared_xaxes=True)
 
for trace in data1:
    fig.append_trace(trace, 1,1)
 
for trace in data2:
    fig.append_trace(trace, 2,1)
# fig = go.Figure(data=data, layout=layout)
 
offline.iplot(fig)
cs

Comments