캔들패턴 전략¶
QuantiqDSL의 OHLC 데이터를 활용하여 캔들스틱 패턴을 감지하는 전략 예제입니다.
1. 망치형 (Hammer) 패턴¶
하락 추세에서 긴 아래 꼬리와 작은 몸통을 가진 양봉이 나타나면 반전 신호입니다.
version("1.0")
description("망치형(Hammer) 패턴 감지 전략")
c = chart("1D")
sma20 = ta.sma(c.close, 20)
# 캔들 구성 요소
body = abs(c.close[0] - c.open[0])
upper_wick = c.high[0] - max(c.close[0], c.open[0])
lower_wick = min(c.close[0], c.open[0]) - c.low[0]
full_range = c.high[0] - c.low[0]
# 망치형 조건
is_hammer = (
full_range > 0 and
lower_wick > body * 2 and # 아래 꼬리가 몸통의 2배 이상
upper_wick < body * 0.5 and # 위 꼬리가 작음
body > 0 and # 양봉
c.close[0] > c.open[0]
)
# 하락 추세 확인
downtrend = c.close < sma20
c.line("SMA 20", sma20, color="blue")
if is_hammer and downtrend:
c.marker("HAMMER", color="green", position="below", shape="triangle")
buy(tag=f"망치형 패턴 — 하락추세 반전 기대")
else:
hold()
2. 장악형 (Engulfing) 패턴¶
이전 봉을 완전히 감싸는 큰 봉이 나타나면 추세 전환 신호입니다.
version("1.0")
description("장악형(Engulfing) 패턴 전략")
c = chart("1D")
# 이전 봉
prev_open = c.open[1]
prev_close = c.close[1]
prev_body = abs(prev_close - prev_open)
# 현재 봉
curr_open = c.open[0]
curr_close = c.close[0]
curr_body = abs(curr_close - curr_open)
# 상승 장악형: 이전 음봉을 현재 양봉이 감쌈
bullish_engulf = (
prev_close < prev_open and # 이전: 음봉
curr_close > curr_open and # 현재: 양봉
curr_open <= prev_close and # 현재 시가 <= 이전 종가
curr_close >= prev_open and # 현재 종가 >= 이전 시가
curr_body > prev_body # 현재 몸통 > 이전 몸통
)
# 하락 장악형: 이전 양봉을 현재 음봉이 감쌈
bearish_engulf = (
prev_close > prev_open and # 이전: 양봉
curr_close < curr_open and # 현재: 음봉
curr_open >= prev_close and # 현재 시가 >= 이전 종가
curr_close <= prev_open and # 현재 종가 <= 이전 시가
curr_body > prev_body # 현재 몸통 > 이전 몸통
)
if bullish_engulf:
c.marker("BUL ENG", color="green", position="below", shape="triangle")
buy(tag="상승 장악형 패턴")
elif bearish_engulf:
c.marker("BER ENG", color="red", position="above", shape="triangle")
sell(tag="하락 장악형 패턴")
else:
hold()
3. 도지 (Doji) 패턴¶
시가와 종가가 거의 같은 봉으로, 시장의 불확실성을 나타냅니다.
version("1.0")
description("도지(Doji) + 추세 반전 전략")
param("doji_threshold", "doji threshold", 0.1)
c = chart("1D")
rsi = ta.rsi(c.close, 14)
body = abs(c.close[0] - c.open[0])
full_range = c.high[0] - c.low[0]
# 도지 조건: 몸통이 전체 범위의 10% 이하
is_doji = full_range > 0 and (body / full_range) < script_params["doji_threshold"]
if is_doji:
c.marker("DOJI", color="yellow", position="above", shape="circle")
log(f"도지 감지 — 몸통 비율: {body/full_range*100:.1f}%")
# 도지 + RSI 조합으로 방향 판단
if rsi[0] < 30:
buy(tag="도지 + RSI 과매도 → 반등 기대")
elif rsi[0] > 70:
sell(tag="도지 + RSI 과매수 → 반락 기대")
else:
hold(tag="도지 감지 — 방향 불확실")
else:
hold()
4. 연속 양봉/음봉 전략¶
연속으로 같은 방향의 봉이 나타나면 추세가 강하다고 판단합니다.
version("1.0")
description("연속 양봉/음봉 전략")
param("count", "count", 3)
c = chart("1D")
# 연속 양봉 카운트
bullish_count = 0
for i in range(script_params["count"]):
if c.close.is_valid(i) and c.close[i] > c.open[i]:
bullish_count = bullish_count + 1
else:
break
# 연속 음봉 카운트
bearish_count = 0
for i in range(script_params["count"]):
if c.close.is_valid(i) and c.close[i] < c.open[i]:
bearish_count = bearish_count + 1
else:
break
target = script_params["count"]
if bullish_count >= target:
buy(tag=f"{bullish_count}연속 양봉 — 강한 상승 모멘텀")
elif bearish_count >= target:
sell(tag=f"{bearish_count}연속 음봉 — 강한 하락 모멘텀")
else:
hold()
5. 갭 전략¶
갭업/갭다운 발생을 감지하여 매매합니다.
version("1.0")
description("갭(Gap) 전략")
param("gap_pct", "gap pct", 2.0)
c = chart("1D")
# 갭 계산 (현재 시가 vs 이전 종가)
if c.close.is_valid(1):
gap = (c.open[0] - c.close[1]) / c.close[1] * 100
if gap > script_params["gap_pct"]:
c.marker("GAP UP", color="green", position="below", shape="arrow")
log(f"갭업: {gap:.1f}%")
# 갭업 후 양봉이면 추세 지속
if c.close[0] > c.open[0]:
buy(tag=f"갭업({gap:.1f}%) 후 양봉 — 상승 지속")
else:
hold(tag="갭업 후 음봉 — 되메움 가능성")
elif gap < -script_params["gap_pct"]:
c.marker("GAP DN", color="red", position="above", shape="arrow")
log(f"갭다운: {gap:.1f}%")
rsi = ta.rsi(c.close, 14)
if rsi[0] < 30:
buy(tag=f"갭다운({gap:.1f}%) + RSI 과매도 반등")
else:
sell(tag=f"갭다운({gap:.1f}%) — 하락 지속")
else:
hold()
else:
hold()