from __future__ import annotations import sys import subprocess from pathlib import Path ROOT = Path(__file__).resolve().parents[2] if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) from src.quant_engine.execution_slippage_store_v1 import ( ASSUMED_SLIPPAGE_BPS, MIN_SAMPLE_FOR_COMPARISON, build_slippage_comparison_report, fetch_all_samples, insert_realized_slippage_sample, ) def test_report_is_data_gated_below_minimum_sample(tmp_path): db_path = tmp_path / "execution_slippage.db" report = build_slippage_comparison_report(db_path) assert report["status"] == "DATA_GATED" assert report["sample_n"] == 0 assert report["actual_mean_slippage_bps"] is None def test_buy_slippage_sign_is_positive_when_filled_worse(tmp_path): db_path = tmp_path / "execution_slippage.db" result = insert_realized_slippage_sample( db_path, ticker="005930", side="buy", intended_price=70000, actual_fill_price=70070, recorded_at="2026-06-21", ) # BUY 체결가가 의도가보다 비싸게 체결됐으면 양수 슬리피지(불리) assert result["slippage_bps_actual"] > 0 assert abs(result["slippage_bps_actual"] - 10.0) < 1e-6 # 70/70000 = 10bps def test_sell_slippage_sign_is_positive_when_filled_worse(tmp_path): db_path = tmp_path / "execution_slippage.db" result = insert_realized_slippage_sample( db_path, ticker="000660", side="SELL", intended_price=200000, actual_fill_price=199900, recorded_at="2026-06-21", ) # SELL 체결가가 의도가보다 싸게 체결됐으면 양수 슬리피지(불리) assert result["slippage_bps_actual"] > 0 def test_report_compares_against_assumed_bps_once_min_sample_reached(tmp_path): db_path = tmp_path / "execution_slippage.db" for i in range(MIN_SAMPLE_FOR_COMPARISON): insert_realized_slippage_sample( db_path, ticker="005930", side="BUY", intended_price=70000, actual_fill_price=70070, # 항상 10bps 불리하게 체결 recorded_at=f"2026-06-{21 + i}", ) samples = fetch_all_samples(db_path) assert len(samples) == MIN_SAMPLE_FOR_COMPARISON report = build_slippage_comparison_report(db_path) assert report["status"] == "OK" assert abs(report["actual_mean_slippage_bps"] - 10.0) < 1e-6 assert abs(report["gap_bps"] - abs(10.0 - ASSUMED_SLIPPAGE_BPS)) < 1e-6 assert report["recommendation"] def test_intended_price_must_be_positive(tmp_path): db_path = tmp_path / "execution_slippage.db" import pytest with pytest.raises(ValueError): insert_realized_slippage_sample( db_path, ticker="005930", side="BUY", intended_price=0, actual_fill_price=100, recorded_at="2026-06-21", ) def test_cli_report_is_data_gated_below_minimum_sample(tmp_path): db_path = tmp_path / "execution_slippage.db" report_path = ROOT / "Temp" / "execution_slippage_report_v1.json" if report_path.exists(): report_path.unlink() result = subprocess.run( [ sys.executable, "tools/evaluate_execution_slippage_v1.py", "--db", str(db_path), "report", ], cwd=ROOT, check=True, capture_output=True, text=True, encoding="utf-8", ) assert "DATA_GATED" in result.stdout payload = report_path.read_text(encoding="utf-8") assert '"status": "DATA_GATED"' in payload