파이썬 이치모쿠 자동매매 전략

이치모쿠 지표란?

이치모쿠 킨코효(一目均衡表)는 일본의 기자 호소다 고이치가 1930년대에 개발한 기술적 분석 지표입니다. “한눈에 균형을 본다”는 뜻 그대로, 하나의 차트에서 추세 방향, 지지·저항, 모멘텀을 동시에 파악할 수 있습니다. 서양의 이동평균선과 달리 5개의 구성 요소가 유기적으로 작동하여 더 풍부한 매매 신호를 제공합니다.

이치모쿠는 암호화폐와 주식 시장 모두에서 효과적입니다. 특히 추세 추종 자동매매에 적합하며, 서킷브레이커와 함께 사용하면 안정적인 트레이딩 시스템을 구축할 수 있습니다.

이치모쿠 5대 구성 요소

  • 전환선(Tenkan-sen): 최근 9봉의 (최고가 + 최저가) / 2. 단기 추세를 나타냅니다.
  • 기준선(Kijun-sen): 최근 26봉의 (최고가 + 최저가) / 2. 중기 추세이자 핵심 지지·저항선입니다.
  • 선행스팬A(Senkou Span A): (전환선 + 기준선) / 2를 26봉 앞에 표시. 구름의 한쪽 경계입니다.
  • 선행스팬B(Senkou Span B): 최근 52봉의 (최고가 + 최저가) / 2를 26봉 앞에 표시. 구름의 다른 경계입니다.
  • 후행스팬(Chikou Span): 현재 종가를 26봉 뒤에 표시. 과거 가격과의 관계로 모멘텀을 확인합니다.

파이썬 이치모쿠 계산

pandas를 활용하여 이치모쿠 지표를 계산하는 함수입니다.

import pandas as pd
import numpy as np

def calc_ichimoku(df, tenkan=9, kijun=26, senkou_b=52, displacement=26):
    """
    이치모쿠 지표 계산
    :param df: OHLCV DataFrame (columns: high, low, close)
    :param tenkan: 전환선 기간 (기본 9)
    :param kijun: 기준선 기간 (기본 26)
    :param senkou_b: 선행스팬B 기간 (기본 52)
    :param displacement: 선행 이동 기간 (기본 26)
    """
    # 전환선 (Tenkan-sen)
    high_tenkan = df['high'].rolling(window=tenkan).max()
    low_tenkan = df['low'].rolling(window=tenkan).min()
    df['tenkan_sen'] = (high_tenkan + low_tenkan) / 2

    # 기준선 (Kijun-sen)
    high_kijun = df['high'].rolling(window=kijun).max()
    low_kijun = df['low'].rolling(window=kijun).min()
    df['kijun_sen'] = (high_kijun + low_kijun) / 2

    # 선행스팬 A (Senkou Span A)
    df['senkou_a'] = ((df['tenkan_sen'] + df['kijun_sen']) / 2).shift(displacement)

    # 선행스팬 B (Senkou Span B)
    high_senkou = df['high'].rolling(window=senkou_b).max()
    low_senkou = df['low'].rolling(window=senkou_b).min()
    df['senkou_b'] = ((high_senkou + low_senkou) / 2).shift(displacement)

    # 후행스팬 (Chikou Span)
    df['chikou_span'] = df['close'].shift(-displacement)

    # 구름 상단/하단
    df['cloud_top'] = df[['senkou_a', 'senkou_b']].max(axis=1)
    df['cloud_bottom'] = df[['senkou_a', 'senkou_b']].min(axis=1)

    return df

이치모쿠 매매 신호

이치모쿠에서 도출할 수 있는 핵심 매매 신호는 다음과 같습니다.

  • TK 크로스 (강력 매수): 전환선이 기준선을 상향 돌파하면서, 가격이 구름 위에 위치할 때.
  • TK 크로스 (강력 매도): 전환선이 기준선을 하향 돌파하면서, 가격이 구름 아래에 위치할 때.
  • 구름 돌파: 가격이 구름을 상향/하향 돌파하면 추세 전환 신호입니다.
  • 후행스팬 확인: 후행스팬이 과거 가격 위에 있으면 상승 추세 확인, 아래면 하락 추세 확인.
  • 구름 두께: 구름이 두꺼울수록 지지·저항이 강하고, 얇으면 돌파 가능성이 높습니다.
def generate_ichimoku_signals(df):
    """이치모쿠 기반 매매 신호 생성"""
    signals = pd.DataFrame(index=df.index)
    signals['signal'] = 0  # 0: 관망, 1: 매수, -1: 매도

    for i in range(1, len(df)):
        # 전환선-기준선 크로스
        tk_cross_up = (df['tenkan_sen'].iloc[i] > df['kijun_sen'].iloc[i] and
                       df['tenkan_sen'].iloc[i-1] <= df['kijun_sen'].iloc[i-1])
        tk_cross_down = (df['tenkan_sen'].iloc[i] < df['kijun_sen'].iloc[i] and
                         df['tenkan_sen'].iloc[i-1] >= df['kijun_sen'].iloc[i-1])

        # 가격과 구름의 관계
        price = df['close'].iloc[i]
        above_cloud = price > df['cloud_top'].iloc[i]
        below_cloud = price < df['cloud_bottom'].iloc[i]

        # 강력 매수: TK 골든크로스 + 가격이 구름 위
        if tk_cross_up and above_cloud:
            signals['signal'].iloc[i] = 1

        # 강력 매도: TK 데드크로스 + 가격이 구름 아래
        elif tk_cross_down and below_cloud:
            signals['signal'].iloc[i] = -1

    return signals

def signal_strength(df, idx):
    """신호 강도 평가 (1~5)"""
    score = 0
    price = df['close'].iloc[idx]

    # 1. 가격 vs 구름
    if price > df['cloud_top'].iloc[idx]:
        score += 1
    # 2. 전환선 vs 기준선
    if df['tenkan_sen'].iloc[idx] > df['kijun_sen'].iloc[idx]:
        score += 1
    # 3. 구름 색상 (선행A > 선행B = 상승 구름)
    if df['senkou_a'].iloc[idx] > df['senkou_b'].iloc[idx]:
        score += 1
    # 4. 후행스팬 vs 과거 가격
    chikou_idx = idx - 26
    if chikou_idx >= 0 and price > df['close'].iloc[chikou_idx]:
        score += 1
    # 5. 구름 두께 (두꺼울수록 강한 지지)
    cloud_pct = abs(df['senkou_a'].iloc[idx] - df['senkou_b'].iloc[idx]) / price * 100
    if cloud_pct > 2:
        score += 1

    return score

자동매매 봇 통합

이치모쿠 신호를 실제 자동매매에 통합하는 전체 흐름입니다. ccxt로 시세를 받아 신호를 생성하고 TWAP 실행 전략으로 주문합니다.

import ccxt

class IchimokuBot:
    def __init__(self, exchange, symbol, timeframe='4h',
                 capital=10000):
        self.exchange = exchange
        self.symbol = symbol
        self.timeframe = timeframe
        self.capital = capital
        self.position = None  # {'side', 'qty', 'entry_price'}

    def fetch_data(self, limit=100):
        """OHLCV 데이터 조회"""
        ohlcv = self.exchange.fetch_ohlcv(
            self.symbol, self.timeframe, limit=limit
        )
        df = pd.DataFrame(ohlcv,
            columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
        df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
        return df

    def run(self):
        """메인 실행 루프"""
        df = self.fetch_data()
        df = calc_ichimoku(df)
        signals = generate_ichimoku_signals(df)

        latest = signals['signal'].iloc[-1]
        strength = signal_strength(df, len(df) - 1)
        price = df['close'].iloc[-1]

        print(f"[{self.symbol}] 가격: ${price:,.2f} | "
              f"신호: {latest} | 강도: {strength}/5")

        # 매수 신호 + 강도 3 이상 + 포지션 없음
        if latest == 1 and strength >= 3 and not self.position:
            qty = (self.capital * 0.02) / price  # 자본의 2% 리스크
            print(f"매수 진입: {qty:.6f} @ ${price:,.2f}")
            # order = self.exchange.create_market_order(
            #     self.symbol, 'buy', qty)
            self.position = {
                'side': 'long', 'qty': qty, 'entry_price': price
            }

        # 매도 신호 + 롱 포지션 보유
        elif latest == -1 and self.position:
            pnl_pct = (price - self.position['entry_price']) / 
                       self.position['entry_price'] * 100
            print(f"포지션 청산: PnL {pnl_pct:+.2f}%")
            # order = self.exchange.create_market_order(
            #     self.symbol, 'sell', self.position['qty'])
            self.position = None

        # 기준선 손절
        elif self.position:
            kijun = df['kijun_sen'].iloc[-1]
            if price < kijun:
                pnl_pct = (price - self.position['entry_price']) / 
                           self.position['entry_price'] * 100
                print(f"기준선 손절: PnL {pnl_pct:+.2f}%")
                self.position = None

# 사용 예시
exchange = ccxt.binance({
    'apiKey': 'YOUR_KEY', 'secret': 'YOUR_SECRET'
})
bot = IchimokuBot(exchange, 'BTC/USDT', '4h', capital=10000)
bot.run()

이치모쿠 최적 타임프레임

이치모쿠는 원래 일봉 기준으로 설계되었지만, 암호화폐 시장에서는 다양한 타임프레임에서 활용됩니다.

  • 1시간봉: 단기 스윙에 적합. 노이즈가 많아 신호 강도 필터링이 중요합니다.
  • 4시간봉: 가장 인기 있는 설정. 노이즈와 반응 속도의 균형이 좋습니다.
  • 일봉: 전통적 설정. 중장기 추세 포착에 최적이며 신호 신뢰도가 가장 높습니다.
  • 주봉: 장기 투자자용. 큰 추세 전환점을 포착하지만 진입 시점이 늦습니다.

암호화폐 시장은 24/7 운영되므로 전통 설정(9, 26, 52) 대신 암호화폐 최적 설정(10, 30, 60)을 사용하는 트레이더도 많습니다. 백테스트를 통해 자신의 전략에 맞는 파라미터를 검증하는 것이 중요합니다.

마무리

이치모쿠 킨코효는 하나의 지표로 추세, 모멘텀, 지지·저항을 동시에 파악할 수 있는 강력한 도구입니다. 파이썬으로 자동화하면 감정에 흔들리지 않는 체계적 매매가 가능합니다. TK 크로스와 구름 위치를 조합한 신호, 기준선 기반 손절, 신호 강도 필터링까지 적용하면 실전에서도 견고한 이치모쿠 자동매매 시스템을 운영할 수 있습니다.

위로 스크롤
WordPress Appliance - Powered by TurnKey Linux