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

볼린저 밴드와 일목균형의 조화에서 매수신호 찾기

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

이번 글에서는 일목균형표와 볼린저밴드라는 지표들  사이의 관계에서 등장하는 매수 신호를 찾아보겠습니다.

개인적으로 찾은 것이기에, 계속 검증이 필요한 상황입니다. 필요한 것은

 

일목균형표의 전환선 볼린저 밴드의  하단선

 

입니다. 이 두 선의 위치관계를 가지고 매수 신호를 찾아볼까 합니다.

 

 

일목균형표 전환선

 

일목균형표에 대해서는 구름위로 날라가보자 - 일목균형표

 

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

주식 차트 기술적 지표 중 대표적인 것으로서 일목균형표라는 것이 있습니다. 무려 120년도 더 전에 일본에서 태어난 호소타 코이치라는 큰 개미께서 만든 기술적 지표인데, 주식의 시고저종에

sine-qua-none.tistory.com

를 참고하시기 바랍니다.  일목균형표 5형제 중 전환선은

 

전환선:  (과거 9일간의 최고가 + 과거 9일간의 최저가 ) / 2

로 정의합니다. 주가 흐름의 단기적인 추세를 나타내주죠.

 

 

 

볼린저 밴드 하단선

 

볼린저 밴드는 본 블로그에서는 처음 등장하는 개념이나 주식 차트의 기술적 지표로서 아주 대중적이고 널리 알려져 있기에 우선 개념만 간단하게 소개하겠습니다.

볼린저 밴드는 크게 3가지 선으로 이루어져 있습니다.

구분 내용
중심선 주가의 20일 이평선
상단선 중심선 + 주가의 20일 표준편차 × 2 
하단선 중심선  - 주가의 20일 표준편차 × 2

 

통계학적으로 따지자면,  주가의 평균을 $\mu$, 표준편차를 $\sigma$라 했을 때, 하단선은

$$\mu-2\sigma$$

이죠.  상단선은

$$\ mu +2\sigma$$ 입니다.

따라서  주가를 정규분포로 봤을 때, 주가 $S$ 가 하단선/상단선 사이에 위치할 확률은

$$ \mathbb{P}(\mu-2\sigma < S < \mu+2\sigma ) = 95.44 \%$$

라는 이야기입니다.  아래 그림을 참고해 보시기 바랍니다. 

 

 

 

 

주가는 굉장히 높은 확률로 하단선을 지지하며 움직이게 됩니다.  

 

 

매수 신호 

 

따라서 이렇게 생각해 봤습니다.

단기추세인 전환선이 볼린저 밴드 하단선을 뚫고 내려간다.
그러다가 다시 전환선이 하단선을 뚫고 올라간다. 즉 추세의 전환.
약 2주(10 영업일) 내로 이러한 현상이 발생하면, 
이때가 기회!!

 

그림으로 그려보면 이렇습니다. 전환선이 다시 볼린저 밴드 하단선을 뚫고 올라올 때가 매수 찬스라고 생각하는 겁니다.

 

 

 

파이썬으로 코딩하여 종목들을 관찰해 보겠습니다.

 

 

Python Code

 

 

import pandas as pd
import numpy as np
import yfinance
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 Ichimoku_and_Bollinger():
    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 = '005380'  # 제이에스티나
    # stk_code = '037950'  # 엘컴텍
    # stk_code = '270660'  # 에브리봇
    # stk_code = '005500'  # 삼진제약  이친구
    # stk_code = '298020'  # 화천기공
    stk_code = '383220'  # F&F

    df = load_data(stk_code, start_date, end_date)
    # df.index = df.index.map(mpl_dates.date2num)
    df['Date'] = df.index
    # print(df[['Date', 'Close']])
	
    # 일목균형표에서 전환선만 쓸 예정
    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)
    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')
    
    # Bollinger band에서 Bollinger_under 만 쓸 예정
    df['Bollinger_Average'] = df.Close.rolling(20).mean()
    df['Bollinger_Std'] = df.Close.rolling(20).std()
    df['Bollinger_upper'] = df['Bollinger_Average'] + 2 * df['Bollinger_Std']
    df['Bollinger_under'] = df['Bollinger_Average'] - 2 * df['Bollinger_Std']
    
    # golden_cross 변수는 볼린저 하단선이 일목 전환선을 golden cross한다는 뜻
    golden_cross = (df['Bollinger_under'].shift(1) < df['Conversion_Line'].shift(1)) & (
            df['Bollinger_under'].shift(0) > df['Conversion_Line'].shift(0))
    
    # dead_cross 변수는 볼린저 하단선이 일목 전환선을 dead cross 한다는 뜻
    dead_cross = (df['Bollinger_under'].shift(1) > df['Conversion_Line'].shift(1)) & (
            df['Bollinger_under'].shift(0) < df['Conversion_Line'].shift(0))

    # golden_cross = True 시 1, dead_cross =True 시 -1 , 나머지 0인 column을 만듬
    df['cross_signal'] = np.where(golden_cross, 1, np.where(dead_cross, -1, 0))

    # 볼린저 하단이 전환선 하단을 golden cross하고 10일내에 dead cross하는 시점 찾음
    # dead cross =1 이고 그 시점에서 과거 10일의 cross_signal에 1이 한번이라도 등장하면 signal =True
    df['signal']=(df.cross_signal ==-1) & (df.cross_signal.rolling(10).max()==1)

    
    fig, ax = plt.subplots(1, 1, sharex=True, figsize=(10, 6))  # share x axis and set a figure size
    date_format = mpl_dates.DateFormatter('%y/%b/%d')
    ax.xaxis.set_major_formatter(date_format)
    
    ax.plot(df.index, df.Close, linewidth=2, label='stock value', c='gray')
    ax.plot(df.index, df.Conversion_Line, linewidth=2, label='Conversion', c='lightsteelblue')
    ax.plot(df.index, df['Bollinger_under'], linewidth=2, label='Bolinger Under', c='cornflowerblue')
    
    # signal 출현시 circle marker 로 표시, size =100
    ax.scatter(df[df['signal'] == True].index, df[df['signal'] == True].Close * 1.02,
               marker='o', c='black', label='signal', s=100)

    ax.legend()
    plt.title(f'{stk_code}')

    plt.show()


if __name__ == '__main__':
    
    Ichimoku_and_Bollinger()

 

위 코드의 주석처리된 종목들을 살펴보았습니다.

 

 

오르비텍(046120)

 

 

중간즈음 검은 circle marker가 보이죠? 회색선이 주가인데요. circle marker를 지나 조금 눌림을 주더니 강하게 상승하는 모습을 보입니다. 물론, 상승이 계속 진행되진 않았지만요.

 

 

 

삼진제약(005500)

 

삼진제약이라는 기업인데, 22년 5월 즈음 circle marker가 소담스럽게 떠 있네요. 약 4개월 뒤에 시세 한 번 주는 모습을 볼 수 있습니다.

 

 

 

고려신용정보(049720)

 

 

고려신용정보라는 주식입니다. circle marker가 2번 떴는데요. 첫 번째 marker 후에는 아주 큰 시세가 나왔고, 최근 나온 시그널에서 반짝 한번 올라갔군요.

 

 

 

 

플럼라인생명과학(222670)

 

 

circle marker가 다수 등장한 종목입니다. 2020년 5월이나 2023년 1월의 시그널 뒤 큰 시세를 주었죠. 하지만 중간의 몇몇 시그널들에서는 실망스러운 모습도 발견됩니다, 손절 라인을 좀 미리 정하고 대응해야 할 필요가 있어 보입니다.

 

 

 

 

볼린저 밴드의 하단선과 일목균형표의 전환선을 이용하여 매수 신호를 띄우는 로직은 제가 자체적으로 관찰하다가 발견한 저만의 로직입니다.  개인적으로는 잘 맞아 보여서 소개를 했지만, 확증편향에 기인했을 가능성도 있습니다. 계속 로직을 다듬고 개선해야겠죠. 로직의 개선이 있으면 업데이트할 예정입니다.

 

 

 

 

728x90
반응형

댓글