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

Protocol Registry

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

ODTS-49: tradedesign — Protobuf 协议中心(约 6.5 年,15,014 commits 的消息总线枢纽)

目标读者:需要理解 CICC OTC 衍生品系统 37 个以上子系统如何通过 Protobuf 协议通信的 BA/PM

数据来源:git 历史(15,014 commits, 230 authors, 1,709 proto 文件, 2015-09-17 → 2022-04-06 停滞)

核心开发者(按提交数):chenkun (682), Yuping Ai (632), Shaonan Cheng (462), Ou Zhao (348), wangyh3 (249)


业务问题

35+ 个子系统如何知道彼此的存在?当一个系统要查找一笔交易的信息时,它怎么知道该调用什么接口、传入什么参数、得到什么格式的响应?

答案是一个集中式的协议注册中心(Protocol Registry)。这不是一个运行时服务(没有进程、没有部署),而是一个被所有项目引用的 JAR 包,包含了整个 CICC OTC 衍生品生态系统中每个服务之间通信所使用的全部 Protobuf 消息定义。

这就是 tradedesign 项目。它的 15,014 次提交和 1,709 个 .proto 文件定义了 37 个子系统之间的全部通信契约。


Tradedesign 概览

tradedesign/

├── PbMessageEnum.proto          ← 全局消息类型枚举(381 行)
├── PbMessageHead.*              ← 37 个子系统的消息头文件

├── bookingAs/                   ← 簿记系统协议(50+ 子域)
├── hedgingAs/                   ← 对冲/定价系统协议
├── trade/                       ← 交易系统协议
├── gwmsAdm/                     ← GWMS 管理协议
├── gwmsIc/                      ← GWMS IC 协议
├── gwmsWm/                      ← GWMS 财富管理协议
├── gwmsUser/                    ← GWMS 用户协议
├── interBank/                   ← 银行间协议
├── mm/                          ← 做市商(Market Maker)协议
├── sacAS/                       ← SAC 监管报送协议
├── ta/                          ← 交易助理(Trade Assistant)协议
├── web/                         ← Web 前端协议
├── pricingAS/                   ← 定价服务协议
├── gateway/                     ← 网关协议
├── reck/                        ← 结算核对(Reckoning)协议
├── ac/                          ← 账户协议
├── seCustom/                    ← 策略引擎自定义协议
├── util/                        ← 工具层协议
├── dataCenter/                  ← 数据中心协议
└── resources/                   ← 资源文件

两种视角看 tradedesign

视角一:编译期依赖。所有 Java 项目(eds-web-app、hedging-as、sac-report、eds-price-server 等)在 pom.xmlbuild.gradle 中依赖 tradedesign 的 JAR 包。Proto 文件被编译为 Java 类,所有服务的 request/response 对象都来自同一个来源。

视角二:运行时不存在。Tradedesign 不是一个服务。没有 tradedesign 进程在运行。它只是一个定义。实际的通信走 Netty TCP、HTTP REST 或文件,但消息的**形状(shape)**由 tradedesign 定义。


沟通模型:Message 信封

整个体系的通信统一使用一个 Message Proto 信封:

message Message {
    required MSG   msgType = 1;    // 消息类型(是查询还是响应?)
    required int32 msgMode = 2;    // 消息模式(0=查询, 1=响应)
    required string sequence = 3;  // 消息序列号(请求-响应配对)
    required string sessionId = 4; // 会话 ID
    optional Notification notification = 7;
    optional string gatewayId = 8;
    optional string userId = 9;
    // ...
}

每个子系统有自己的 PbMessageHead.* 文件,通过 import 机制引入各自需要的 Proto 文件,然后在 Message 信封的 notification 字段中承载具体的业务消息。

MSG 枚举分配了每个子系统的消息号空间:

子系统Msg 起始说明
Notification1000通用通知
Util10000工具类消息
Trade20000交易系统
MarketMaker21000做市商
Gateway30000网关
Reck40000结算核对
Web50000Web 前端
GwmsAdm60000GWMS 管理
GwmsIc60001GWMS IC
GwmsWm60002GWMS 财富管理
GwmsUser60003GWMS 用户
Ta60005交易助理

每个子系统在自己的消息号空间内定义具体的消息类型(如 Trade_Msg_OpenPositionGateway_Msg_Login),避免了跨系统的消息 ID 冲突。


37 个子系统协议

每个 PbMessageHead.* 文件对应一个子系统,定义了该子系统使用的全部消息类型:

Head 文件子系统协议内容
1webApp新一代 Web 应用new-edsweb 使用的 API
acApp账户应用账户管理的 App 端
acWeb账户 Web账户管理 Web
acct会计会计分录、科目
algo算法交易算法交易指令
bookingAs簿记系统核心 OTC 簿记(详见下节)
ciccQuantAS量化平台CICC 量化分析服务
comm-agw商品网关大宗商品系统桥接
core核心跨系统共用功能
edsAppEDS 应用主后端 eds-web-app
gui桌面 GUI交易员桌面客户端
gui.odtsOTC GUIOTC 专用桌面客户端
gw通用网关通用网关协议
gwms财富管理GWMS 主协议
gwmsAdmGWMS 管理产品、费用、审核
gwmsIcGWMS IC内部管控
gwmsUserGWMS 用户用户管理
gwmsWmGWMS 财富财富管理业务
hedgingAS对冲系统定价、对冲、风险(hedging-as)
hk香港香港业务专属
interBank银行间银行间市场
interbankGW银行间网关银行间桥接
login登录统一认证
marketMaker做市商做市报价、成交
mmgui做市 GUI做市桌面客户端
priceServer定价服务独立定价服务(eds-price-server)
pricingAS定价服务(新)新一代定价应用
reckReckoning结算核对(EOD批量中的对账)
riskEngine风险引擎风险计算
sacAsWebSAC 报送监管报送 Web
se策略引擎策略执行引擎
strategyEngine策略引擎策略定义和执行
ta交易助理交易辅助功能
trade交易核心交易协议
util工具通用基础协议
webWeb 前端通用 Web 协议

BookingAs:OTC 核心域模型(50+ 子域)

bookingAs/ 是 tradedesign 中最大的协议集合,定义了 OTC 衍生品簿记系统的全部业务对象。它与 hedging-as 系统的 com.cicc.hedging.contract.* Java 类一一对应。

bookingAs/
├── accountsubject/    ← 会计科目
├── ams/               ← 资产管理
├── bank/              ← 银行信息
├── cashmovement/      ← 资金变动
├── clientVersion/     ← 客户端版本
├── confirmation/      ← 交易确认书
├── contract/          ← 合约(核心!36 个 proto 文件)
├── contractMargin/    ← 合约保证金
├── contractSettle/    ← 合约结算
├── contractevent/     ← 合约事件(分红、行权等)
├── corpration/        ← 公司信息
├── counterPartyId/    ← 对手方 ID 管理
├── counterparty/      ← 对手方
├── currency/          ← 币种
├── deskEntity/        ← 交易台实体
├── dividendRate/      ← 股息率
├── dynamic/           ← 动态属性
├── element/           ← EAV 元素定义
├── employee/          ← 员工
├── eod/               ← EOD 数据
├── event/             ← 权益事件
├── futureInfo/        ← 期货信息
├── global/            ← 全局配置
├── historyTrade/      ← 历史交易
├── instrument/        ← 标的物
├── interestRate/      ← 利率
├── model/             ← 定价模型
├── netAsset/          ← 净资产
├── netPosition/       ← 净持仓
├── netValue/          ← 净值
├── nqaIndexContract/  ← NQA 指数合约
├── paramShift/        ← 参数偏移
├── parameter/         ← 参数
├── pricingModel/      ← 定价模型参数
├── product/           ← 产品
├── productLine/       ← 产品线
├── reckoning/         ← 对账
├── refresh/           ← 刷新
├── report/            ← 报表
├── risk/              ← 风险
├── status/            ← 状态
├── tagMgt/            ← 标签管理
├── template/          ← 模板
├── todayTrade/        ← 当日交易
├── tradeaccount/      ← 交易账户
├── underlying/        ← 标的物管理
├── underlyingApply/   ← 标的物申请
├── underlyingControl/ ← 标的物控制
├── user/              ← 用户
├── volatility/        ← 波动率

这 50+ 个子域映射了 CICC OTC 系统的完整领域模型。每个子域包含若干 Bean*.proto(数据对象)和 Msg*.proto(请求/响应消息)。例如 contract/ 下有 BeanContract.proto(合约数据)、MsgContract.proto(合约请求/响应)、MsgContractAudit.proto(合约审核)等。


按模块分布的 Proto 文件量

trade/order/                     136  ← 交易指令(最大模块)
hedgingAs/contract/               77  ← 对冲合约
trade/query/                      73  ← 交易查询
gateway/msg/                      57  ← 网关消息
util/bean/                        44  ← 工具数据对象
gwmsAdm/ofs/                      44  ← GWMS 开放式基金
util/msg/                         42  ← 工具消息
web/product/                      40  ← Web 产品
web/risk/                         37  ← Web 风控
gwmsWm/msg/                       37  ← GWMS 财富消息
hedgingAs/quotation/              36  ← 对冲报价
bookingAs/contract/               36  ← 簿记合约
hedgingAs/position/               28  ← 对冲持仓
bookingAs/volatility/             27  ← 簿记波动率
web/nav/                          26  ← Web 净值
interBank/query/                  26  ← 银行间查询
bookingAs/risk/                   26  ← 簿记风控

Total: 1,709 个 Proto 文件


跨系统消息流示例:一笔交易的生命周期

以一笔雪球期权交易为例,展示 tradedesign 如何协调 7 个子系统的通信:

交易员敲入交易


[1] web/product       ← 交易员在前端选择产品类型
    │                    (MsgGetProductAssesment, MsgGetBusinessFee)

[2] bookingAs/contract ← 簿记系统创建合约
    │                    (MsgContract → BeanContract)

[3] hedgingAs/contract ← 对冲系统接收合约,计算 Greeks
    │                    (BeanContract → MsgCalHedgeTrade)

[4] hedgingAs/quotation ← 生成报价
    │                     (MsgQuotationNew, BeanQuotation)

[5] trade/order        ← 确认成交
    │                    (MsgOpenPosition)

[6] bookingAs/confirmation ← 生成确认书
    │                        (MsgConfirmation)

[7] gateway/msg        ← 通过网关发送给 IMS
                         (Gateway_Msg_Contract → IMS)

每一步的消息结构都由 tradedesign 中的 Proto 文件定义。这意味着没有”接口文档过期”的问题——消息定义本身就是文档,代码自动从 Proto 编译生成,永远不会与运行时不一致。


Gateway 层:跨系统的消息路由器

gateway/ 目录定义了 57 个网关协议,是整个系统的”神经系统”:

gateway/msg/           ← 网关消息(57 个 proto 文件)
    ├── MsgLogin.proto          ← 登录请求
    ├── MsgHeartbeat.proto      ← 心跳
    ├── MsgSubscribe.proto      ← 订阅行情
    ├── MsgUnsubscribe.proto    ← 取消订阅
    ├── Gateway_Msg_Contract.proto  ← 合约转发(→ IMS)
    ├── Gateway_Msg_Trade.proto     ← 交易指令转发
    └── ...

Gateway 的作用:

  • 协议转换:将 Protobuf 消息转换为 IMS(Investment Management System)能理解的格式
  • 路由分发:根据消息类型,将请求转发到正确的后端系统
  • 会话管理:维护客户端到后端的长连接
  • 流控:控制消息发送速率(做市商场景下尤其重要)

Gateway 消息类型(从 PbMessageEnum 推断):

  • Gateway_Msg_Login — 认证登录
  • Gateway_Msg_Subscribe — 订阅行情
  • Gateway_Msg_Contract — 合约信息同步
  • Gateway_Msg_Trade — 交易指令
  • Gateway_Msg_HeartBeat — 心跳维持
  • Gateway_Msg_Knock — 成交回报
  • Gateway_Msg_Quotation — 行情推送

为什么有 15,014 次提交?

从 git 历史看,tradedesign 与实现系统几乎是同期启动的:它的第一个提交在 2015-09-17,比主后端 eds-web-app(2016-12-28)早约 15 个月,比定价引擎 eds-price-server(2016-12-21)早约 1 年。提交峰值在 2017-2019 年(每年超过 1,500 次),然后逐步下降。它并不是”比实现早 6 年”的超前规划,而是在系统从 Excel/原型走向多子系统架构的同一时期,同步生长出来的协议中枢。

原因一:协议定义先行。tradedesign 是整个系统的”先有接口,后有实现”策略的产物。 每次新功能开发的第一步,就是在这里定义 Proto 消息。然后各自实现方(前端、后端、网关)根据同样的 Proto 定义开发。这保证了各方对接口的理解一致。tradedesign 在 2015 年起步,eds-web-app / eds-price-server 在 2016 年底跟进——协议定义比首批实现早约一年,为后续 37 个子系统的接入铺好了地基。

原因二:跨团队协作。 每个团队修改自己负责子系统的 Proto 文件时都会产生一次提交。37 个子系统、70+ 位开发者的修改汇聚于此。当 chenkun(682 次提交,最多产的贡献者)修改一个合约字段时,可能触发了 bookingAs、hedgingAs、gwms 三个团队的上下游联动,产生 5-10 次往返提交。

原因三:生成的 Java 类也在这个 repo 里。 Proto 文件编译后的 Java 类(com/framework/protobuf/)直接提交到了版本控制中。这意味着每次修改 proto → 重新编译 → 提交生成代码,双倍提交。


为什么它停更了?

Tradedesign 在 2022 年初之后不再有新提交。原因是:

直接原因:Protobuf 不再主导新开发。 2022 年之后的新系统(odyssey report-processing-service、new-edsweb)不再使用 tradedesign 的 Protobuf 协议。它们使用 REST API(JSON)或 Kafka 消息队列,消息格式在各自项目中定义,不再需要集中的协议注册中心。

业务原因:开发范式转变。 2015-2022 年的系统(hedging-as、eds-web-app)依赖 Netty TCP + Protobuf 进行跨进程通信,因此需要集中的协议定义。2022 年之后,HTTP REST + JSON 成为新服务的标准通信方式,协议定义从”集中的 Proto 文件”变成了 “各自 Swagger/OpenAPI 文档”。

遗留效果: tradedesign 作为历史存档仍然宝贵——它记录了 2015-2022 年间 CICC OTC 系统的全部接口契约。如果未来需要理解某个遗留消息的格式,tradedesign 是唯一的权威来源。


业务启示

Tradedesign 的故事告诉读者三件事:

第一,集中式协议注册中心是大型金融系统的常见模式。 当系统数量超过 5 个时,分散的接口文档会让集成变成噩梦。CICC 选择了 Protobuf + 集中式协议仓库作为解决方案,这与 Google 内部的做法一致(Google 的所有 RPC 接口定义都在一个中央仓库中)。

第二,协议定义先行(contract-first)的开发模式在 2015 年是领先的。 今天这种模式叫 “API-first” 或 “Schema-first”(OpenAPI/AsyncAPI),但在 2015 年前后使用 Protobuf 集中定义所有接口,仍然是一个早于行业普遍采用(大多在 2018 年之后)的选择。

第三,架构迁移的代价在协议层最明显。 2022 年转向 REST + JSON 意味着 tradedesign 被废弃——但这不是一个简单的决定。因为现有的 Protobuf 消息格式已经嵌入了约 7 年的业务逻辑。迁移到新协议意味着重写所有消息格式,而不仅仅是换一个序列化框架。

Tradedesign 是一个”看不见”的系统——没有进程、没有部署、没有告警——但它在约 6.5 年间(2015-2022)定义了 37 个子系统之间的全部通信契约。它是 CICC OTC 生态系统的”宪法”,规定了每个系统如何与邻居对话。15,014 次提交的积累最终在 2022 年被 REST API 取代,但它留下的 1,709 个 Proto 文件仍然是理解这个系统架构的最好入口。