按项目方决定处理三件事。 ## 510300(沪深300ETF) 决定:保留 fund_manager = "南方基金" 作演示口径,**不**改成"华泰柏瑞" (改了它会退出 MarketQuoteSyncService 的同步范围,投顾与知识条目也不该再算自家产品), 但净值与费率改成真实值,并在产品页显式披露它不是本公司产品。 - 回填(tools/backfill_product_snapshot.py --codes 510300 --apply --overwrite): current_nav 4.500000 → 4.5794、current_nav_at 同步为 2026-09-11 15:00:00、 management_fee_rate 0.5000 → 0.15、custodian_fee_rate 0.1000 → 0.05 - 产品页披露:mock-data.js 给这只加 product_note,详情页新增提示块渲染它 ("本产品为同指数参考产品,非本公司发行的基金,仅用于功能演示")。 同时把 mock 里这只的净值/费率也对齐真实值,避免出现"页面显示 mock 值、 库里是真实值"两套数字。 - 产品详情页的 css/js 版本参数提到 20260913-5,避免旧缓存。 ## 511810(货币ETF南方) 之前说它"三个数量级不一致"是**我比错了接口**:QUOTE_API 返的是**场内交易价格** (货币 ETF 约 100 元/份),而 current_nav 的口径是 DWJZ 单位净值。 查证结果:库里 0.2661 正是 09-11 的真实 DWJZ,快照时间也对得上 —— 不是脏数据,是旧值。 口径由其余 19 只的一致性确定(current_nav == DWJZ)。 要不要刷新到最新(0.2332)属运维节奏问题,**本次未执行**。 ## 最小交易金额 按项目方口径:一律**以产品字段为准**(100.00 元),不用「1 手 × 净值」推算金额 —— 后者会与字段值不一致,客户会看到两套数字。docs/42 的 1.1 节据此重写。 ## 工具改名 tools/backfill_product_fees.py → tools/backfill_product_snapshot.py:扩展为 净值 + 费率统一入口,新增 --codes 限定范围(避免顺手把全部快照刷成最新, 全量刷新是 ProductHistorySyncService / MarketQuoteSyncService 的职责)。 安全设计不变:默认 dry-run、默认只补 NULL(净值永不为空,所以刷净值需显式 --overwrite)、写入走单事务。 门禁:ruff 通过 / mypy 249 文件 0 错 / 单元+契约 1377 passed 2 skipped。
16 KiB
场内基金知识条目草稿(待审核,尚未入库)
状态:草稿。尚未写入知识库 —— 审核通过后再走
POST /api/v1/knowledge/documents入库。数据来源:净值取自东方财富真实行情 —— 走项目自带的
app/infrastructure/fund_market_adapter.py(与下单链路、MarketQuoteSyncService同源), 取数时间 2026-09-13;产品属性(代码/名称/交易所/风险等级/交易单位)取自fin_product表。 共 20 只(ETF 13 + LOF 7)。复现命令:python tools/fetch_live_quotes.py。 原则:只写表里确实有值的字段;缺失的字段一律写"以交易页面为准", 不补编数字(编费率是最容易出事的一类错误)。为什么需要它:知识库现有的产品素材是一套"南方科技有限公司 个人理财产品手册", 里面没有本项目的场内基金条目。所以客户问"南方沪深300ETF 的起投金额"时, 检索到的是"南方结构性存款:起投金额 20万"这类别的产品,分数 0.6818、 与次优间隙只有 0.0034 —— 客服按置信度规则转人工。转人工是对的(硬答会答错产品), 缺的是本项目的产品知识。
一、通用交易规则(建议优先入库)
1.1 场内基金怎么买、最小单位是多少
问:场内基金怎么买?最小买多少?
答:本平台的场内基金按"手"撮合,1 手 = 100 份,委托数量必须是 100 份的整数倍。 最小交易金额以产品详情页披露的字段为准(本平台产品库中登记为 100.00 元); 实际所需金额按成交价 × 份数计算,随市价变动。 实际可买数量与所需金额请以交易页面的实时报价为准。
1.2 场内基金的费用有哪些
问:买场内基金要交哪些费用?费率是多少?
答:场内基金涉及两类费用 ——
(1)基金自身的费用,从基金资产中按日计提、体现在净值里,不向您单独收取: 本平台 20 只场内基金的管理费率为 0.15%~1.20%/年、托管费率为 0.05%~0.20%/年, 每只产品的具体费率见下一节的产品清单。ETF 通常较低(如沪深300ETF 管理费 0.15%/年、 托管费 0.05%/年),LOF 与主动管理型较高(如南方积极配置混合 1.20%/年、托管 0.20%/年)。 货币 ETF 另收销售服务费(如货币ETF南方 0.25%/年)。
(2)交易费用,即您买卖时产生的券商佣金,费率由您开户的券商决定, 本平台不代收、也不设定该费率。
具体以产品详情页披露与交易页面展示为准。
1.3 价格最小变动单位
问:场内基金报价最小变动多少?
答:本平台场内基金的最小价格变动单位为 0.001 元。
1.4 风险等级与适当性
问:我能买什么风险等级的产品?
答:产品风险等级从 R1 到 R5,由低到高。平台按您的有效风险测评结果做匹配校验: 测评等级与产品等级不匹配时,下单会被拦截。请先完成风险承受能力测评, 并以交易页面的校验结果为准。客服不能修改您的测评结果,也不能代为开通跨级权限。
1.5 场内基金与场外基金的区别
问:场内基金和场外基金有什么不一样?
答:场内基金(ETF/LOF)在交易所挂牌,按市价、以"手"为单位实时撮合成交; 场外基金按当日净值申赎,通常 T+1 确认。本平台的模拟交易针对场内基金, 下单即按市价全额成交;场外基金的业务流程与本模块相互独立。
口径已定(项目方 2026-09-13):「最小交易金额」一律以产品字段为准, 不用「1 手 × 净值」推算金额 —— 后者会与字段值不一致,客户会看到两套数字。
二、产品清单(20 只,数据来自 fin_product)
| 代码 | 名称 | 交易所 | 类型 | 风险等级 | 真实净值 | 当日涨跌 | 净值日期 |
|---|---|---|---|---|---|---|---|
| 159329 | 沙特ETF南方 | SZSE | ETF | R5 | 0.9167 | -0.01% | 2026-09-10 |
| 159382 | 创业板人工智能ETF南方 | SZSE | ETF | R4 | 2.5841 | -0.49% | 2026-09-11 |
| 159511 | 通信ETF南方 | SZSE | ETF | R4 | 2.3755 | +0.61% | 2026-09-11 |
| 159615 | 恒生生物科技ETF南方 | SZSE | ETF | R5 | 1.1027 | -1.39% | 2026-09-11 |
| 159687 | 亚太精选ETF南方 | SZSE | ETF | R5 | 1.8891 | -0.38% | 2026-09-10 |
| 159700 | 科创债ETF南方 | SZSE | ETF | R2 | 101.8009 | +0.01% | 2026-09-11 |
| 159948 | 创业板ETF南方 | SZSE | ETF | R4 | 3.6895 | -0.49% | 2026-09-11 |
| 510300 | 沪深300ETF | SSE | ETF | R3 | 4.5794 | -0.83% | 2026-09-11 |
| 510500 | 中证500ETF南方 | SSE | ETF | R4 | 7.6027 | -1.79% | 2026-09-11 |
| 511070 | 公司债ETF南方 | SSE | ETF | R2 | 103.0145 | +0.01% | 2026-09-11 |
| 511810 | 货币ETF南方 | SSE | ETF | R1 | 0.2332 ⚠️ | 0.00% | 2026-09-13 |
| 588890 | 科创芯片ETF南方 | SSE | ETF | R4 | 1.2327 | -1.36% | 2026-09-11 |
| 160105 | 南方积极配置混合(LOF) | SZSE | LOF | R3 | 1.2514 | -1.34% | 2026-09-11 |
| 160127 | 南方新兴消费增长股票(LOF)A | SZSE | LOF | R4 | 0.8364 | -0.64% | 2026-09-11 |
| 160128 | 南方金利定开债券A | SZSE | LOF | R2 | 1.0260 | 0.00% | 2026-09-11 |
| 160129 | 南方金利定开债券C | SZSE | LOF | R2 | 1.0240 | 0.00% | 2026-09-11 |
| 160142 | 南方优势产业(LOF) | SZSE | LOF | R3 | 1.0623 | -2.09% | 2026-09-11 |
| 160143 | 南方创业板2年定期开放混合 | SZSE | LOF | R3 | 1.6105 | -1.14% | 2026-09-11 |
| 501018 | 南方原油A | SSE | LOF | R5 | 2.0750 | +3.86% | 2026-09-10 |
| 501062 | 南方瑞合定开混合(LOF) | SSE | LOF | R3 | 2.1048 | -0.49% | 2026-09-11 |
本表净值是真实数据,取数时间 2026-09-13,来源为项目自带的东方财富适配器 (
app/infrastructure/fund_market_adapter.py:push2.eastmoney.com行情 +api.fund.eastmoney.com历史净值)。复现命令:python tools/fetch_live_quotes.py。核对结果:20 只全部取到真实数据;其中 18 只与库里
fin_product.current_nav完全一致 (库里存 6 位小数,如0.916700,数据源给 4 位0.9167,是同一笔数), 2 只不一致 ——510300与511810,见下方 3.1 与第四节。
问:平台上有哪些场内基金?产品代码是什么?
答:本平台模拟交易范围内共有 20 只场内基金,包含 13 只 ETF 和 7 只 LOF, 基金管理人均为南方基金。代表性的有:沪深300ETF(510300,R3)、 中证500ETF南方(510500,R4)、创业板ETF南方(159948,R4)、 货币ETF南方(511810,R1)、科创债ETF南方(159700,R2)等。 完整清单与实时净值请以产品列表页为准。
三、重点产品条目
3.1 沪深300ETF(510300)—— ⚠️ 这只的身份存疑,见下方红字
问:沪深300ETF 的起投金额是多少?南方沪深300ETF 怎么买?
答:沪深300ETF 的产品代码为 510300,在**上交所(SSE)**挂牌,属于 ETF, 风险等级 R3。它按"手"交易,1 手 = 100 份, 按最新净值 4.5794 元(2026-09-11)估算,买入 1 手约需 458 元; 产品库中登记的最小交易金额为 100.00 元。 该产品的管理费率为 0.15%/年、托管费率为 0.05%/年(从基金资产中计提,不单独向您收取)。 实际成交金额、可买数量与费用请以交易页面的实时报价为准。
✅ 已按项目方决定处理(2026-09-13):保留
fund_manager = "南方基金"作为演示口径 —— 不改成"华泰柏瑞",因为改了它就会退出MarketQuoteSyncService的同步范围, 投顾与知识条目也不该再把它算作自家产品;改为在产品页显式披露:common/mock-data.js给这只加了product_note,详情页会显示 「本产品为同指数参考产品,非本公司发行的基金,仅用于功能演示」。同时净值与费率已回填为真实值:
python tools/backfill_product_snapshot.py --codes 510300 --apply --overwrite
字段 原值 现值(真实) current_nav4.500000 4.5794 current_nav_at2026-09-13 08:19:37 2026-09-11 15:00:00 management_fee_rate0.5000 0.15 custodian_fee_rate0.1000 0.05 上面词条里的数字已按真实值书写。保留一条披露备查:这只的真实全称是 「华泰柏瑞沪深300交易型开放式指数证券投资基金」,其余 19 只全称都以"南方"开头; 且
0.50/0.10恰好是另外四只 ETF(159329/159382/159511/588890)的真实费率, 原先那组值像是照抄来的。
3.2 其他产品(简版模板)
其余 19 只按同一模板生成,净值取第二节的表、费率取 4.3 的表:
问:<产品名> 是什么?代码是多少?风险等级?费率多少?
答:<产品名>(代码 <product_code>)在<上交所/深交所>挂牌,属于 <ETF/LOF>, 风险等级 <R?>。按"手"交易,1 手 = 100 份。最新净值 <净值>(<净值日期>)。 管理费率 %/年、托管费率 %/年,从基金资产中计提、不单独向您收取; 买卖时的券商佣金由您开户的券商决定,本平台不代收。 具体以产品详情页与交易页面为准。
费率数值直接取 4.3 —— 20 只都有真实值,不必再写"以页面为准"这种模糊话术。
四、数据缺口(需要业务或产品侧补,我不会代填)
| 字段 | 现状 | 影响 |
|---|---|---|
management_fee_ratecustodian_fee_rate |
已补齐:20 只真实费率全部取到,见 4.3 | 库里 19 只为空;510300 的值与真实冲突(0.5000/0.1000 vs 0.15/0.05) |
transaction_fee_rate |
20/20 全空 | 场内交易佣金由券商收取,本就不该由平台登记,保留为空是合理的 |
min_amount |
19 只为 0.00,510300 为 100.00 |
场内产品的"最小金额"语义待确认 |
risk_disclosure_required 等三项 |
全部为 0 |
与"严格风险等级匹配"的业务口径是否需要区分产品,待确认 |
| 产品"起投金额" | 表里没有这个字段 | 场内按手交易,本就没有固定起投金额;建议统一按 1.1 的口径回答 |
4.2 真实数据核对结果(2026-09-13)
用 python tools/fetch_live_quotes.py 拉东方财富真实行情,与库里 fin_product.current_nav 逐只比对:
| 结果 | 只数 | 说明 |
|---|---|---|
| 完全一致 | 18 | 库里存 6 位小数(0.916700)、数据源给 4 位(0.9167),是同一笔数 |
| 不一致 | 2 | 见下 |
510300 沪深300ETF:库里 4.500000 vs 真实 4.5794
- 库里快照时间是
2026-09-13 08:19:37(就是今天),其余 19 只都停在2026-09-11 15:00:00 - ⇒ 这一条是被人为改过的演示值(4.5 是整数,正好凑"1 手 = 450 元")
- 要决定的:知识条目用真实值还是演示值。若交易链路按库里的 4.5 成交, 而知识说 4.5794,两处口径会打架 —— 这比"知识库有没有这条"更要紧
511810 货币ETF南方:不是脏数据,是数据已更新 —— 而且我一开始比错了接口
查证结果(2026-09-13):
| 日期 | DWJZ(单位净值) |
LJJZ(累计净值) |
|---|---|---|
| 2026-09-13 | 0.2332 | 0.8740 |
| 2026-09-11 | 0.2661 | 0.8740 |
- 库里存的
0.266100正是 09-11 的真实DWJZ,快照时间2026-09-11 15:00:00也对得上 ⇒ 它不是脏数据,只是旧值 - 我先前说的"差三个数量级"是我自己用错了接口:
QUOTE_API返的是场内交易价格 (货币 ETF 约 100 元/份,所以 100.012),而current_nav的口径是DWJZ单位净值。 两者不是一回事,不能混比 - 口径由既有数据确定:其余 19 只的
current_nav与fetch_history的DWJZ逐只一致
⇒ 这只若要刷新,按 DWJZ 口径刷成 0.2332 即可:
python tools/backfill_product_snapshot.py --codes 511810 --apply --overwrite
本次未执行,等你确认 —— 因为 0.2661 本身也是真实值(只是旧一天), 刷新属于"要不要把快照推进到最新",是运维节奏问题,不是修错。
复现:
python tools/fetch_live_quotes.py(默认表格对比,--json输出结构化结果,--no-fees可跳过费率抓取)。该脚本只报告差异、不写库 ——fin_product.current_nav的刷新属于ProductHistorySyncService/MarketQuoteSyncService的职责。
4.3 真实费率(2026-09-13 取自东方财富 f10 基金概况页)
20 只全部取到,库里 19 只为空、1 只与真实冲突。费率是长期稳定字段, 下列数值可放心写进知识条目:
| 代码 | 名称 | 管理费 %/年 | 托管费 %/年 | 销售服务费 %/年 |
|---|---|---|---|---|
| 159329 | 沙特ETF南方 | 0.50 | 0.10 | — |
| 159382 | 创业板人工智能ETF南方 | 0.50 | 0.10 | — |
| 159511 | 通信ETF南方 | 0.50 | 0.10 | — |
| 159615 | 恒生生物科技ETF南方 | 0.50 | 0.15 | — |
| 159687 | 亚太精选ETF南方 | 0.20 | 0.05 | — |
| 159700 | 科创债ETF南方 | 0.15 | 0.05 | — |
| 159948 | 创业板ETF南方 | 0.15 | 0.05 | — |
| 160105 | 南方积极配置混合(LOF) | 1.20 | 0.20 | — |
| 160127 | 南方新兴消费增长股票(LOF)A | 1.20 | 0.20 | — |
| 160128 | 南方金利定开债券A | 0.50 | 0.15 | — |
| 160129 | 南方金利定开债券C | 0.50 | 0.15 | — |
| 160142 | 南方优势产业(LOF) | 1.20 | 0.20 | — |
| 160143 | 南方创业板2年定期开放混合 | 1.20 | 0.20 | — |
| 501018 | 南方原油A | 1.00 | 0.20 | — |
| 501062 | 南方瑞合定开混合(LOF) | 1.20 | 0.20 | — |
| 510300 | 沪深300ETF | 0.15 | 0.05 | — |
| 510500 | 中证500ETF南方 | 0.15 | 0.05 | — |
| 511070 | 公司债ETF南方 | 0.15 | 0.05 | — |
| 511810 | 货币ETF南方 | 0.30 | 0.05 | 0.25 |
| 588890 | 科创芯片ETF南方 | 0.50 | 0.10 | — |
规律:宽基/债券 ETF 多为 0.15% 管理费,行业主题 ETF 多为 0.50%, 主动管理型 LOF 为 1.00%~1.20%。只有货币 ETF 收销售服务费。
📌 一处提醒:数据源没有给出场内交易的佣金费率(
transaction_fee_rate20 只全空), 这是正常的 —— 佣金由客户开户的券商决定,平台不该也不能登记它。 所以"交易费率是多少"这个问题,标准答法是引到券商,而不是从产品库取值。
五、入库方式(审核通过后我执行)
# 走知识库管理端点上传,服务端自动切分并投向量同步事件
POST /api/v1/knowledge/documents
{ "filename": "场内基金产品手册_v1.md", "knowledge_type": "product",
"content_base64": "<本文件的 base64>" }
入库后建议复核:
- 用访客浮窗问「南方沪深300ETF 的起投金额是多少」,看是否从"转人工"变为正常作答;
- 问「平台上有哪些场内基金」,应命中第二节的清单条目;
- 复查分数是否越过阈值(
HIGH_SCORE=0.75直接答;0.55~0.75之间还要求 top1 领先次优 ≥MIN_GAP=0.07)。
⚠️ 另外提醒:
fin_knowledge_meta表当前是空的,而 Milvus 里有知识且检索正常 —— 说明现有知识是直接灌进 Milvus 的,没写 MySQL 元数据。 走上面这个端点入库会正常写元数据,但两批数据的元数据状态会不一致 (旧的仍旧查不到、删不掉)。要不要把旧数据一并纳入治理,请你定。