fix(demo): 把未上市的 160129 换成真实挂牌的 515450,并修掉种子假行情盖住真行情
## 1. 160129 本就不该在场内清单里 `160129`(南方金利定开债券C)是 `160128`(金利定开债券 **A** 类)的 C 类份额, 而 C 类份额只在场外销售、**不在交易所挂牌** —— 行情源对它永远返回空,下单只能走 净值降级(`source=eastmoney_nav_fallback`),既掩盖了"该产品并不交易"这一事实, 又让成交价带上折溢价偏差。 选型依据:把南方基金全部 **882 个代码**逐个问过腾讯行情源(该源只对交易所上市证券 返回数据),确认真实上市交易的只有 **109 个**;其中 R1/R2 的场内产品 (159700、160128、511070、511810)**原先已在清单内**,所以替换品只能来自 R3 及以上。 选定 **`515450` 红利低波50ETF南方**:仍是南方基金旗下、成交额约 1.3 亿元流动性充足、 红利低波定位偏稳健,与它替换掉的债券 LOF 定位最接近;客户风险等级已覆盖 R3 (原有 `510300` 即 R3)。 改动:`hq.py` 的 `FUND_TYPE_GROUPS`、`tools/import_hq_test_products.py` 的场内映射, 两处都留了注释防止被加回来;`docs/42` / `docs/43` 的产品表与费率表同步 (净值 1.4027、管理费 0.50%、托管费 0.10%);`docs/42` 另加了一条决策记录。 库内用**复用 `fin_product.id = 9100005`** 的方式替换,使 `fin_holding` / `fin_sim_order` / `fin_transaction` / `fin_market_price` 的既有引用自动跟随, 不产生孤儿数据。那笔历史成交保留 `quote_source='eastmoney_nav_fallback'` —— 它确实是当时的事实,不该被粉饰。同时清掉了 `fin_market_price` 里那条净值降级行, 全库净值降级行情行数归零。 ## 2. 种子假行情会盖住真实行情(更严重,且会反复出现) `seed_sim_account_demo.py` 原来按"今天"upsert 一条假行情(510300=4.50、 510500=6.20,`source='eastmoney_demo_seed'`),而真实行情来自行情源、日期是 **最近交易日**。下单按 `trade_date DESC` 取行情,这条种子行**永远排在真实行情前面**; 它的 `source_updated_at` 只是 seed 运行时刻,过了 `MAX_QUOTE_AGE`(15 分钟)就让整个 产品变成 `503 行情已过期` —— 而库里明明躺着一条刚同步好的真实行情。周末尤其明显: `trade_date` 落在**非交易日**,价格还是编的。 实测表现:`tools/seed_demo_data.py` 跑完第 4 步刚同步过真实行情,冒烟脚本的下单仍报 `503`,且本该 4.579 的成交价被查到 4.50。 改为:**已有任何行情行就绝不插手**(真实行情优先,种子不参与竞争); 一条都没有时才补,且 `trade_date` 退到最近交易日。 验证:`tools/e2e_smoke_test.py` → **40/40**(下单成交价 4.579 = 真实行情); ruff 通过;mypy 250 文件 0 错;unit+contract 1381 passed / 0 failed。
This commit is contained in:
@@ -202,8 +202,11 @@ class MarketPriceSyncService:
|
||||
|
||||
⚠️ **净值不等于市价**:若该产品确实在交易所交易,用它当收盘价会有折溢价偏差。
|
||||
所以这条路径只应落在"行情源没有覆盖"的产品上,且值得业务侧复核 ——
|
||||
实测触发它的 `160129` 是 C 类份额(其 A 类 `160128` 在腾讯源有行情),
|
||||
它很可能未上市交易,那它本就不该出现在场内产品列表里。
|
||||
曾经触发它的 `160129` 是 C 类份额(其 A 类 `160128` 在腾讯源有行情):
|
||||
C 类份额只在场外销售、**不在交易所挂牌**,本就不该出现在场内产品列表里,
|
||||
2026-09-13 已替换为 `515450`(红利低波50ETF南方)。
|
||||
所以这条降级**再次被触发时,先怀疑清单里混进了非上市份额**(C 类、场外份额),
|
||||
而不是行情源出了问题。
|
||||
"""
|
||||
history = await self.adapter.fetch_history(code, date.today())
|
||||
nav = history.get("nav")
|
||||
|
||||
Reference in New Issue
Block a user