Coverage for strategies / oneil_common_types.py: 100%
125 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-04 15:08 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-04 15:08 +0000
1# strategies/oneil/common_types.py
2from dataclasses import dataclass
3import os
4from strategies.base_strategy_config import BaseStrategyConfig
6@dataclass
7class OneilUniverseConfig(BaseStrategyConfig):
8 """오닐 유니버스(종목 발굴) 관련 설정."""
9 # 유니버스 필터
10 min_avg_trading_value_5d: int = 10_000_000_000 # 5일 평균 거래대금 100억 원
11 near_52w_high_pct: float = 20.0 # 52주 최고가 대비 20% 이내
13 # 워치리스트 갱신 시각 (장 시작 후 경과 분)
14 watchlist_refresh_minutes: tuple = (10, 30, 60, 90, 60*3, 60*5)
16 # 스퀴즈 조건
17 bb_period: int = 20
18 multiplier: float = 2.0 # 표준편차의 배수
19 squeeze_tolerance: float = 1.2 # BB 폭이 20일 최소폭의 1.2배 이내
21 # 마켓 타이밍
22 kosdaq_etf_code: str = "229200" # KODEX 코스닥150
23 kospi_etf_code: str = "069500" # KODEX 200
24 market_ma_period: int = 20
25 market_ma_rising_days: int = 3
27 # V2 스코어링
28 rs_period_days: int = 63
29 rs_top_percentile: float = 10.0
30 rs_score_points: float = 30.0
31 profit_growth_threshold_pct: float = 25.0
32 profit_growth_score_points: float = 20.0
33 api_chunk_size: int = 10
35 # 전일기준우량주 / 당일급등주 설정
36 premium_stocks_file: str = os.path.join("data", "premium_stocks.json")
37 premium_stocks_kospi_size: int = 20
38 premium_stocks_kosdaq_size: int = 40
40 premium_stocks_cap_min: int = 200_000_000_000 # 2000억
41 premium_stocks_cap_max: int = 20_000_000_000_000 # 20조
42 daily_surge_size: int = 30
44 max_watchlist: int = premium_stocks_kospi_size + premium_stocks_kosdaq_size + daily_surge_size # 최대 감시 종목 수
46 # 돌파 기준 기간 (데이터 수집용)
47 high_breakout_period: int = 20
49 # 스마트 머니 (수급) 스코어링
50 smart_money_lookback_days: int = 3 # 3일 누적 기준
51 smart_money_to_mcap_pct: float = 0.5 # 시총의 0.5% 이상 매집 시
52 smart_money_to_tv_pct: float = 10.0 # 또는 누적 거래대금의 10% 이상 매집 시
53 smart_money_score_points: float = 15.0 # +15점 부여
56@dataclass
57class OneilBreakoutConfig(BaseStrategyConfig):
58 """오닐 돌파 매매 전략(Strategy B) 설정."""
59 # 매수 조건
60 volume_breakout_multiplier: float = 1.5 # 20일 평균 거래량의 150%
61 program_net_buy_min: int = 0 # pgtr_ntby_qty > 0
62 program_to_trade_value_pct: float = 10.0 # (프로그램순매수금/거래대금) >= 10%
63 program_to_market_cap_pct: float = 0.5 # (프로그램순매수금/시총) >= 0.5%
65 # 매도 조건
66 stop_loss_pct: float = -5.0
67 trailing_stop_pct: float = 8.0
68 time_stop_days: int = 5
69 time_stop_box_range_pct: float = 2.0
70 trend_exit_ma_period: int = 10
72 # 자금 관리
73 total_portfolio_krw: int = 10_000_000
74 position_size_pct: float = 5.0
75 min_qty: int = 1
78@dataclass
79class OSBWatchlistItem:
80 """감시 종목 정보 (Universe Service -> Strategy 전달 객체)."""
81 code: str
82 name: str
83 market: str # "KOSPI" or "KOSDAQ"
84 high_20d: int # 20일 최고가 (돌파 기준)
85 ma_20d: float # 20일 이동평균
86 ma_50d: float # 50일 이동평균
87 avg_vol_20d: float # 20일 평균 거래량
88 bb_width_min_20d: float # 최근 20일간 BB 밴드폭 최소값
89 prev_bb_width: float # 전일 BB 밴드폭
90 w52_hgpr: int # 52주 최고가
91 avg_trading_value_5d: float # 5일 평균 거래대금
92 market_cap: int = 0 # 시가총액
94 # 스코어링
95 rs_return_3m: float = 0.0
96 rs_score: float = 0.0
97 profit_growth_score: float = 0.0
98 smart_money_score: float = 0.0
99 total_score: float = 0.0
102@dataclass
103class OSBPositionState:
104 """보유 포지션 추적 상태."""
105 entry_price: int # 진입가
106 entry_date: str # 진입일 (YYYYMMDD)
107 peak_price: int # 진입 후 최고가 (트레일링 스탑용)
108 breakout_level: int # 진입 시 20일 최고가
111@dataclass
112class OneilPocketPivotConfig(BaseStrategyConfig):
113 """포켓 피봇 & BGU 전략(Strategy C) 설정."""
114 # 공통 스마트 머니 필터
115 program_to_trade_value_pct: float = 10.0 # PG순매수금/거래대금 >= 10%
116 program_to_market_cap_pct: float = 0.3 # PG순매수금/시총 >= 0.3%
117 execution_strength_min: float = 120.0 # 체결강도 >= 120%
119 # Entry A: Pocket Pivot
120 pp_ma_proximity_lower_pct: float = -2.0 # MA 대비 하한 (-2%)
121 pp_ma_proximity_upper_pct: float = 4.0 # MA 대비 상한 (+4%)
122 pp_down_day_lookback: int = 10 # 하락일 거래량 비교 기간 (일)
124 # Entry B: BGU (Buyable Gap-Up)
125 bgu_gap_pct: float = 4.0 # 시가 갭 >= 4%
126 bgu_volume_multiplier: float = 3.0 # 50일 평균거래량의 300%
127 bgu_whipsaw_after_minutes: int = 10 # 장 시작 후 10분 경과 후 진입
129 # 매도: 손절
130 pp_stop_loss_below_ma_pct: float = -2.0 # PP: 지지MA 대비 -2% 이탈 시 손절
132 # 매도: 7주 홀딩 룰
133 holding_rule_days: int = 35 # 7주 = 35거래일
134 holding_rule_ma_period: int = 50 # 50일선 기준
135 holding_profit_anchor_pct: float = 5.0 # +5% 이상 수익 시 holding_start_date 기록 (1회만)
137 # 매도: 부분 익절
138 partial_profit_trigger_pct: float = 15.0 # +15% 도달 시 50% 익절
139 partial_sell_ratio: float = 0.5 # 50% 매도
141 # 매도: 하드 스탑
142 hard_stop_from_peak_pct: float = -10.0 # 고점 대비 -10% 하락 시 즉시 청산
144 # 자금 관리
145 total_portfolio_krw: int = 10_000_000
146 position_size_pct: float = 5.0
147 min_qty: int = 2 # 부분 익절을 위해 최소 2주 매수
150@dataclass
151class PPPositionState:
152 """포켓 피봇 / BGU 포지션 추적 상태."""
153 entry_type: str # "PP" or "BGU"
154 entry_price: int # 진입가
155 entry_date: str # 진입일 (YYYYMMDD)
156 peak_price: int # 진입 후 최고가
157 supporting_ma: str # PP전용: "10"/"20"/"50" (지지 MA 종류)
158 gap_day_low: int # BGU전용: 갭업 당일 장중 저가
159 partial_sold: bool = False # deprecated (JSON 하위호환용)
160 holding_start_date: str = "" # 수익 안착일 (+5% 돌파 시 1회만 기록, 7주 룰 기산점)
161 last_partial_sell_price: int = 0 # 마지막 부분익절 가격 (0=미실행, >0=기준가)
164@dataclass
165class HTFConfig(BaseStrategyConfig):
166 """하이 타이트 플래그 전략 설정."""
167 # Phase 1: 깃대 (Pole)
168 pole_lookback_days: int = 40 # 40거래일 스캔
169 pole_min_surge_ratio: float = 1.90 # max(high)/min(low) >= 1.90
171 # Phase 2: 깃발 (Flag)
172 flag_min_days: int = 5 # 최소 횡보 기간 (한국형: Short Stroke 대응)
173 flag_max_days: int = 25 # 최대 횡보 기간
174 flag_max_drawdown_pct: float = 20.0 # 고점 대비 최대 하락폭 (종가 기준)
175 flag_volume_shrink_ratio: float = 1.2 # 깃발 평균거래량 < 50일평균 * 1.2
177 # Phase 3: 돌파 (Breakout)
178 volume_breakout_multiplier: float = 2.0 # 예상거래량 >= 50일평균 * 200%
179 execution_strength_min: float = 120.0 # 체결강도 >= 120%
181 # Phase 4: 청산 (Exit)
182 stop_loss_pct: float = -5.0 # 칼손절
183 trailing_ma_period: int = 10 # 10일 MA 트레일링스탑
185 # 자금 관리
186 total_portfolio_krw: int = 10_000_000
187 position_size_pct: float = 5.0
188 min_qty: int = 1
191@dataclass
192class HTFPositionState:
193 """HTF 포지션 추적 상태."""
194 entry_price: int # 진입가
195 entry_date: str # 진입일 (YYYYMMDD)
196 peak_price: int # 진입 후 최고가
197 pole_high: int # 깃대 최고점 (돌파 기준가)