diff --git a/tools/seed_sim_account_demo.py b/tools/seed_sim_account_demo.py index 311b808..1256269 100644 --- a/tools/seed_sim_account_demo.py +++ b/tools/seed_sim_account_demo.py @@ -26,7 +26,7 @@ import sys from datetime import UTC, datetime, timedelta from decimal import Decimal -from sqlalchemy import func, insert, select +from sqlalchemy import func, insert, select, update from sqlalchemy.orm import Session from app.core.config import get_settings @@ -118,7 +118,32 @@ async def _upsert_product(session: Session, spec: dict) -> int: async def _upsert_market_price(session: Session, product_id: int, spec: dict) -> None: + """写入/刷新当日行情。 + + ⚠️ 当天已有行时**必须刷新**,不能直接 return(2026-09-12 实测到的缺陷): + + 行情是**时效数据**,`FundQuoteService` 会按 `source_updated_at` 判新鲜度, + 过期即返回 `503 FUND_QUOTE_UNAVAILABLE`,连带 `T001` 仪表盘与 `T006` 持仓一起不可用。 + 原先"已存在就跳过"会让同一天重跑**不更新 `source_updated_at`** —— + 表现为"刚灌完种子能用,过十几分钟仪表盘就 503",而这与种子无关、极难归因。 + + 幂等的正确含义是**不产生重复行**(`(product_id, trade_date)` 唯一), + **不是"不更新值"**。账户/持仓的"已存在则跳过"是另一回事 —— + 那是业务数据,不该被种子覆盖。 + """ today = datetime.now(UTC).date() + now = datetime.now(UTC).replace(tzinfo=None) + values = { + "open_price": spec["close_price"], + "high_price": spec["close_price"] + Decimal("0.05"), + "low_price": spec["close_price"] - Decimal("0.05"), + "close_price": spec["close_price"], + "volume": Decimal("1000000"), + "turnover_amount": spec["close_price"] * Decimal("1000000"), + "total_fund_shares": spec["total_fund_shares"], + "source": "eastmoney_demo_seed", + "source_updated_at": now, + } existing = ( await session.execute( select(FundMarketPrice.id).where( @@ -128,25 +153,20 @@ async def _upsert_market_price(session: Session, product_id: int, spec: dict) -> ) ).scalar_one_or_none() if existing is not None: + await session.execute( + update(FundMarketPrice).where(FundMarketPrice.id == existing).values(**values) + ) return - now = datetime.now(UTC).replace(tzinfo=None) next_id = await _next_id(session, FundMarketPrice) - stmt = insert(FundMarketPrice).values( - id=next_id, - product_id=product_id, - trade_date=today, - open_price=spec["close_price"], - high_price=spec["close_price"] + Decimal("0.05"), - low_price=spec["close_price"] - Decimal("0.05"), - close_price=spec["close_price"], - volume=Decimal("1000000"), - turnover_amount=spec["close_price"] * Decimal("1000000"), - total_fund_shares=spec["total_fund_shares"], - source="eastmoney_demo_seed", - source_updated_at=now, - created_at=now, + await session.execute( + insert(FundMarketPrice).values( + id=next_id, + product_id=product_id, + trade_date=today, + created_at=now, + **values, + ) ) - await session.execute(stmt) async def _upsert_account(session: Session, customer_id: int) -> FundSimAccount: