[알고리즘 트레이딩] 국소 극값 (Local Extreme Values) 활용
Local Extreme Values (국소 극값) 개념은 알고리즘 트레이딩에서 여러 가지 방식으로 활용됩니다. 대표적인 사용 사례는 다음과 같습니다.
1. 지지선 및 저항선 탐색
- 국소 최대값(local maxima) → 저항선(Resistance Level) 후보
- 국소 최소값(local minima) → 지지선(Support Level) 후보
- 특정 주기의 국소 극값을 이용해 가격이 특정 지점을 돌파하는지 확인하는 돌파 전략(Breakout Strategy) 에 사용됨.
2. 추세 분석 및 반전(Trend Reversal) 감지
- 국소 최대/최소값을 기반으로 고점과 저점 패턴을 분석하여 추세 전환 가능성을 탐지.
-- 고점이 낮아지고 저점이 낮아지는 패턴 → 하락 추세(Downtrend)
-- 저점이 높아지고 고점이 높아지는 패턴 → 상승 추세(Uptrend)
- 대표적인 지표:
-- ZigZag Indicator: 일정 임계값 이상 변화한 지점에서 국소 극값을 찾음.
-- Fractal Indicator: 특정 패턴을 기반으로 국소 극값을 식별하여 추세 반전을 찾음.
3. 볼린저 밴드 및 평균 회귀(Mean Reversion) 전략
- 볼린저 밴드를 사용할 때, 가격이 국소 최소값일 때 과매도(Oversold) 신호로 간주하여 매수.
- 국소 최대값일 때 과매수(Overbought) 신호로 간주하여 매도.
- 사용자는 이미 볼린저 밴드의 %b 값을 사용 중이므로, 국소 극값과의 조합도 고려 가능.
4. 피보나치 되돌림(Fibonacci Retracement) & 확장(Fibonacci Extension)
- 피보나치 비율을 적용할 때, 국소 최대/최소값을 기준으로 주요 되돌림 구간을 찾음.
- 하지만 사용자는 현재 피보나치 관련 로직을 삭제한 상태이므로, 적용할 가능성은 낮음.
5. 모멘텀 기반 전략 (Divergence Detection)
- RSI, MACD 등의 모멘텀 지표와 국소 극값을 비교하여 다이버전스(Divergence) 감지.
-- 예: 가격이 새로운 국소 최대값을 형성하는데, RSI는 더 낮은 고점을 형성 → 약세 다이버전스(매도 신호).
사용자 전략과 연결 가능성
- 사용자는 현재 볼린저 밴드의 %b 값을 기반으로 매수/매도 전략을 구현 중.
- 국소 최소값이 형성될 때 %b가 0 이하라면 더 신뢰할 수 있는 매수 신호가 될 가능성이 있음.
- 반대로 국소 최대값이 형성될 때 %b가 1 이상이라면 매도 신호 강화 가능.
국소 극값(Local Extreme Values)을 찾는 대표적인 알고리즘과 파이썬 구현 코드
1. ZigZag Algorithm (가격 변화율 기반)
개념:
- 일정 임계값(%) 이상 가격이 변할 때 국소 최대/최소값을 찾는 방식
- 작은 변동을 제거하여 중요한 추세만 남김
- 단점: 임계값을 어떻게 설정하느냐에 따라 결과가 크게 달라질 수 있음
파이썬 코드:
import numpy as np
import pandas as pd
def find_zigzag_extremes(prices, threshold=5):
"""
ZigZag 알고리즘을 이용한 국소 극값 찾기
:param prices: 가격 데이터 (리스트 또는 NumPy 배열)
:param threshold: 극값을 판단하는 임계값 (%)
:return: 극값이 있는 인덱스와 해당 가격
"""
peaks = []
valleys = []
last_extreme = None
last_extreme_idx = None
direction = None # 'up' 또는 'down'
for i in range(1, len(prices)):
change = ((prices[i] - prices[i - 1]) / prices[i - 1]) * 100
if direction is None:
direction = "up" if change > 0 else "down"
if direction == "up":
if change < -threshold:
valleys.append((last_extreme_idx, last_extreme))
direction = "down"
last_extreme = prices[i]
last_extreme_idx = i
elif prices[i] > (last_extreme or prices[i-1]):
last_extreme = prices[i]
last_extreme_idx = i
elif direction == "down":
if change > threshold:
peaks.append((last_extreme_idx, last_extreme))
direction = "up"
last_extreme = prices[i]
last_extreme_idx = i
elif prices[i] < (last_extreme or prices[i-1]):
last_extreme = prices[i]
last_extreme_idx = i
return peaks, valleys
# 예제 데이터
prices = [100, 105, 110, 95, 90, 115, 120, 80, 85, 130]
peaks, valleys = find_zigzag_extremes(prices, threshold=5)
print("Peaks:", peaks)
print("Valleys:", valleys)
해석:
- 일정 임계값(%) 이상 가격이 오르면 고점(peak), 내리면 저점(valley) 로 인식
- 주어진 가격 리스트에서 (인덱스, 가격) 형태로 극값을 반환
2. SciPy argrelextrema (미분 기반)
개념:
- 국소적으로 최대/최소가 되는 지점을 찾기 위해 1차 미분 개념 활용
- 특정 구간에서 주변보다 높은 값을 최대값, 낮은 값을 최소값으로 간주
- 장점: 매개변수 설정이 간단
- 단점: 노이즈가 많으면 너무 많은 극값이 검출됨
파이썬 코드:
import numpy as np
import pandas as pd
from scipy.signal import argrelextrema
def find_local_extremes(prices, order=3):
"""
SciPy의 argrelextrema를 이용한 국소 극값 찾기
:param prices: 가격 데이터 (리스트 또는 NumPy 배열)
:param order: 극값을 찾을 때 비교할 기준 (n개의 앞뒤 데이터와 비교)
:return: 최대값 인덱스, 최소값 인덱스
"""
prices = np.array(prices)
# 국소 최대값 (Peak)
local_max_idx = argrelextrema(prices, np.greater, order=order)[0]
# 국소 최소값 (Valley)
local_min_idx = argrelextrema(prices, np.less, order=order)[0]
return local_max_idx, local_min_idx
# 예제 데이터
prices = [100, 105, 110, 95, 90, 115, 120, 80, 85, 130]
max_idx, min_idx = find_local_extremes(prices, order=2)
print("Local Maxima:", max_idx)
print("Local Minima:", min_idx)
해석:
- order=3이면 앞뒤 3개 가격과 비교하여 국소 극값인지 판단
- argrelextrema는 연속 데이터의 국소 극값을 찾기에 유용
- 노이즈를 줄이려면 order 값을 증가시켜야 함
3 Fractal Indicator (Bill Williams 방식, 캔들 패턴 기반)
개념:
- 5개 캔들(봉) 을 사용하여 국소 극값을 찾는 방식
- 특정 패턴이 충족될 때만 극값으로 판단
- 장점: 추세 분석과 함께 사용 가능
- 단점: 지연 발생 가능 (최소 2개 이상 캔들이 더 필요함)
파이썬 코드:
import pandas as pd
import numpy as np
def find_fractals(prices):
"""
Fractal Indicator를 이용한 국소 극값 찾기
:param prices: 가격 데이터 (리스트 또는 NumPy 배열)
:return: 최대값, 최소값 인덱스 리스트
"""
max_idx = []
min_idx = []
for i in range(2, len(prices) - 2):
# 국소 최대값: 중앙 값이 좌우 2개 값보다 높음
if prices[i] > prices[i-1] and prices[i] > prices[i-2] and \
prices[i] > prices[i+1] and prices[i] > prices[i+2]:
max_idx.append(i)
# 국소 최소값: 중앙 값이 좌우 2개 값보다 낮음
if prices[i] < prices[i-1] and prices[i] < prices[i-2] and \
prices[i] < prices[i+1] and prices[i] < prices[i+2]:
min_idx.append(i)
return max_idx, min_idx
# 예제 데이터
prices = [100, 105, 110, 95, 90, 115, 120, 80, 85, 130]
max_idx, min_idx = find_fractals(prices)
print("Fractal Maxima:", max_idx)
print("Fractal Minima:", min_idx)
해석:
- 5개 캔들 중 중앙 값이 가장 크면 국소 최대값
- 5개 캔들 중 중앙 값이 가장 작으면 국소 최소값
댓글
댓글 쓰기