feat(sim): 물타기(애버리징) 토글 — 하락 시 손절 대신 평단↓ 추가매수
- config: AVERAGING_ENTRY·AVERAGING_DROP_PCT(0.10)·CRASH_DROP_PCT(0.10) - signals.evaluate_holding: market_ok 인자 + 물타기 분기 (직전매수가 -10% 하락 시 ADD-down, 한도/강세장/비급락 조건, 당일 -10%급락은 손절·약세장 금지) - engine·backtest: add_kind='down'이면 손절선 낮은 평단 기준 재설정(up은 위로 래칫 유지), engine은 market_ok 전달 - 첫 매수는 기존 검증 진입 그대로(우량주만 물타기) - 백테스트: 즉시매수와 반대로 유리(10/20/60 수익·승률↑) → 라이브 변이 3개(v301/302/303) 등록, 총 223 - 웹 '물타기' 칩 + 설명 토스트 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -266,11 +266,12 @@ def evaluate_candidate(code, name, sources, ind, flow, analyst, market_ok) -> di
|
||||
'reason': f'눌림목 대기 — 지정가 {limit:,}'}
|
||||
|
||||
|
||||
def evaluate_holding(position, ind, flow, analyst, held_days=None) -> dict:
|
||||
def evaluate_holding(position, ind, flow, analyst, held_days=None, market_ok=True) -> dict:
|
||||
"""보유 종목 판단. 우선순위: 손절/추세이탈(전량) → 시간손절 → 분할익절(scale_out) → 추격매수(add) → 유지.
|
||||
|
||||
position 의 stop/peak/trailing/scaled_out 갱신값도 position_update 로 함께 반환.
|
||||
held_days: 보유 경과 일수(달력). None이면 시간손절 미적용(엔진·백테스트가 산정해 전달).
|
||||
market_ok: 시장 강세 여부(물타기 허용 판단용, 백테스트는 중립 True).
|
||||
"""
|
||||
price = ind['price']
|
||||
entry = position['entry_price']
|
||||
@@ -314,6 +315,23 @@ def evaluate_holding(position, ind, flow, analyst, held_days=None) -> dict:
|
||||
'price': price, 'checks': checks, 'action': None, 'state': 'HOLD',
|
||||
'position_update': upd, 'pnl_pct': pnl_pct}
|
||||
|
||||
# 0. 물타기(애버리징) — 켜진 변이만. 하락 시 손절 대신 추가매수로 평단↓ (한도·강세장·비급락 조건).
|
||||
# 당일 단일 급락(-CRASH%↓)은 물타기 금지→손절 우선(그림 #3), 약세장도 금지(그림 #4).
|
||||
avg_on = getattr(config, 'AVERAGING_ENTRY', 0)
|
||||
if avg_on:
|
||||
prev_close = ind.get('prev_close') or price
|
||||
today_chg = (price / prev_close - 1) if prev_close else 0
|
||||
crash = today_chg <= -getattr(config, 'CRASH_DROP_PCT', 0.10)
|
||||
avg_trigger = last_add * (1 - getattr(config, 'AVERAGING_DROP_PCT', 0.10))
|
||||
budget_left = tranches < config.ENTRY_TRANCHES
|
||||
# 트레일링/익절 전 + 한도 남음 + 강세장 + 비급락 + 직전매수가 -X% 도달 → 물타기
|
||||
if (budget_left and market_ok and not crash and not trailing_on and not scaled_out
|
||||
and price <= avg_trigger):
|
||||
return {**base, 'state': 'ADD', 'action': 'add', 'add_kind': 'down',
|
||||
'reason': f'물타기 — {tranches + 1}/{config.ENTRY_TRANCHES}차 (평단↓, -{config.AVERAGING_DROP_PCT*100:.0f}%)'}
|
||||
# 물타기 한도 소진(또는 급락/약세장)인데 손절선 깨짐 → 최종 손절
|
||||
# (한도 남았는데 급락이면 아래 일반 손절로 자연 처리)
|
||||
|
||||
# 1. 손절·추세이탈 — 전량
|
||||
if price <= stop:
|
||||
reason = '트레일링 익절' if (trailing_on and price > entry) else '손절'
|
||||
|
||||
Reference in New Issue
Block a user