fix: 트레이딩 로직/AI 정확도 8종 수정 (Altman 과발생·CV누수·MACD·손절역전)
트레이딩 전문가 관점 로직 감사 후 라이브 추천·자동매매 영향 8종 수정. [명백한 버그] - MACD 시그널선: macd_line[-9:] 9개만 EMA→평활 거의 안 됨. 전체 시리즈로 수정 (ta-engine) - 매수 손절가 역전: 하락추세(price<MA60)서 ma60*0.95가 진입가 위로 올라가 RR 역전·즉시손절 → [-10%,-4%] 밴드로 클램프. 매도(숏)도 대칭 수정 (ta-engine) - 12-1 모멘텀: closes[-1]은 보유데이터 길이(200~259)따라 룩백 가변→closes[min(251,len-1)] 12개월 고정 [모델 품질] - Ridge 무스케일 학습: 피처 -100~수천 혼재로 L2 왜곡. StandardScaler 파이프라인 + 계수 원본공간 역변환 저장(predict-price 무변경, 재구성 오차 3.5e-15) - CV 패널 누수: 인덱스 분할이 같은 score_date를 train/test로 가르고 +30일 라벨윈도가 test 피처와 겹침. 날짜분할 + 임바고(7d→12일/30d→39일)로 차단→정직한 IC/r2 [캘리브레이션·리스크] - Altman Z: 2항 변형에 원본 4항 임계값(2.6/1.1) 적용→전시장 31%가 '부도위험' 오발생. 실측분포(중앙값1.98/p10 0.51) 기준 부도0.7/안전3.0 재보정 - 일일 -3% halt: realized_pnl만 봐서 평가손실·무매도일 누락. 미실현손익 합산으로 수정 빌드·재기동·라이브 스모크 검증 완료. 자동매매 capital 실잔고 연동은 향후 과제(paper모드 무관). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+10
-4
@@ -80,7 +80,9 @@ def _macd(closes: List[float]) -> tuple:
|
||||
e12 = _ema_series(closes, 12)
|
||||
e26 = _ema_series(closes, 26)
|
||||
macd_line = [a - b for a, b in zip(e12, e26)]
|
||||
signal_line = _ema_series(macd_line[-9:] if len(macd_line) >= 9 else macd_line, 9)
|
||||
# 시그널선 = MACD선 전체에 대한 9-EMA. 과거 9개(-9:)만 쓰면 평활이 거의 안 돼
|
||||
# 표준 MACD 시그널과 달라짐 → 전체 시리즈로 EMA 계산.
|
||||
signal_line = _ema_series(macd_line, 9)
|
||||
macd = macd_line[-1]
|
||||
signal = signal_line[-1]
|
||||
return round(macd, 4), round(signal, 4), round(macd - signal, 4)
|
||||
@@ -335,9 +337,11 @@ def calc_price_targets(price: int, ind: dict, sig: str) -> dict:
|
||||
t2 = r10(price * 1.14)
|
||||
t3 = r10(min(price * 1.22, h52 * 0.97))
|
||||
t3 = t3 if t3 > t2 else r10(price * 1.22)
|
||||
# 손절: max(-8%, MA60 -5%) — 최대 -10% 이내 제한
|
||||
# 손절: max(-8%, MA60 -5%)를 [-10%, -4%] 밴드로 제한해 항상 진입가 아래 유지.
|
||||
# (하락추세로 price<MA60이면 MA60*0.95가 현재가 위로 올라가 손절가>진입가가 되어
|
||||
# RR이 역전·즉시 손절되는 버그 차단)
|
||||
raw_stop = max(price * 0.92, ma60 * 0.95)
|
||||
stop = r10(max(raw_stop, price * 0.90)) # 최소 -10%
|
||||
stop = r10(min(max(raw_stop, price * 0.90), price * 0.96))
|
||||
er1 = round((t1 - price) / price * 100, 1)
|
||||
sl_r = round(abs(stop - price) / price * 100, 1)
|
||||
# M3: ATR 기반 trailing stop (현재가 기준 2 ATR 아래)
|
||||
@@ -360,8 +364,10 @@ def calc_price_targets(price: int, ind: dict, sig: str) -> dict:
|
||||
t2 = r10(price * 0.86)
|
||||
t3 = r10(max(price * 0.78, l52 * 1.03))
|
||||
t3 = t3 if t3 < t2 else r10(price * 0.78)
|
||||
# 숏 손절: [+4%, +10%] 밴드로 제한해 항상 진입가(+2%) 위 유지
|
||||
# (price>MA20이면 ma20*1.05가 현재가 아래로 내려가 손절가<진입가 역전되는 버그 차단)
|
||||
raw_stop = min(price * 1.08, ma20 * 1.05)
|
||||
stop = r10(min(raw_stop, price * 1.10))
|
||||
stop = r10(max(min(raw_stop, price * 1.10), price * 1.04))
|
||||
er1 = round((price - t1) / price * 100, 1)
|
||||
sl_r = round(abs(stop - price) / price * 100, 1)
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user