Learning
VOL. VII · NO. 62 · OTC Derivatives · 19 JUL 2026

Client Onboarding

OTC 衍生品 · 19 JUL 2026 · 14 min read · 2,709 words
· · ·

ODTS 13 — 客户上线:从电话到第一笔交易

业务流程

客户在交易之前必须经过上线 (onboarding) 流程:

第 1 步:销售找到客户
第 2 步:KYC (Know Your Client) — 了解客户身份和资金来源
第 3 步:ISDA/CSA 谈判 — 管辖 OTC 交易的法律协议
第 4 步:授信额度审批 — 交易台可以承担多少敞口
第 5 步:运营设置 — 客户代码、联系人名单、交割指令
第 6 步:系统设置 — 添加至系统、分配角色/权限
第 7 步:第一笔交易

时间线: 2 周(理想情况)到 6 个月(复杂的中资机构客户)。

延迟上线的机会成本: 一个机构客户准备入场做 1 亿 RMB TRS(100bp spread),年化收入贡献约 100 万 RMB。如果上线拖了 3 个月(常见的中资机构走合规审批速度),交易台损失 2 个月的交易时间 ≈ 17 万 RMB。一年 10 个这样的新客户,就是 170 万的机会成本。更糟的是,有些客户因为上线太慢直接就走了——销售口中”客户等不了,去了 XYZ 证券”的故事,每个销售都能讲两三个。

系统在哪里介入

系统参与第 5 步和第 6 步

系统不做:
  - KYC(独立的合规系统)
  - ISDA/CSA 谈判(Word 文档、邮件)

系统做:
  - 客户主数据(名称、代码、联系人)
  - 授信额度跟踪
  - 交割指令 (settlement instructions)
  - 交易簿记权限控制

客户在系统中如何表示

客户记录

ClientController.java

一个客户在系统中:
  clientId:       "CLT0001"
  shortName:      "UBP_HK"         (内部讨论时用)
  legalName:      "Union Bancaire Privée, Hong Kong Branch"
  clientType:     "PRIVATE_BANK"   (用于保证金规则和报告)
  riskRating:     "A"              (A/B/C — 驱动 ISDA CSA 保证金阈值)
  creditLimit:    500,000,000      (RMB — 最大敞口)

客户代码

一个客户有多个不同用途的代码:

clientId: "CLT0001"
├── isdaMasterAgreement: "ISDA-CLT-0001-2018"  (法律文件引用)
├── settlementInstructions:
│   ├── CNY: "BOC SHANGHAI, ACC 12345678"
│   └── USD: "CITI HK, ACC 87654321"
├── fixingsSources:
│   └── CNY: "CFETS 4:30 PM"
└── clientContact:
    ├── trading: "trader@client.com"     (交易确认发送至此)
    ├── operations: "ops@client.com"     (追保通知发送至此)
    └── compliance: "compliance@client.com"

代码位置:

eds-web-app/src/com/cicc/edsBoot/dao/ClientDao.java
ContractClientInfo 表

系统不记录什么

系统的客户模型很薄。它不知道:

  • 客户的实益拥有人是谁(KYC 详情在合规系统)
  • 客户的投资策略是什么(销售知道,系统不知道)
  • 客户以前是否违约过(风控知道,系统不会标记)
  • 客户和哪些其他交易台交易(外汇台、固收台各有一套系统)

缺口: 如果客户 A 在外汇交易上违约(在其他系统簿记),股权交易台不知道。我们系统中的授信额度没有变。违约后的第一笔交易可能超过实际风险承受能力。这个缺口存在是因为系统之间不共享交易对手数据。

实际案例——信用风险盲区: 某年,一个机构客户在另一个交易台的外汇 NDF 上发生了交割违约。外汇台暂停了该客户的交易。但股权衍生品交易台不受影响——因为两个交易台的授信系统相互独立。该客户的股权 TRS 敞口在违约消息传出后不仅没有被冻结,反而因为在系统层面仍被视为”正常”,销售又撮合了两笔新交易。直到月底风控汇总报表时,才发现该客户的总敞口(外汇 + 股权)已超过公司层面的授信上限。这个”系统隔阂”导致超额敞口维持了整整 3 周才被发现。

客户发起申请 (Counterparty Apply) 工作流

新客户上线通过交易对手申请流程 (Counterparty Apply) 驱动。这个流程在系统中有专门的收件箱 (Inbox) 机制:

counterpartyApply 状态流转:
  DRAFT(草稿)
    → SUBMITTED(已提交)
    → 合规反洗钱通过 (CPAML PASS, status=27) → 授信审批
    → 合规反洗钱拒绝 (CPAML REJECT, status=28) → 退回
    → 合规反洗钱回退 (CPAML RETURN, status=29) → 修改后重提
    → 授信审批通过 → 系统设置完成 → 客户上线

数据库中通过 EDS_COUNTERPARTYAPPLY_INBOX 全局常量配置收件箱类型,EDS_ELEMENTDICT_INPUTTYPE 定义输入类型(如”日期列表”)。合规反洗钱检查是上线流程中的第一个硬关卡——系统通过 Inbox 机制将申请推送到合规团队的待办事项列表中。

KYC 与 AML

KYC/AML 检查不在 ODTS 系统中完成。合规团队使用独立的系统进行客户尽职调查:

ODTS 的角色:
  发起申请 → 发送到合规 Inbox → 等待合规结果
  合规通过 → 继续上线流程
  合规拒绝 → 终止上线流程

合规的角色:
  接收 ODTS 推送的申请
  在独立系统中进行背景调查
  将结果反馈到 ODTS Inbox(通过/拒绝/回退)

但有一个整合点:EDS_COUNTERPARTYAPPLY_INBOX 配置了 CPAML 作为收件箱类型,意味着 ODTS 通过这个 Inbox 机制与合规系统集成——ODTS 发送申请,合规操作后更新状态码。

结算指令——一个小失误的放大效应

客户上线流程中最容易被忽视但代价最高的细节是结算指令 (settlement instructions) 的准确性。

结算指令告诉系统:当你需要从这个客户收钱或付钱时,资金应该走哪家银行、哪个账号、哪个 SWIFT 代码。如果这个信息错了,后果很直接:

场景:客户入金 1000 万 RMB 作为保证金
  运营按系统记录的结算指令发了付款指示
  银行按账号处理 → 资金去了另一个客户的账户
  发现错误 → 联系银行追回 → 银行需要客户授权 → 3-5 个工作日
  这 3-5 天里,客户的保证金不足
  交易台不能开新仓,或者需要临时降低信用额度

这种结算指令错误的常见原因:

  • 客户提供了新账号,但邮件被销售转发时遗漏了附件(每年至少 1–2 次)
  • 运营手动录入时抄错了一位数字(每年 2–3 次,但大部分被银行端的风控拦截)
  • 客户更换了结算银行,但没有正式通知(占比较小,但发生时最棘手)

真实案例——账号抄错一位数: 某年,运营录入某客户的 USD 结算账号时,28 位账号的最后一位抄错了。第一笔 500 万美元的入金因此失败,银行在 2 个小时后返回”账号不存在”的错误。运营花了 2 小时核实、更正、重新发送。当天晚些时候客户说他们其实已经更改了收款行——但只通知了销售,销售忘了转给运营。这个失误总耗时 4 小时,涉及 3 个人(运营 × 2、销售 × 1),但核心问题是流程本身——没有”客户结算指令变更必须通过正式渠道”的硬性规定。

客户门户 (Client Portal)

目前状态:无门户

客户目前没有自助门户。他们通过以下方式看到自己的数据:

1. 月度客户账单 (PDF)
   生成:eds-web-app
   模板:Word (.docx) 通过 Apache POI 生成
   发送:运营人工发送(没有自动投递)

2. 投资组合报告 (Excel)
   生成:eds-web-app
   格式:按客户定制的 Excel
   频率:头部 20 家客户每日发送,其他每周

3. 追保通知 (邮件/电话)
   生成:hedging-as 保证金引擎
   发送:运营(邮件模板)

尚未构建:

  • 客户门户(客户网页端查看头寸)
  • 自动报告投递
  • 供客户系统直接拉取数据的 API

这样做的影响:2023 年交易台花了 1.5 个全职员工的人力来回答客户的持仓和保证金问题。一个客户门户可以节省这笔成本,但从未被优先于创收功能。

这 1.5 个人的工作量拆解:

  • 每天约 10–15 个客户邮件/电话问”我现在的 P&L 是多少?“——客户看不到系统,只能问。每个回答需要运营查系统、写邮件、发出去,平均 10 分钟。
  • 每天 3–5 个追保相关问题——“为什么保证金涨了?""我还有多少额度?“平均 15 分钟。
  • 每周 2–3 次定制报告请求——客户要某个特定时间范围的交易明细,运营手动从系统导出 Excel,调整格式,发出去。每次 30–60 分钟。
  • 每月初集中发送客户账单——运营花 2–3 天生成和发送 50+ 份 PDF 客户账单。

这些工作每一个单独看都不大,但加起来每年就是 1.5 个人的全部时间。交易台的人工成本是 50–80 万/人/年,所以回答客户问题这件事本身的直接成本就是 75–120 万/年。还没有算客户的等待体验和销售因此花在安抚客户上的时间。

Protobuf 客户端接口

虽然没有客户门户,但系统通过 Protobuf 协议向外部系统暴露了一些客户端接口:

MsgGwClientInfo.proto          — 客户端信息网关消息
MsgClientLogin.proto           — 客户端登录
MsgClientLoginInfo.proto       — 客户端登录信息
MsgClientResetPwd.proto        — 客户端密码重置
MsgSwapClientList.proto        — 互换客户端列表

这些接口服务于内部客户端(如 FUXI 前台系统),而非终端零售客户。tradedesign/gateway/msg/MsgGwClientInfo.prototradedesignapp/gateway/msg/MsgGwClientInfo.proto 两处有重复定义——这是网关模块与交易设计模块之间的接口定义复制问题。

CRM 功能

ODTS 没有内置 CRM (客户关系管理)。客户联系信息存储在 ContractClientInfo 表中,但管理系统是:

功能缺失:
  - 客户互动历史(没有电话记录、会议纪要)
  - 客户生命周期管理(没有"沉睡客户"标记)
  - 客户分群和标签(没有按策略分组)
  - 销售业绩追踪(没有按客户统计 P&L)

这意味着:销售团队使用 Excel 跟踪客户关系,与交易系统物理隔离。如果需要回答”招商银行这个月给我们贡献了多少收入?“,需要从交易系统导出 P&L 数据,到 Excel 中按客户汇总。

ISDA/CSA 工作流

ISDA — International Swaps and Derivatives Association 主协议。它是 OTC 衍生品交易的法律框架。

CSA — Credit Support Annex(信用支持附件)。它定义了如何交换保证金 (collateral)。

影响系统的关键 CSA 条款:
  - Threshold: 低于此额免交保证金(如 5000 万 RMB)
  - Minimum Transfer Amount: 最小追保金额(如 100 万 RMB)
  - Rounding: 保证金取整到最近的 1 万
  - Eligible Collateral: 什么可以作为保证金(仅现金?国债?)
  - Haircuts: 担保品的折扣率(如国债打 95 折)

在系统中:

eds-web-app/src/com/cicc/edsBoot/dao/CsaDao.java
ContractCsaInfo 表

字段:
  threshold, minTransferAmount, rounding
  eligibleCollateral (枚举: CASH, GOVT_BOND, STOCK, LETTER_OF_CREDIT)
  haircutPercent

系统根据 CSA 条款计算追保。但如果系统中的 CSA 没有更新(如手动录入的字段过期了),追保金额可能不对。

“纸面协议”问题

一半的客户的 CSA 条款从来没有被正确地录入系统。

为什么: 法务团队用 Word 谈判 CSA。运营团队手动将条款录入系统。交易员也有自己的理解。这三个版本经常不一致。

法务的 CSA(签署文件):
  Threshold: 5000 万 RMB
  MTA: 100 万 RMB
  Rounding: 1 万

系统的 CSA(数据录入):
  Threshold: 4500 万 RMB  (笔误——有人录入了 45 而不是 50)
  MTA: 100 万 RMB
  Rounding: 1 万

交易员的记忆:
  Threshold: 5000 万 RMB
  MTA: 100 万 RMB
  Rounding: 1 万

每日追保使用系统中(错误的)CSA。客户收到 4500 万的追保通知而不是 5000 万。客户打电话给运营。运营花了 30 分钟找出原因。

修复方案(从未实现): “CSA 对账”流程——每月将法律 CSA 与系统 CSA 对比一次,标记所有差异。

此类问题的累积成本: 系统 CSA 与法律 CSA 不一致的情况在运营中出现的频率大概是每月 1–2 次。每次的处理流程是:客户收到追保通知后有疑问 → 客户致电运营 → 运营查找纸质 CSA 对比系统数据 → 发现差异 → 手动修正系统 → 重新生成追保通知。一次处理 30–60 分钟。一个月就是 30–120 分钟。一年 10–24 次差异 = 运营 5–24 小时的处理时间。时间本身不多,但每次差异都让客户感到系统不可靠——客户信任的消耗是线性累积的,而信任崩塌是瞬间的。

客户 P&L

系统通过 ClientTradePnl 模型跟踪客户级别的 P&L:

eds-utility/src/com/domian/ClientTradePnl.java
  extends TradePnl

这个类扩展了通用 P&L 模型,增加了客户维度。ClientTradePnlService 提供按客户汇总 P&L 的功能。

但 P&L 是按客户汇总的,而不是按”交易员-客户”维度。如果一个交易员管理多个客户,系统无法区分哪个客户贡献了多少收入。这对于销售激励(谁带来最多收入?)和客户盈利能力分析(哪个客户成本最高?)都是关键缺口。

一个实际影响: 某次,管理团队要求分析”哪些客户在盈亏平衡线以下”——即扣除融资成本和运营成本后,哪些客户是亏钱的。因为系统不按客户维护运营成本(如这个客户每天产生多少对账工作量),分析团队只能手动估算:拿 Excel 导出每个客户的 P&L,然后按交易笔数平均分摊运营成本。这个过程花了数据分析师 3 天。结果发现有两个中小客户,交易量不大但运营成本特别高(因为它们的结算指令经常变,每次都需要人工更新),实际上在亏损。但因为没有系统层面的客户盈利分析,这两个客户一直没有被标记为”需重新定价”。

关键文件

组件路径
客户 DAOeds-web-app/src/.../dao/ClientDao.java
CSA DAOeds-web-app/src/.../dao/CsaDao.java
客户信息表ContractClientInfo
CSA 信息表ContractCsaInfo
CPAML 收件箱EDS_COUNTERPARTYAPPLY_INBOX(全局常量)
CPAML 迁移脚本eds-web-app/db/EDS/arch/V1.3/EDS20170412130001_INSERT_GC_FOR_CPAML.sql
客户 P&L 模型eds-utility/src/.../domian/ClientTradePnl.java
客户 P&L 服务eds-utility/src/.../service/ClientTradePnlService.java
客户登录 Prototradedesign/gateway/msg/MsgClientLogin.proto
客户信息 Prototradedesign/gateway/msg/MsgGwClientInfo.proto
客户信息 Proto (app)tradedesignapp/gateway/msg/MsgGwClientInfo.proto

业务影响: 客户上线是系统流程和人工流程的混合体。系统管了客户主数据和信用额度,但 KYC 在外部系统、ISDA 谈判在 Word 文档里、客户门户不存在。1.5 个全职人力花在回答客户问题上——这是一笔可以自动化但未被优先考虑的成本。