Trade Lifecycle Code Map
ODTS-33: Trade Lifecycle Code Map(基于 CICC 真实代码库)
目标读者:需要阅读 CICC OTC 衍生品系统代码的 BA/PM
前置阅读:ODTS-01 产品体系, ODTS-31 合同运营
本文定位:这是一份代码地图,不是功能列表。它回答的是”这段代码在哪个文件、哪个类里、表长什么样”。
1. 什么是代码地图
CICC(中金公司)的 OTC 衍生品系统是一个 10+ 年演进的庞然大物。两个世代并存:
- odts1(一代):Struts2 + Spring Boot 混合,单体应用
- odyssey(二代):Spring Boot 微服务 + Vue.js,逐步替代一代
对于一个 BA/PM 来说,最大的障碍不是业务概念——而是你知道业务上应该有个逻辑,但不知道那坨逻辑在代码的哪个角落里。
本文按交易生命周期组织代码路径,让你能快速定位。
2. 系统顶层架构
┌─────────────────────────────────────────────────────────────┐
│ FRONTEND (Vue.js) │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌─────────┐ │
│ │ eds-rm-web │ │ odts- │ │ odyssey- │ │ odts- │ │
│ │ (Risk Mgt) │ │ option-web │ │ swap-web │ │linear-web│ │
│ └──────┬─────┘ └─────┬──────┘ └─────┬──────┘ └────┬────┘ │
└─────────┼──────────────┼──────────────┼──────────────┼───────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ BACKEND (Java, 多个独立进程) │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ eds-web-app (主后端, ~4000 Java 文件) │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ edsBoot/ │ │ action/ │ │ service/ │ │sblbooking│ │ │
│ │ │(Spring) │ │(Struts2) │ │(Spring) │ │ (SBL) │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
│ └────────────────────────────────────────────────────────┘ │
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ hedging-as │ │ eds-price- │ │ sac-report │ │
│ │ (对冲+风控) │ │ server │ │ (监管报送) │ │
│ └─────────────┘ └──────────────┘ └──────────────────┘ │
│ ┌─────────────┐ │
│ │ eva-master │ (Python, Prometheus 监控 + Oracle SQL) │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ DATA + MESSAGING │
│ Oracle DB │ ActiveMQ │ Kafka │ Redis │ DolphinDB │ Protobuf│
└─────────────────────────────────────────────────────────────┘
二代微服务(~/odyssey/):正在逐步从 odts1 迁移出来
odyssey-option-web/odyssey-swap-web/odts-linear-web:Vue 前端odyssey-quotation-service:二代报价服务odyssey-cash-manager-service:二代资金管理odyssey-report-processing-service:二代报表处理odyssey-internal-gateway:二代网关ciccchecker:合规检查
3. 核心数据模型
理解 CICC 系统的关键在于理解它的字段编码体系。
3.1 EdsSubContract——你的数据入口
这是整个系统最核心的数据模型。文件路径:
~/odts1/eds-web-app/src/com/cicc/action/dynamic/model/EdsSubContractDBModel.java
它有 80+ 个字段,每个业务字段都带一个 E编码。这个编码对应数据字典 EDS_ELEMENTDICT 中的一条记录。例如:
| 字段名 | 编码 | 含义 | 示例值 |
|---|---|---|---|
contractname_e000024 | E000024 | 合约名称 | ”XQQ 1M TRS” |
contractstatus_e000025 | E000025 | 合约状态 | NEW / OPEN / EXPIRED |
tradeaccount_e000026 | E000026 | 交易账户 ID | ”TA001234” |
product_e000027 | E000027 | 产品类型 | ”2”=TRS, “4”=RISKY, “5”=RHEG |
bsflag_e000029 | E000029 | 买卖方向 | B=Buy, S=Sell |
tradedate_e000034 | E000034 | 交易日 | 20250115 |
observationenddate_e000035 | E000035 | 观察结束日/到期日 | 20260115 |
initquantity_e000113 | E000113 | 期初数量/名义本金 | 1000000 |
bookdate_e000114 | E000114 | 记账日 | 20250115 |
settledate_e000169 | E000169 | 结算日 | 20250117 |
TRS 专属字段(E02 开头):
| 字段名 | 编码 | 含义 |
|---|---|---|
needpricingpbtrs_e020001 | E020001 | 是否需要定价 |
pricepbtrs_e020002 | E020002 | 定价 |
currencypbtrs_e020003 | E020003 | 币种 |
initnppbtrs_e020008 | E020008 | 期初名义本金 |
interestindexpbtrs_e020010 | E020010 | 利率指数 (如 SHIBOR) |
interestindexratepbtrs_e020011 | E020011 | 利率费率 |
interestbpspbtrs_e020012 | E020012 | 利率基点 (BPS) |
initialmarginrtpbtrs_e020014 | E020014 | 初始保证金率 |
mtcmarginratio1pbtrs_e020015 | E020015 | MTC 保证金率 1 |
mtcmarginratio2pbtrs_e020016 | E020016 | MTC 保证金率 2 |
标的物字段:
| 字段名 | 编码 | 含义 |
|---|---|---|
slunderlyingid_e010001 | E010001 | 标的物 ID (股票代码) |
leftquantity_e010007 | E010007 | 剩余数量 |
accrualdays_e010010 | E010010 | 计息天数 |
解约相关:
| 字段名 | 含义 |
|---|---|
unwindtext_e020020 | 解约文本 |
unwindintrule_e020021 | 解约利息规则 |
unwindhedgetool_e020022 | 解约对冲工具 |
ptya_unwind_comm_in | A方解约佣金(入) |
ptya_unwind_comm_out | A方解约佣金(出) |
ptyb_unwind_comm_in | B方解约佣金(入) |
产品类型映射(代码中硬编码):
product_e000027 = "2" → contractType = "TRS"
product_e000027 = "4" → contractType = "RISKY"
product_e000027 = "5" → contractType = "RISKY_HEDGE"
3.2 为什么用 EAV——flexible schema
CICC 不把合约字段展开成表列,而是用 EAV 模式:
EDS_CONTRACTELEMENTVALUEEOD 表:
contractId | elementId | elementValue | isModifiable | isVisible
---------------------------------------------------------------
C001 | E000024 | "XQQ TRS" | Y | Y
C001 | E000025 | "OPEN" | N | Y
C001 | E000027 | "2" | N | Y
代码中的 Java 模型 EdsSubContractDBModel 则是这个 EAV 表的一行宽表映射——把 80+ 个 element 拉平成 Java 字段。两种方式都存在:
action/dynamic/model/EdsContractContext/EdsContract.java+EdsContractElementValue.java:EAV 方式,用于模板渲染action/dynamic/model/EdsSubContractDBModel.java:宽表快照,用于业务逻辑
这就是为什么你会看到有些代码读 EDS_CONTRACTELEMENTVALUEEOD 表、有些代码直接用 EdsSubContractDBModel。
3.3 EdsSubRequest——合约事件请求
~/odts1/eds-web-app/src/com/cicc/action/dynamic/model/EdsSubRequestDBModel.java
每个合约可以关联多个”事件请求”,由 contractEventId 区分:
CE202:一种事件类型(如敲出/分红)CE203:另一种事件类型
一个 EdsSubContractDBModel 持有一个 requestMap:
HashMap<String, HashMap<String, EdsSubRequestDBModel>> requestMap
// key=contractEventId → key=hedgetradeid → request
请求字段包括:
quantitydelta_e010101:数量变化(对冲交易量)initialmargin_e020401:初始保证金变化commission_e020402:佣金exchangefee_e020403:交易所费用dividendamt_e020411:分红金额fixingrate_e020415:Fixing 利率hedgetradeid_e020417:关联的对冲交易 IDrealizedcommcalccy/realizedcommsettccy:已实现佣金realizedannualfeecalccy/realizedannualfeesettccy:已实现年费
3.4 Contract(旧模型)
~/odts1/eds-web-app/src/com/cicc/action/contract/model/Contract.java
这是一个较早的合约模型,与 EdsSubContractDBModel 是两套体系,存在于不同历史阶段。它的字段不带 E 编码,命名风格也不同:
tradeDate, type, clientDentifier, underlyingFullTicker, stkid, exchid,
quantity, price, amount, feeFlag, initQuantity, PNL, isDividendStock,
status, contractName, templateId, productId, bsFlag, leftQuantity, ...
注意这个模型有 PNL 字段(盈亏),在 EdsSubContractDBModel 中不存在。这个模型中的 underlyingId 和 stkid 可以关联到 EdsSubContract 中的 slunderlyingid_e010001。
4. 核心产品类型的代码路径
定价引擎中有 30+ 种结构类型,以下是最核心的几种及对应的代码位置。
TRS(Total Return Swap, productId=2)
系统中最核心的产品线。代码路径:
| 活动 | 代码位置 |
|---|---|
| TRS 定价 | ~/odts1/eds-price-server/src/com/cicc/priceserver/pricingengine/ → PricingEngine.java 中 productId=“2” 的 switch branch |
| TRS 合约创建 | edsBoot/controller/ContractController.java + PbTrsContractGroupController.java |
| TRS 保证金 | ~hedging-as/src/com/cicc/pricingengine/ → QuotationMarginServiceImpl.java |
| TRS 日终清算 | eds-web-app/src/com/cicc/sblbooking/service/InterestEodService.java |
| TRS 利率计算 | 通过 interestindexpbtrs_e020010 (SHIBOR/FR007) + interestbpspbtrs_e020012 (基点) |
| TRS 合约组 | pbtrscontractgroup_e020024 字段关联到 PbTrsContractGroup 模型 |
| AB股交易 | action/dynamic/model/newAB/ 下的 ABTradeBean, NewABContractBean 等 |
典型字段值:
product_e000027 = "2"
contractType = "TRS"
interestindexpbtrs_e020010 = "SHIBOR 3M" 或 "FR007"
interestbpspbtrs_e020012 = "100" (即 +1.00%)
Risky Structure(雪球, productId=4)
| 活动 | 代码位置 |
|---|---|
| 雪球定价 | PricingEngine → 结构类型 switch: RISKY, ACPS, ZCC, BR, DSF, SF, PPDSF 等 |
| 敲出事件 | action/equityevents/ + EdsSubRequestDBModel 中的 CE202/CE203 事件 |
| 观察日逻辑 | action/dynamic/model/ 下的观察日期逻辑 |
在 PricingEngine 中支持的结构类型列表(所有能在代码中看到的):
VAN(普通香草), ACPS(自动赎回), CPS, ZCC(雪球), BR(保本),
RISKREVESAL, BUTTERFLY, STD(标准), DIG(二元), SF, DSF,
STEP, STEP2, IPP, SPP, SPPF, RISKY(雪球), IPKSFSF, IPKVANSF,
LOAN, TRS, ETRS, PPSF, PPDSF, NPP, BR3, FCPS, CLQ(经典),
RA, REP, OT, ASIAN(亚式), ESF, CCSF, DCCS, STP, IDP, DCCSP
这些类型对应 PricingEngine 中的 StructuredProduct 子类:
VANValue→ 香草SPPValue→ 雪球TRSValue→ TRS- 等
RHEG(Range Hedge, productId=5)
product_e000027 = "5"
contractType = "RISKY_HEDGE"
5. EOD(End of Day)批处理
EDS 系统有大量的 EOD 批处理任务,集中在 edsBoot/ 包中:
~/odts1/eds-web-app/src/com/cicc/edsBoot/
├── consumer/ → ActiveMQ/Kafka 消费者(异步 EOD 任务)
│ ├── book/ → 簿记消费者
│ ├── order/ → 订单消费者 (含 PbContractTypeEnum)
│ └── trade/ → 交易消费者
├── controller/ → REST API(EDS 的主要后端入口)
│ ├── contract/ → 合约相关
│ ├── risk/ → 风控(含 OptiverFileUploadController)
│ ├── newab/ → A/B 股交易
│ ├── etf/ → ETF
│ └── equityevents/ → 权益事件
├── service/
│ ├── OptionExecutionService.java → 期权行权
│ ├── OptionSubscribeService.java → 期权认购
│ ├── HedgeTradeService.java → 对冲交易生成
│ ├── PreBookService.java → 预记账
│ ├── ClosePriceService.java → 收盘价
│ ├── RiskService.java → 风控规则
│ └── margin/ → 保证金服务
├── model/
│ ├── optionExecution/
│ ├── profit/
│ └── margin/enums/ProductType.java
├── mapper/ → MyBatis Mapper
└── resource/mapper/ → XML Mapper
5.1 利息 EOD(InterestEodService)
~/odts1/eds-web-app/src/com/cicc/sblbooking/service/InterestEodService.java
处理 TRS 产品的利息日终。方法:
| 方法 | 用途 |
|---|---|
dealInterestEod() | 主利息 EOD 处理 |
dealPbriskEod() | PB 风险 EOD |
dealCatsEod() | CATS EOD |
dealPbriskEodByReckTimes() | 按清算次数处理 PB 风险 |
清算次数(reckTimes)是 EDS 的一个核心概念——一笔业务可能分多次清算。
5.2 清算(Reckoning)
~/odts1/eds-web-app/src/com/cicc/action/dynamic/reckoning/
~/odts1/eds-web-app/src/com/cicc/reckoning/
~/odts1/eds-web-app/src/com/cicc/edsBoot/controller/ReckoningController.java
EdsReckoningUtils.java:清算工具类(含getPrevSysTradeDate)- 清算流程包括:预记账 → 正式清算 → 结算
5.3 Optiver 集成
~/odts1/eds-web-app/src/com/cicc/edsBoot/controller/risk/OptiverFileUploadController.java
~/odts1/eds-web-app/src/com/cicc/edsBoot/service/OptiverFileUploadServiceImpl.java
Optiver 是一家知名的全球做市商/高频交易公司。CICC 与 Optiver 之间通过 SFTP 批量交换文件:
| 接口 | 用途 |
|---|---|
/Optiver/Valuation/upload | 上传估值文件给 Optiver |
/Optiver/riskMargin/upload | 上传风控保证金文件 |
/Optiver/limitUnderlying/upload | 上传限售股清单 |
/Optiver/upload/file | 上传清算文件 |
/Optiver/upload/reckoningFile | 上传 CSDC(中登公司)清算文件 |
这意味着 CICC 可能与 Optiver 有 OTC 衍生品交易对手关系,通过批处理文件交换估值和风控数据。
6. 对冲引擎(hedging-as)
~/odts1/hedging-as/
这是一个独立的 Java 应用服务器,启动入口 HedgingAS.java。启动顺序揭示了它的模块结构:
1. QuotationService → 报价服务
2. GatewaySessionManager → 网关会话(Protobuf RPC)
3. HedgingRpcService → 对冲 RPC 服务
4. BookingService → 簿记服务
5. ActiveMQ (HedgingEntry) → 消息队列消费者
6. QuotationInfoCache → 行情缓存
7. PythonApplicationManager → Python 估值集成
8. ContractStateMachineManager → 合约状态机
9. QuotationMarginService → 报价保证金
10. UnderlyingValuePool → 标的值池
11. JFinal Web Server → 嵌入式 HTTP 服务
核心组件:
| 模块 | 用途 |
|---|---|
QuotationService | 实时报价生成 |
HedgingRpcService | 对冲交易 RPC 接口 |
ContractStateMachineManager | 合约状态转换(NEW→OPEN→EXPIRED…) |
QuotationMarginServiceImpl | 保证金计算 |
PythonApplicationManager | 调用 Python 估值模型 |
UnderlyingValuePool | 基础标的值缓存 |
QuotationInfoCache | 行情缓存 |
BaseRiskCheckControl | 基础风控检查 |
合约状态(来自 ContractStatus.java):
PRETRADE → NEW → OPEN → EXPIRED
7. 定价引擎(eds-price-server)
~/odts1/eds-price-server/src/com/cicc/priceserver/
├── pricingengine/
│ ├── PricingEngine.java → 主入口
│ └── StructuredProduct/ → 各种产品定价模型
├── gpricingengine/pricing/
│ └── GPricingEngine.java → Greeks 计算引擎
├── webservice/ → SOAP Web 服务
└── cache/ → 缓存
PricingEngine.java 有两个用途:
- 定价(Pricing):实时报价,返回 Premium
- 估值(Valuation):盘中/盘后计算 NPV
输出指标(Greeks):
OptionNPV | DeltaNPV | GammaNPV | ThetaNPV | VegaNPV | RhoNPV | PremiumNPV | TotalNPV
定价引擎在 hedging-as 中有一个 SOAP Web Service 接口:
Endpoint: http://10.110.224.205:9091/PricingEngine?wsdl
用途:IRS curve pricing, 摊销 IRS pricing
8. 监管报送(sac-report)
~/odts1/sac-report/
├── src/SacReportAs.java → 主入口
├── src/com/cicc/report/
│ ├── SacReportUtil.java
│ └── ...
└── ...
启动入口 SacReportAs.java 启动一个独立的 Process,包含:
SacReportUtil.sacReportInitStart():初始化报送引擎- 支持 SAC/ISDA/NAFMII 三大协议体系的报告格式
- 前端 ProtoBuf 服务器(
ProtoBufServerForFrontAccess)用于前台访问 - 20 线程池处理 ACP 消息
- 嵌入式 Spring Boot Web
代码路径 action/web/dao/sacreport/model/ 下包含三个子目录:
module/sac/:SAC 模板(中国证券业协会)module/isda/:ISDA 模板(国际)module/nafmii/:NAFMII 模板(中国银行间市场交易商协会)
9. EVA 监控平台(Python)
~/odts1/eva-master/
├── run.py → Prometheus metrics server (port 5000)
├── service/
│ ├── odts.py → 核心 Oracle SQL 查询
│ ├── health.py → 健康检查
│ └── git.py → Git 信息
├── lib/
│ ├── routing.py
│ └── singlepattern.py
└── config/
EVA 监控的是运营和业务状态,不是技术监控。它的 odts.py 中的 Oracle SQL 查询回答了这些问题:
| 查询 | 含义 |
|---|---|
| Notional by currency | 各币种名义本金 |
| Counterparty count history | 交易对手数量变化 |
| Trade account stats | 交易账户统计 |
| Primary & secondary reckoning progress | 一次/二次清算进度 |
| Linear PB totals & trends | 线性 PB 总量和趋势 |
| Non-linear option structure breakdown | 期权结构分类统计 |
| Valuation table generation monitoring | 估值表生成监控 |
| Event processing dashboard | 事件处理仪表盘 |
| Business operation flow | 业务操作流程 |
10. 前端架构
一代前端(odts1)
eds-rm-web(风险管理):
src/views/
├── risk-management/ → 风控 (control, counterparty, var, rate, sbl, template...)
├── margin-manage/ → 保证金 (margin-call, pre-margin-call, control-detail...)
├── hedge-monitor/ → 对冲监控
├── stress-testing/ → 压力测试
└── home/ → 仪表盘
odts-option-web(期权交易):只有 home/ 目录(可能是更老的应用)
二代前端(odyssey)
odts-linear-web(线性产品,最完整的二代前端,27 个模块):
src/views/pages/
├── trade/ → 交易管理 (HedgeTrade, RealTimeTrades)
├── contract/ → 合约管理
├── reckoning/ → 清算
├── riskMgt/ → 风险管理
├── eod/ → 日终
├── ValuationMgt/ → 估值管理
├── account/ → 账户管理
├── positon/ → 持仓(注意拼写是 positon 不是 position)
├── recon/ → 对账
├── dma/ → 直接市场接入
├── pks/ → PKS 集成
├── equity/ → 权益事件
├── gma/ → GMA
├── dayTrading/ → 日内交易
├── reportMgt/ → 报告管理
├── sbl/ → 证券借贷
├── pbContractFile/ → PB 合约文件
├── underlying/ → 标的物管理
└── idx/ → 指数
odyssey-option-web:期权(新,只有 home) odyssey-swap-web:互换(新,交易+合约+help+user)
11. 生命周期到代码的映射
阶段 一代代码 二代代码
────────────────────────────────────────────────────────────────────────────────────
定价/报价 eds-price-server/ quotation-service
hedging-as/QuotationService
交易录入 edsBoot/controller/ContractController odts-linear-web/trade/
edsBoot/controller/newab/NewABTradeController
合约创建 action/contract/model/Contract.java odts-linear-web/contract/
action/dynamic/model/EdsSubContractDBModel.java
事件管理 EdsSubRequestDBModel (CE202/CE203) odts-linear-web/equity/
action/equityevents/
盘中对冲 hedging-as/HedgingRpcService
edsBoot/service/HedgeTradeService
估值/Pricing eds-price-server/PricingEngine odts-linear-web/ValuationMgt/
hedging-as/PythonApplicationManager
保证金 hedging-as/QuotationMarginService odts-linear-web/riskMgt/
eds-rm-web/margin-manage/
日终(EOD) sblbooking/InterestEodService odts-linear-web/eod/
edsBoot/consumer/order/
清算 reckoning/ReckoningController odts-linear-web/reckoning/
sblbooking/service/InterestEodService
结算 edsBoot/controller/PBContractFileGenerate
action/web/contractSettle/
监管报送 sac-report/ odyssey-report-processing-service/
action/sacReport/
风控 eds-rm-web/risk-management/ odts-linear-web/riskMgt/
hedging-as/BaseRiskCheckControl
运营监控 eva-master/ (Python + Prometheus) (无)
12. 如何快速定位代码
场景 1:找到某个合约的字段在哪里用
- 字段名里有 E 编码的 → 搜索
_eXXXXXX。如_e020001在 NeedsPricingPBtrs 中使用 - 字段名没有编码的 → 搜索字段名(如
underlyingProperty) - EAV 模式存储的 → 搜索
EDS_CONTRACTELEMENTVALUEEOD
场景 2:理解一个 API 端点的处理流程
- 在
edsBoot/controller/下找到对应的 Controller - 查看它调用了哪个 Service(在
edsBoot/service/下) - Service 通常会调用 MyBatis Mapper(在
edsBoot/mapper/下) - Mapper 的 SQL 在
edsBoot/resource/mapper/下的 XML 文件中
场景 3:区分一代和二代的代码
com.cicc.action.*→ Struts2(一代,逐渐淘汰)com.cicc.edsBoot.*→ Spring Boot(一代后期,当前主力)~/odyssey/*→ 二代微服务(新开发)
场景 4:找到产品的定价逻辑
- 从合约的
product_e000027确定产品类型(“2”/“4”/“5”) - 去
eds-price-server/下找 PricingEngine 中对应的 switch case - 对应的
StructuredProduct子类实现具体的定价模型
13. 一些你需要知道的缩写
| 缩写 | 全称 | 含义 |
|---|---|---|
| EDS | Equity Derivatives System | 股权衍生品系统 |
| SBL | Securities Borrowing and Lending | 证券借贷 |
| PB | Prime Brokerage | 主经纪商 |
| TRS | Total Return Swap | 总收益互换 |
| RHEG | Range Hedge | 区间保本 |
| ACA | Automatic Callable | 自动赎回结构(雪球) |
| MTC | Mark-to-Call / Margin to Cover | 追保 |
| NPP | Net Present Principal | 净名义本金 |
| BPS | Basis Points | 基点 (1bp = 0.01%) |
| EOD | End of Day | 日终批处理 |
| SAC | Securities Association of China | 中国证券业协会 |
| CSDC | China Securities Depository and Clearing | 中登公司 |
| ACP | Application Communication Protocol | 应用通信协议 |
| OMS | Order Management System | 订单管理系统 |
| PKS | 项目专用缩写 | (可能是外包或通道) |
14. 为什么这份地图存在——没有它的业务代价
新人在代码海洋中迷路的 3 个月
新人 A(2023 年入职):
第 1 周:配环境(ODTS 1 项目 4 个子模块,每个有不同构建方式)
第 2 周:PR 来了——"修改某 ISDA 合同的结算日期逻辑"
新人花了 3 天找到代码在哪——EdsSubContractDBModel 的 80+ 字段
因为不知道"结算日期"在数据库里叫 settleDate 还是 settlementDate 还是 payDate
最后发现有 3 个不同的日期字段在 3 个不同的地方被设置
第 3 周:另一个 PR——"修复保证金计算 bug"
这次他找到了代码——但改了 trade 模块的保证金计算,影响了 eod 模块的调用
测试没覆盖到,UAT 才发现
第 4-12 周:逐渐摸索出代码结构
前 3 个月平均每个 PR 要 2-3 天(其中 50% 时间花在找代码位置)
业务成本:
→ 3 个月的非生产力期 × 月薪 = 约 15 万人民币的隐性成本
→ 期间出的 bug(修改错模块)需要 senior 花时间 review 和回滚
→ Senior 的 review 时间被稀释——原本可以花在架构改进上的时间
生产事故中浪费的定位时间
2022 年生产事故:
→ 某个场外期权的估值在某个条件下显示为 0
→ 值班开发花了 2 小时才找到原因——代码在 GPricingEngine 的
一个深层路径里,被 5 层 if-else 包裹
→ 但实际上这个 bug 在 6 个月前就被引入了一块代码
"看起来和估值无关"的 refactoring 改了一个 return 值
→ 修复只花了 10 分钟——找到代码花了 2 小时
经济损失:
2 小时 × 值班团队(1 开发 + 1 运维 + 1 业务验证)
如果是在交易时段,估值显示问题可能导致错误的风险暴露判断
虽然这次没有直接资金损失,但时间成本是真实的
”看起来对”的模块——改错地方的代价
案例(2021 年):
需求:"修改合约终止日期的显示格式"
开发找到了"显示日期"的代码——在一个前端格式化工具类里
改了 3 行代码,测试通过,部署上线
一个月后运营发现某个报表的终止日期是全 0
→ 因为那个工具类被 12 个不同地方调用
→ 开发只测试了"自己知道的那 3 个调用方"
→ 另外 9 个没测的调用方直接崩了
影响:
→ 报表修复花了 1 周
→ 运营对该时间段内的报表数据信任度下降
→ 最终追查发现:这个需求应该改的是后端日期计算逻辑,而不是前端格式化
没有代码地图时,"看起来对的修改"往往是"偶发正确"。
有了地图,才能判断"这段代码在哪里"和"谁在用这段代码"。
Senior 开发的单点依赖
这套系统在 10 年里有超过 20 人的开发人员进出。代码地图解决的不仅是技术问题——它解决的是人员流动的风险。
现实:
→ 2020 年 eds-web-app 的原始架构师离职
→ 他脑子里有一张完整的代码地图:"xx 功能在 xx 包下的 xx 文件"
→ 这张地图没有文档化
→ 他走后,后续团队花了大约 6 个月才重建同等程度的代码认知
→ 这 6 个月里,任何涉及跨模块的修改都充满了不确定性
这就是 ODTS-33 存在的理由——不让"代码知识"随人走。
15. 代码阅读路线图(推荐顺序)
如果你刚进入这个系统,按这个顺序读代码:
第一天:读模型
EdsSubContractDBModel.java→ 理解 80+ 个字段和编码体系EdsSubRequestDBModel.java→ 理解事件机制ProductType.java→ 理解产品分类
第二天:读定价 4. PricingEngine 的 switch-case → 理解 30+ 产品结构类型 5. GPricingEngine → 理解 Greeks 计算
第三天:读交易流程 6. edsBoot/controller/ → 理解 API 入口 7. edsBoot/service/ → 理解业务逻辑 8. InterestEodService → 理解 EOD 流程
第四天:读前端 9. odts-linear-web 的 27 个模块 → 理解产品功能全貌 10. eds-rm-web → 理解风控
第五天:读周边系统 11. hedging-as → 理解对冲和状态机 12. sac-report → 理解监管报送 13. eva-master → 理解运营监控