fix: backfill auction amount history on fresh deployments
This commit is contained in:
+42
-2
@@ -453,6 +453,45 @@ class MarketInsightsService:
|
|||||||
)
|
)
|
||||||
return history
|
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(
|
def _with_auction_watchlist(
|
||||||
self,
|
self,
|
||||||
result: dict[str, Any],
|
result: dict[str, Any],
|
||||||
@@ -558,7 +597,7 @@ class MarketInsightsService:
|
|||||||
carried_forward = data_date != trade_date
|
carried_forward = data_date != trade_date
|
||||||
cache_key = data_date
|
cache_key = data_date
|
||||||
if not force:
|
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:
|
if cached:
|
||||||
result = copy.deepcopy(cached)
|
result = copy.deepcopy(cached)
|
||||||
result["meta"] = {
|
result["meta"] = {
|
||||||
@@ -695,6 +734,7 @@ class MarketInsightsService:
|
|||||||
}
|
}
|
||||||
prior_snapshot = self.database.get_snapshot(baseline_date) or {}
|
prior_snapshot = self.database.get_snapshot(baseline_date) or {}
|
||||||
themes = self._auction_theme_evidence(prior_snapshot, candidates + one_price_rows)
|
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)
|
amount_history = self._auction_amount_history(data_date)
|
||||||
prior_amounts = [item["amount_billion"] for item in amount_history[:-1]]
|
prior_amounts = [item["amount_billion"] for item in amount_history[:-1]]
|
||||||
current_amount = round(sum(item["amount_million"] for item in normalized) / 100, 2)
|
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,
|
"one_price_rows": one_price_rows,
|
||||||
"rows": candidates,
|
"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)
|
return self._with_auction_watchlist(result, data_date, user_id)
|
||||||
|
|
||||||
def _theme_directory(self) -> list[dict[str, Any]]:
|
def _theme_directory(self) -> list[dict[str, Any]]:
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ class FakeMarketClient:
|
|||||||
def query(self, api_name, params=None, fields=""):
|
def query(self, api_name, params=None, fields=""):
|
||||||
params = params or {}
|
params = params or {}
|
||||||
date = params.get("trade_date", "")
|
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":
|
if api_name == "stock_basic":
|
||||||
return [
|
return [
|
||||||
{"ts_code": "000001.SZ", "name": "平安银行", "industry": "银行", "market": "主板", "list_date": "19910403"},
|
{"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(payload["rows"][0]["expectation"], "超预期")
|
||||||
self.assertEqual(set(payload["expectations"]), {"超预期", "符合预期", "低于预期"})
|
self.assertEqual(set(payload["expectations"]), {"超预期", "符合预期", "低于预期"})
|
||||||
self.assertFalse(payload["news_feedback"]["available"])
|
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["amount_history"][-1]["stock_count"], 2)
|
||||||
self.assertEqual(payload["focus_rows"][0]["code"], "000001")
|
self.assertEqual(payload["focus_rows"][0]["code"], "000001")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user