"""trade_helpers 추격매수/트렌드 필터 — KIS 일봉 순서(최신 우선) 회귀 테스트.""" import asyncio from datetime import timedelta from unittest.mock import AsyncMock from app.services import trade_helpers as th from app.core.timeutil import now_kst def _bars(n, today_included=True, last=100.0, old=80.0): """KIS 순서(최신 우선) n봉. 최근 3봉은 last, 이전은 old.""" base = now_kst() - timedelta(days=0 if today_included else 1) rows = [] for i in range(n): d = (base - timedelta(days=i)).strftime("%Y%m%d") px = last if i < 4 else old rows.append({"stck_bsop_date": d, "stck_clpr": str(px), "stck_hgpr": str(px * 1.01), "stck_lwpr": str(px * 0.99)}) return rows def _api(**kw): api = type("A", (), {})() for k, v in kw.items(): setattr(api, k, v) return api def test_surge_blocks_recent_rally(monkeypatch): monkeypatch.setattr(th, "korea_investment_api", _api(get_daily_chart=AsyncMock(return_value={"output2": _bars(30)}))) assert asyncio.run(th.check_surge_prevention("005930", True, "", 120.0))["skip"] is True def test_surge_ignores_month_old_rally(monkeypatch): monkeypatch.setattr(th, "korea_investment_api", _api(get_daily_chart=AsyncMock(return_value={"output2": _bars(30)}))) assert asyncio.run(th.check_surge_prevention("005930", True, "", 101.0)) == {"skip": False} def test_surge_today_bar_absent(monkeypatch): monkeypatch.setattr(th, "korea_investment_api", _api(get_daily_chart=AsyncMock(return_value={"output2": _bars(30, False)}))) assert asyncio.run(th.check_surge_prevention("005930", True, "", 101.0)) == {"skip": False} assert asyncio.run(th.check_surge_prevention("005930", True, "", 120.0))["skip"] is True def test_trend_filter_no_data_passes(monkeypatch): monkeypatch.setattr(th, "TREND_FILTER_ENABLED", True) monkeypatch.setattr(th, "korea_investment_api", _api(get_daily_chart=AsyncMock(return_value={"output": _bars(30)}))) r = asyncio.run(th.check_trend_filter("005930", "x", True, "", 100.0, {"ma20": 100.0})) assert r == {"skip": False} def test_trend_filter_uses_stock_ma60_no_kis_call(monkeypatch): monkeypatch.setattr(th, "TREND_FILTER_ENABLED", True) monkeypatch.setattr(th, "korea_investment_api", _api(get_daily_chart=AsyncMock(side_effect=AssertionError("KIS 호출 금지")))) r = asyncio.run(th.check_trend_filter("005930", "x", True, "", 100.0, {"ma20": 90.0, "ma60": 100.0})) assert r["skip"] is True