"""다이버전스 유형 복합 기법.""" from __future__ import annotations import pandas as pd from deepcoin.techniques.base import BaseTechnique, TechniqueParams, TechniqueSignal from deepcoin.techniques.composite_base import ( cluster_events, collect_weighted_events, score_clusters_to_signals, ) from deepcoin.techniques.macd_cross import MacdCrossTechnique from deepcoin.techniques.macd_divergence import MacdDivergenceTechnique from deepcoin.techniques.obv_divergence import ObvDivergenceTechnique from deepcoin.techniques.rsi_divergence import RsiDivergenceTechnique from deepcoin.techniques.rsi_swing import RsiSwingTechnique _SUB = [ RsiDivergenceTechnique(), MacdDivergenceTechnique(), ObvDivergenceTechnique(), RsiSwingTechnique(), MacdCrossTechnique(), ] _WEIGHTS: dict[str, tuple[float, float]] = { "rsi_divergence": (2.5, 2.5), "macd_divergence": (2.5, 2.5), "obv_divergence": (2.0, 2.0), "rsi_swing": (1.2, 1.2), "macd_cross": (1.0, 1.0), } class CompositeDivergenceTechnique(BaseTechnique): """다이버전스 Bd/Sd 유형 전담 복합 기법.""" technique_id = "composite_divergence" technique_name = "다이버전스 복합" category = "composite" causal = True description = "RSI/MACD/OBV 다이버전스 가중 투표 (Bd/Sd)" def default_extra_params(self) -> dict: return {"min_score": 2.0, "merge_bars": 5, "trend_ema_span": 60} def generate_signals(self, df: pd.DataFrame, params: TechniqueParams) -> list[TechniqueSignal]: min_score = float(params.extra.get("min_score", 2.0)) merge_bars = int(params.extra.get("merge_bars", 5)) trend_span = int(params.extra.get("trend_ema_span", 60)) events = collect_weighted_events(_SUB, _WEIGHTS, df, params) clusters = cluster_events(events, merge_bars=merge_bars) return score_clusters_to_signals( df, clusters, min_score=min_score, trend_span=trend_span, use_trend_filter=False, )