"""감사 P1 수정 검증: MDD 수량 반영 / 전략명 명시 / 국내 DT 태깅.""" import inspect import pytest def test_mdd_reduction_reflects_quantities(): """MDD 축소는 ActiveTrade·Portfolio·DT 인메모리 수량을 모두 줄여야 한다.""" from app.services import mdd_manager as m src = inspect.getsource(m) assert src.count("_reflect_reduction(stock_code, sell_qty") == 2, "두 축소 경로 모두 반영 필요" assert '"quantity": remaining_qty' in src helper = inspect.getsource(m._reflect_reduction) assert "reflect_sell" in helper and "day_trading_state" in helper assert "remove_position" in helper and 'pos["quantity"] = _left' in helper def test_swing_exit_always_passes_strategy_name(): """전략명을 비우면 db_worker 가 최신 active 행(=DT)을 닫거나 덮어쓴다.""" from app.services.swing import exit_service as se src = inspect.getsource(se) assert "strategy_name=None" not in src, "close 호출에 전략명 누락" assert 'strategy_name=_strategy or "swing"' in src assert '"strategy_name": _at_strategy' in src # 트레일링 고점 upsert assert '"strategy_name": _strategy or "swing"' in src # 분할매도 upsert def test_executor_sell_excludes_daytrading_shares(): """Portfolio 행은 스윙+DT 합계 → 스윙 청산이 DT 보유분까지 팔면 안 된다.""" from app.services import trade_executor as te src = inspect.getsource(te._execute_sell) assert "day_trading_state" in src and "_dt_qty" in src assert "owned_by_daytrading" in src assert 'total_qty = _own' in src assert '"strategy_name": stock.get("strategy_type", "swing")' in src def test_sync_dt_tagging_applies_to_domestic_and_survives_missing_output1(): from app.api.endpoints import portfolio as pf src = inspect.getsource(pf.sync_portfolio) # 국내 신규/기존 행 + 해외 = 태깅 지점 4곳 assert src.count('quantity <= _dt_qty.get(stock_code, 0)') == 4 # 정의가 output1 블록보다 앞이어야 NameError 가 없다 assert src.index("_dt_codes = set(_dt_qty)") < src.index('if "output1" in balance_data')