매매전략 수정중

This commit is contained in:
2026-03-06 20:46:08 +09:00
parent 2b9a90a03f
commit 12460b7c9e
15 changed files with 752 additions and 105 deletions

View File

@@ -1,3 +1,12 @@
"""
기술적 지표 분석 모듈
- 이동평균(MA/EMA), 볼린저 밴드, RSI, MACD, 스토캐스틱, ATR, ADX, OBV 등 계산
- 급등 과열 필터(analyze_overheat): 단기 급등 종목 매수 차단
- 추세 필터(_passes_uptrend): MA 정배열 기반 상승 추세 확인
- 커스텀 신호(analyze_custom_signals): 이격도 필터 포함 이동평균 기반 신호
- 모든 함수는 chart_data(KIS API 응답 리스트) 또는 순수 수치 리스트를 입력으로 받음
"""
import logging
from typing import Optional
@@ -21,6 +30,7 @@ OVERHEAT_DISPARITY_MAX = float(getattr(settings, "OVERHEAT_DISPARITY_MAX", 108.0
def _ma(values: list, window: int) -> Optional[float]:
"""단순 이동평균(SMA) 계산. 데이터 부족 시 None 반환."""
try:
if len(values) < window:
return None
@@ -48,6 +58,11 @@ def _ema(values: list, window: int) -> Optional[float]:
def _passes_uptrend(closes: list, ma_short: int = TREND_MA_SHORT, ma_long: int = TREND_MA_LONG, tol: float = TREND_TOLERANCE_PCT) -> Optional[bool]:
"""MA 정배열 기반 상승 추세 확인.
MA_SHORT >= MA_LONG AND 현재가 >= MA_SHORT (허용 오차 tol 적용).
데이터 부족 시 None 반환.
"""
if not closes or len(closes) < max(ma_short, ma_long):
return None
ma_s = _ma(closes, ma_short)
@@ -139,6 +154,11 @@ def analyze_custom_signals(chart_data):
def analyze_macd(chart_data: list) -> dict:
"""MACD 골든크로스/데드크로스 신호 분석.
EMA12, EMA26으로 MACD 라인 계산 후 Signal(EMA9)과 교차 여부 판단.
Returns: {"signal": "buy"/"sell"/None, "description": str}
"""
if len(chart_data) < 26:
return {"signal": None, "description": "데이터 부족"}
@@ -273,6 +293,11 @@ def analyze_rsi(chart_data: list) -> dict:
def analyze_bollinger(chart_data: list) -> dict:
"""볼린저 밴드 신호 분석.
현재가가 하한선 이하 → buy, 상한선 이상 → sell.
Returns: {"signal": "buy"/"sell"/None, "description": str}
"""
bb_period = settings.BOLLINGER_PERIOD # 기본값 20
bb_stddev = settings.BOLLINGER_STDDEV # 기본값 2.0
if len(chart_data) < bb_period:
@@ -296,6 +321,11 @@ def analyze_bollinger(chart_data: list) -> dict:
def analyze_moving_average(chart_data: list) -> dict:
"""이동평균선(5/20/60일) 정배열/역배열 신호 분석.
MA5 > MA20 정배열 → buy, MA5 < MA20 < MA60 역배열 → sell.
Returns: {"signal": "buy"/"sell"/None, "description": str}
"""
ma_long = settings.MA_LONG_PERIOD # 기본값 60
ma_short = settings.MA_MEDIUM_PERIOD # 기본값 20
ma_quick = settings.MA_SHORT_PERIOD # 기본값 5
@@ -320,6 +350,11 @@ def analyze_moving_average(chart_data: list) -> dict:
def analyze_stochastic(chart_data: list) -> dict:
"""스토캐스틱 %K 과매도/과매수 신호 분석.
%K < 30 → buy, %K > 70 → sell (14봉 기준 Fast Stochastic).
Returns: {"signal": "buy"/"sell"/None, "description": str}
"""
if len(chart_data) < 14:
return {"signal": None, "description": "데이터 부족"}
@@ -346,6 +381,12 @@ def analyze_stochastic(chart_data: list) -> dict:
def analyze_volatility_breakout(chart_data: list, k: float = 0.5) -> dict:
"""변동성 돌파 전략 신호 분석.
목표가 = 당일 시가 + 전일 변동폭 × k (기본 0.5).
현재가 >= 목표가 → buy.
Returns: {"signal": "buy"/None, "description": str}
"""
if len(chart_data) < 2:
return {"signal": None, "description": "데이터 부족"}
@@ -371,6 +412,11 @@ def analyze_volatility_breakout(chart_data: list, k: float = 0.5) -> dict:
def analyze_adx(chart_data: list) -> dict:
"""ADX(Average Directional Index) 추세 강도 신호 분석.
ADX < 20 → 횡보장(평균회귀 유리) buy, ADX > 30 → 강추세(평균회귀 위험) sell.
Returns: {"signal": "buy"/"sell"/None, "description": str, "adx": float}
"""
if len(chart_data) < 29:
return {"signal": None, "description": "데이터 부족", "adx": None}
@@ -390,6 +436,12 @@ def analyze_adx(chart_data: list) -> dict:
def analyze_obv(chart_data: list) -> dict:
"""OBV(On-Balance Volume) 기반 거래량 신호 분석.
최근 5봉 거래량 추세 확인: 거래량 1.5배 증가 + 상승 → buy,
거래량 0.5배 감소 + 하락 → sell.
Returns: {"signal": "buy"/"sell"/None, "description": str}
"""
if len(chart_data) < 2:
return {"signal": None, "description": "데이터 부족"}