fix(stock): Phase 2 결정엔진 견고화 (빈노드 제외·cur=0 손절·params기본값·NaN MA·테스트)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -141,3 +141,50 @@ def test_decide_action_matrix():
|
||||
# 이탈 없음 보통 강도 → hold
|
||||
a, _ = hi.decide_action(50, {}, 1)
|
||||
assert a == "hold"
|
||||
|
||||
|
||||
# ---- Phase 2 hardening tests (m3) ----
|
||||
|
||||
def _ticker_prices_hl(closes, highs, vols):
|
||||
n = len(closes)
|
||||
base = dt.date(2025, 1, 1)
|
||||
return pd.DataFrame({
|
||||
"ticker": ["005930"] * n,
|
||||
"date": [(base + dt.timedelta(days=i)).isoformat() for i in range(n)],
|
||||
"open": closes,
|
||||
"high": highs,
|
||||
"low": closes,
|
||||
"close": closes,
|
||||
"volume": vols,
|
||||
})
|
||||
|
||||
|
||||
def test_exit_rules_climax():
|
||||
closes = [1000] * 30
|
||||
highs = [1000] * 29 + [1100] # 마지막날 상단꼬리(종가1000 < 고가1100*0.97)
|
||||
vols = [1000] * 29 + [5000] # 거래량 5x
|
||||
flags = hi.exit_rules({"avg_price": 900, "current_price": 1000},
|
||||
_ticker_prices_hl(closes, highs, vols), {})
|
||||
assert flags["climax"] is True
|
||||
|
||||
|
||||
def test_exit_rules_ma200_break():
|
||||
closes = list(range(1000, 1000 + 260))[::-1] # 하락 추세 → 종가 < MA200
|
||||
df = _ticker_prices(closes)
|
||||
flags = hi.exit_rules({"avg_price": 2000, "current_price": closes[-1]}, df, {})
|
||||
assert flags["ma200_break"] is True
|
||||
|
||||
|
||||
def test_technical_posture_short_history_returns_low_not_crash():
|
||||
ctx = _toy_ctx(("005930",), n=100) # <252 → MA 노드 NaN→0, but no crash
|
||||
scores = hi.technical_posture(ctx, ["005930"])
|
||||
assert "005930" in scores
|
||||
assert 0.0 <= scores["005930"] <= 100.0
|
||||
|
||||
|
||||
def test_technical_posture_empty_kospi_not_penalized():
|
||||
# rs_rating는 빈 kospi에서 빈 Series → combine에서 제외되어야 (C1)
|
||||
ctx = _toy_ctx(("005930",), n=300) # kospi 빈 fixture
|
||||
scores = hi.technical_posture(ctx, ["005930"])
|
||||
# ma_alignment+momentum만으로 정규화 → 상승추세면 충분히 높은 점수
|
||||
assert scores["005930"] > 50.0
|
||||
|
||||
Reference in New Issue
Block a user