From 149c468240cbdede22d0386747bb817f037b49c6 Mon Sep 17 00:00:00 2001 From: leefer Date: Fri, 24 Jul 2026 17:41:21 +0800 Subject: [PATCH] fix: backfill auction amount history on fresh deployments --- market_insights.py | 44 +++++++++++++++++++++++++++++++++-- tests/test_market_insights.py | 6 +++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/market_insights.py b/market_insights.py index 5fa088a..ed7e046 100644 --- a/market_insights.py +++ b/market_insights.py @@ -453,6 +453,45 @@ class MarketInsightsService: ) return history + def _ensure_auction_amount_history(self, trade_date: str, target_days: int = 10) -> None: + existing = set(self.database.auction_factor_dates(trade_date, target_days + 5)) + if len(existing) >= target_days: + return + end = datetime.strptime(trade_date, "%Y%m%d") + start = (end - timedelta(days=35)).strftime("%Y%m%d") + try: + calendar = self.client.query( + "trade_cal", + { + "exchange": "SSE", + "start_date": start, + "end_date": trade_date, + "is_open": 1, + }, + "cal_date,is_open", + ) + except TushareError: + return + dates = sorted( + str(item.get("cal_date") or "") + for item in calendar + if int(_number(item.get("is_open"))) == 1 and item.get("cal_date") + )[-target_days:] + for current_date in dates: + if current_date in existing: + continue + try: + rows = self.client.query( + "stk_auction", + {"trade_date": current_date}, + "ts_code,trade_date,vol,price,amount,pre_close,turnover_rate,volume_ratio,float_share", + ) + except TushareError: + break + if rows: + self.database.upsert_auction_factors(rows) + existing.add(current_date) + def _with_auction_watchlist( self, result: dict[str, Any], @@ -558,7 +597,7 @@ class MarketInsightsService: carried_forward = data_date != trade_date cache_key = data_date if not force: - cached = self.database.get_data_snapshot("auction_center_v4", cache_key) + cached = self.database.get_data_snapshot("auction_center_v5", cache_key) if cached: result = copy.deepcopy(cached) result["meta"] = { @@ -695,6 +734,7 @@ class MarketInsightsService: } prior_snapshot = self.database.get_snapshot(baseline_date) or {} themes = self._auction_theme_evidence(prior_snapshot, candidates + one_price_rows) + self._ensure_auction_amount_history(data_date) amount_history = self._auction_amount_history(data_date) prior_amounts = [item["amount_billion"] for item in amount_history[:-1]] current_amount = round(sum(item["amount_million"] for item in normalized) / 100, 2) @@ -738,7 +778,7 @@ class MarketInsightsService: "one_price_rows": one_price_rows, "rows": candidates, } - self.database.save_data_snapshot("auction_center_v4", cache_key, "market", result) + self.database.save_data_snapshot("auction_center_v5", cache_key, "market", result) return self._with_auction_watchlist(result, data_date, user_id) def _theme_directory(self) -> list[dict[str, Any]]: diff --git a/tests/test_market_insights.py b/tests/test_market_insights.py index cfcc7d5..eb0702f 100644 --- a/tests/test_market_insights.py +++ b/tests/test_market_insights.py @@ -18,6 +18,11 @@ class FakeMarketClient: def query(self, api_name, params=None, fields=""): params = params or {} date = params.get("trade_date", "") + if api_name == "trade_cal": + return [ + {"cal_date": f"202607{day:02d}", "is_open": 1} + for day in range(14, 24) + ] if api_name == "stock_basic": return [ {"ts_code": "000001.SZ", "name": "平安银行", "industry": "银行", "market": "主板", "list_date": "19910403"}, @@ -96,6 +101,7 @@ class MarketInsightsTests(unittest.TestCase): self.assertEqual(payload["rows"][0]["expectation"], "超预期") self.assertEqual(set(payload["expectations"]), {"超预期", "符合预期", "低于预期"}) self.assertFalse(payload["news_feedback"]["available"]) + self.assertEqual(len(payload["amount_history"]), 10) self.assertEqual(payload["amount_history"][-1]["stock_count"], 2) self.assertEqual(payload["focus_rows"][0]["code"], "000001")