from __future__ import annotations import ast import unittest from datetime import datetime, timedelta, timezone from pathlib import Path from tushare_client import _sector_coverage_issue def load_method(name: str): source = Path("server.py").read_text(encoding="utf-8") tree = ast.parse(source) dashboard_service = next( node for node in tree.body if isinstance(node, ast.ClassDef) and node.name == "DashboardService" ) method = next( node for node in dashboard_service.body if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) and node.name == name ) module = ast.Module(body=[method], type_ignores=[]) namespace = { "datetime": datetime, "Any": object, "_sector_coverage_issue": _sector_coverage_issue, } exec(compile(ast.fix_missing_locations(module), "server.py", "exec"), namespace) return namespace[name] MARKET_MODE = load_method("_heaven_market_mode") QUALITY_ISSUES = load_method("_heaven_trend_quality_issues") TZ = timezone(timedelta(hours=8)) class MarketModeTests(unittest.TestCase): def test_closed_rt_snapshot_is_closed_not_intraday(self): dashboard = {"meta": {"realtime": True, "market_status": "closed"}} now = datetime(2026, 7, 20, 16, 27, tzinfo=TZ) self.assertEqual(MARKET_MODE("20260720", dashboard, now), "closed") def test_trading_snapshot_is_intraday(self): dashboard = {"meta": {"realtime": True, "market_status": "trading"}} now = datetime(2026, 7, 20, 10, 30, tzinfo=TZ) self.assertEqual(MARKET_MODE("20260720", dashboard, now), "intraday") def test_historical_date_is_always_historical(self): dashboard = {"meta": {"realtime": True, "market_status": "trading"}} now = datetime(2026, 7, 20, 10, 30, tzinfo=TZ) self.assertEqual(MARKET_MODE("20260717", dashboard, now), "historical") @staticmethod def intraday_layers(trade_date: str): index_context = { "trade_date": trade_date, "precise": True, "realtime": True, "indices": [{"trade_date": trade_date}] * 3, } sector = { "trade_date": trade_date, "precise": True, "realtime": True, "taxonomy": "sw_l2", "schema_version": 3, "coverage": 100, "relative_turnover": 1.2, } stock = { "trade_date": trade_date, "code": "002141", "precise": True, "realtime": True, "turnover_source": "float_share", "activity_source": "historical_progress", } return index_context, sector, stock @staticmethod def historical_layers(trade_date: str): index_context = { "trade_date": trade_date, "precise": True, "realtime": False, "source": "tushare", "indices": [{"trade_date": trade_date}] * 3, } sector = { "trade_date": trade_date, "precise": True, "realtime": False, "taxonomy": "sw_l2", "schema_version": 3, "source": "tushare_sw_daily+member_daily", "coverage": 97, } stock = { "trade_date": trade_date, "code": "002141", "precise": True, "realtime": False, "data_source": "tushare", } return index_context, sector, stock def test_intraday_accepts_verified_realtime_layers(self): trade_date = "20260720" index_context, sector, stock = self.intraday_layers(trade_date) dashboard = { "meta": { "realtime": True, "market_status": "closed", "updated_at": datetime.now(TZ).isoformat(), } } issues = QUALITY_ISSUES( trade_date, dashboard, index_context, sector, stock, "intraday" ) self.assertEqual(issues, []) def test_intraday_sector_coverage_90_passes_89_blocks(self): trade_date = "20260720" index_context, sector, stock = self.intraday_layers(trade_date) dashboard = {"meta": {"realtime": True, "market_status": "closed"}} sector["coverage"] = 90 self.assertEqual( QUALITY_ISSUES(trade_date, dashboard, index_context, sector, stock, "intraday"), [], ) sector["coverage"] = 89 issues = QUALITY_ISSUES( trade_date, dashboard, index_context, sector, stock, "intraday" ) self.assertTrue(any("覆盖率" in issue for issue in issues)) def test_intraday_sector_requires_relative_turnover(self): trade_date = "20260720" index_context, sector, stock = self.intraday_layers(trade_date) sector["relative_turnover"] = 0 issues = QUALITY_ISSUES( trade_date, {"meta": {}}, index_context, sector, stock, "intraday" ) self.assertTrue(any("相对全市场换手" in issue for issue in issues)) def test_sector_must_use_shenwan_l2_taxonomy(self): trade_date = "20260720" index_context, sector, stock = self.intraday_layers(trade_date) sector["taxonomy"] = "ths" issues = QUALITY_ISSUES( trade_date, {"meta": {}}, index_context, sector, stock, "intraday" ) self.assertTrue(any("申万二级" in issue for issue in issues)) def test_historical_accepts_official_daily_layers(self): trade_date = "20260717" index_context, sector, stock = self.historical_layers(trade_date) issues = QUALITY_ISSUES( trade_date, {"meta": {}}, index_context, sector, stock, "historical" ) self.assertEqual(issues, []) def test_historical_rejects_realtime_index_layer(self): trade_date = "20260717" index_context, sector, stock = self.historical_layers(trade_date) index_context["realtime"] = True issues = QUALITY_ISSUES( trade_date, {"meta": {}}, index_context, sector, stock, "historical" ) self.assertTrue(any("指数层" in issue for issue in issues)) def test_historical_rejects_realtime_sector_layer(self): trade_date = "20260717" index_context, sector, stock = self.historical_layers(trade_date) sector["realtime"] = True issues = QUALITY_ISSUES( trade_date, {"meta": {}}, index_context, sector, stock, "historical" ) self.assertTrue(any("行业层" in issue for issue in issues)) def test_historical_rejects_non_tushare_stock(self): trade_date = "20260717" index_context, sector, stock = self.historical_layers(trade_date) stock["data_source"] = "dashboard" issues = QUALITY_ISSUES( trade_date, {"meta": {}}, index_context, sector, stock, "historical" ) self.assertTrue(any("个股层" in issue for issue in issues)) def test_stock_must_be_precise(self): trade_date = "20260717" index_context, sector, stock = self.historical_layers(trade_date) stock["precise"] = False issues = QUALITY_ISSUES( trade_date, {"meta": {}}, index_context, sector, stock, "historical" ) self.assertTrue(any("个股层" in issue for issue in issues)) def test_closed_mode_ignores_nonessential_dashboard_status(self): trade_date = "20260720" index_context, sector, stock = self.historical_layers(trade_date) dashboard = {"meta": {"realtime": True, "market_status": "trading"}} issues = QUALITY_ISSUES( trade_date, dashboard, index_context, sector, stock, "closed" ) self.assertEqual(issues, []) def test_closed_mode_accepts_finalized_realtime_shenwan_snapshot(self): trade_date = "20260720" index_context, sector, stock = self.historical_layers(trade_date) sector.update({ "realtime": True, "finalized": True, "inner_precise": True, "outer_precise": True, "relative_turnover": 1.2, }) issues = QUALITY_ISSUES( trade_date, {"meta": {}}, index_context, sector, stock, "closed" ) self.assertEqual(issues, []) if __name__ == "__main__": unittest.main()