Regulatory Reporting
ODTS 19 — 监管报送 Regulatory Reporting: 每笔交易不可协商的输出
业务问题
在中国境内,每一笔场外衍生品交易必须在 T+1 内向中国证券业协会 (SAC) 报送。报送内容包括交易要素(对手方、产品类型、名义本金、期限)、风险要素(Delta、Gamma、Vega、对手方敞口)和抵押品要素(IM、VM 金额)。
这不是可选项。如果交易未报送:
- 监管罚款:每笔漏报 10 万–100 万人民币
- 声誉损失:“中金公司因 OTC 报送违规被处罚”的新闻
- 极端情况下:SAC 可以暂停交易资格
核心问题: SAC 每 6–12 个月修改一次报送格式。每次修改都需要系统升级。
监管报送全景
| 监管机构 | 管辖区域 | 报送内容 | 频率 |
|---|---|---|---|
| SAC | 中国境内 | 所有境内 OTC 交易 | T+1 |
| 香港证监会 (SFC) | 香港 | 所有香港簿记的 OTC 交易 | T+1 |
| 中国证监会 (CSRC) | 中国 | 所有涉及零售投资者的结构化产品 | T+1 |
| ISDA Trade Repository (TR) | 全球 | 交易报告库报送 | T+1 |
SAC 报送详解
SAC 报送规则引擎
SAC 报送的核心逻辑不是硬编码在生成器中的,而是通过一套规则引擎实现的。规则代码位于 eds-utility/src/com/cicc/rules/sac/,每个产品类型有自己的规则类:
rules/sac/
├── EDSOptionContractRule.java — EDS 期权合约报送规则
├── EdsTrsContractRule.java — TRS 合约报送规则
├── EdsDurationMgtRule.java — EDS 期限管理报送规则
├── PBOptionContractRule.java — PB 期权合约报送规则
├── PBSwapContractRule.java — PB 互换合约报送规则
├── FISwapRule.java — FI 互换规则
├── FiSwapDurationRule.java — FI 互换期限管理
├── DurationMgtRule.java — 通用期限管理
├── EnsureAgrmtRule.java — 担保协议规则
├── MasteragrmtRule.java — 主协议规则
├── MasterRelaAgrmtRule.java — 主协议关联规则
├── SupAgrmtRule.java — 补充协议规则
├── AddUnderlyingAutoMappingRule.java — 标的自映射
└── model/ — 规则数据模型
├── SACReport/ — 报告模型(附件、协议、行权等)
├── OptionContract/ — 期权合约模型(EDS/PB/质押物等)
├── TrsContract/ — TRS 合约模型
├── DurationMgt/ — 期限管理模型
└── UnderlyingAutoMapping/ — 标的自映射模型
数据流是:交易在 EOD 批处理中被规则引擎处理,每条规则提取需要的字段,填充到对应的 Model 对象,最终汇聚到报告文件。这种架构让新产品的报送支持只需要添加新的规则类,而不需要修改报告生成器的核心代码。
SAC 模板列
报送格式列映射(简化):
| SAC 字段 | 含义 | 来源 | 规则类 |
|---|---|---|---|
| tradeId | 交易编号 | 系统协议号 | TrsContract / OptionContract |
| underlying | 标的资产 | 产品配置 | UnderlyingAutoMapping |
| masterAgreement | 主协议类型 | 客户协议 | MasteragmtRule |
| counterparty | 交易对手 | 客户信息 | 公共列 |
| notional | 名义本金 | 产品参数 | TrsContract / OptionContract |
| delta/gamma/vega | Greeks | EOD 风险表 | OptionContract |
| marginAmount | 抵押品 | 质押物 | EnsureAgrmtRule |
SAC 校验与报送
报送前,SacReportValidateAction 对生成的数据进行校验:必填字段非空检查、字段格式(如日期、金额精度)、交易对序号唯一性。校验通过后,SacReportAction 将数据通过 HTTP Protobuf 批量提交到 SacAS(SAC Application Server)。
dailyCheck 界面流程(Vue.js 前端):
SacReportDaily.vue — 日报检查主页面
sacreportTable.vue — 待报送交易列表
sacreportSubtable.vue — 单笔交易详情
运营人员在 dailyCheck 界面中查看待报送交易,确认无误后触发提交。
SAC 报送工作流
T+0, 18:00 — EOD 批处理结束
T+0, 18:30 — SacReportGenerator 运行(EOD 第 9 步)
→ 规则引擎逐产品类型处理 → 填充 SAC Model → 生成 XML
→ 根据 schema 校验 XML
→ 将 XML 文件保存到磁盘
T+1, 09:00 — 运营在 dailyCheck 界面审核
T+1, 10:00 — 运营触发提交 → SacAS Protobuf 自动报送
T+1, 10:30 — SacAS 返回结果回执
为什么有手动审核步骤? 监管报送的”不可逆”特性——一旦提交错误数据,修改需要向 SAC 提交正式说明。运营人员宁可花 30 分钟审核也不愿花 3 天写说明。
SacAS:实际报送系统
ODTS 对接的监管报送系统是 SacAS(SAC Application Server),通过 HTTP + Protobuf 批量提交交易数据。
SacReportBean — 报送数据的核心结构
报送请求的核心数据载体是 SacReportBean,位于 sac-report 模块和 eds-web-app 中各有一份:
sac-report/src/.../bean/sacMiddle/SacReportBean.java — 中间层数据模型
eds-web-app/src/.../action/dynamic/model/SacReportBean.java — 报送接口模型
关键字段:
| 字段 | 类型 | 说明 |
|---|---|---|
userId | String | 操作员 ID |
requestType | String | 请求类型(报送/查询/删除) |
reportType | int | 报告类型(SAC/SFC/ISDA) |
deskEntityId | long | 交易台实体 ID |
docType | String | 文档类型(TRS/OPTION/SWAP) |
optType | String | 操作类型(INSERT/UPDATE/DELETE) |
busiDataSeqs | List<String> | 业务数据序列号列表(每笔交易的唯一 ID) |
optBusiDataSeqs | List<String> | 被操作的数据序列号 |
sacReportExportMap | Map | 导出参数映射(文件路径、格式等) |
批量提交流程
// SacReportAction.java — 批量提交入口
SacReportBean bean = new SacReportBean();
bean.setUserId("operator01");
bean.setRequestType("SUBMIT");
bean.setReportType(SAC_REPORT);
bean.setDeskEntityId(1001L);
bean.setDocType("TRS");
bean.setOptType("INSERT");
bean.setBusiDataSeqs(Arrays.asList("TRS202507001", "TRS202507002", "TRS202507003"));
// 通过 HTTP Protobuf 发送到 SacAS
SacAsClient.submit(bean);
2022 年 SAC Schema 变更危机
2022 年,SAC 发布了一次重大 schema 更新:新增 30 个字段(包括信用估值调整 CVA 和信用风险数据),15 个字段改名(破坏性变更),XML 命名空间也变了(旧 XSLT 失效)。
修复耗时 3 周:
- 第 1 周:理解新 schema(200 页文档)
- 第 2 周:更新模型和规则(改了 80+ 个文件,每个产品规则类都需要检查和适配新字段)
- 第 3 周:测试和校验(对比新旧输出)
修复期间: 用旧 schema 生成报告,运营人员手工在 Excel 中添加新字段。2 名运营人员全职做这件事,耗时 3 周。
规则引擎架构在这次变更中展示了价值——新增字段只需要修改对应产品类型的规则类(如 EDSOptionContractRule.java 中添加 CVA 字段映射),而不是重写整个生成器。但 80 个文件的修改量说明规则与模型的耦合仍然紧密。
SFC 报送(香港)
对于在香港簿记的交易,香港证监会 (SFC) 要求通过 HKTR (Hong Kong Trade Repository) 报送。系统代码路径在 eds-web-app/src/.../action/hktr/ 下。
SFC 报送比 SAC 简单——schema 更稳定(修改频率约 18-24 个月 vs SAC 的 6-12 个月),字段更少(约 100 个 vs SAC 的 200 个)。
CSRC 报送
中国证监会 (CSRC) 要求所有涉及零售投资者的结构化产品进行报送。格式和规则与 SAC 不同——CSRC 关注的是产品结构和销售行为而非交易风险指标。
ODTS 对 CSRC 报送的处理没有独立的模块——数据通过 SacAS 的 reportType = CSRC_REPORT 提交,复用了 SAC 的报送通道,但产品筛选逻辑不同(只选涉及零售客户的结构化产品)。
sac-report 独立模块
系统有一个独立的 sac-report/ 模块:
sac-report/
└── src/com/cicc/report/
├── bean/
│ └── sacMiddle/SacReportBean.java — 中间层数据
├── builder/ — 报表构建器
├── exporter/ — 数据导出
└── validator/ — 报送校验
这个模块的存在原因:SAC 报送不仅需要从 ODTS 的交易数据生成报告,还需要中间层数据转换——将 ODTS 的领域模型(交易、头寸、抵押品)映射为 SAC 的监管模型(合同、协议、质押物)。sacMiddle 包名中的 “Middle” 正是这个中间层的含义。
报告对账之痛
交易台同时向 SAC 和(有时)ISDA Trade Repository 提交同一批交易。SAC 报告和 ISDA TR 报告应该一致,但实际上:
SAC 报告:150 笔交易已报送
ISDA TR: 148 笔交易已接收
差异:2 笔交易
原因:
- 1 笔交易在 SAC 截止时间后簿记(次日报送)
- 1 笔交易在 ISDA TR 中的交易 ID 不同
找差异:运营手工核对(每天 30 分钟)
为什么交易 ID 会不同?SAC 使用 ODTS 系统协议号作为交易 ID,ISDA TR 使用另一个 ID 生成规则。系统没有统一的”全局交易 ID”。
对账的隐性成本: 每天 30 分钟的跨系统对账听起来不多,但一年就是 125 小时——一个运营人员 3 周的工作。更关键的是,对账是人工比较 Excel 列,靠肉眼发现差异。2023 年有过一次 SAC 和 ISDA TR 之间 3 笔交易的差异没被对账发现,直到次月的监管巡查才被指出。虽然没有罚款(巡查期修复合规),但合规部门专门出了一个”整改报告”,团队花了 2 周写流程改进文档。运营主管说:“每次监管巡查前,我们都加班做三遍对账。”
Schema 变更——监管风险的另一面: SAC 每 6–12 个月改一次 schema。如果团队在截止时间前没完成适配,交易台只能用旧格式报送——但 SAC 可能拒收旧格式。被拒收 = 漏报。2022 年的 schema 变更,团队 3 周完成,但 SAC 给的过渡期只有 6 周。如果是一个更复杂的变更(比如 50 个新字段而不是 30 个),6 周可能不够。交易台的对策是:在过渡期内,用旧格式生成报告 + 运营手工在 Excel 中添加新字段。但手工添加的字段在 T+1 的紧节奏下难免出错——2022 年有 5 笔交易的 CVA 字段填错了,SAC 发了整改通知。交易台的”罚款”不是直接罚钱,而是被 SAC 列入”重点关注名单”——这意味着未来 6 个月,每一次报送都会被 SAC 人工审核,任何小错误都会被放大。
报送的代价
| 活动 | 时间/天 | 负责人 |
|---|---|---|
| SAC 报告生成(系统自动) | 20 分钟 | 系统 |
| SAC 审核和上传 | 30 分钟 | 运营 |
| SFC 报告生成+上传 | 20 分钟 | 运营 |
| ISDA TR 上传 | 15 分钟 | 运营 |
| 报告对账 | 30 分钟 | 运营 |
| Schema 变更适配 | 每年 2-3 周 | 开发 + QA |
| 跨系统对账 | 30 分钟 | 运营 |
| 年度总人工成本 | 约 24 万 RMB | 2 个岗位分摊 |
关键文件
| 组件 | 路径 |
|---|---|
| 报送接口 (SacAS) | eds-web-app/src/.../action/sacReport/SacReportAction.java |
| 报送接口 (search) | eds-web-app/src/.../action/sacReport/SearchSacReportAction.java |
| 校验 Action | eds-web-app/src/.../action/dynamic/SacReportValidateAction.java |
| 生成 Action | eds-web-app/src/.../action/dynamic/GenerateSacReportAction.java |
| SacReportBean | eds-web-app/src/.../action/dynamic/model/SacReportBean.java |
| GenerateSacReportBean | eds-web-app/src/.../action/dynamic/model/GenerateSacReportBean.java |
| sac-report 中间层 | sac-report/src/.../bean/sacMiddle/SacReportBean.java |
| SAC 期权规则 | eds-utility/src/.../rules/sac/EDSOptionContractRule.java |
| SAC TRS 规则 | eds-utility/src/.../rules/sac/EdsTrsContractRule.java |
| SAC 主协议规则 | eds-utility/src/.../rules/sac/MasteragrmtRule.java |
| SAC 担保协议 | eds-utility/src/.../rules/sac/EnsureAgrmtRule.java |
| SAC 全局管理 | eds-utility/src/.../sac/SacGlobalManager.java |
| SAC 工具类 | eds-utility/src/.../utils/SacRuleUtil.java |
| SAC 期权工具 | eds-utility/src/.../utils/SacRuleEdsOptionUtil.java |
| 模型—期权 | eds-utility/src/.../rules/sac/model/OptionContract/ |
| 模型—TRS | eds-utility/src/.../rules/sac/model/TrsContract/ |
| 模型—SAC报告 | eds-utility/src/.../rules/sac/model/SACReport/ |
| 模型—期限管理 | eds-utility/src/.../rules/sac/model/DurationMgt/ |
| Daily Check UI | new-edsweb/src/views/eod/sacreportTable.vue |
| Daily Check sub | new-edsweb/src/views/eod/sacreportSubtable.vue |
业务现实: 监管报送每年耗费约 0.5 个运营人力 + 3 周开发时间。这是不可协商的、不创收的强制工作。规则引擎架构(每产品类型 → 独立规则类)让适配新 schema 变得可管理,但 80 个文件的修改量说明模型与规则的耦合仍然需要改进。
总成本算一笔账: 运营每天花 30 分钟审核 SAC + 20 分钟 SFC + 15 分钟 ISDA + 30 分钟对账 = 约 2 小时/天。一年 500 小时 = 0.3 FTE × 60 万 = 18 万/年。加上 schema 变更适配每年 3 周 × 2 人(1 个开发 + 1 个 QA) = 6 人周 × 4 万/人月 = 6 万。团队总成本约 24 万/年。这些钱不产生一分收入——它是做 OTC 衍生品生意的”入场券”。SAC schema 变更频率越高,这张入场券就越贵。