Files
zszq-trs/项目文档/互换收益结算审核后状态卡死阻止收盘问题分析.md
hjhan cd03fc53fb 互换两个独立bug分析文档+诊断测试
Bug①利息默认值偏大: 互换结清后eod的InterestProfitSum(待实现)没归零
(=RealizedInterest=77.26), 导致后续平仓默认值=77.26(本该0)+增量→偏大。
6-29收盘后三天对比坐实: 6-30默认83.70, 7-1默认90.14, 均含已实现的77.26。
根因 eod公式cs:829 对互换场景扣减失效(TdInterestIncome≈TdCloseInterest抵消)。

Bug②收益结算审核后状态卡死: ApproveSwapTrade(cs:1525)漏ExerciseDate判断,
到期互换审核后状态退回'确认成交'(CloseMethod默认0≠全部平仓1),
导致EodCheckMaturityTrade一直阻止收盘。引入点083848fb(2025-05-28)。

- 新增利息偏大分析文档(根因/修复方案A扣RealizedInterest/B eod归零)
- 新增审核状态卡死分析文档(根因/修复补ExerciseDate判断)
- 新增SwapPartialUnwindInterestDefaultTest(Step0探查/Step0b诊断/Step0d三天对比)
2026-07-01 09:57:25 +08:00

130 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 互换收益结算审核后状态卡死、阻止收盘问题分析
> 本文分析到期互换"收益结算(互换)审核通过后,交易状态不流转,导致收盘到期检查一直阻止"的问题。
> 成文于 2026-07-01。
---
## 一、问题概述
**复现场景**:一笔互换交易到期日(如 2026-06-29),用户在界面做"收益结算(互换)"并审核通过,但:
- 交易状态没变成"已到期"或"已平仓",仍是"确认成交"
- 不管做多少次收益结算+审核,状态依旧不变
- 收盘报错:`[检查当日到期交易]当日到期的场外交易未全部操作完成,请操作完成后再执行收盘操作:收益互换 GLMS-20260427-0001`
---
## 二、根因:审核路径 ApproveSwapTrade 漏了到期日判断
### 代码对照(铁证)
**免审核路径 `SwapIncome`(正确,基线就有)**`SwapDealService.cs:1481-1485`
```csharp
if (td.ExerciseDate <= unwindData.ValueDate) // 判断到期
{
td.Notional = 0;
td.StockEqvNotional = 0;
td.TradeStatus = "已到期"; // ✅ 到期 → 已到期
}
```
**审核路径 `ApproveSwapTrade`(漏了)**`SwapDealService.cs:1525-1538`
```csharp
if (swapEvent.unwindData.CloseMethod == (int)CloseMethodEnum.全部平仓)
td.TradeStatus = "已平仓";
else
{
td.TradeStatus = ConsTrade.确认成交; // ❌ 到期互换落到这里!没有 ExerciseDate 判断
td.HasPartialUnWind = 1;
}
```
`ApproveSwapTrade` **完全没有 `ExerciseDate` 到期判断**,而互换操作的 `CloseMethod` 又是默认值 0`InitIncome` cs:216 从不设它)→ 0 ≠ 全部平仓(1) → 走 else → 状态退回"确认成交"。
### 为什么互换必然走 else 分支
- `CloseMethodEnum`Unknown=0 / 全部平仓=1 / 部分平仓=2
- 互换初始化 `InitIncome`cs:216-292**从不给 `unwindData.CloseMethod` 赋值** → 默认 0
- 只有平仓路径(`InitUnwind`/`InitLongShortUnwind`)才设 `CloseMethod=全部平仓`
- 0 ≠ 1 → 必走 else → 退回"确认成交"
### 收盘检查为什么一直阻止
`EodCheckMaturityTrade.cs:27-33`(到期检查):
```csharp
var predicate = PredicateBuilder.Create<trade>(t =>
t.ExerciseDate >= startDate && t.ExerciseDate <= settleDate // 今日到期
&& t.TradeStatus == ConsTrade.确认成交 // ★ 状态还是"确认成交"
&& t.SettlementFlag != 1);
```
判断口径只看 `TradeStatus``TradeCompleteStatus = { 已到期, 已执行, 已平仓 }`ConsTrade.cs:33)。审核后状态停在"确认成交"(不在完成列表里)→ 永远命中 → 永远阻止。
---
## 三、关于"提交数量但审核时数量0"
用户还反馈"提交了数量但审核时候数量0"。经查:
1. `InitIncome`cs:216-292**从没给 `unwindData.CloseQty` 赋值**(对比 `InitUnwind` cs:90 有赋值)→ `CloseQty` 默认 0
2. `SaveSwapDeal`cs:1597)的 `item.Quantity = unwindData.CloseQty``eventType == 平仓` 条件挡住 → 互换(3)不执行
但这不是核心问题——**核心是状态没流转**。互换的 Quantity 语义与平仓不同(互换是收益结清,不是按数量平仓),数量为 0 可能是设计如此。状态卡死才是阻止收盘的直接原因。
---
## 四、引入时间(git blame
| 路径 | 提交 | 时间 | 说明 |
|------|------|------|------|
| `SwapIncome` 到期判断(正确)| `f9d8a256` | 2024-05-09 | 山证基线,一直有 |
| `ApproveSwapTrade` 状态分支(漏判断)| `083848fb` | 2025-05-28 | 审核流程重构,漏同步 ExerciseDate 判断 |
`083848fb`(2025-05-28)重构审核流程时把状态分支改成 `CloseMethod==全部平仓` 判断,但**忘了同步 `SwapIncome` 里的 `ExerciseDate` 到期判断**。
---
## 五、涉及文件
| 文件:行号 | 问题 |
|----------|------|
| `SwapDealService.cs:1525-1538`ApproveSwapTrade| **漏 ExerciseDate 判断**,到期互换退回"确认成交" |
| `SwapDealService.cs:1481-1485`SwapIncome)| 正确对照(有到期判断)|
| `SwapDealService.cs:216`InitIncome| 不设 CloseMethod → 默认 0,必然走 else |
| `EodCheckMaturityTrade.cs:27-33` | 阻止收盘的检查(只认 TradeStatus|
| `ConsTrade.cs:33` | TradeCompleteStatus 定义(确认成交不在内)|
---
## 六、修复方向(最小改动)
`ApproveSwapTrade`cs:1534-1538)的 else 分支补到期判断,与 `SwapIncome` 对齐:
```csharp
else
{
// 补:到期互换应设为"已到期"(与 SwapIncome cs:1481 对齐)
if (td.ExerciseDate <= swapEvent.unwindData.ValueDate)
{
td.Notional = 0;
td.StockEqvNotional = 0;
td.TradeStatus = "已到期";
}
else
{
td.TradeStatus = ConsTrade.确认成交;
td.HasPartialUnWind = 1;
}
}
```
改后到期互换审核通过 → 状态正确变成"已到期" → 收盘检查通过。
---
## 七、团队决策问题
1. **互换的 CloseMethod 是否应该设值**:当前 `InitIncome` 不设 CloseMethod(默认 0),是否应在互换初始化时根据是否全额结清设为"全部平仓"?这会影响 `ApproveSwapTrade` 走哪个分支。
2. **互换 Quantity=0 是否符合预期**`InitIncome` 不设 CloseQty,导致互换 flow_event 的 Quantity=0。需业务确认这是设计意图还是遗漏。
3. **历史卡住的交易怎么处理**GLMS-20260427-0001 等已卡住的交易,是否需要手动改 TradeStatus 为"已到期"才能继续收盘?