본문 바로가기
주식분석/Quant 분석(프로그래밍)

구름위로 날라가보자 - 일목균형표

by hustler78 2023. 3. 22.
728x90
반응형

 

주식 차트 기술적 지표 중 대표적인 것으로서 일목균형표라는 것이 있습니다.  무려 120년도 더 전에 일본에서 태어난 호소타 코이치라는 큰 개미께서 만든 기술적 지표인데,  주식의 시고저종에서 얻을 수 있는 5개의 곡선을 이용하여 주가의 상태와 추세를 예측하는 방법입니다.

 

 

 

일목균형 5형제

일목균형표를 이루는 다섯 개의 선은 아래와 같이 정의합니다.

 

선 이름 내용
전환선 ( 과거 9일간 최고가 + 과거 9일간 최저가)  / 2
기준선 ( 과거 26일간 최고가 + 과거 26일간 최저가)  / 2 
후행스팬 오늘의 종가를 26일 영업일 전으로 후행(後行)시킨 선
선행스팬1 (오늘의 전환선 + 오늘의 기준선) / 2  의 값을 26 영업일 앞(미래)으로 선행(先行) 시킨 선
선행스팬2 ( 과거 52일간 최고가 + 과거 52일간 최저가)  / 2 의 값을 26 영업일 앞(미래) 으로 선행(先行) 시킨 선
구름대 선행스팬1 과 선행스팬2 사이의 영역을 구름대라 하고 선행스팬1의 값이 더 큰 경우 양운, 반대의 경우에는 음운이라 함

 

○ 중요한 숫자로 9 , 26, 52 가 쓰입니다. 각각, 단기/중기/장기를 의미합니다.

 

○ 전환선/기준선은 오늘에 대한 얘기,  후행스팬은 과거에 그리고,  선행스팬은 미래에 그립니다.

 

 

Naver 금융에서 삼성전자(005930) 일목균형 차트를 보면 아래와 같습니다.

 

흐릿한 회색선이 후행스팬, 빨갛고 파란 영역(구름)의 경계선이 각각 선행스팬1,2 인데요. 앞선 설명대로 선행스팬은 미래에 그려지므로 구름대는 차트보다 더 오른쪽(미래) 방향으로 이어집니다. 반면에 후행스팬은 회색선은 주가차트보다 더 과거에 멈추죠. 설명을 덧붙이면 아래와 같습니다.

 

 

주가의 끝은 기점으로 후행스팬의 끝은 왼쪽(과거),  선행스팬의 끝은 오른쪽(미래)에 위치합니다.

 

그럼 이제 매수타점을 잡아볼까요?

 

 

 

일목균형표에서 매수타점 잡기

 

가장 잘 알려진 매수타점 중 기본이 되는 것은 바로

(기본) 일목균형표상 저항선 역할을 하는 빨간 구름을 주가가 깨고 올라갈 때,

입니다. 빨간구름대란, 양운으로서 선행스팬 1이 선행스팬 2보다 높게 위치한 구름대를 말합니다. 위의 (기본)을 전제조건으로 깔고 입맛에 맞게 로직을 정해봅니다. 많이 알려진 매수 타점 잡기 로직은 크게

 

(I). 종가가 전환선을 골든 크로스(Golden Cross) 할 때,  

 

(II). 전환선이 기본선을 골든 크로스(Golden Cross) 할 때,

 

(III). 후행스팬이 전환선을 골든 크로스할 때, 
즉, 오늘의 종가가 26일 전의 전환선을 골든 크로스 할 때,

 

를 생각할 수 있습니다.  골든 크로스는 아래 더보기 글을 보시기 바랍니다.

더보기

골든 크로스란?

 

곡선 (A)가 곡선 (B)를 골든 크로스 한다는 뜻은  (A)가 (B)의 밑에서부터 다가와 (B)를 깨며 올라가는 것을 말함

 

 

반대의 경우 즉, (A)가 (B)의 위에서부터 밑으로 깨고 내려가는 모습은 Dead Cross라고 함

 

 

이제, python으로 일목균형표 5형제 선을 구축하고 위에 소개한 로직들을 설계하여 매수 타점들을 잡아봅시다.

 

 

 

Python Code : 일목균형표

 

import pandas as pd
import numpy as np
from mpl_finance import candlestick_ohlc
import mplfinance
import matplotlib.dates as mpl_dates
import matplotlib.pyplot as plt
import datetime
from dateutil.relativedelta import relativedelta
import FinanceDataReader as fdr
from matplotlib import gridspec

def load_data(stock_code, start_date, end_date):
    df = fdr.DataReader(stock_code, start_date, end_date)
    return df

def Ichimoku():
    end_date = datetime.datetime.today()
    start_date = end_date - relativedelta(years=3)

    stk_code = '005930'    # 삼성전자
    # stk_code = '065770'  # CS
    # stk_code = '010780'  # 아이에스동서
    # stk_code = '008350'  # 남선알미늄
    # stk_code = '312610'  # 에이에프더블류
    # stk_code = '148150'  # 세경하이테크
    # stk_code = '046120'  # 오르비텍
    # stk_code = '090370'  # 메타랩스
    # stk_code = '000850'  # 화천기공
    # stk_code = '026040'  # 제이에스티나

    df = load_data(stk_code, start_date, end_date)
    df['Date'] = df.index
	
    # ---- 일목균형 5형제 소개 --------------
    # Conversion line : 전환선
    # Base line       : 기준선
    # Lagging line    : 후행스팬
    # Leading span1   : 선행스팬1
    # Leading span2   : 선행스팬2
    # --------------------------------------
    
    df['Conversion_Line'] = (df.High.rolling(9).max() + df.Low.rolling(9).min()) / 2
    df['Base_Line'] = (df.High.rolling(26).max() + df.Low.rolling(26).min()) / 2
    df['Lagging_Line'] = df.Close.shift(-26)
    df['Leading_Span1'] = ((df.Conversion_Line + df.Base_Line) / 2).shift(26)
    df['Leading_Span2'] = ((df.High.rolling(52).max() + df.Low.rolling(52).min()) / 2).shift(26)
    
    # ---- cloud 만들기--------------------------------------------------------
    # 선행스팬1과 선행스팬2 중 최대값을 cloud의 위 경게, 최솟값을 cloud의 아래 경계
    # 선형스팬1 > 선행스팬2 면 양운(red cloud), 반대면 음운(blue cloud)
    # ------------------------------------------------------------------------
    
    df['cloud_upper'] = df[['Leading_Span1', 'Leading_Span2']].max(axis=1)
    df['cloud_under'] = df[['Leading_Span1', 'Leading_Span2']].min(axis=1)
    df['cloud_type'] = np.where(df.Leading_Span1 > df.Leading_Span2, 'red', 'blue')

    # ----- 전제조건 ----------------------------------------------------------
    # 종가가 구름대 사이에 있고 ( cloud under < 종가 < cloud upper)
    # 어제 종가는 구름 밑에 있었으며 ( close(1) < cloud_under(1) )
    # 구름의 type은 red cloud
    # -------------------------------------------------------------------------
    
    condition_up_trend = (df['Close'] < df['cloud_upper']) & (df['Close'] > df['cloud_under']) & (
            df['cloud_type'] == 'red') & (df['Close'].shift(1) < df['cloud_under'].shift(1))
            
    # ----- logic (I) ------------------------------------------------------------
    # 종가와 전환선이 golden cross ( 어제종가 < 어제전환선 and 오늘 종가> 오늘 전환선)
    # 위의 기본전제조건은 동시에 충족해야 함
    # ----------------------------------------------------------------------------
    c1 = df.Close.shift(1) < df.Conversion_Line.shift(1)
    c2 = df.Close.shift(0) > df.Conversion_Line.shift(0)
    df['GC(close, conversion)'] = c1 & c2 & condition_up_trend

    # ----- logic (II) ------------------------------------------------------------
    # 전환선과 기준선의 golden cross ( 어제 전환선 < 어제 기준선 and 오늘 전환선 > 오늘 기준선)
    # 위의 기본전제조건은 동시에 충족해야 함
    # ----------------------------------------------------------------------------
    c3 = df.Conversion_Line.shift(1) < df.Base_Line.shift(1)
    c4 = df.Conversion_Line.shift(0) > df.Base_Line.shift(0)
    df['GC(conversion, base)'] = c3 & c4 & condition_up_trend


    # ----- logic (III) ------------------------------------------------------------
    # 후행스팬과 전환선의 golden cross ( 즉, 어제 전환선 > 27일전 종가,  오늘 전환선 < 26어제 기준선 and 오늘 전환선 > 오늘 기준선)
    # 기준선이 상승세라는 조건도 덧붙임 (condition c5)
    # 위의 기본전제조건은 동시에 충족해야 함
    # ----------------------------------------------------------------------------
    c5 = (df.Base_Line.shift(2) <= df.Base_Line.shift(1)) & (df.Base_Line.shift(1) <= df.Base_Line.shift(0))
    c6 = df.Conversion_Line.shift(26) < df.Close.shift(0)
    c7 = df.Conversion_Line.shift(27) > df.Close.shift(1)
    df['CG(lagging, conversion)'] = c5 & c6 & c7 & condition_up_trend

    df = df.iloc[-500:]
    df_ohlc = df[['Date', 'Open', 'High', 'Low', 'Close']]
    fig, ax = plt.subplots(1, 1, sharex=True, figsize=(20, 9))  # share x axis and set a figure size
    date_format = mpl_dates.DateFormatter('%y/%b/%d')
    ax.xaxis.set_major_formatter(date_format)
    
    # candle 차트를 아래처럼 그릴 수 있으나 지저분해져서 생략
    # candlestick_ohlc(ax, df_ohlc.values, width=0.6, \
    #                  colorup='red', colordown='blue', alpha=0.8)

    ax.plot(df.index, df.Close, linewidth=2, label='stock value', c='gray')
    
    # base, conversion, lagging line를 아래와 같이 그릴 수 있으나 지저분해져서 주석처리
    # ax.plot(df.index, df.Conversion_Line, linewidth=2, label='Conversion', c='lightsteelblue')
    # ax.plot(df.index, df.Base_Line, linewidth=2, label='Base', c='cornflowerblue')
    # ax.plot(df.index, df.Lagging_Line, linewidth=2, label='Lagging', c='gray')
    
    # fill_between 문법을 사용하여 양운(red cloud), 음운(blue cloud) 그림
    ax.fill_between(df.index, df.Leading_Span1, df.Leading_Span2, where=df.Leading_Span1 >= df.Leading_Span2,
                    color='mistyrose')
    ax.fill_between(df.index, df.Leading_Span1, df.Leading_Span2, where=df.Leading_Span2 >= df.Leading_Span1,
                    color='lightcyan')
    
    # 각 logic에 부합하는 시점의 chart에 circle marker로 표시
    ax.scatter(df[df['GC(close, conversion)'] == True].index, df[df['GC(close, conversion)'] == True].Close * 1.02,
               marker='o', c='black', label='GC(close, conversion)', s=100)

    ax.scatter(df[df['GC(conversion, base)'] == True].index, df[df['GC(conversion, base)'] == True].Close * 1.02,
               marker='o', c='crimson', label='GC(conversion, base)', s=100)

    ax.scatter(df[df['CG(lagging, conversion)'] == True].index, df[df['CG(lagging, conversion)'] == True].Close * 1.02,
               marker='o', c='darkviolet', label='CG(lagging, conversion)', s=100)

    ax.legend()
    plt.title(f'{stk_code}')
    plt.show()
   
if __name__ == '__main__':
    Ichimoku()

 

 

몇몇 종목들을 볼까요?

 

삼성전자(005930) 

 

 

2023년 1월달에 로직(I)의 신호가 뜨고 (검은색 marker) 상승추세를 잠시 이어간 것을 볼 수 있습니다.

 

 

 

남선알미늄(008350) 

 

2023년 1~2월에 검은  marker가 하나 떠 있네요. 그리고 조금의 상승세를 이어갑니다.

 

 

 

신한지주(055550)

 

 

현대차(005380)

 

 

 

 

 

신한지주, 현대차 등 굵직한 종목들도 marker 시그널 뒤에 다소 상승을 보여 준다는 것을 알 수 있습니다. 물론 항상 로직이 맞지는 않겠지만, 다른 분석과 섞어 참고하기에는 안성맞춤인 지표일 듯합니다.

 

 

 

728x90
반응형

댓글