본문 바로가기
종목분석

캔들스틱 패턴 마스터하기: 모닝스타부터 행잉맨까지, 시장의 신호를 읽는 법!

by 다빈치스탁 2024. 4. 16.
728x90
반응형

https://youtu.be/549ZejxBtZM

 

안녕하세요, 다빈치스탁입니다. 오늘은 트레이딩에서 자주 사용되는 캔들스틱 패턴들인 모닝스타, 이브닝스타, 역망치, 행잉맨 캔들에 대해 알아보려고 합니다. 이러한 패턴은 시장의 반전과 지속을 알리는 기술적 분석의 한 형태인데요. 특정 시간 동안의 주식 가격 움직임으로 형성되며, 시장의 심리를 파악하는데 도움을 줍니다.

 

지금부터 이 패턴들의 특징과 해석 방법을 알아보고, 파이썬 코드를 사용하여 특정 기간 동안 어떤 패턴들이 집중되었는지 살펴보겠습니다. 시작해볼까요?

 

우선 모닝스타 패턴입니다. 이 패턴은 하락 추세의 끝에서 나타나는 상승 반전 캔들로 다음과 같은 세 개의 캔들로 구성됩니다.

1. 긴 하락 캔들.

2. 작은 몸통의 캔들이 아래로 갭이 생기며 나타남.

3. 첫 번째 캔들의 몸통 안에서 마감하는 긴 상승 캔들.

 

이 패턴은 매도 압력이 줄어들고 상승 반전이 임박했다는 것을 나타냅니다.

 

둘째, 이브닝스타 패턴입니다. 이브닝스타는 모닝스타의 반대로 상승 추세의 끝에서 나타나는 하락 반전 패턴입니다. 역시 세 개의 캔들로 구성됩니다.

1. 긴 상승 캔들.

2. 작은 몸통의 캔들이 위로 갭이 생기며 나타남.

3. 첫 번째 캔들의 몸통 안에서 마감하는 긴 하락 캔들.

 

이 패턴은 매수 압력이 줄어들고 하락 반전이 가능하다는 것을 나타냅니다.

이어서, 역망치 패턴입니다. 역망치 캔들은 하락 추세의 바닥에서 나타나고 강세 반전의 전조로 간주되며 다음과 같은 특징을 가집니다.

1. 작은 몸통.

2. 긴 상단 윗꼬리.

3. 거의 없거나 아주 작은 밑 꼬리.

 

패턴은 하락세 동안의 매도 압력에 맞서 매수세가 강력하게 반격했음을 의미합니다.

 

마지막으로, 행잉맨 패턴입니다. 이 패턴은 망치형과 동일한 형태이지만 하락 반전 캔들을 암시하며 다음과 같이 식별됩니다.

1. 작은 몸통.

2. 긴 하단 밑 꼬리.

3. 거의 없거나 아주 작은 윗꼬리.

이 패턴이 상승 추세 중에 나타났다는 것은, 매도 압력이 매수 압력을 능가하기 시작한다는 것을 알리며, 가능한 하락을 시사합니다. 이와 반대로 하락의 추세 끝에서 나타났다면 매수 압력이 강화되고 상승이 시작될 있는 반전인 망치형 패턴으로 해석할 있습니다.

 

하지만 이러한 패턴은 차트의 아주 미시적인 구조를 관심 있게 살펴봐야 하기에 자칫하면 중요한 패턴들을 놓치는 경우가 많습니다. 따라서 지금부터는 파이썬을 이용하여 이러한 패턴들을 차트에 표시하고 특정 기간 동안 얼마나 높은 빈도로 출현했는지 확인하는 방법을 알려드리겠습니다.

 

각 각의 패턴들은 보시는 것과 같이 직접 함수를 통해 구현하였으며 데이터는 야후파이낸스 라이브러리를 통해 수집하였습니다. 이 코드를 실행하여 삼성전자의 지난 5개월간 캔들 패턴을 살펴보면, 상승과 하락의 중요한 변곡점에서 모닝스타와 이브닝스타 패턴들이 발생하는 것을 보실 수 있습니다.

 

이러한 캔들스틱 패턴은 강력한 도구이지만, 항상 패턴대로 진행되는 것은 아니며 때로는 적절한 패턴의 형성 없이 상승하거나 하락하기도 하고 패턴 발생 후 반대로 움직이는 경우도 다수 존재합니다.

 

따라서 투자를 진행함에 있어 캔들패턴과 함께 큰 프레임을 다루는 추세지표, 거래량 등 여러 가지 요인들을 종합적으로 분석하시는 것이 좋습니다.

 

파이썬 소스코드

def is_morning_star(candles):
    # 모닝스타 패턴은 3개의 캔들로 구성됩니다.
    first, second, third = candles[-3], candles[-2], candles[-1]
    # 첫 번째 캔들은 음봉, 두 번째 캔들은 작은 실체, 세 번째 캔들은 양봉이어야 합니다.
    return (first['Close'] < first['Open'] and
            #abs(second['Close'] - second['Open']) <= (second['High'] - second['Low']) * 0.3 and
            abs(second['Close'] - second['Open']) < abs(first['Close'] - first['Open']) * 0.5 and
            third['Close'] > third['Open'] and
            third['Close'] > first['Close'])

def is_evening_star(candles):
    # 이브닝스타 패턴은 3개의 캔들로 구성됩니다.
    first, second, third = candles[-3], candles[-2], candles[-1]
    # 첫 번째 캔들은 양봉, 두 번째 캔들은 작은 실체, 세 번째 캔들은 음봉이어야 합니다.
    return (first['Close'] > first['Open'] and
            abs(second['Close'] - second['Open']) < abs(first['Open'] - first['Close']) * 0.5 and
            third['Close'] < third['Open'] and
            third['Close'] < first['Close'])

def is_hanging_man(candles):
    # 행잉맨 패턴은 상승 추세에서 나타나는 장대음봉입니다.
    # 이 함수는 마지막 캔들이 행잉맨 패턴인지 확인합니다.
    last_candle = candles[-1]
    body_size = last_candle['Open'] - last_candle['Close']
    lower_wick = last_candle['Close'] - last_candle['Low']
    upper_wick = last_candle['High'] - max(last_candle['Open'], last_candle['Close'])
    # 몸통은 작고, 아래 꼬리는 몸통보다 길어야 합니다.
    return (body_size > 0 and
            lower_wick >= 2 * body_size and
            upper_wick < body_size)

def is_inverted_hammer(candles):
    # 역망치 패턴은 하락 추세에서 나타나는 장대양봉입니다.
    # 이 함수는 마지막 캔들이 역망치 패턴인지 확인합니다.
    last_candle = candles[-1]
    body_size = last_candle['Close'] - last_candle['Open']
    lower_wick = last_candle['Open'] - last_candle['Low']
    upper_wick = last_candle['High'] - max(last_candle['Open'], last_candle['Close'])
    # 몸통은 작고, 위 꼬리는 몸통보다 길어야 합니다.
    return (body_size > 0 and
            upper_wick >= 2 * body_size and
            lower_wick < body_size)

# 차트데이터를 불러오는 라이브러리
import yfinance as yf
# 차트 및 글꼴을 설정하기 위한 라이브러리
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as ticker
import matplotlib.font_manager as fm
# 캔들차트를 그리기 위한 라이브러리
from mplfinance.original_flavor import candlestick_ohlc

df = yf.download("005930.KS", start="2023-11-01", end="2024-04-16")

print(len(df))
# OHLC 데이터 준비
ohlc = df[['Open', 'High', 'Low', 'Close']]
ohlc = ohlc.reset_index()

# 날짜를 숫자로 변환합니다.
ohlc['Date'] = ohlc['Date'].apply(mdates.date2num)

# 캔들차트 그리기
fig, ax = plt.subplots(figsize=(10, 6))
candlestick_ohlc(ax, ohlc.values, width=0.6, colorup='red', colordown='blue')
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d')) # x축 눈금을 날짜로 표시
ax.xaxis.set_major_locator(ticker.MaxNLocator(10)) # x축 눈금 개수 설정
plt.xticks(rotation=45) # x축 눈금 라벨 회전
plt.grid() # 그리드 표시

# 패턴 발생 횟수를 저장할 변수 초기화
morning_star = 0
evening_star = 0
hanging_man_count = 0
inverted_hammer_count = 0


# 나눔고딕 폰트 경로 (실제 경로는 사용자의 환경에 따라 다를 수 있음)
font_path = 'NanumGothic.ttf'

# 폰트 로드
fontprop = fm.FontProperties(fname=font_path)

# Carmine 색상 (Inverted Hammer)
#carmine_hex = '#84141E'  # Carmine의 HEX 코드
carmine_hex = 'purple'  # Carmine의 HEX 코드

# Royal Blue 색상 (Hanging Man)
royal_blue_hex = '#4169E1'  # Royal Blue의 HEX 코드


# 5일, 20일, 60일 이동평균 계산
sma_5 = ohlc['Close'].rolling(window=5).mean()
sma_20 = ohlc['Close'].rolling(window=20).mean()
sma_60 = ohlc['Close'].rolling(window=60).mean()


# 차트에 이동평균선 추가
ax.plot(ohlc['Date'], sma_5, label='5-day SMA', color='#367588', linewidth=1.5)
ax.plot(ohlc['Date'], sma_20, label='20-day SMA', color='orange', linewidth=1.5)
ax.plot(ohlc['Date'], sma_60, label='60-day SMA', color='green', linewidth=1.5)

# 캔들패턴 식별 및 어노테이션 추가
for i in range(2, len(ohlc)):
    # 현재 및 이전 캔들 정보
    current_candle = ohlc.iloc[i]
    prev_candle = ohlc.iloc[i-1]
    prev_prev_candle = ohlc.iloc[i-2]

    # 모닝스타 패턴 식별
    if is_morning_star([prev_prev_candle, prev_candle, current_candle]):
        if sma_20[i] < sma_20[i-1]:
            morning_star +=1 
            
            ax.annotate('Morning', xy=(current_candle['Date'], current_candle['Low']*0.99), 
                        xytext=(0, -30), textcoords='offset points', 
                        arrowprops=dict(facecolor='red', shrink=0.05), horizontalalignment='center', color='red')

    # 이브닝스타 패턴 식별
    if is_evening_star([prev_prev_candle, prev_candle, current_candle]):
        if sma_20[i] > sma_20[i-1]:
            evening_star +=1 
            
            ax.annotate('Evening', xy=(current_candle['Date'], current_candle['High']*1.01), 
                        xytext=(0, 25), textcoords='offset points', 
                        arrowprops=dict(facecolor='blue', shrink=0.05), horizontalalignment='center', color='blue')
    
    # 역망치 패턴 식별
    if is_inverted_hammer([current_candle]):
        if sma_20[i] < sma_20[i-1]:
            inverted_hammer_count  += 1
            
            ax.annotate('Inverted', xy=(current_candle['Date'], current_candle['Low']*0.98), 
                        xytext=(0, -30), textcoords='offset points', 
                        arrowprops=dict(facecolor=carmine_hex, shrink=0.05), horizontalalignment='center', color=carmine_hex)
    
    # 행잉맨 패턴 식별
    if is_hanging_man([current_candle]):
        if sma_20[i] > sma_20[i-1]:
            # 상승 추세에서 행잉맨 패턴
            hanging_man_count += 1
            
            ax.annotate('Hanging', xy=(current_candle['Date'], current_candle['High']*1.02), 
                        xytext=(0, 25), textcoords='offset points', 
                        arrowprops=dict(facecolor=royal_blue_hex, shrink=0.05), 
                        horizontalalignment='center', color=royal_blue_hex)

# 차트에 패턴 발생 횟수 표시
ax.text(0.01, 0.97, f'Morning Star: {morning_star}', transform=ax.transAxes, color='red', fontsize=10)
ax.text(0.01, 0.94, f'Evening Star: {evening_star}', transform=ax.transAxes, color='blue', fontsize=10)
ax.text(0.01, 0.91, f'Inverted Hammer: {inverted_hammer_count}', transform=ax.transAxes, color=carmine_hex, fontsize=10)
ax.text(0.01, 0.88, f'Hanging Man Pattern: {hanging_man_count}', transform=ax.transAxes, color=royal_blue_hex, fontsize=10)


# 차트 표시
plt.show()
728x90
반응형

댓글