From cb45d742daaef4ec0d56a17d7eff6a13d28f3d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=80=BB=E7=AE=A1?= Date: Wed, 9 Sep 2026 11:29:52 +0800 Subject: [PATCH] fix(HEL-356): use completed history for intraday metrics Co-authored-by: multica-agent --- backend/data/providers/tushare_dashboard.py | 13 +++++++++++-- backend/features/heaven/market_context.py | 5 ++++- config/architecture-inventory.json | 8 ++++---- tests/test_realtime_dashboard.py | 14 +++++++++++++- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/backend/data/providers/tushare_dashboard.py b/backend/data/providers/tushare_dashboard.py index 1099323..b55ca7a 100644 --- a/backend/data/providers/tushare_dashboard.py +++ b/backend/data/providers/tushare_dashboard.py @@ -467,7 +467,10 @@ class DashboardMixin: { "ts_code": ts_code, "start_date": (end - timedelta(days=30)).strftime("%Y%m%d"), - "end_date": reference_date, + # Intraday bars are not official daily history yet. Asking + # the hub for today's daily row makes a complete historical + # range look incomplete and discards otherwise valid data. + "end_date": (end - timedelta(days=1)).strftime("%Y%m%d"), }, "ts_code,trade_date,vol,amount", ) @@ -592,7 +595,13 @@ class DashboardMixin: start_date = (end - timedelta(days=20)).strftime("%Y%m%d") rows = self.query( "daily_basic", - {"ts_code": ts_code, "start_date": start_date, "end_date": end_date}, + { + "ts_code": ts_code, + "start_date": start_date, + # Same rule as price history: today's official valuation is + # unavailable during the session, so use the latest prior row. + "end_date": (end - timedelta(days=1)).strftime("%Y%m%d"), + }, "ts_code,trade_date,turnover_rate,volume_ratio,total_share,float_share," "free_share,total_mv,circ_mv", ) diff --git a/backend/features/heaven/market_context.py b/backend/features/heaven/market_context.py index 5e81a19..5715e4d 100644 --- a/backend/features/heaven/market_context.py +++ b/backend/features/heaven/market_context.py @@ -217,11 +217,14 @@ class HeavenMarketContextMixin: start_date = ( datetime.strptime(trade_date, "%Y%m%d") - timedelta(days=20) ).strftime("%Y%m%d") + history_end = ( + datetime.strptime(trade_date, "%Y%m%d") - timedelta(days=1) + ).strftime("%Y%m%d") for quote in quotes: ts_code = code_map[str(quote.get("code") or "")] history = client.query( "index_daily", - {"ts_code": ts_code, "start_date": start_date, "end_date": trade_date}, + {"ts_code": ts_code, "start_date": start_date, "end_date": history_end}, "ts_code,trade_date,close,pct_chg", ) history.sort(key=lambda item: str(item.get("trade_date") or "")) diff --git a/config/architecture-inventory.json b/config/architecture-inventory.json index 9a91efa..751c516 100644 --- a/config/architecture-inventory.json +++ b/config/architecture-inventory.json @@ -498,8 +498,8 @@ }, { "path": "backend/data/providers/tushare_dashboard.py", - "bytes": 33560, - "lines": 776 + "bytes": 34082, + "lines": 785 }, { "path": "database.py", @@ -568,8 +568,8 @@ }, { "path": "backend/features/heaven/market_context.py", - "bytes": 14409, - "lines": 354 + "bytes": 14535, + "lines": 357 }, { "path": "frontend/shared/session.js", diff --git a/tests/test_realtime_dashboard.py b/tests/test_realtime_dashboard.py index 73d3166..15eb3d6 100644 --- a/tests/test_realtime_dashboard.py +++ b/tests/test_realtime_dashboard.py @@ -180,7 +180,13 @@ class RealtimeDashboardTests(unittest.TestCase): self.client.try_quotes = lambda codes: [ row for row in FREE_QUOTES if row["ts_code"] in set(codes) ] - quote = self.client.realtime_stock_quote("000003.SZ") + calls = [] + original_query = self.client.query + self.client.query = lambda api, params=None, fields="": ( + calls.append((api, dict(params or {}))) + or original_query(api, params, fields) + ) + quote = self.client.realtime_stock_quote("000003.SZ", "20260720") self.assertEqual(quote["name"], "丙") self.assertEqual(quote["sector"], "元器件") @@ -188,6 +194,12 @@ class RealtimeDashboardTests(unittest.TestCase): self.assertEqual(quote["amount_billion"], 3.0) self.assertAlmostEqual(quote["turnover_rate"], 0.01) self.assertEqual(quote["trade_date"], "20260720") + history_calls = [ + params for api, params in calls + if api in {"daily", "daily_basic"} and params.get("start_date") + ] + self.assertTrue(history_calls) + self.assertTrue(all(params.get("end_date") == "20260719" for params in history_calls)) def test_close_dashboard_marks_official_limit_data(self): dashboard = self.client.dashboard("20260720")