# 业务链路核对设计 本文是 post_clear_check 按业务链路核对的设计。以后改某一条链路,先改本文里的该条,再改代码。 现行怎么跑仍以 `doc/使用说明.md` 为准。 ## 1. 结论 核对仍按 11 条业务链路的节点往下算:这一环应不应该出现,出现了的字段算得对不对。字段公式写在节点里。飞书不再按「一条链路、一个归属对象」发卡。 对外只发四个方向:订单链路、发行报表、销售报表、TRS 报表。一张方向卡汇总这一端本轮的全部结论行。标题写方向和结论。正文按摘要、分节或分报表、错误清单、可疑清单、无法展开来排。计算过程仍是字段、期望、实据、依据、结论。 内部链路代码留在结论行上,用来查依据和涉及步骤。方向只决定收进哪一张卡,不改公式、人口和挂链。OTC003 的结论行仍挂在买入执行或卖出执行上,展示时按产生来源归进发行报表或销售报表,不在订单卡里再写一遍。 三端 23 个清算步骤不各建一条链路。有权威公式且清算后仍能复核的步骤,挂到已有链路做节点;没有权威口径或事后无法复核的,在本文写不支持及原因,不发卡。 增额、展期不与 OTC009、OTC012 落库表比对:这两张表没有写入方,节点本身不成立(见 4.8、4.9)。 改公式时仍先改本文第 4 节的对应链路,再改代码。不按报表编号横向改公式。 ## 2. 核对范围 ### 2.1 在范围内 - 时点:三端清算完成后。开跑门禁沿用 `doc/使用说明.md`「一轮里做什么」。 - 营业日:本营业日,一轮只核一天。 - 市场:A 股。 - 订单:已完成或已结算的 ORD 主订单(`completed`、`settled`)。 - 报表:这一天发行端、销售端、TRS 的日常报表,以及发行端、销售端的票据实时详情。 核对人口与参照数据分开: - 核对人口:交易日等于本轮交易日的主订单。只有它们跑订单执行公式(买入执行、卖出执行的执行节点),也只有它们要求「两端 OTC003 必须有该主订单的行」。 - 参照数据:清算日的报表天然包含往日订单。T+1 交收的买入在交收日出现在 OTC003、OTC007、OTC010 和资金流水里,存续票据的已卖出合计要累计往日卖单。报表行引用的主订单、票据、资金账户都要读进来,用来挂链路、取方向、取子单执行值和流水,但不再重复跑执行公式,同一订单不会每天出一次执行卡。 - 读取范围:主订单取「本轮交易日的主订单」与「当日报表行引用的主订单编号」的并集;资金账户取「这些订单的资金账户」与「当日报表行上的资金账户」的并集,流水仍只读本营业日;票据已卖出合计按报表票据号读已完成或已结算的卖单,交易日不晚于本轮交易日,晚于本轮的卖单不计入。订单和票据只读已发布数据集的 `cleared/0`。往日卖单不在这份归档里时不退回实时表。实时表只留给后续窗口的当前投影节点。 - 对冲和执行根只读核对人口的。它们只供委托执行、用户资产两条 TRS 链路,范围是本批对冲;参照订单的对冲已在它的交易日核过。 - 报表行引用了主订单或资金账户、但读取后仍找不到的,属于工具取数缺口,进未归链路记错误,原因写「取数缺口」,与「主订单方向取不到」等业务原因分开。 - 工具自身的门禁:报表早于批次完成、TRS 批次未完成、业务表缺失。 数字公式以 `docs/tmp/product_prototype/共赢票据重要字段、计算公式等说明V2.xlsx` 为准。某个动作该不该发生、报表边界在哪,以产品原型为准。步骤核对和取数口径以 `docs/架构设计/清算/` 与 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md` 为准。 ### 2.2 不在范围内 | 事项 | 原因 | |---|---| | 询价、报价 | 清算前的交易前动作,不在清算后核对 | | 票据风控(预警、危险、强平比例与价格、风控状态) | 盘中实时风控,不是清算结果 | | TRS 授信、信用、预警线、平仓线 | 本期不做(仓库根 `AGENTS.md`「本期不做范围」) | | 市场汇率、TRS 清算步骤 3 计算用户汇率 | 市场汇率本期不做;用户汇率没有纳入本范围的权威公式 | | 港美股、OTC011 | 本期只接 A 股 | | B 类订单、B 类票据 | 本期不做 | | 基金持仓市值 | 本期不做,TRS 总资产里该项按 0 | | TRS011、TRS015 | 清算报表入口不产出 TRS015;TRS011 不读 | | 两端 OTC009、OTC012 的报表行 | 实时导出,没有落库结果,清算后无法复核。增额、展期改核业务事实,见 4.8、4.9 | | 清算过程本身(开批、备份、生成数据集、推进日期、完成清算) | 中间产物,清算后无法按公式再算一遍。见第 5 节 | | 三端业务库写入 | 业务连接只读,本工具不改三端数据 | ## 3. 链路合同 一条链路固定下面这些内容,登记在链路登记表里(见 8.2)。 - 名称:业务说法,例如「买入执行」「资金变动」。不拿 OTC002、TRS002 当链路名。 - 代码:英文,写进自有库 `check_result.chain_name`。卡片上显示中文名称。 - 归属:这条链路的结论归谁。只用现有四种:主订单、资金账户、用户账号、清算批次。可以写优先顺序,例如「主订单,对不上时用户账号」。 - 人口:哪些对象进入这条链路。没进入的不下结论。 - 涉及:这条链路经过的系统和清算步骤,有几个写几个。 - 节点:有序。每个节点先写应不应该(必须出现、必须不出现、允许为空),再写对不对(本节点公式,上一节点的结果作为下一节点的输入)。 - 结论:只用 `correct`、`error`、`suspect`。一张卡的总结论取卡内最严重的一档。生成口径(例如清算当批新流水没有流水编号)在金额算对时仍是正确,说明写在代入行里,不单独抬成可疑。 依据只有三种,都必须能打开原文定位到那一句: | 种类 | 写法 | |---|---| | 产品原型 | `docs/tmp/product_prototype/` 下的相对路径,加文档里的口径名称或列名 | | 计算公式 | `共赢票据重要字段、计算公式等说明V2` 的工作表名、行号、该行名称。同一行有多条公式、只写行号对不准时,再写列号(公式在 E 列「计算公式」) | | 研发设计 | `docs/` 下 leopard 自己的方案 markdown(不含 `product_prototype`),加章节标题 | 数字公式仍以 Excel 那一行为准。研发设计只用来标明实现口径,例如哪一步清算生成流水、流水编号为什么为空。依据不能写成「根据某处」。 ## 4. 范围内的 11 条链路 ### 4.1 总表 | 序 | 名称 | 代码 | 归属 | 涉及 | |---|---|---|---|---| | 1 | 买入执行 | `buy_execution` | 主订单 | 发行端步骤 2、3、5;销售端步骤 3、7;TRS 步骤 5 | | 2 | 卖出执行 | `sell_execution` | 主订单 | 发行端步骤 2、3、5;销售端步骤 3、7;TRS 步骤 5 | | 3 | 资金变动 | `cash_change` | 资金账户 | 销售端步骤 2、3、4、6、7 | | 4 | 资金交收 | `cash_settlement` | 资金账户 | 发行端步骤 4、5;销售端步骤 2、3、4、7 | | 5 | 账户资产 | `account_asset` | 资金账户 | 销售端步骤 2、3、4、5、6、7 | | 6 | 票据存续 | `note_holding` | 资金账户 | 发行端步骤 2、3、5;销售端步骤 3、6、7 | | 7 | 增额 | `topup` | 资金账户 | 发行端步骤 2、3 | | 8 | 展期 | `extension` | 资金账户 | 发行端步骤 2、3 | | 9 | 委托执行 | `trade_execution` | 主订单,对不上时用户账号 | TRS 步骤 1、5、6、7、8 | | 10 | 用户资产 | `user_asset` | 用户账号 | TRS 步骤 1、3、4、5、6、7、8 | | 11 | 核对门禁 | `check_gate` | 清算批次 | 核对工具自身;发行端步骤 1、6;销售端步骤 1、7;TRS 步骤 9、10 | 这 11 条是本范围的全部业务链路。另有一个收容桶「未归链路」(代码 `unassigned`,归属清算批次),只收挂不上链路或没有归属键的结论行,结论一律记错误,避免静默丢失。它不是业务链路。 表里步骤名的全称: - 发行端:步骤 1 开启清算;步骤 2 备份清算前数据;步骤 3 订单及票据处理;步骤 4 交易交收处理;步骤 5 备份清算完成的数据、生成营业日日终数据与核心日常报表、更新T+1实时数据;步骤 6 确认交易日切换、推进营业日、票据激活、清算完成。 - 销售端:步骤 1 开启清算;步骤 2 备份清算前数据;步骤 3 订单及票据处理;步骤 4 交易交收处理;步骤 5 备份清算完成的数据;步骤 6 更新T+1交易日的票据详情实时数据;步骤 7 营业日日切。 - TRS:步骤 1 开启清算与清算前备份;步骤 3 计算用户汇率;步骤 4 确认应付利息;步骤 5 订单与资金清算;步骤 6 持仓清算;步骤 7 生成已清算数据集;步骤 8 生成清算报表;步骤 9 确认交易日切换并推进营业日;步骤 10 完成清算。 报表在哪一步生成,以 `docs/清算/三端清算最终实施方案.md`「9. 报表与日切最终口径」为准:发行端第 5 步产出 OTC003、OTC004、OTC007、OTC008;销售端第 7 步产出 OTC001、OTC002、OTC003、OTC004、OTC007、OTC008、OTC010;TRS 第 8 步产出 TRS001—TRS014、TRS016。OTC005、OTC009、OTC012 是实时导出,不经清算步骤生成:销售端见上述第 9 节;发行端报表定义里这三张同样标为实时。`ddl/` 里的 `report_topup_payment`、`report_extension_fee` 两张表在三端代码里没有写入方。 ### 4.2 买入执行 - 归属:主订单。 - 人口:本轮交易日已完成或已结算、方向为买入的 ORD 主订单跑全部节点。往日买单(例如 T+1 在本营业日交收的)只作参照:它们的 OTC003 行照常按「报表行」节点核对,执行节点不再重复,也不要求必须有 OTC003 行。 - 涉及:发行端清算步骤2 备份清算前数据;发行端清算步骤3 订单及票据处理;发行端清算步骤5 备份清算完成的数据、生成营业日日终数据与核心日常报表、更新T+1实时数据;销售端清算步骤3 订单及票据处理;销售端清算步骤7 营业日日切;TRS清算步骤5 订单与资金清算。 - 现有核对:`buy_execution`、`hedge_link`,两端 OTC003 的买入行。执行事实是 `input/0` 的 `exec_notional_trade`、`order_avg_px`,并与实时源表这两列对照。结算口径读 `work/3`:累计股数、累计金额、对冲含费均价、`fx_settle`、买入 `order_qty`、`exec_notional_settle`、执行面值、执行发行费、执行发行价。累计和汇率用 `input` 的对冲记录汇总。本批 `clearing_trs_result` 有该对冲记录时,发生金额改用这份结果的绝对值(TRS 卖出金额带负号),再按两币种合计反推汇率;没有结果的自定义记录保持 `input` 原值。不用 TRS 导出的汇率原值,也不用订单上的 `fx_settle`、买入 `order_qty` 当输入,也不用实时表上的这些列。报价和发行费用用 `input` 子单上的 `a_quote_ratio` 与封存的 A 类买入发行费标准。`work/4` 与 `cleared/0` 的结算口径列应与 `work/3` 一致。报表对 `cleared` 子单,不用回写 `after_val`。发行端买入不计算承销费用和执行总金额,这两列不核;销售端 OTC003 仍核承销费用。 | 节点 | 应不应该 | 对不对 | 依据 | |---|---|---|---| | 执行事实 | `input/0` 必须有该子单,实时源表也必须有 | `exec_notional_trade`、`order_avg_px` 两边一致。这两列是清算只读输入 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | 对冲执行根 | 有 TRS 对冲的订单,TRS 执行根必须唯一存在;从未建单的合法结局允许不存在 | 执行根成交股数等于对冲记录成交股数 | 研发设计 `docs/清算/三端清算最终实施方案.md`「5.4 TRS 核对、订单和交收计算」 | | 累计成交股数、累计发生金额 | `work/3` 必须出现 | 等于有效对冲记录之和。有效金额:有本批 `clearing_trs_result` 时用其发生金额绝对值,否则用 `input` | Excel「买入订单」第 14 行「累计成交股数」、第 17 行「累计发生金额(交易币种)」、第 18 行「累计发生金额(结算币种)」 | | 对冲含费成交均价 | `work/3` 必须出现 | 累计发生金额 ÷ 累计成交股数 | Excel「买入订单」第 15 行「对冲含费成交均价」 | | 订单成交均价 | 人工未改时必须出现 | 等于对冲含费成交均价。被核对的值在 `input`,人工改过则不核 | Excel「买入订单」第 22 行「订单成交均价」 | | 结算汇率 | `work/3` 必须出现 | 按上面的有效对冲两币种发生金额反推,对 `work/3` 的 `fx_settle`。不读订单上、实时表上或 TRS 结果里的 `fx_settle` 当输入 | Excel「买入订单」第 19 行「结算汇率」 | | 执行订单名义本金 | 交易币种在 `input`,结算币种在 `work/3` | 结算币种等于 `input` 的执行名义本金乘以上面反推出的汇率 | Excel「买入订单」第 20、21 行「执行订单名义本金」 | | 订单买入股数 | `work/3` 必须出现 | `order_qty` = `input` 的执行名义本金 ÷ `input` 的订单成交均价。不读实时 `order_qty` | Excel「买入订单」第 23 行「订单买入股数」 | | 票据面值 | `work/3` 必须出现 | 执行名义本金(结算币种)× `input` 的 A 类报价。报价缺失是错误,不默认 100% | Excel「买入订单」第 24 行「票据面值」 | | 发行费用 | `work/3` 必须出现 | 按 `input` 封存的 A 类买入发行费标准计算。没有这一行是错误,不当成 0 | Excel「买入订单」第 25 行「发行费用」;研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | 票据发行价 | `work/3` 必须出现 | 执行面值 + 执行发行费 | Excel「买入订单」第 26 行「票据发行价」 | | T日订单结算 | `work/3`、`work/4`、`cleared/0` 都必须有该子单 | 结算口径列一致 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | 当前投影 | 实时子单必须存在 | 实时结算口径列等于 `cleared`。执行事实列由执行事实节点核对,清算不回写这两列 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | 报表行 | 两端 OTC003 必须有该主订单的行 | 报表列等于 `cleared` 子单。不用回写 `after_val`。发行端总金额不含承销费用,不再另出「含承销费用」的可疑行;销售端承销费用等于已发布销售订单的 `exec_underwrite_fee_settle`,发行子单没有这一列 | 产品原型 OTC003(见 4.13) | | 对冲仓位 | 有清算副本时必须出现 | 股数、已结算实现盈亏等于本批 `hedge_position` 清算副本按票据汇总。没有副本时不读实时持仓,仍记可疑 | 研发设计发行端 OTC003 用清算副本 `hedge_position` | ### 4.3 卖出执行 - 归属:主订单。强平、到期订单走这条,不另开链路。 - 人口:本轮交易日已完成或已结算、方向为卖出的 ORD 主订单,订单类型含正常、强平、到期。往日卖单只作参照,口径同买入执行。 - 涉及:同买入执行。 - 现有核对:`sell_execution`、`hedge_link`,两端 OTC003 的卖出行。执行事实读 `input/0`:`exec_notional_trade`、`order_avg_px`、`order_qty`、`sold_face_value`、`sold_add_amt`、`realized_dividend`,并与实时源表对照。结算口径读 `work/3`:累计股数、累计金额、对冲含费均价、`fx_settle`、`exec_notional_settle`、`underlying_pnl`、`exec_total_amt_settle`、`final_pnl`。累计和汇率用 `input` 的对冲记录;有本批 `clearing_trs_result` 时发生金额改用其绝对值后再反推汇率,口径同买入执行。`work/4` 与 `cleared/0` 的结算口径列应与 `work/3` 一致。报表对 `cleared` 子单,不用回写 `after_val`。卖出股数仍因无法判断是不是最后一笔而记可疑,被核对的值在 `input`。 | 节点 | 应不应该 | 对不对 | 依据 | |---|---|---|---| | 执行事实 | `input/0` 必须有该子单,实时源表也必须有 | 成交名义本金、订单成交均价、卖出股数、卖出面值、卖出增额、实现分红两边一致 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | 对冲执行根 | 同买入执行 | 同买入执行 | 研发设计 `docs/清算/三端清算最终实施方案.md`「5.4 TRS 核对、订单和交收计算」 | | 累计成交股数、累计发生金额、对冲含费成交均价、结算汇率 | `work/3` 必须出现 | 等于有效对冲记录汇总,有效金额口径同买入执行。汇率不读订单上或 TRS 结果里的 `fx_settle` 当输入 | Excel「卖出订单」第 12 行「累计成交股数」、第 13 行「对冲含费成交均价」、第 14、15 行「累计发生金额」、第 16 行「结算汇率」 | | 订单卖出股数 | 必须出现 | 按卖出比例;最后一笔取剩余股数。无法判断是不是最后一笔时记可疑。被核对的值在 `input` | Excel「卖出订单」第 19 行「订单卖出股数」 | | 卖出票据面值、卖出增额金额、实现分红 | 必须出现(见右列例外) | 比例 × 卖出前的票据值。被核对的值在 `input`。部分卖出(当前名义本金大于 0):比例 = 本次执行名义本金 ÷ 票据当前名义本金,面值、增额、分红用当前值。全部卖出后当前名义本金被扣成 0:比例 = 本次执行名义本金 ÷ 初始名义本金,等于初始名义本金时就是 100%;一笔票据分多笔卖完时,每笔用自己的执行名义本金去除,面值改乘初始面值(当前面值已是 0)。当前名义本金缺失(没有这列或为空)而执行名义本金已有,是错误;全部卖出时初始名义本金缺失或为 0,也是错误。执行名义本金没有时不核这三列,日志记一行。全部卖出后增额或分红已是 0、订单上对应金额却不是 0 的,卖出前金额没有留在票据上,**本列不核**(不出结论行);因此缺独立增额时「总金额」也不核。面值仍核;底层盈亏在分红跳过时改用订单已落库的实现分红代入 | Excel「卖出订单」第 21 行「卖出票据面值」、第 22 行「卖出增额金额」、第 23 行「实现分红」 | | 底层资产盈亏 | `work/3` 必须出现 | 按两个汇率分别换算。股数和均价读 `input` | Excel「卖出订单」第 24 行「底层资产盈亏」 | | 总金额 | `work/3` 必须出现(增额因全卖无快照不核时本列也不核) | 按执行信息计算。收益比例是百分数(10 表示 10%),乘之前除以 100。缺独立算出的卖出增额时不出结论行 | Excel「卖出订单」第 25 行「总金额」 | | 最终盈亏 | `work/3` 必须出现 | 总金额读 `work/3`,卖出面值和卖出增额读 `input` | Excel「卖出订单」第 26 行「最终盈亏」 | | T日订单结算 | `work/3`、`work/4`、`cleared/0` 都必须有该子单 | 结算口径列一致 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | 当前投影 | 实时子单必须存在 | 实时结算口径列等于 `cleared`。执行事实列由执行事实节点核对 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | 报表行 | 两端 OTC003 必须有该主订单的行 | 报表列等于 `cleared` 子单。不用回写 `after_val` | 产品原型 OTC003(见 4.13) | ### 4.4 资金变动 - 归属:资金账户。能对上主订单的流水,代入行里同时写主订单编号。 - 人口:销售端本营业日已入账的资金流水,以及同日 OTC002 报表行。资金账户取当日报表行上的账户与本轮订单资金账户的并集,当日没有新订单的账户(往日买单交收、入金)也读流水。 - 涉及:销售端清算步骤2 备份清算前数据;销售端清算步骤3 订单及票据处理;销售端清算步骤4 交易交收处理;销售端清算步骤6 更新T+1交易日的票据详情实时数据;销售端清算步骤7 营业日日切。 - 现有核对:`sales_cash.check_otc002` 对已发布 `kind=cleared` 里营业日等于 T 的流水,不对实时流水。步骤节点读 `kind=input` 与 `kind=cleared`。第 3 步和第 4 步没有各自的快照,用 `input` 加重算,再与 `cleared` 比。不读 `pre_clearing`。 | 节点 | 应不应该 | 对不对 | 依据 | |---|---|---|---| | 非零已入账流水 | 必须出现在 OTC002 | — | 产品原型 OTC002「报表用途」 | | 金额为 0 的冻结、解冻 | 必须不出现 | — | 产品原型 OTC002「不包含冻结解冻数据」 | | 买入、卖出待交收流水 | 必须出现 | 金额等于订单总金额,买入为流出、卖出为流入 | Excel「买入订单」第 28 行「总金额」;Excel「卖出订单」第 25 行「总金额」;研发设计 `docs/清算/三端清算最终实施方案.md`「6.4 资金与交收口径」 | | 入金等非交易流水 | 必须出现 | 金额等于流水金额,营业日按归属日 | 研发设计 `docs/清算/非交易业务归属营业日及清算配合方案V1.md`「4. 归属日解析规则」 | | 清算当批新流水 | 允许没有流水编号 | 没有编号时改用订单总金额对,不记可疑 | 研发设计 `docs/清算/三端清算最终实施方案.md`「6.5 回写、延后消息与重算」 | | 原始流水 | `input` 中营业日不早于 T 的原始流水必须出现 | 这些流水的步骤号不是 3 或 4。营业日早于 T、步骤号为 3 的买卖待交收是上一批未交收来源,允许留在 `input`。状态只允许 posted、reversed | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.2 销售端(7 步)」 | | T日流水 | `cleared` 中营业日等于 T 的流水必须出现 | 等于 `input` 中营业日等于 T 的原始流水,加上按本批 `cleared` 订单重算的步骤 3 解冻与买卖待交收,再加上封存交收日到期时重算的步骤 4 交收。不读 `pre_clearing` | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.2 销售端(7 步)」 | | 延后流水 | 允许没有 | 实时表中营业日晚于 T、且不在 `input` 里的流水,营业日必须晚于本营业日,不得出现在 `cleared` | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.2 销售端(7 步)」 | 报表节点仍按流水编号核金额。步骤 3、4 的派生流水不在 `input` 里,由 T日流水按订单重算后与 `cleared` 闭合。 ### 4.5 资金交收 - 归属:资金账户。 - 人口:本营业日交收到期的买卖流水,两端 OTC007、OTC008,销售端 OTC010,以及本批发行 `work/4`、`cleared/0` 的交收台账和销售 `input`、`cleared` 的交收来源。资金账户范围同资金变动;往日买单在本营业日交收的,按参照订单读子单和交收台账。 - 一张 OTC007、OTC008 行只核到同一张订单上:行上的业务类型(`buy_note`、`sell_note`)必须与主订单方向一致,行上有交易日时必须等于主订单交易日。同一票据既有往日买单又有当日卖单时,卖出的行不会算进买单。同一票据当天有多张订单时,再按名义本金、面值、总金额把行认领到唯一的一张;卖出的面值用卖出票据面值,不用恒为 0 的执行票据面值。只有一张订单的票据不认领,金额对错仍逐列报。 - 涉及:发行端清算步骤4 交易交收处理;发行端清算步骤5 备份清算完成的数据、生成营业日日终数据与核心日常报表、更新T+1实时数据;销售端清算步骤2 备份清算前数据;销售端清算步骤3 订单及票据处理;销售端清算步骤4 交易交收处理;销售端清算步骤7 营业日日切。 - 现有核对:两端 `issue_settle`、`sales_settle`,`sales_cash.check_otc010`,加上发行 `work/4` 与销售 `input`、`cleared` 的步骤节点。发行交收台账读 `work/4`,报表落表用这份台账,不读实时台账。`cleared/0` 应与 `work/4` 一致。销售第 3 步和第 4 步用 `input` 重算后与 `cleared` 比,不读 `pre_clearing`。 | 节点 | 应不应该 | 对不对 | 依据 | |---|---|---|---| | 已交收记录 | 交收日已到的必须出现在 OTC007、OTC010;金额为 0 的流水(展期费冻结、解冻)只动冻结桶、不改现金余额,不要求出现在 OTC010 | 交收日等于流水交收日 | 产品原型 OTC007、OTC010;研发设计 `docs/清算/三端清算最终实施方案.md`「6.4 资金与交收口径」 | | 未交收记录 | 必须出现在 OTC008,不得出现在 OTC010 | 实际交收日为空 | 产品原型 OTC008 | | 交收日未到 | 不要求已交收行存在 | — | 研发设计 `docs/清算/三端清算最终实施方案.md`「5.4 TRS 核对、订单和交收计算」第 4 步交收段 | | 交收金额 | 必须出现 | 等于原买卖流水金额 | Excel「资金账户钱包信息」第 4 行「现金余额(已交收)」备注 | | 报表金额列 | 必须出现 | 名义本金、发行费用按子单执行列;面值买入取执行票据面值、卖出取卖出票据面值;总金额买入按面值 + 发行费用(销售端再加承销费用)复算,卖出才对子单执行总金额(子单 `exec_total_amt_settle` 只在卖出时写入,买入恒为 0)。销售端承销费用取已发布销售订单的 `exec_underwrite_fee_settle` | 产品原型 OTC007、OTC008 | | 交收推演 | `work/4` 必须留下本批应有的台账 | 同一子订单只有一行。交易日早于 T 且本批实际交收日等于本营业日的,状态为 settled,金额买入等于执行发行价、卖出等于执行总金额。交易日等于 T 的新台账状态为 pending,实际交收日为空。`input` 中实际交收日为空且交易日早于 T 的台账,`work/4` 仍有同一子订单 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | T日交收结果 | `cleared/0` 与 `work/4` 按子订单同时有或同时没有 | 状态、预计交收日、实际交收日、交收金额一致 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | 历史未交收 | `input` 中营业日早于 T、金额非 0 的买卖来源必须能对上期初 | 金额绝对值合计等于上一已发布 `cleared` 的买入待交收、卖出待交收。来源含上一批封存下来的第 3 步买卖待交收;第 4 步交收流水不是来源 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.2 销售端(7 步)」 | | 销售交收 | 到期来源在 `cleared` 中必须有对应交收流水;未到期不得有 | 买入交收金额为来源金额的相反数,卖出等于来源金额。同一来源只生成一笔。不读 `pre_clearing` | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.2 销售端(7 步)」 | ### 4.6 账户资产 - 归属:资金账户。 - 人口:销售端本营业日 OTC001 非全零行,以及本批 `kind=cleared` 钱包、`kind=input` 流水能落到的资金账户。 - 涉及:销售端清算步骤2 备份清算前数据;销售端清算步骤3 订单及票据处理;销售端清算步骤4 交易交收处理;销售端清算步骤5 备份清算完成的数据;销售端清算步骤6 更新T+1交易日的票据详情实时数据;销售端清算步骤7 营业日日切。 - 现有核对:`sales_asset.check_otc001`,加上本批销售 `input`、`cleared` 的步骤节点。钱包只核本批冻结归档里的 T 日结果:期初加上 `input` 中营业日等于 T 的流水,再与本批 `kind=cleared` 钱包比。不读实时钱包,也不把 T-1、T+1 或其他交易日的流水加进这个结果。第 3 步和第 4 步没有各自的快照,用 `input` 加本批 `cleared` 订单上已经落账的发行结果重算。不读 `pre_clearing`。本窗口只核总钱包,不另建分市场钱包节点。 | 节点 | 应不应该 | 对不对 | 依据 | |---|---|---|---| | 现金余额 | 必须出现 | 现金余额 = 现金余额(已交收) − 现金余额(买入待交收) + 现金余额(卖出待交收)。公式里的买入待交收是钱包科目正数,报表列按原型展示为负值,代入时取报表列的相反数 | Excel「资金账户钱包信息」第 3 行「现金余额」 | | 待交收列的符号 | 必须出现 | 报表买入待交收不大于 0,卖出待交收不小于 0 | 产品原型 OTC001「现金余额(买入待交收)」「现金余额(卖出待交收)」 | | 现金可用 | 必须出现 | 现金可用 = 现金余额 + 当日卖出 − 当日买入 − 冻结金额。当日买入、当日卖出取本批销售日终资金快照 `daycut_fund_eod` 的同币种行;快照缺行时记可疑 | Excel「资金账户钱包信息」第 12 行「现金可用」 | | 钱包科目 | 必须出现 | 已交收、买入待交收、卖出待交收、现金可用、冻结金额等于本批日终资金快照同币种行;买入待交收按报表负值与快照正数比较 | 产品原型 OTC001 | | 票据估值 | 必须出现 | 同一资金账户、结算币种等于本行币种的待生效与存续期票据估值之和 | 产品原型 OTC001「票据估值」 | | 报表其他列 | 必须出现 | 以现有 `check_otc001` 为准 | 产品原型 OTC001 | | 期初钱包 | 有上一已发布 `cleared` 时,同账户同币种必须有一行。没有上一批时,`input` 里没有更早营业日流水的账户从 0 起 | 科目等于上一已发布 `cleared`。该行当日买卖为 0。不拿实时钱包减去后续发生额,也不读 `pre_clearing` | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.2 销售端(7 步)」 | | T日钱包 | 本批 `cleared` 必须有该账户该币种 | 已交收、买入待交收、卖出待交收、交易冻结、非交易冻结等于期初科目,加上 `input` 中营业日等于 T 且状态为 posted 或 reversed 的流水效果,加上 T 日终态订单的解冻与待交收,再加上封存交收日到期的交收效果。算完后当日买卖为 0。买入且冻结额大于 0 时交易冻结减少该冻结额,但 `input` 里已经有该订单 posted 的 `:unfreeze` 凭证时不再减,盘中解冻效果只计这一次;已完成或已结算的买入把执行总金额加入买入待交收,执行总金额为 0 是错误;卖出执行总金额大于 0 时加入卖出待交收,为 0 不生成待交收。今天不是封存交收日则不加交收效果;是交收日时,金额非 0 且订单实际交收日不晚于本营业日的来源,买入同时减少买入待交收和已交收,卖出减少卖出待交收并增加已交收,同一来源只交收一次。效果缺失或摘要对不上记错误,不用流水金额猜测科目。重放按流水主键 id 升序。这条查询走 `(dataset_id, idem_hash)` 唯一索引,返回顺序不是入账顺序。科目为负只按 id 顺序检查;哈希顺序里解冻排在对应冻结前面造成的中途为负不记错误。按 id 顺序出现的中途为负仍记错误。不读 `pre_clearing` | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.2 销售端(7 步)」 | | 候选范围 | 本批 `cleared` 钱包必须出现 | `cleared` 流水的营业日不晚于 T,当日买卖为 0,不含交易日晚于 T 的当日买卖凭证 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.2 销售端(7 步)」 | 账户资产的等式只用 Excel「资金账户钱包信息」的写法,不用别的加减组合代替。OTC001 一行是「资金账户 × 币种」,所有跨表取值(快照、票据估值)都按本行币种过滤。日终资金快照按 `clearing_batch_id` 等于本轮销售批次读,与已发布候选比。钱包核对不读实时钱包。发行和销售日报只读 `status=active`,同一营业日的 superseded、deprecated 旧行不参与核对。等值港币资产净值按账面汇率换算现金可用、冻结金额和票据估值;乘、除两个方向四舍五入到分后如果相同,方向视为已确定。 ### 4.7 票据存续 - 归属:资金账户。能对上当日主订单的票据,代入行里同时写主订单编号。步骤节点没有报表行时,取子票据 `fund_account_ref`。 - 人口:本营业日两端 OTC004 的全部行(存续、待生效、当日到期的票据),两端 OTC005 的实时票据,以及本批发行 `work/2`、`cleared/0` 里的子票据。 - 涉及:发行端清算步骤2 备份清算前数据;发行端清算步骤3 订单及票据处理;发行端清算步骤5 备份清算完成的数据、生成营业日日终数据与核心日常报表、更新T+1实时数据;销售端清算步骤3 订单及票据处理;销售端清算步骤6 更新T+1交易日的票据详情实时数据;销售端清算步骤7 营业日日切。 - 现有核对:`issue_otc004`、`sales_otc004` 的 `check_otc004`、`check_otc005`,加上本批 `input`、`work/2`、`work/4`、`cleared/0` 的步骤节点。T 日票据只读 `cleared/0`,不读实时表。实时表只用于第 5 步当前投影和第 6 步销售当前票据。 | 节点 | 应不应该 | 对不对 | 依据 | |---|---|---|---| | 日切切片行 | 存续票据必须有 OTC004 行 | — | 产品原型 OTC004 | | 数量、面值、增额、分红 | 必须出现 | 等于本批 `cleared/0` 的当前值。没有这张票据的 `cleared` 行就是缺失,不改读实时表。最新价用本交易日 `cfg_daily_close_price` 收盘价,不用票据上的盘中最新价 | Excel「票据」第 6 行「票据股票数量」、第 9 行「票据面值」、第 14 行「增额金额」、第 15 行「分红金额」 | | 发行价 | 必须出现 | 按票据计算 | Excel「票据」第 10 行「票据发行价」 | | 底层浮动盈亏、估值、浮动盈亏、净值 | 必须出现 | 底层资产浮动盈亏 = 最新价 × 股票数量 × 账面汇率 − 期初价格 × 股票数量 × 初始汇率 + 分红金额。结算金额是交易金额乘汇率,不从名义本金和面值反推乘除。最新价用本交易日收盘价。估值按 YA 大于 0 时面值 + 增额 + YA × 收益比例,否则 MAX(0, 面值 + 增额 + YA)。报表浮动盈亏等于估值 − 面值 − 增额。已卖出的票据当前面值已被置 0,浮动盈亏和发行价不再按存续公式用当前面值;估值改为合计卖出金额,净值改为合计卖出金额 / (合计卖出金额 − 合计卖出 A 类盈亏) × 100。这些公式不读 `yesterday_*` | Excel「票据」第 21 行「底层资产浮动盈亏」、第 23 行「A类票据估值(结算币种)」、第 24 行「A类票据浮动盈亏」、第 26 行「A类票据净值」 | | 已卖出合计 | 有卖出时必须出现 | 按卖出累计:该票据全部已完成或已结算的卖单,含往日卖单,交易日不晚于本轮交易日 | Excel「票据」第 27 行「已卖出票据面值」至第 30 行「合计卖出A类盈亏」 | | 实时详情 | 实时票据必须有 OTC005 行 | 没有后续事实时与当日 OTC004 同列一致。已有步骤快照时,差额改由当前投影节点解释,不再把后续增额、展期或卖出记成切片错误 | 产品原型 OTC005 | | 期初结转 | `work/2` 必须有结转票据和新票据 | 结转票据的当前数量、面值、增额、分红等于上一已发布 `cleared` 的同列。`input` 里的新票据,`work/2` 当前列等于初始列,增额和分红为 0,状态为存续(买入完成后清算装入工作态即写成 active)。首日开账不得出现结转票据。不读实时余额 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | T日票据结果 | `cleared/0` 与 `work/4` 都必须有该票据 | 数量、面值、增额、分红、到期日、状态一致。报表对 `cleared`,不对实时票据 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | 当前投影 | 实时票据必须存在 | 实时增额等于 `cleared` 增额加上归属日晚于本营业日的增额发生额;到期日等于更晚的已通过展期,没有则等于 `cleared`。没有交易日晚于本营业日的卖出时,数量和面值等于 `cleared`。有后续卖出时不在本链路重算卖出公式 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | 昨基线 | 本批 `cleared` 有对冲持仓时,实时持仓必须有同主键 | 实时 `yesterday_*` 等于本批 `cleared` 持仓的日终数量、成本和已实现分红。清算公式不读这几列 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | 销售当前票据 | 销售 `note_view` 和 `clr_note_view_cleared` 都必须有该子票据 | `clr_note_view_cleared` 等于发行 `cleared`,不得写成当前投影。`note_view` 的同步版本低于发行实时版本时必须已被覆盖;版本相等时当前列等于发行实时票据;版本更高时不覆盖 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.2 销售端(7 步)」 | ### 4.8 增额 - 归属:资金账户。取增额所在子票据的 `fund_account_ref`。 - 人口:本批发行 `input/0` 里 `change_type=top_up` 且归属本营业日的增额,以及实时表里同一归属日的增额。卖出释放(`sell_release`)是卖出订单的派生记录,**不进冻结主键集合**,但增额累计要把同日 `sell_release` 发生额计入。不读实时 `after_add_amt` 当起点。 - 涉及:发行端清算步骤2 备份清算前数据;发行端清算步骤3 订单及票据处理。 - 现有核对:`issue_event.check_topup`。不读 `report_topup_payment`,不出 OTC009 报表行。 | 节点 | 应不应该 | 对不对 | 依据 | |---|---|---|---| | 增额冻结集合 | 归属本营业日的 `top_up` 必须同时出现在 `input/0` 和实时表 | 两边主键集合相同。多出的实时主键是冻结漏记,多出的冻结主键是实时已没有这条记录 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | 增额累计 | 增额或同日卖出释放对应的子票据必须出现在 `work/2` 和 `work/3` | `work/3` 增额 = `work/2` 增额 + 本批 `input` 里该子票据本营业日 `top_up` 与 `sell_release` 发生额之和。`work/4` 与 `cleared/0` 的增额等于 `work/3`。不使用实时增额减去后续发生额 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | OTC009 报表行 | 不支持 | — | 实时导出,没有落库结果,清算后无法复核。研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.4 仍然不进范围」 | Excel 没有增额的计算公式(「票据」第 14 行「增额金额」只有说明),本条链路的依据是研发设计。 ### 4.9 展期 - 归属:资金账户。取展期任务上的 `fund_account_ref`,没有时取子票据的 `fund_account_ref`。 - 人口:本批发行 `input/0` 里 `status=approved` 且 `approve_business_date` 为本营业日的展期,以及实时表里同一审批归属日的已通过展期。待审批、撤销、驳回不进人口。不读实时到期日当起点。展期费流水不在本条链路核对。 - 涉及:发行端清算步骤2 备份清算前数据;发行端清算步骤3 订单及票据处理。 - 现有核对:`issue_event.check_extension`。不读 `report_extension_fee`,不出 OTC012 报表行。 | 节点 | 应不应该 | 对不对 | 依据 | |---|---|---|---| | 展期冻结集合 | 审批归属本营业日的已通过展期必须同时出现在 `input/0` 和实时表 | 两边主键集合相同 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | 展期后到期日 | 展期对应的主票据必须出现在 `work/2` 和 `work/3` | 有本营业日展期或改到期日事件时,`work/3` 到期日等于这些事件按主键重放后的 `after_date`(与清算 `note_replay` 一致;展期之后仍可能被改到期日覆盖)。没有这类事件时,有已通过展期任务则取最后一条的 `approve_after_maturity`,否则 `work/3` 保持 `work/2`。`work/4` 与 `cleared/0` 的到期日等于 `work/3`。审批归属晚于本营业日的展期只进入当前投影,不改 `work/3` | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | OTC012 报表行 | 不支持 | — | 实时导出,没有落库结果,清算后无法复核。研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.4 仍然不进范围」 | ### 4.10 委托执行 - 归属:对得上主订单的归主订单,对不上的归用户账号。 - 人口:本批对冲能定位到的 TRS 用户的委托、成交、持仓。 - 涉及:TRS清算步骤1 开启清算与清算前备份;TRS清算步骤5 订单与资金清算;TRS清算步骤6 持仓清算;TRS清算步骤7 生成已清算数据集;TRS清算步骤8 生成清算报表。 - 现有核对:`trs_trade`(TRS002、TRS003、TRS004)、`hedge_link`,`trs_flow` 里的 TRS005、TRS008,加上本批 `kind=cleared` 的步骤节点。T 日委托、成交、持仓读 cleared,不读实时表当 T 日结果。第 5 步和第 6 步没有各自留存的快照,不拆成两个节点。报表对 cleared。 | 节点 | 应不应该 | 对不对 | 依据 | |---|---|---|---| | 封存成交 | 按 `trade_date` 等于 T、证券市场等于本轮市场重查到的源表委托、成交,必须与本批 cleared 的 `src_id` 集合相同 | 多出或缺少都是错误。不把实时持仓数量当 T 日起点 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.3 TRS(10 步)」 | | 执行根 | 自动单按 `ext_ref`、补录单按委托号或母单号必须唯一存在;从未建单的合法结局不要求存在;算法子单不当成没有订单 | — | 研发设计 `docs/清算/三端清算最终实施方案.md`「5.4 TRS 核对、订单和交收计算」 | | 成交数量 | 必须出现 | 算法母单或普通委托的成交数量等于对冲记录。被核对的委托是 cleared | 产品原型 `TRS/4 业务引起数据变化及计算公式/4 业务引起数据变化及计算公式.md`「持仓与交易引起的字段变化及计算公式」 | | 报表行 | 成交数量大于 0 的普通主订单或算法母单必须有 TRS002 行,成交数量大于 0 的执行订单必须有 TRS003 行,有成交事实时 TRS004 必须有对应行。已撤、废单、未成交(成交数量为 0)不进这三张报表。对冲带回委托号或母单号,本身不要求有行 | 报表列等于 cleared 的委托或成交,不读实时委托。TRS002 的 `master_order_no` 是算法号时只对算法母单(含无发行对冲的 CRM 母单);子单上盖的 `algo_no` 只供累加成交金额,不能当主单命中。成交金额等于该委托成交回报 `fill_amount` 之和(算法母单、拆单主单累加其执行子单),四舍五入到分;不是成交数量乘成交均价。TRS004 没有成交金额列,不核这一列 | 产品原型 TRS002、TRS003、TRS004(见 4.13);研发设计清算报表按成交回报汇总 | | T日委托 | cleared 里该用户的成交必须能挂上 cleared 委托 | 交易日不晚于 T。后续成交不在这批里,不按 T 日用户汇率重算它们的发生额 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.3 TRS(10 步)」 | | 持仓 | TRS005 必须有对应行 | 持仓数量等于本批 cleared 的 `clr_user_position.position_qty`。持仓成本金额等于同一行的 `book_cost_amount`,不对 `cost_amount`。TRS005 按通道拆行时,先按证券+交易渠道+结算币种汇总报表再对清算聚合持仓 | 产品原型 `TRS/4 …/4 业务引起数据变化及计算公式.md`「持仓与交易引起的字段变化及计算公式」;产品原型 TRS005 | | 持仓行 | 有 T 日持仓时 cleared 必须有该行;没有持仓时可以没有 | 同一行上 `position_qty`、`cost_amount`、`cost_px`、`book_cost_amount` 是第 5 步的值。`available_qty` 等于 `position_qty`,`frozen_qty` 为 0。`market_value`、`float_pnl`、`book_float_pnl` 是第 6 步写在同一行上的结果。不另找一份第 5 步快照,也不在本节点重算估值 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.3 TRS(10 步)」 | | 候选成交 | cleared 的委托和成交必须出现 | `trade_date` 不晚于 T。源表里 `trade_date` 晚于 T 的委托和成交,主键不得出现在 cleared 的 `src_id` | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.3 TRS(10 步)」 | | 平仓已实现盈亏 | 有卖出时 TRS008 必须有行 | 报表列等于业务行 | 产品原型 TRS008 | 订单是否终态是 TRS 步骤 2 的准入条件,在本链路里体现为「执行根应不应该出现」,不单独核对。 ### 4.11 用户资产 - 归属:用户账号。 - 人口:本批对冲能定位到的 TRS 用户。 - 涉及:TRS清算步骤1 开启清算与清算前备份;TRS清算步骤3 计算用户汇率;TRS清算步骤4 确认应付利息;TRS清算步骤5 订单与资金清算;TRS清算步骤6 持仓清算;TRS清算步骤7 生成已清算数据集;TRS清算步骤8 生成清算报表。 - 现有核对:`trs_account`(TRS001、TRS010、TRS014、TRS016),`trs_flow` 里的 TRS006、TRS007、TRS009、TRS012、TRS013,加上本批 `kind=cleared` 和快照的步骤节点。T 日资金读 cleared 的 `clr_fund_account`,第 6 步不替换这张表。汇率调整读本批快照里的 `clearing_fund_ledger`,不读实时 `fund_ledger`。TRS006 仍按流水主键对合并后的快照。不计算用户汇率应该等于多少。 | 节点 | 应不应该 | 对不对 | 依据 | |---|---|---|---| | 封存资金 | 本批快照里的 `fund_ledger`、`fund_base_asset_adjust`、`user_position_journal` 主键,必须与按交易日、营业日规则重查的源表一致 | 买卖凭证按所属委托的 `trade_date` 等于 T,非交易按 `business_date` 等于 T,排除 `idem_key` 以 `CLR:` 开头的流水。快照带正整数 `user_id` 但不在本轮核对人口内的,不属于本用户,不记无法归属。没有 `user_id` 或不是正整数才记无法归属。账面汇率取本批 `stock_financing_limit_input` 的 `book_rate`,报表 `fx_book` 等于该封存值;同币种为 1,不把反向汇率换算出来。融资额度只读这份封存,不读实时额度。不把实时资金余额和持仓当 T 日起点 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.3 TRS(10 步)」 | | 封存汇率 | 本批 `clr_fx_user` 有该币种对时,第 5 步和第 8 步必须使用这一行 | 成交数量大于 0 的委托,以及全部成交的 `fx_settle`,还有报表 `user_fx`,等于封存的 `rate`。成交数量为 0 的委托保留下单汇率,不与封存汇率比较。没有封存行时不计算应该等于多少,也不拿实时 `fx_book` 填上 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.3 TRS(10 步)」 | | 基础总资产 | 必须出现 | 本金金额 + 融资金额 | 产品原型 `TRS/4 …/4 业务引起数据变化及计算公式.md`「重点字段与计算公式」基础总资产 | | 杠杆 | 必须出现 | 融资金额 = 本金金额 × 杠杆比例 | 同文件「用户交易或后台操作引起的字段变化及计算公式」 | | 总资产 | 必须出现 | 可用金额 + 冻结金额 + 持仓市值(基金持仓市值本期按 0) | 同文件「重点字段与计算公式」总资产 | | 可用金额流水、出入金 | 有变动时 TRS006、TRS009 必须有行 | 报表列等于业务行。TRS006 的金额来自本批原始流水快照和 `clearing_fund_ledger`,不读实时流水。TRS009 流水 `amount` 按 `direction` 赋符号后与报表 Amount 比较(入正出负) | 产品原型 TRS006、TRS009 | | 计息 | 有融资利率时必须出现 | 应付利息 = 计息金额 × 融资利率 ÷ 100 ÷ 365。报表年化是百分数,3.2542 表示 3.2542%。利率变动、利息收取与明细一致 | 同文件「重点字段与计算公式」应付利息;产品原型 TRS007、TRS012、TRS013、TRS016;研发设计 `docs/清算/三端清算最终实施方案.md`「4.3 用户汇率和应付利息」 | | T日债务 | 本批 `interest_input` 的 `debt` 行必须保留 T 日债务 | 等于计息日不晚于 T、且未收取或收取营业日晚于 T 的利息合计。T+1 已收取的明细仍算在这笔债务里,不能因为当前状态已是 collected 就冲掉 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.3 TRS(10 步)」 | | 汇率调整 | 差额不为 0 时本批快照必须有一条 `clearing_fund_ledger`;差额为 0 时必须没有 | 金额等于 T 日 cleared 成交现金减 T 日原始买卖凭证。成交现金按卖出加 `amount_settle`、买入减 `amount_settle`。原始凭证只取封存快照里的 `stock_buy`、`stock_sell`,不读实时 `fund_ledger`。后续成交两边都不进 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.3 TRS(10 步)」 | | 资金账户 | 报表有该币种时,cleared 必须有该用户该币种 | 本金、融资、可用、冻结是第 5 步写上的列。第 6 步不替换这张表。TRS001 可用金额等于 `clr_fund_account.available`,冻结金额等于 `frozen`。TRS001 与 TRS014 的持仓市值等于该用户该结算币种 `clr_user_position.market_value` 合计,不乘清算价。TRS016 持仓成本金额等于该用户该结算币种 `book_cost_amount` 合计(与 TRS005 账面成本同源;同币种多通道报表行先汇总再比);有非零持仓成本时 `finance_rate` 不得为空(与区间导出「未维护月度利率则拒绝导出」一致,缺利率记错误)。TRS010 现金结余等于本行承前现金、出入金额、实际盈亏、已付利息之和。TRS013 当日应付利息等于(融资金额 + 授信借贷 + 信用借贷)× 年化 / 100 / 365,年化按百分数;`status=uncollected` 且计息日为本营业日的应付利息必须有报表行 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.3 TRS(10 步)」;产品原型 TRS001、TRS010、TRS013、TRS014、TRS016 | | 候选资金 | 封存的非交易事实必须出现 | 营业日不晚于 T。源表里营业日晚于 T 的非交易流水、持仓流水和基础调整不得出现在本批快照 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.3 TRS(10 步)」 | | 净资产 | 必须出现 | 总资产 − 融资金额 − 应付利息(授信、信用四项本期不做,不单造公式) | 同文件「重点字段与计算公式」净资产 | ### 4.12 核对门禁 - 归属:清算批次。 - 人口:本营业日的三端批次和日切报表。 - 涉及:核对工具自身;发行端清算步骤1 开启清算;发行端清算步骤6 确认交易日切换、推进营业日、票据激活、清算完成;销售端清算步骤1 开启清算;销售端清算步骤7 营业日日切;TRS清算步骤9 确认交易日切换并推进营业日;TRS清算步骤10 完成清算。 - 现有核对:`gate` 的报表早于批次、TRS 批次未完成,编排里的 1146 缺表,以及下面这些只在不一致时记错误的是/否检查。 | 节点 | 应不应该 | 依据 | |---|---|---| | 报表早于批次 | 批次未完成时日切报表不得已有行 | 研发设计 `docs/清算/三端清算最终实施方案.md`「9. 报表与日切最终口径」 | | TRS 批次未完成 | 有对冲的交易日早于今天而 TRS 仍未完成,必须报错 | 研发设计 `docs/tmp/data_check_tool/doc/使用说明.md`「一轮里做什么」 | | 业务表缺失 | 读到 1146 必须报错,不当成没有业务 | 研发设计 `docs/tmp/data_check_tool/doc/使用说明.md`「一轮里做什么」 | | 发行期初基线与上游版本 | 已发布数据集是 opening 时基线为空;是 published 时基线存在且交易日早于本交易日。无对冲时上游 TRS 为空;有对冲时上游批次和数据集等于本批已发布 TRS | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.1 发行端(6 步)」 | | 发行发布 | 进行中的营业日晚于本批,且该交易日恰好一个 published_flag=1 属于本批 | 同上 | | 销售清单版本 | 清单 source_version 的前两段等于发行当前已发布轮次的 batch_id 和 dataset_revision | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.2 销售端(7 步)」 | | 销售发布 | 本批 cleared_dataset_id 指向 kind=cleared、status=active,且属于本批 | 同上 | | TRS 日期 | 有对冲时营业日指针晚于本批。无对冲不查 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「5.3 TRS(10 步)」 | | TRS 版本 | 有对冲时本批数据集为 kind=cleared、copy_no=1、status=available。无对冲不查 | 同上 | | 日终快照与候选 | 只在不一致时记错误。快照表缺失走缺表,不在这里再报 | 研发设计 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md`「6. 现有工具会读错的三处」 | 这些是/否检查没有金额公式。批次 completed 是开跑条件,不单独成卡。 ### 4.13 报表原型路径 卡片上的产品原型依据写全下面的路径。前缀 `docs/tmp/product_prototype/` 省略。 | 编号 | 发行端 | 销售端 | |---|---|---| | OTC001 | — | `Note销售/报表管理(销售后台)/日常报表/1 Account Asset Report/1 Account Asset Report.md` | | OTC002 | — | `Note销售/报表管理(销售后台)/日常报表/2 Cash Change Report/2 Cash Change Report.md` | | OTC003 | `Note发行/报表管理(发行平台)/日常报表 (2)/3 Share Linked Notes Trade Order Report (2)/3 Share Linked Notes Trade Order Report.md` | `Note销售/报表管理(销售后台)/日常报表/3 Share Linked Notes Trade Order Report/3 Share Linked Notes Trade Order Report.md` | | OTC004 | `Note发行/报表管理(发行平台)/日常报表 (2)/4 Share Linked Notes Daily Details Report (2)/4 Share Linked Notes Daily Details Report.md` | `Note销售/报表管理(销售后台)/日常报表/4 Share Linked Notes Daily Details Report/4 Share Linked Notes Daily Details Report.md` | | OTC005 | `Note发行/报表管理(发行平台)/日常报表 (2)/5 Share Linked Notes Real Time Details Report (2)/5 Share Linked Notes Real Time Details Report.md` | `Note销售/报表管理(销售后台)/日常报表/5 Share Linked Notes Real Time Details Report/5 Share Linked Notes Real Time Details Report.md` | | OTC007 | `Note发行/报表管理(发行平台)/日常报表 (2)/7 Notes Trade Order Settlement Report (2)/7 Notes Trade Order Settlement Report.md` | `Note销售/报表管理(销售后台)/日常报表/7 Notes Trade Order Settlement Report/7 Notes Trade Order Settlement Report.md` | | OTC008 | `Note发行/报表管理(发行平台)/日常报表 (2)/8 Notes Trade Order Non-Settlement Report (2)/8 Notes Trade Order Non-Settlement Report.md` | `Note销售/报表管理(销售后台)/日常报表/8 Notes Trade Order Non-Settlement Report/8 Notes Trade Order Non-Settlement Report.md` | | OTC009 | `Note发行/报表管理(发行平台)/日常报表 (2)/9 Share Linked Notes Top-up payment Report (2)/9 Share Linked Notes Top-up payment Report.md` | `Note销售/报表管理(销售后台)/日常报表/9 Share Linked Notes Top-up payment Report/9 Share Linked Notes Top-up payment Report.md` | | OTC010 | — | `Note销售/报表管理(销售后台)/日常报表/10 Cash Settlement Report/10 Cash Settlement Report.md` | | OTC012 | `Note发行/报表管理(发行平台)/日常报表 (2)/12 Share Linked Notes Extension Fee Report (2)/12 Share Linked Notes Extension Fee Report.md` | `Note销售/报表管理(销售后台)/日常报表/12 Share Linked Notes Extension Fee Report/12 Share Linked Notes Extension Fee Report.md` | TRS 报表都在 `TRS/报表管理/TRS报表/` 下: | 编号 | 目录 | |---|---| | TRS001 | `1 Valuable Capital Limited TRS Report/1 Valuable Capital Limited TRS Report.md` | | TRS002 | `2 Master Transaction Order Report/2 Master Transaction Order Report.md` | | TRS003 | `3 Sub Transaction Order Report/3 Sub Transaction Order Report.md` | | TRS004 | `4 Details Transaction Order Report/4 Details Transaction Order Report.md` | | TRS005 | `5 Stock Holdings Report/5 Stock Holdings Report.md` | | TRS006 | `6 Available Amount Change Report/6 Available Amount Change Report.md` | | TRS007 | `7 Interest procedural statement/7 Interest procedural statement.md` | | TRS008 | `8 Stock Realized P/Report/8 Stock Realized P/Report.md`(目录名里的 `P/L` 被拆成了两级) | | TRS009 | `9 Fund-in out Report/9 Fund-in out Report.md` | | TRS010 | `10 Client Balance Summary/10 Client Balance Summary.md` | | TRS012 | `12 Margin rate change statement/12 Margin rate change statement.md` | | TRS013 | `13 Detailed statement of interest payable/13 Detailed statement of interest payable.md` | | TRS014 | `14 Daily Net Asset Report/14 Daily Net Asset Report.md` | | TRS016 | `16 Holdings Amount Interest Report/16 Holdings Amount Interest Report.md` | TRS 的字段公式不在 Excel 里,在产品原型 `TRS/4 业务引起数据变化及计算公式/4 业务引起数据变化及计算公式.md` 的「重点字段与计算公式」和「持仓与交易引起的字段变化及计算公式」两节。 ## 5. 三端 23 个清算步骤 代码里一共 23 步:发行端 `issue_backend/app/service/clearing/clearing_engine.py` 的 `CLEARING_STEPS` 6 步,销售端 `sales_backend/app/constant/clearing_consts.py` 的 `CLEARING_STEPS` 7 步,TRS `trs_backend/app/constant/clearing_consts.py` 的 `CLEARING_STEP_NAMES` 10 步。步骤实际做什么,以 `docs/架构设计/清算/` 下的现行方案和 `docs/tmp/data_check_tool/doc/清算步骤核对改造方案.md` 为准。 每一步只有两种结论: - 挂靠:这一步有需求或 Excel 规定、清算后仍能复核的公式,或是挂在核对门禁上的是/否检查。先看是否属于已有 11 条链路,属于就作为该链路的节点,链路的「涉及」里写这一步。按这个标准,当前 23 步没有一步需要新开链路。 - 不支持:没有可核对的权威口径,清算后无法再算一遍。不发卡,不算漏核对。改造方案判定为不支持的步骤不写进「涉及」。 「不支持」只出现在本文,不进飞书,也不出现在卡片的「涉及」行里。 ### 5.1 发行端(6 步) | 步骤 | 名称 | 结论 | 挂到哪条链路,或不支持的原因 | |---|---|---|---| | 1 | 开启清算 | 挂靠 | 核对门禁。已发布数据集的期初基线与本批固定的 TRS 版本。没有金额公式 | | 2 | 备份清算前数据 | 部分挂靠 | 票据存续、增额、展期、买入执行、卖出执行。资金交收的第 2 步节点尚未挂上 | | 3 | 订单及票据处理 | 挂靠 | 买入执行、卖出执行、票据存续、增额、展期 | | 4 | 交易交收处理 | 挂靠 | 资金交收 | | 5 | 备份清算完成的数据、生成营业日日终数据与核心日常报表、更新T+1实时数据 | 部分挂靠 | 买入执行、卖出执行核 `work/3` 结算口径与 `cleared/0`、`work/4` 一致,并核当前投影。OTC003 挂买入执行、卖出执行;OTC004 对 `cleared/0` 且与 `work/4` 一致,当前投影和昨基线挂票据存续;OTC007、OTC008 挂资金交收 | | 6 | 确认交易日切换、推进营业日、票据激活、清算完成 | 挂靠 | 核对门禁。营业日已推进,且该交易日只有一个 published_flag=1 属于本批 | ### 5.2 销售端(7 步) | 步骤 | 名称 | 结论 | 挂到哪条链路,或不支持的原因 | |---|---|---|---| | 1 | 开启清算 | 挂靠 | 核对门禁。清单锁定的发行版本等于该日当前已发布轮次 | | 2 | 备份清算前数据 | 挂靠 | 账户资产、资金变动、资金交收。只读 `kind=input`。当日原始流水排除步骤 3、4。早于 T 的第 3 步买卖待交收是上一批未交收来源。期初钱包等于上一已发布 `cleared` | | 3 | 订单及票据处理 | 挂靠 | 买入执行、卖出执行、票据存续。账户资产、资金变动、资金交收与第 4 步合成核对,用 `input` 重算,不读 `pre_clearing` | | 4 | 交易交收处理 | 挂靠 | 与第 3 步合成核对,挂账户资产、资金变动、资金交收。发行端交收另读 `work/4` | | 5 | 备份清算完成的数据 | 挂靠 | 账户资产。`cleared` 不含营业日晚于 T 的流水,也不含后续当日买卖 | | 6 | 更新T+1交易日的票据详情实时数据 | 挂靠 | 票据存续。这一步写入的实时钱包不进入钱包核对。`note_view` 按发行当前版本写入,当前值不得写入 `clr_note_view_cleared` | | 7 | 营业日日切 | 部分挂靠 | 生成的 OTC001 挂账户资产,OTC002 挂资金变动,OTC007、OTC008、OTC010 挂资金交收,OTC003 挂买入执行、卖出执行,OTC004 挂票据存续。这些报表对候选。延后流水挂资金变动。发布成功挂核对门禁:本批 kind=cleared 且 status=active | ### 5.3 TRS(10 步) | 步骤 | 名称 | 结论 | 挂到哪条链路,或不支持的原因 | |---|---|---|---| | 1 | 开启清算与清算前备份 | 挂靠 | 委托执行、用户资产。封存集合与按交易日、营业日规则重查源表一致;账面汇率、融资额度用本批封存值。不把实时资金、持仓当 T 日起点 | | 2 | 检查订单终态 | 不支持 | 是「订单必须已终态」的准入,不是公式。订单终态已在委托执行里作为执行根「应不应该出现」的前提 | | 3 | 计算用户汇率 | 部分挂靠 | 用户资产。只核第 5 步和第 8 步用的是本批封存汇率,不计算应该等于多少,也不读事后的实时 `fx_book`。成交数量为 0 的委托不比较 | | 4 | 确认应付利息 | 挂靠 | 用户资产的计息节点。T 日债务不因 T+1 已收取而被冲掉,输入是本批封存的计息证据 | | 5 | 订单与资金清算 | 挂靠 | 委托执行、用户资产。T 日结果读第 7 步 `cleared`。汇率调整读本批快照里的 `clearing_fund_ledger` | | 6 | 持仓清算 | 挂靠 | 委托执行、用户资产。与第 5 步不拆节点。cleared 上数量和成本是第 5 步的值;可用、冻结和估值是第 6 步写在同一行上的结果。`clr_fund_account` 第 6 步不替换 | | 7 | 生成已清算数据集 | 挂靠 | 委托执行、用户资产。`cleared` 不含 `trade_date` 晚于 T 的成交和后续非交易 | | 8 | 生成清算报表 | 挂靠 | 委托执行、用户资产里「报表行应出现」的节点。报表对 `cleared` | | 9 | 确认交易日切换并推进营业日 | 挂靠 | 核对门禁。有对冲时营业日指针已推进到本批之后。无对冲不查 | | 10 | 完成清算 | 挂靠 | 核对门禁。有对冲时版本已切换到本批 kind=cleared、copy_no=1、status=available。批次 completed 不另做一张卡 | 合计挂靠或部分挂靠 22 步(发行 6、销售 7、TRS 9),不支持 1 步(TRS 步骤 2)。 ## 6. 飞书标题 一行,顺序是结论、链路名称、归属名称、主键值: ```text 错误 买入执行 主订单 ORD001202610210004 正确 资金变动 资金账户 FA00012345 可疑 委托执行 用户账号 U0001 错误 核对门禁 清算批次 CB20261021001 错误 未归链路 清算批次 2026-10-21 ``` - 结论用「正确」「错误」「可疑」。 - 归属名称用「主订单」「资金账户」「用户账号」「清算批次」,不再写「主订单编号」。主键值本身已经说明是编号。 - 失败重发在末尾加「重发」:`错误 买入执行 主订单 ORD001202610210004 重发`。 - 标题不写系统和清算步骤。一条链路常跨三端,标题放不下;只写一个又会让人以为只核了这一端。系统和步骤写在正文「涉及」行。 - 同一主订单上有多条链路时,群里是多张卡。看标题就知道哪条链路坏了。 ## 7. 飞书正文 对外只发四张方向卡,顺序固定为订单链路、发行报表、销售报表、TRS 报表。没有结论行的方向不发。核对门禁没有开跑、本轮不算报表时,仍只落原来的清算批次卡,不发四张空卡。 `check_result.card_kind` 为 `dimension`,`chain_name` 为 `order_chain`、`issue_report`、`sales_report`、`trs_report`,`biz_key` 为营业日。`check_run` 的三个计数是这四张卡的总结论,不含已经不再生成的链路概况。已经 `sent` 的旧归属卡不撤回。 四个方向不受 `POST_CLEAR_CHECK_FEISHU_PUSH` 的结论类型和条数截断。截断会直接少掉一个方向。 ### 7.1 标题 ```text 订单链路 可疑 发行报表 正确 ``` - 有错误为红,否则有可疑或无法展开为橙,否则为蓝。无法展开在库里仍是 `suspect`。 - 失败重发在末尾加「重发」。 - 标题不写系统、清算步骤、归属和营业日。 ### 7.2 订单链路 开头三行是营业日、交易日、批次号,用单个换行连在一起。其后按章写:摘要、每单链路、盘中公式、清算对照、关联报表、错误清单、可疑清单、无法展开。没有正确行的计算章不写。三张清单没有行时写「无」。 摘要先写人口:已完成或已结算的 ORD 主单,再按主单计正确、错误、可疑笔数。已撤主单和强平主单不进入买入、卖出公式。三端门禁各一行,只写有没有差异,公式留在对应报表卡。 同一字段的正确行收成一块,结论写「正确(n/n)」。同字段里有错误或可疑时,正确部分仍收成一块,错误和可疑逐条展开,不并进这块。 关联报表不重算。只列本轮主单在三张报表卡上的对错笔数,例如「发行 OTC003:本轮主单 2 笔,正确 2。明细在发行报表。」没有主单号的账户级报表不写进这一章。 ```text 订单链路 可疑 营业日:2026-10-30 交易日:2026-10-30 批次号:ICLR… 摘要 人口:已完成或已结算的 ORD 主单。本方向正确 2 笔,错误 0 笔,可疑 1 笔。 已撤主单、强平主单不进入买入/卖出公式。 发行门禁:无差异。明细在发行报表。 盘中公式 字段:票据面值 期望:执行名义本金(结算币种)× A 类报价 实据:ORD1、ORD2 无差异 依据:共赢票据重要字段、计算公式等说明V2 工作表「买入订单」第 24 行 结论:正确(2/2) 关联报表 发行 OTC003:本轮主单 2 笔,正确 2。明细在发行报表。 错误清单 无 可疑清单 节点:订单卖出股数 期望:按卖出比例 实据:ORD9 依据:共赢票据重要字段、计算公式等说明V2 工作表「卖出订单」第 19 行 结论:可疑。无法判定。 无法展开 无 ``` 章节之间空一行。一张报表或一个字段内部用单个换行,五行连在一起。同一格里有多条期望时,用逗号连成一句,句号收尾。同一份原型文件只写一次,后面接它引用的字段;不同文件仍分行。空的错误、可疑、无法展开各写一行「:无」。 错误结论的分报表块、步骤块、清单逐条块整段 `` 且逐行 `**加粗**`。可疑与无法展开同款:逐行加粗,结论行用 ``(`lark_md` 正文色只有红/绿/灰,没有黄字)。正确块、空清单「:无」、摘要与章名不加版式标签。业务字段仍先把尖括号改成全角,再套上述标签。 ### 7.3 三张报表 发行、销售、TRS 用同一版式:批次门禁、摘要、分报表、步骤核对、错误清单、可疑清单、无法展开。某一张报表没有结论行时,不编一块「正确」,摘要写明目录里缺了哪个编号。 批次门禁只收这一端的门禁行。没有门禁差异时不写这一章。摘要只按 OTC、TRS 编号计正确、错误、可疑的张数,门禁行和步骤节点不计入张数,但它们的错误仍让这张卡的总结论成为错误。发行目录是 OTC003、OTC004、OTC005、OTC007、OTC008。销售目录是 OTC001、OTC002、OTC003、OTC004、OTC005、OTC007、OTC008、OTC010。TRS 目录是 TRS001 到 TRS010、TRS012、TRS013、TRS014、TRS016。OTC009、OTC012、TRS011、TRS015 不进目录。 分报表只收带这些编号的结论行。交收推演、T 日交收、增额主键、增额累计、期初钱包、T 日钱包、候选范围、原始流水、票据与子票据比对是步骤节点,写在「步骤核对」。标题用公式等号左边的步骤名。不拿第一条的票据号、子订单号或币种当报表名。 同一报表、同一依据的正确列收成一块。错误和可疑逐条写节点、期望、实据、依据、结论。没有报表编号的,清单里写步骤和对象。存在性/硬门槛错误(算不出期望数值)时:`calc_text` 首段写正向期望,分号后写失败原因;「期望:」只用首段或公式,「结论:」写原因与当前实据,禁止再套「期望 {失败原因},当前缺失」。主题是错误时,正确列仍留在分报表,不写「正确与可疑留在核对明细」。分报表/步骤总结论为错误或可疑时,整段同样套第 7.2 节的红加粗或黄标签,不只清单逐条。 ```text 销售报表 错误 摘要 本方向报表正确 1 张,错误 1,可疑 0。目录内未出现结论:OTC003、OTC004、OTC005、OTC007、OTC008、OTC010。 分报表 报表:OTC001 资金账户资金报表 筛选:资金账户 FA1 期望:现金余额 = 现金余额(已交收) − 现金余额(买入待交收) + 现金余额(卖出待交收) 实据:1 列无差异 依据:共赢票据重要字段、计算公式等说明V2 工作表「资金账户钱包信息」第 3 行 结论:正确 错误清单 报表:OTC002 现金变动记录 筛选:资金账户 FA00000001 · 主订单 ORD001 节点:买入待交收流水金额 = −订单总金额 期望:−220421.76 实据:当前 -220400.00 依据:共赢票据重要字段、计算公式等说明V2 工作表「买入订单」第 28 行 结论:错误。期望 -220421.76,当前 -220400.00。不符合预期。 ``` ### 7.4 超长与拆分 方向卡不按 3500 字删掉报表块或公式段。删整章会只剩「正确 N 张」和空清单。请求体超过约 28KB 时按结论行拆成多张。每张带同一个记录编号和「第几张,共几张」。拆开发送时整卡仍只有一个 `notify_status`。前面已发出的张下次会再发一遍。 ### 7.5 不改的计算 方向卡不新增公式,也不把巡检稿里的业务判断写成新的对错。已撤主单、强平主单、对冲比例低于建议比例、手填汇率偏离、持仓差额归因、跨表加总,都不在这四张卡里单独成行。库内结论仍只有 `correct`、`error`、`suspect`。 ## 8. 这一步实现什么 这一步只搭骨架和卡片版式:结论行带链路,收卡按链路分,标题和正文换版式,现有结论行挂到 11 条链路上。另外停掉增额、展期与两张空表的比对。不重写 11 条链路的节点公式,不补第 4 节里标明「改这条链路时补上」「在改这条链路时实现」的节点,不补钱包三方闭合。 ### 8.1 需求—实现—测试—库表 | 需求 | 代码落点 | 测试 | 自有库 | |---|---|---|---| | 结论行带链路 | `order_cell.CheckLine` 增加 `chain_name` | 每条现有结论行都带非空链路代码 | — | | 链路登记表 | 新增 `chain.py`:代码、中文名、归属优先顺序、涉及、依据登记;加入 `orchestrate._RULE_FILE_NAMES` | 11 条链路加未归链路齐全;每条链路的涉及与第 5 节一致 | — | | 现有结论行挂链路 | `issue_reports`、`sales_reports`、`trs_reports` 和订单规则入口按调用的核对函数打标签(见 8.3) | 每个核对函数的产出都落到预期链路;OTC003 与订单规则按方向分到买入或卖出 | — | | 收卡按链路 | `orchestrate.assemble_cards`、`_place_line`:按「链路 + 归属种类 + 主键」分卡,归属按链路登记的优先顺序取第一个非空键 | 同一主订单的两条链路分成两张卡;没有归属键或没有链路的行进未归链路且为错误 | — | | 幂等键算入链路 | `orchestrate.dedupe_key` 在卡片种类后加链路代码 | 同一订单两条链路的幂等键不同;超长仍走摘要 | `check_result` 增加 `chain_name` | | 标题 | `feishu.render_title` 改为结论、链路名称、归属名称、主键 | 五种标题样例、重发后缀 | — | | 正文 | `feishu.render_body`、`render_line`:开头加「涉及」;依据到期望结论按内容空行;错误主题只写错误段 | 四种期望句式;错误主题不带正确段和可疑段;超长删段与拆分时「涉及」不丢 | — | | 落库读回 | `SqlRunStore` 写入、读出 `chain_name` | 落库再读回的卡与原卡一致 | 同上 | | 停掉 OTC009、OTC012 空表比对 | `issue_event.check_topup`、`check_extension`(含展期日期比对 `_pair_dates`),`sales_event.check_topup`、`check_extension` 不再读报表行、不再出结论行;`columns` 去掉发行端 OTC009、OTC012 和销售端展期费报表的取数规格,`reader` 不再读这两张表 | 有增额记录、展期记录时不产生结论行;取数不再访问 `report_topup_payment`、`report_extension_fee` | — | 停掉空表比对属于明确的口径变更,原有测试断言要同步改:旧行为是有增额、展期就记「报表无行」错误;新口径是 OTC009、OTC012 为实时导出、不落库,清算后不核报表行;理由是两张表在三端没有写入方,原节点每次必然误报;影响是增额、展期两条链路在改链路之前不出卡。增额、展期记录本身仍照常取数,留给改链路时用。 `check_result.chain_name` 存英文代码,卡片上显示中文名,与 `card_kind`、`verdict` 的做法一致。建表改 `sql/schema.sql` 里 `check_result` 的 `CREATE TABLE`:`chain_name VARCHAR(32) NOT NULL DEFAULT ''`,CHECK 约束允许 12 个代码和空串。空串只出现在加列前的旧轮次,以及回滚后旧代码写入的行;新代码不写空串,由测试守住。已有库由人执行一次 `ALTER TABLE check_result ADD COLUMN chain_name ...`(含同一条 CHECK),语句写进 `doc/使用说明.md`,不写进 `schema.sql`。旧轮次的规则版本与新代码不同,不会再被命中,也不会被重发。 ### 8.2 链路登记表 一条链路登记一项,字段对应第 3 节的链路合同:代码、中文名称、归属优先顺序、涉及(系统与步骤号、步骤名)、依据登记。 依据登记给骨架阶段的现有结论行用,键是「报表编号」或「公式左侧的中文字段名」: - 报表列的复制、存在性核对,依据取 4.13 的原型路径,口径名称取报表列名。 - 订单规则、票据计算等公式行,按公式左侧字段名查 Excel 工作表与行号,例如「卖出票据面值」查到「卖出订单」第 21 行。 - 门禁行取 4.12 的研发设计章节。 现有结论行原来的 `basis` 文字不是三种依据之一,挪到第三行代入式后面作说明。测试逐条守住:每条渲染出来的依据都是三种之一,查不到登记的算测试失败,不在运行期兜底。 ### 8.3 现有结论行挂到哪条链路 | 现有来源 | 报表或规则 | 链路 | |---|---|---| | `order_rules.check_order`、`hedge_link` | 主订单规则 | 按主订单方向:买入执行或卖出执行 | | `issue_otc003`、`sales_otc003` | OTC003 | 按主订单方向:买入执行或卖出执行 | | `issue_otc004`、`sales_otc004` | OTC004、OTC005 | 票据存续 | | `issue_settle`、`sales_settle` | OTC007、OTC008 | 资金交收 | | `sales_cash.check_otc010` | OTC010 | 资金交收 | | `sales_cash.check_otc002` | OTC002 | 资金变动 | | `sales_asset.check_otc001` | OTC001 | 账户资产 | | `issue_event.check_topup`、`sales_event.check_topup` | OTC009 | 增额。本步停掉空表比对,暂无结论行 | | `issue_event.check_extension`、`sales_event.check_extension` | OTC012 | 展期。本步停掉空表比对,暂无结论行 | | `trs_trade` | TRS002、TRS003、TRS004 | 委托执行 | | `trs_flow` | TRS005、TRS008 | 委托执行 | | `trs_flow` | TRS006、TRS007、TRS009、TRS012、TRS013 | 用户资产 | | `trs_account` | TRS001、TRS010、TRS014、TRS016 | 用户资产 | | `gate`、编排缺表 | 报表早于批次、TRS 未完成、1146 | 核对门禁 | | 以上都挂不上,或链路要求的归属键为空 | — | 未归链路,结论为错误 | 链路在调用核对函数的地方打标签,不从正文或报表编号反推。主订单方向取不到的 OTC003 行进未归链路。 票据存续、资金交收归资金账户。OTC004、OTC007、OTC008 的行只有 `fund_account_no`,没有主订单编号列,挂链时把报表行的 `fund_account_no` 写进结论行的 `fund_account`,不改公式和结论。来源记录缺资金账户、对不上报表行的,进未归链路。增额、展期改链路后,按销售端资金流水上的资金账户归属。 ### 8.4 不改什么 - 除停掉 OTC009、OTC012 空表比对外,不改任何核对函数的公式、被核对对象和结论。 - 除不再读那两张空表外,不改开跑门禁、取数、只读会话、飞书签名限流和发送重试。 - 不改三端业务库。 - 不增加第四种结论。 ### 8.5 验证 只跑本次改动相关的定向测试:`tests/test_orchestrate.py`、`tests/test_feishu.py`、`tests/test_schema.py`、`tests/test_order_rules.py`、`tests/test_issue_reports.py`、`tests/test_sales_reports.py`、`tests/test_trs_reports.py`、`tests/test_reader.py`,以及新增的链路登记表用例。不跑全部用例。 上线后规则版本变化,已核对过的营业日会新开一轮,按新版式重新出卡。 ### 8.6 回滚 代码回滚到上一版即可,规则版本随之回到旧哈希。自有库新增的 `chain_name` 列可以保留:旧代码不读它,插入时取默认空串,CHECK 允许空串。若要连列一起撤,人工执行一次 `ALTER TABLE check_result DROP COLUMN chain_name`。 ## 9. 之后怎么改链路 骨架落地后,每次只改一条链路的节点:先改本文第 4 节该条,再改代码和测试。不顺手改其他链路。 例如改资金变动时才补:金额非零的已入账流水必须出现、金额为 0 的冻结解冻必须不出现、买卖待交收金额按订单公式链复算再与流水闭合。 ## 10. 明确不做 - 不把三端 23 个清算步骤各建成一条链路,不用「TRS清算-步骤1」这种步骤名做标题。 - 不在这一步重写 11 条链路的节点公式。 - 不把询价报价、票据风控、授信、信用、预警线、平仓线、市场汇率算进这 11 条。 - 过程步骤不写加减式,也不收进核对门禁假装算过。 - 不改三端业务库。不增加第四种结论。