技术博客

基金申购赎回的确认流程:批量确认引擎的内部结构

第 102 / 141 篇 · 2025-10-29 · secfin · 基金TA系统确认引擎

上一篇(《开放式基金 TA 系统总览》)把一笔申请从 T 日下单到 T+2 入账的链路走了一遍。这篇往下钻一层:T+1 凌晨那个批量确认引擎内部到底在做什么。它是 TA 系统的心脏,也是最没法"先上线再补"的部分——确认错了不是改一条记录的事,是要回滚确认文件、通知全渠道的重事故。

确认批量的流水线结构

把日终批量拆开,是一条单向的管道,每一步的产物是下一步的输入:

  1. 文件接收与登记:T 日晚各销售机构的申请文件陆续到达,先入"待确认区",只登记不处理。这里有个容易忽略的设计:文件按申请日归档而不是接收日。跨日 24 点到达的文件算 T 日申请还是 T+1 申请,直接决定适用的净值和费率,所以接收时就要按文件名和批次号钉死申请日;
  2. 账户与合规校验:基金账户状态(正常/冻结/销户)、反洗钱名单、风险等级匹配(《销售适当性与双录》篇详述)。这一步只产生拒绝码,不动账;
  3. 申请合法性校验:金额是否低于起购点、是否超过单日累计限额、巨额赎回预检(赎回申请占昨日总份额比例,超过 10% 触发分支,见下篇);
  4. 费用计算:申购按金额分段费率,赎回按持有期分段费率,都是查档计算;
  5. 净值确认:拿到 T 日净值后统一算份额(申购)或金额(赎回);
  6. 总额守恒与尾差归集;
  7. 确认文件生成与下发。

为什么要分段而不是一个大循环跑完?因为第 5 步依赖外部输入。净值 21 点才来,前面 1~4 步 18 点就能跑完。分段之后,1~4 步的任何失败当天就能暴露,不用等到半夜净值到了才发现某个销售机构的文件格式错了,整场确认重来。我在生产里见过的 TA 调度,1~4 步和 5~7 步之间都有一个显式的"等净值"栅栏,和《清算任务编排》里等文件的场景一模一样。

费用计算:分段函数而不是查表

申购费最常见的结构是金额分档:

$$ \text{申购费} = \begin{cases} 0.015 \times M, & M < 100\,\text{万} \\ 0.012 \times M, & 100\,\text{万} \le M < 500\,\text{万} \\ 1000\,\text{元(固定)}, & M \ge 500\,\text{万} \end{cases} $$

注意净申购金额是倒挤出来的,不是正着乘的。前端收费模式下,客户付 10 万,费率 1.5%,那么:

$$ \text{净申购金额} = \frac{100000}{1 + 0.015} \approx 98522.17\ \text{元} $$

$$ \text{确认份额} = \frac{98522.17}{1.0234} \approx 96269.27\ \text{份} $$

为什么除而不是乘(100000 × (1−1.5%) = 98500)?因为监管口径的申购费以净申购金额为计费基础,用 10 万直接乘 1.5% 会把费率算在"含费金额"上,多收客户约 22 元。这个口径差异在批量里就是一条公式写错的问题,但对客解释时是合规问题。赎回费按持有期分档(持有 7 天内通常 1.5% 惩罚性费率),依赖份额来源流水里的取得日期——这就是 TA 数据模型里"份额来源可追溯"字段的用途,不是冗余设计。

舍入与总额守恒

份额保留两位小数,逐户四舍五入后加总几乎必然和"按总额直接除"差几分钱。处理原则只有一个方向:逐户确认,总差归集。先算出全部账户的确认份额(每户四舍五入),再算总差额:

$$ \Delta = \text{round}\left(\frac{\sum_i \text{净申购金额}_i}{\text{净值}}, 2\right) - \sum_i \text{round}\left(\frac{\text{净申购金额}_i}{\text{净值}}, 2\right) $$

把 $\Delta$ 份调整到大户或最后一笔流水上(各家实现不同,原则是可追溯、可解释),保证 TA 份额总账与明细合计严格相等。《净值计算的四则运算》里讲的舍入坑,在确认端原样再犯一次——基金系统的精度事故一半出在"谁归集尾差"没有写死。

拒绝与部分确认

校验失败的申请不产生确认份额,但流水必须落账:申请流水保留原始记录,确认流水记一条拒绝记录(带拒绝码)。审计查的是"这笔申请为什么没了",不是"结果对不对"。

部分确认出现在两个场景:一是巨额赎回按比例确认(下篇展开);二是"定期定额"类申请的当日扣款不足。部分确认的关键是剩余部分算拒绝还是算撤单——算拒绝要收撤回部分的流水,算撤单则整笔消失,监管口径认定后不能两边摇摆,系统里用不同的确认状态码固定下来。

确认文件下发后,销售机构侧的入账是另一场对账的起点:客户看到的份额以销售机构记账为准,TA 记的是权威账,两边每日互核,差一笔都要追到申请流水号。

T+1 日确认引擎:两段式批量,中间隔着一道等净值栅栏 文件接收登记 按申请日归档 账户合规校验 只产拒绝码不动账 费用计算 净申购额 = 总额/1+r 总额守恒 尾差 Δ 归集调整 栅栏:等 T 日净值 净值约 21 点到 份额确认 份额 = 净申购额/净值 确认流水落账 拒绝也记带码流水 确认文件下发 渠道侧再对账 第一段 18 点前可跑完,失败当天暴露;栅栏后只做依赖净值的三步,窗口压缩到几小时

确认引擎没有撮合系统那种戏剧性的性能故事,它的难度在于分支完备:每一种拒绝都要有码、有账、有文件字段;每一分尾差都要归集得可解释。做这种系统的心态和写清算一样——你写的不是业务逻辑,是审计证据链。