hjhan
|
e188ba5038
|
test(swap): 新增 ClosePercent 口径A产品契约测试,防止平仓比例被改为占剩余口径
新增前后端回归测试,锁定产品需求:ClosePercent 永远是占期初名义本金的比例。后端 CPC_001~010 装配测试验证 SwapDealService 真实执行 ToRemainingClosePercent/ToOriginalClosePercent 转换;前端 16 项接线测试验证 unwindSwapTrade.js 使用 NotionalValue 作为分母且 postData 携带 notionalValue 字段。测试背景:c9071a4e 曾将 ClosePercent 改为占剩余口径导致回归但现有测试全通过,本测试通过源码装配与契约验证弥补该缺口。
|
2026-07-27 13:18:32 +08:00 |
|
tengyufan
|
4987962aca
|
#EQD-6597 国联民生-簿记时新增基本费率字段(开平仓费用),并且自动计算
feat: 完善互换平仓交易费用自动计算
- 支持百分比和单位数量模式自动计算平仓交易费用
- 支持全部平仓和部分平仓联动重算
- 保持手动互换不自动填充平仓交易费用
- 补充前后端相关单测
|
2026-07-27 11:57:20 +08:00 |
|
张名锐
|
32af85d35c
|
Merge branch 'glms/feature/dotnumber' into glms/feature/1.4.2
# Conflicts:
# YLErpWeb/Views/SwapTrade2/TradeEdit.cshtml
# YLErpWeb/wwwroot/Scripts/app/swaptrade/swapTradeEdit.js
|
2026-07-23 17:53:37 +08:00 |
|
hjhan
|
7b007bddfa
|
refactor(swap-test): 抽取 TestableSwapEodPositionService 公共基类收敛重复 Stub
- 新建 TestableSwapEodPositionService 收敛 8/8 Stub 重复的高频 override
(PersistEodSwapPosition/SaveAllChanges/GetCurrencyRate/AddClientCash)
+ 统一 OptUserInfo 构造 + PersistedPositions/SaveChangesCount 输出捕获
- SwapEodPositionService.DealInterests 改 protected virtual(行为零变化)
- 8 个 ScenarioTest 改为继承基类,删除重复 override
- 消灭 DealInterestsScenarioTest/DealInterestsGoldenReplayTest 的反射调用
(typeof().GetMethod().Invoke → 直接调用 DealInterests)
验证:dotnet build 0 错误;dotnet test SwapModule 284通过/6跳过/0失败
|
2026-07-23 11:16:11 +08:00 |
|
张名锐
|
0755233ab6
|
fix(swap): 统一处理【名义本金】数值精度舍入问题
- 在多个位置添加 Math.Round 函数确保金额计算精度
- 新增 NormalizeNotionalValues 方法统一处理 UnwindData 中的名义本金舍入
- 修复交易平仓时 StockEqvNotional 扣减计算的精度问题
- 解决持仓数据 PosiNotionalValue 的精度舍入处理
- 修复前端页面显示格式化问题
- 添加单元测试验证名义本金舍入逻辑正确性
|
2026-07-22 13:05:49 +08:00 |
|
hjhan
|
e7c6e432e1
|
test: 修复陈旧 golden 与恢复 Step1 Ignore
golden_互换结清后待实现归零.json 的 RealizedPnl 0->8.219(f4ffe710 修复后未重录,8.219为正确值); SwapReEodDeleteManualCashRecordTest.Step1 恢复 [Ignore](与类头契约一致,避免污染入库 golden)。
|
2026-07-21 15:28:17 +08:00 |
|
hjhan
|
985162242d
|
feat(greeks): 新增 risk-factor bump 计算与注册
ParameterBase.Clone() 保留运行时类型深拷贝; ValueCalculator 两个薄接入方法; GreeksBumpCalculator/GreeksRiskFactor 引擎。加法性重定价桥,不动现有定价输出。
|
2026-07-21 15:28:15 +08:00 |
|
hjhan
|
a179675efd
|
refactor(swap-deal): 前端盈亏校验抽为 SwapFrontendPnlValidator
BuildFrontendValidationDiffs/FrontendPnlDiff/AddDiffIfOverThreshold 从2043行 SwapDealService 移至新文件,本文件仅留调用+日志。纯位置迁移,零行为变更。
|
2026-07-21 15:28:14 +08:00 |
|
hjhan
|
a153a1d1a6
|
refactor(swap-eod): 抽出期末头寸纯函数并放宽可见性
SetFixedLegRealizedPnl 替换4处复制粘贴(清理L1296双分号); NormalizeInterestSignForReport 替换16行内联报表分支; CalculateWeightedMarginInterest private->public static。均为纯静态无实例依赖,配套无库单测锁定行为。
|
2026-07-21 15:28:13 +08:00 |
|
hjhan
|
494a7a06cc
|
test(swap): 修正平仓利息复现用例标的代码为 2500002.IB
- 将 GLMS20260703CloseInterestTest 中 UnderlyingCode 由 511160.SH 更正为真实标的 2500002.IB
- 核心复现用例(复利真实FR007→-13667.85 / 单利→-13668.02)保留, 作为代码级验算样例
|
2026-07-20 18:41:16 +08:00 |
|
hjhan
|
98bfe8fb5d
|
test(swap): 增加 GLMS-20260703-0002 平仓利息复现用例(真实FR007+真实函数)
- 调用系统 GetInterests 真实路径(复利/单利两条), 用截图中的真实 FR007 定盘值
在 07-06/07-13 两个重置点真实取数, 复现系统值 -13,667.85 与业务实际值 -13,668.02
- 断言两者差异 0.17 元来自复利第二段本金并入
- 仅保留调用系统函数的断言, 不内嵌手算, 验算见 GLMS20260703_平仓利息验算.xlsx
|
2026-07-20 18:31:19 +08:00 |
|
hjhan
|
e261137c1d
|
fix(swap): 修复多次部分平仓 ClosePercent 口径(A占期初→B占剩余)转换缺失
- SwapDealService.ApplySwapTrade 入口补 ToRemainingClosePercent(A→B) 转换,与 SwapUnwind 保持一致;缺此转换导致 SaveSwapDealInternal 的 B→A 还原出错(GLMS-20260701-0006:第二次部分平仓50%被错误还原为32.5%)
- unwindSwapTrade.js 改用 swapCalc.calcCloseQtyByOriginalPercent 的 roundHalfAwayFromZero,规避 JS 浮点精度偏差(32500000*(0.5/0.65) 应为 25000000)
- SwapUnwind.cshtml 引入 swapCalc.js
- 新增 ApplySwapTradeClosePercentBugTest 回归测试;补充 swapCalc.test.js 精度用例与 GLMS20260701DbDiagnoseTest 诊断测试([Ignore])
|
2026-07-17 10:59:18 +08:00 |
|
张名锐
|
415539704d
|
fix(swap): 修复债券结息价差盈亏计算逻辑
- 将价差盈亏计算从使用CloseNotionalValue改为使用PositionQty和ContractSize
- 更新前端JavaScript代码中的计算公式,按持仓数量和合约乘数计算价差盈亏
- 在UnwindInput模型中添加PositionQty和ContractSize字段
- 修正后台计算服务中的数据映射逻辑
- 添加FC_009测试用例验证债券价差按数量计算的正确性
- 更新现有测试用例的输入参数以匹配新的计算方式
|
2026-07-17 10:58:31 +08:00 |
|
张名锐
|
f37a5b997c
|
Merge remote-tracking branch 'origin/glms/feature/1.4.2' into glms/feature/1.4.2
|
2026-07-17 10:02:18 +08:00 |
|
张名锐
|
ce0908c53b
|
fix(swap): 修复浮动端已实现盈亏计算逻辑
- 添加了SetFloatingRealizedPnl方法统一计算已实现盈亏
- 已实现盈亏现在正确包含盯市、分红和费用三个组成部分
- 修复了多处RealizedPnl计算错误,确保数值准确性
- 为DF_008测试场景添加了专门的单元测试验证
- 移除了重复的盈亏计算代码,提高代码可维护性
|
2026-07-17 10:02:06 +08:00 |
|
hjhan
|
2395aa9856
|
test(swap): 补 6676b625 掉期保证金利息方向反向单元测试
抽 CalculateSwapRealizedPnl 为 public static 纯函数(用 ConsTrade.InterestMarginModels 替代实例 marginTypes), 新增 8 个单元测试覆盖: 非保证金腿收取/支付原向, 保证金腿(初始预付金/追加预付金)收取/支付反向, 完整 5 字段汇总两种方向, RealizedInterest=0 边界. 锁定 6676b625 修复的保证金腿利息方向反向契约, 防止后续误改回归.
|
2026-07-17 08:40:19 +08:00 |
|
hjhan
|
96a64ae82d
|
test(swap): 修复 GLMS20260701DbDiagnoseTest 编译错误并加 2.3c 模拟 API 流程
L208-209 Convert.ToDecimal 修复 double? decimal 隐式转换错误(CS0266)和非 nullable double ?? 0 错误(CS0019). 新增 2.3b 直接调用 ResolveInterestLegPositions 验证 Clone 行为, 2.3c 模拟 controller 完整流程(ToRemainingClosePercent + GetUnwindInterests) 等价于 HTTP API. 该测试带 [TestCategory(DbDiagnose)] 标记不进 CI, 作为可重复手动诊断工具保留.
|
2026-07-17 08:24:00 +08:00 |
|
hjhan
|
43679393bb
|
test(swap): 补 e2fb456b InitUnwind 默认 ClosePercent 单元测试
抽 CalcDefaultInitClosePercent 静态纯函数(PosiNotionalValue/NotionalValue), InitUnwind L270 改为调用此函数, 新增 6 个单元测试覆盖: 未平仓/已平30%/除零保护/GLMS-20260701-0013 真实快照/与 ToRemainingClosePercent 联动自洽不变式/全平完边界场景. 填补 e2fb456b 提交的测试覆盖缺口.
|
2026-07-17 08:23:50 +08:00 |
|
hjhan
|
238824f4f4
|
fix(预付金返回/平仓比例): 恢复占期初语义并在后端入口统一转占剩余
之前提交 4f46e263 误将平仓比例改为占剩余持仓(Definition B)语义,与需求不符。
正确需求:每次打开平仓/提前终止均基于最开始原始名义本金(Definition A),
但每次返回的预付金金额需正确(后端按占剩余计算)。
- SwapDealService: 新增 ToRemainingClosePercent/ToOriginalClosePercent 双语义转换;
SwapUnwind 入口把前端传来的占期初(A)转为占剩余(B),全计算链公式不动;
SaveSwapDealInternal 序列化前还原为 A 落库,事件列表读取即显示占期初比例。
- SwapTrade2Controller.GetUnwindInterestList: 接收期初/剩余名义本金,预览利息按 B 计算。
- unwindSwapTrade.js: 回退为占期初语义(ClosePercent/平仓名义本金用 NotionalValue,
oriClosePercent=剩余/期初),提前终止同理。
- 单测 UW_007/008 覆盖 A→B 全平/部分平仓判定。
不影响收盘后盯市/估值(仅平仓入口与展示口径)。
|
2026-07-16 19:54:26 +08:00 |
|
hjhan
|
3c9d22f60d
|
test(swap): 浮动腿 fpositions 用 orig 不影响预付金结果 — 诊断测试
验证 GLMS-20260701-0008 的预付金 bug 修复无需触碰浮动腿(fpositions / posiLong/posiShort):
- 本 deal 利息腿仅 mode 9(标的期初全价) + mode 5(初始预付金),无「多头/空头存续名义本金」腿。
- CalcNotionalByMode 中 posiLong/posiShort 仅在「多头/空头存续名义本金」分支被消费(L709-716),
mode 9/5 均不依赖之;故 fpositions 用 orig 100M 不影响预付金「返回预付金」计算。
- 诊断用例用反射调 private CalcNotionalByMode 实证:mode9 closePrincipal=posiNotional×比例、
mode5 closePrincipal=实时腿 Fix×比例,均与 posiLong(orig 100M) 无关;并证明若存在
多头存续名义本金腿则 orig 会算错(10M vs 正确 6.89M)——普通收益互换的潜在同类 bug,本 deal 不触发,属修复范围外。
不改动任何生产代码。3 个诊断用例全过。
|
2026-07-16 13:00:21 +08:00 |
|
hjhan
|
d51dd8a60b
|
test(swap): 回归测试对齐 GLMS-20260701-0008 四次部分平仓快照
生产 deal 又平仓两次(共四次),实时预付金腿 InterestPrincipalFix 由 73,260
降至 66,813.12(4 次返还 9,900+15,840+3,663+2,783.88=32,186.88;
99,000−32,186.88=66,813.12,与 dev 库实时腿完全勾稽)。
- SwapUnwindPrepayOrigVsRealBugTdd:RemainingFix 常量 73,260→66,813.12;
头部注释同步为四次平仓;新增 GLMS20260701_四次部分平仓_LiveSnapshot 用例,
把 4 次平仓真实数据硬编码为忠实回归(日后该 deal 再平仓需同步更新)。
- 纳入此前遗漏提交的连库诊断测试 GLMS20260701DbDiagnoseTest.cs
(使用 DbContextFactory 取连接串,无硬编码密码,安全)。
验证:dotnet test --filter SwapUnwindPrepay → 26 passed(19+7)失败 0;
YLErpDAL / UnitTestProject 编译通过(仅既有警告)。
|
2026-07-16 11:09:47 +08:00 |
|
hjhan
|
24266cfad4
|
fix(swap): 多次部分平仓预付金返还默认显示初始值(GLMS-20260701-0008)
根因: GetUnwindInterests 利息腿迭代源取 origPositions(IsInitial=1),
其预付金腿 InterestPrincipalFix 恒为初始值(99000); 而"当前剩余本金"(73260)
存于实时腿 realPositions(IsInitial=0)。CalcNotionalByMode 与 InitSwapDealInterest
均读 position.InterestPrincipalFix, 导致多次部分平仓后平仓页默认按初始本金计算
返还。首次平仓 orig==real 掩盖了 bug, 故此前"只修好一次部分平仓"。
修复: 抽纯函数 ResolveInterestLegPositions(orig, real)——迭代源仍用 origPositions
(保留 orig.id -> eod_swap_position.PositionId 的日终匹配, 全库 eod 均按 orig.id 归档,
换 realPositions 会破坏 preEod 匹配导致利息重算错误), 仅对预付金腿(初始5/追加6)
Clone 覆盖 InterestPrincipalFix 为实时腿剩余本金; real.PositionId == orig.id 精确
1:1 关联; orig==real 时返回原始腿本身不克隆。
测试: 新增 SwapUnwindPrepayOrigVsRealBugTdd(6 用例)直接单测该纯函数, 覆盖既有
19 个用例(均绕过 orig/real 选择)的盲区。dotnet test --filter SwapUnwindPrepay
25 passed(19+6) 失败 0。
|
2026-07-16 10:49:12 +08:00 |
|
hjhan
|
7689436364
|
test(swap): 补 CalcDailySimpleInterest 全腿模式+日终路径覆盖,锁定无更大影响
用户要求确认 CalcDailySimpleInterest 所有调用方(含日终)覆盖完整性。
代码事实纠正:日终(settment=true)走 CalcEodInterest → CalcDailySimpleInterestByEod
(closePercent 硬编码 1m、且该函数从不改写 InterestPrincipal),根本不调用本函数;
本函数唯一真实调用链 = GetInterests(settment=false) → CalcUnwindInterest。
故'含日终'的正确命题是:日终不受此 bug 影响,应有用例锁定该不变量。
新增 CalcByMode 驱动各 InterestMode + 日终路径(rest_days=7, closePercent<1):
- 追加预付金(6)/多头存续(7)/空头存续(8)/合约名义本金规模(2):断言线性 closePrincipal
- 固定值(1):强制 newClosePercent=1,对平仓比例免疫,断言恒=Fix
- 日终 预付金(5)/标的期初全价(9):断言结果恒为线性 closePrincipal(证明 ByEod 正确变体不受影响)
SwapUnwindPrepayPrincipalBugTdd 现 19 绿;SwapModule 全量 196 通过/4 跳过,无回归。
|
2026-07-14 17:23:33 +08:00 |
|
hjhan
|
9bf3c4b9c6
|
test(swap): 补非预付金单利腿(标的期初全价)部分平仓回归,实证修复对所有单利腿通用
用户追问修复是否波及非预付金腿。CalcDailySimpleInterest 是所有单利腿
(InterestType=0)的盘中计息通用函数,预付金腿(mode5/6)只是使用者之一。
新增非预付金腿(标的期初全价=9,orginPv 走交易名义本金、不对齐 Fix)用例:
- 50%%→500,000、10%%→100,000、100%%→1,000,000(N=1,000,000)
- buggy 会给 N×closePercent^7,证明非预付金腿此前也中招、修复后统一线性缩放
- 100%% 用例锚定 closePercent=1 时修复前后恒等(零影响于日常计息/全平)
SwapUnwindPrepayPrincipalBugTdd 现 12 绿。
|
2026-07-14 16:45:27 +08:00 |
|
hjhan
|
83a55dab33
|
fix(swap): 修复平仓预付金应返还本金被 closePercent^N 指数级缩小
根因:CalcDailySimpleInterest 单利非重置日 else 分支曾把已×closePercent 的
InterestPrincipal 回填给计息基数 tdDynomicPrincipal,使下一个非重置日再乘一次,
累积成 InterestPrincipal = Fix × closePercent^N(N=计息天数),部分平仓时指数级缩小。
100% 因 1^N=1 不显现,故此前漏测。
修复:非重置日与重置日、日终 CalcDailySimpleInterestByEod 三者对齐——
显示本金 InterestPrincipal = 基数×closePercent(只缩放一次),计息基数不缩放。
TDD 铁证(GLMS-20260701-0006, interest_rest_days=7, Fix=9,180,000):
- 修复前 50%→71,718.75(=Fix×0.5^7)、10%→0.918(=Fix×0.1^7)
- 修复后 50%→4,590,000、10%→918,000、100%→9,180,000
新增 CalcUnwindMultiDay helper + 3 用例,SwapUnwindPrepayPrincipalBugTdd 共 9 绿,
SwapModule 全量 186 通过无回归。
|
2026-07-14 16:33:59 +08:00 |
|
hjhan
|
bfcfc74717
|
test: 平仓预付金bug回归测试贴合生产铁证(精确notional + 不计息断言)
- 客户截图级用例 notional 由反推的 306,191,860.22 更正为生产精确值
306,191,860.26,使 2*Fix-Notional = -287,820,348.64 与生产 event15997 精确 0 误差。
- 生产该预付金腿三条 swap_flow_event 的 InterestAmount 全=0(债券类预付金腿不计息),
仅 InterestPrincipal 中招;故客户级/Trade1813 用例改断言 InterestAmount==0、用 rate=0 贴合生产。
- 显式带息加固用例(rate=0.01,验证计息基数也基于保证金本金自身)保留,但注释标明为
合成场景、非该笔生产的真实症状,避免与生产现象混淆。
- 固化生产双平仓记录佐证:同腿"盘中错(event15997)/EOD对(event15998)"两条平仓,
恰好印证修复方向(盘中 orginPv 对齐 EOD=Fix)正确。
|
2026-07-14 14:46:42 +08:00 |
|
hjhan
|
f7988e8fd3
|
fix: 修正预付金腿平仓计息基数 orginPv 维度错误导致应返还本金巨负
平仓(盘中)路径对预付金(保证金)腿将 orginPv 取为整笔交易名义本金,
使公式 dynomicPrincipal=TdInterestPrincipal+posiPrincipal-orginPv 把名义本金
(千万~亿级)当减项扣掉,导致"应返还本金"(InterestPrincipal)与计息基数变成巨负值。
修复:仅对初始预付金(5)/追加预付金(6)腿,将 orginPv 对齐为自身保证金本金
InterestPrincipalFix,与日终(EOD)路径 SwapEodPositionService 中预付金腿
orginPv=InterestPrincipalFix 的既有正确行为保持一致。债券本金腿(模式9)及其它
计息模式仍用交易名义本金,不受影响。
新增 SwapUnwindPrepayPrincipalBugTdd 回归测试(6 用例全绿),含客户截图级
0 误差复现、真实库 Trade1813 复现、多次部分平仓及计息基数断言。
|
2026-07-14 11:33:15 +08:00 |
|
hjhan
|
86825cb2a1
|
test(swap): SwapPositionComposeScenarioTest(4场景)+CopyEodPosition/UpdateEodPosition/SaveCurrentEodInitalPosi走PersistEodSwapPosition seam
借鉴 testable 分支 SwapPositionComposeScenarioTest,基于当前分支 seam 重写4场景:
- SPC_001 首次归档(无前日eod):PosiQuantity=初始持仓
- SPC_002 Copy分支(有前日eod无事件):PosiGrossPrice原样复制
- SPC_003 Update分支(有平仓事件):PosiQuantity=1000-400=600, TdCloseQty=400
- SPC_004 未收盘抛异常(非交易首日无前日eod)
SwapEodPositionService 改动(零行为变更):
- CopyEodPosition/UpdateEodPosition/SaveCurrentEodInitalPosi 的 DbContext.eod_swap_position.Add
改为调 PersistEodSwapPosition seam(3处),使测试可拦截持久化
利息腿场景(自动互换)因 CalcSwapInterests 参数适配复杂留后续。
SwapModule 177测试全绿(+4),无回归。
|
2026-07-03 18:37:46 +08:00 |
|
hjhan
|
4fede8339a
|
refactor(test): SwapDealSettlementTest拆分为SwapUnwind/SwapIncome+提取共享stub
按业务拆分原 SwapDealSettlementTest(8场景)为3个文件,提升可读性:
- TestableSwapDealService.cs: 共享stub(7个seam override)+工厂方法(CreateTrade/CreateUnwindData)
- SwapUnwindScenarioTest.cs: 平仓全流程6场景(UW_001~006: 全平/部分平/含预付金/含费价重算/审核/提交)
- SwapIncomeScenarioTest.cs: 结息2场景(SI_001~002: 正常结息/含预付金返息)
命名对齐 testable 分支风格(SwapUnwindScenarioTest),场景前缀改 UW_/SI_ 更直观。
删除 SwapDealSettlementTest.cs(内容已拆分迁移)。
SwapModule 173测试全绿,无回归。
|
2026-07-03 18:12:52 +08:00 |
|
hjhan
|
99958f9b43
|
test(swap): SwapDealSettlementTest补部分平仓+含预付金场景(借鉴testable)
借鉴 testable 分支 SwapUnwindScenarioTest.Scenario2,补当前分支缺失的2个场景:
SD_007 部分平仓:CloseMethod=部分平仓 → HasPartialUnWind=1,TradeStatus不变,
StockEqvNotional/TradeAmount按比例扣减(原100万-50万=50万)
SD_008 含预付金平仓:SwapMarginAmount≠0 → 2条资金流水(平仓费+应付预付金)
SwapDealSettlementTest 现8场景,SwapModule 173测试全绿(+2),无回归。
|
2026-07-03 18:03:38 +08:00 |
|
hjhan
|
b501e21904
|
test(swap): 启用MergeCompose场景6/7+SwapFlowEventService录制钩子+RecordingSwapFlowEventService
1. MergeComposeScenarioTest 场景6/7 启用(去掉Ignore):
此前失败是stale binary(未重新编译),重新build后8场景全部通过。
- 场景6 单条merge无持仓→DealNoPosition创建交易
- 场景7 两条merge无持仓→创建交易+平仓
2. SwapFlowEventService 补OnBefore/OnAfterMergePageEvent录制钩子(默认空实现):
- OnBefore: DB查询完成、合成逻辑执行前触发,可捕获输入快照
- OnAfter: PersistEvents后触发,捕获输出事件
生产路径为空方法体,零行为影响。
3. 移植RecordingSwapFlowEventService(借鉴testable分支):
override OnAfterMergePageEvent录制golden文件,备用录制工具。
内联GoldenFileModel(简单POCO)。FullRecord_WithPreBookingPositions连库测试自动跳过。
SwapModule 171测试全绿,无回归。
|
2026-07-03 09:38:05 +08:00 |
|
hjhan
|
f0ef37b599
|
test(swap): SwapFlowEventService seam改造+MergePageEventScenarioTest(6场景全绿)
借鉴 testable 分支,只取 seam(排除 PosiPnl/NetSettmentAmount 公式改动和 MergePageEvent 拆分),
填补当前分支对开平仓合成(MergePageEvent)零覆盖的空白。
SwapFlowEventService 新增11个 protected virtual seam:
- FindTrade/FindTradeExtend/FindPositions/FindAndInvalidateFutureEvents
- GetUnderlying/GetNextBusinessDay/ResolvePositionId
- PersistEvents(替代InitEvent内联Add+SaveChanges)/BeginTransaction/CommitTransaction/RollbackTransaction
MergePageEvent/InitEvent: private→protected virtual,内联DB调用替换为seam。
InitEvent 移除 DbContext.swap_flow_event.Add(转入PersistEvents,纯函数化)。
SwapTradeBaseService.UpdateDbOption: public void→public virtual(测试override用)。
新增测试(借鉴testable分支):
- TestableSwapFlowEventService.cs(集中式共享包装类)
- MergePageEventScenarioTest.cs(6场景全绿):
Scenario1 单条无持仓开仓 / Scenario2 同向追加 / Scenario3 反向全平
Scenario4 反向部分平+开 / Scenario5 一开一平 / Scenario6 复杂组合
**未借鉴**:SearchPositionFlowEvent的PosiPnl/NetSettmentAmount公式改动(行为变更)、
MergePageEvent拆分ProcessSingleFlow等(非必需重构)。
SwapModule 169测试全绿(+6),无回归。
|
2026-07-03 09:26:13 +08:00 |
|
hjhan
|
6e9bae94c5
|
test(swap): MergeRestModeCompose seam调用替换+移植MergeComposeScenarioTest(6/8场景)
借鉴 testable 分支,把 SwapTradeAutoService 的 MergeRestModeCompose/MergeRestModelItem/
DealNoPosition/DealHasPosition 内联DB调用替换为seam调用,生产行为不变。
替换的调用点:
- MergeRestModeCompose: FindActiveSwapTrades/FindTradeExtends/FindActivePositions/GetNextBusinessDayBefore/QueryFloatRates
- MergeRestModelItem: FindClient/GetEtradingRule/FindAssetUnit/FindUnderlying/GetSwapFloatRate/FindFlowEventsForCashCheck/FindValidTrades/SaveChanges
- DealNoPosition: CreateNewSwapTrade/AutoSwapUnwind
- DealHasPosition: AutoSwapUnwind
新增测试(借鉴testable分支):
- TestableSwapTradeAutoService.cs(集中式共享包装类)
- MergeComposeScenarioTest.cs(8场景):
Scenario1-5/8 通过: 客户/权限/账户/标的校验链 + 空流水返回
Scenario6/7 [Ignore]: 创建交易路径,DealNoPosition内部实现细节待对齐后启用
SwapModule 163测试全绿(+6),无回归。
|
2026-07-03 09:20:59 +08:00 |
|
hjhan
|
e4a92c93ee
|
feat(swap): 后端只读校验告警-搬FrontendCalcReference+SwapIncome/SwapUnwind插校验
前端保持快速反馈(用户改输入立即算),后端不替代前端,仅做合理性兜底校验。
1. 搬FrontendCalcReference到YLErpDAL/Helpers(测试与生产共用同一份公式,避免分叉)
- 从FrontendCalcCharacterizationTest提取,改public,8个FC测试搬迁后全绿验证一致
2. SwapDealService新增ValidateFrontendPnL只读校验:
- 从unwindData.FlowEvents取浮动腿,PosiGrossPrice==0时跳过(避免误报)
- 调FrontendCalcReference重算,与前端传值逐字段比对
- 差异>0.01记Logger.Error(带输入快照便于排查)
- 整体try/catch吞异常,校验自身错误绝不阻断交易
- SwapUnwind/SwapIncome各插一处(FindTrade后、ExecuteInTransaction前)
不碰NLog配置(告警进Console,生产由运维采集)。SwapModule 157测试全绿。
|
2026-07-03 09:04:57 +08:00 |
|
hjhan
|
129e4bed0d
|
test(swap): 补ApproveSwapTrade/ApplySwapTrade测试+3个seam(借鉴testable分支)
借鉴 origin/glms/feature/refactor-swap-event-testable 的 SwapUnwindScenarioTest 场景4/5,
补全当前分支缺失的平仓审批流程覆盖。
SwapDealService 新增3个 protected virtual seam:
- FindSwapEvent(查待审核事件)
- FindFlowEventsByEventId(查事件关联流水)
- CloseReCheckSetTrade(前置校验包装)
ApproveSwapTrade/ApplySwapTrade 重构为调seam,生产行为不变。
SwapDealSettlementTest 新增2个测试(SD_005/006,共6个):
- SD_005 ApproveSwapTrade 全平仓审核: 反序列化swap_event.EventData→资金流水→TradeStatus
- SD_006 ApplySwapTrade 提交审核: CloseReCheck前置校验+SwapRealizedPnL=SwapCloseAmount
融合策略: 保留当前分支SwapIncome资金流水断言独特价值(SD_001/002),
借鉴testable分支审批流程覆盖(SD_005/006),不二选一。
SwapModule 157测试全绿,无回归。
|
2026-07-03 08:30:36 +08:00 |
|
hjhan
|
cf0d965ff8
|
test(swap): 前端计算逻辑特征化测试(8场景含用户可变输入)
用C#忠实重写前端JS公式作参考实现(FrontendCalcReference),冻结前端计算行为,
为后端校验/重算兜底提供金标准(注:前端保持快速反馈,不搬到后端)。
8个场景覆盖用户可变输入分支:
- FC_001-005 平仓页: 默认值/改标的价格/改平仓数量/改利息金额/非债券空头方向因子
- FC_006-008 结息页: 全量结算/改标的价格/含利息腿与预付金腿总额
参考实现内部用规范命名(EntryDirtyPrice/ExitDirtyFeePrice/floatRatio/longRatio),
践行《互换价格字段命名规范决策文档》,作命名规范活样板。
|
2026-07-03 08:22:55 +08:00 |
|
hjhan
|
a207927f1b
|
test(swap): SwapDealService抽7个virtual seam + 手动结算内存测试
攻克SwapIncome/SwapUnwind零单元测试覆盖的盲区(此前仅DBRecording,CI不跑)。
SwapDealService补7个protected virtual seam(参考已验证的SwapEodPositionService模式):
- FindTrade/AddClientCash/SaveSwapDeal(原private改protected virtual)
- SaveAllChanges/ExecuteInTransaction/CallSaveSwapTradeClientCash/TriggerRealtimeSwapPosition
生产实现行为不变,SwapIncome/SwapUnwind/ApproveSwapTrade重构为调seam。
新增SwapDealSettlementTest.cs(4个内存测试):
- SD_001 SwapIncome资金流水金额=-SwapRealizedPnL
- SD_002 含预付金返息双流水
- SD_003 SwapUnwind全平仓持仓归零+状态变更
- SD_004 DealFloatPosition含费价重算(后端唯二真做计算处)
红灯验证通过(改错金额符号测试立即失败)。
|
2026-07-03 08:22:43 +08:00 |
|
hjhan
|
f88da59874
|
日期 事件 期望行为
D1=2026-01-06 无事件(Copy 分支) TdPosiDividend=1天增量,PosiDividendSum=增量
D2=2026-01-07 部分平仓 30%(EventType=2, Quantity=300, DividendIn=按比例) PosiQuantity→700,TdPosiDividend按(700)算,PosiDividendSum递推
D3=2026-01-08 无事件 增量按剩余700算
D4=2026-01-09 互换结算(EventType=3, DividendIn=部分待实现金额,不扣持仓) PosiQuantity不变=700,TdCloseDividend=互换DividendIn,PosiDividendSum递推
D5=2026-01-10 无事件 继续按700累积
D6=2026-01-11 全平(EventType=2, Quantity=700, 全部待实现作DividendIn) PosiQuantity→0,PosiDividendSum=0(else分支)
|
2026-07-02 12:59:16 +08:00 |
|
hjhan
|
0910969e3f
|
fix(swap): PosiDividendSum精度差异修复(GLMS-20260105-0007)
问题:互换后PosiDividendSum=-89999.64(应为-90000),差0.36元。
根因:UpdateEodPosition cs:1635从头重算PosiDividendSum
(Round(全程,2)-已实现),与CopyEodPosition逐天递增
(每天Round(增量,2)累积)产生舍入误差累积。
修复:cs:1635改为递增模式
PosiDividendSum = eod.PosiDividendSum + TdPosiDividend - TdCloseDividend
与InterestIncomeSum的递增模式一致,避免从头重算的精度差异。
验证(golden录制/回放TDD):
- 真实数据录制GLMS-20260105-0007的eod快照+输入数据
- 回放重新调UpdateEodPosition:修复前=-89999.64(红灯),
修复后=-90000(绿灯,精确匹配)
- 121个测试全通过,无回归
|
2026-07-02 10:47:23 +08:00 |
|
hjhan
|
0e045d89db
|
test(swap): GLMS-20260105-0007分红精度差异golden红灯(复现0.36差异)
用真实测试库数据录制golden,回放复现0.36精度差异:
- 互换前 PosiDividendSum=-90400,互换支付-400
- 期望 PosiDividendSum=-90000,实际=-89999.64,差异0.36
- 回放断言失败(红灯坐实bug)
根因:UpdateEodPosition cs:1635从头重算PosiDividendSum
(Round(全程,2)-已实现),与CopyEodPosition逐天递增
(每天Round(增量,2)累积)产生舍入误差。
录制方法Record_FromRealDB标[Ignore],手动跑生成golden。
回放方法Replay_VerifyPrecisionDiff进CI,当前红灯(期望=-90000,实际=-89999.64)。
|
2026-07-02 10:28:23 +08:00 |
|
hjhan
|
d11e332ff3
|
test(swap): golden录制/回放基础设施+DealInterests场景
引入golden回放框架,补充合成测试的精确值验证缺口。
新增GoldenReplayFramework.cs:
- GoldenScenarioModel: 通用golden数据模型(输入+期望输出)
- GoldenAssert: 精确字段对比(容许指定位数误差),逐字段验证
新增DealInterestsGoldenReplayTest.cs:
- Record_AllGoldenScenarios: 生成golden JSON(标Ignore,手动跑)
- Replay_AllGoldenFiles: 读golden重跑+精确对比(进CI)
2个golden场景:
- 互换结清后待实现归零: InterestIncomeSum=0.82191780822(精确到11位)
- 普通日归档递增(回放暂不支持自动重放,留后续)
golden文件持久化到Resources/GoldenFiles/DealInterestsGolden/
价值:重构时如果任何字段变了(哪怕第8位小数),回放立刻失败。
守恒测试验证大方向对,golden验证精确值对。
验证: 119+1(回放)=120全通过。
|
2026-07-02 09:37:18 +08:00 |
|
hjhan
|
64f0c82bbb
|
test(swap): 多步生命周期守恒测试(数学不变量验证)
用数学守恒约束验证利息在多次操作后不丢失/不重复。
这类测试的价值:不管代码怎么改,只要守恒不成立就报错。
4个守恒场景:
- MS_001: 连续收盘10天,每天增量之和=10天总利息(防指数增长/丢失)
- MS_002: 半平50%+后续全平,两次利息都>0不为负(防consumedInterest扣过头)
- MS_003: 互换结清后再平仓只有增量(单利靠eod归零传递)
- MS_004: 多次互换(第5天+第10天)+最终平仓(第15天),
累计consumed+平仓=全程复利利息(守恒不变量)
StubDealService支持构造注入consumedInterest和floatRate。
CalcEodInterest返回(当日增量,全程累计)元组,正确区分TdInterestAmount和InterestAmount。
验证: 115+4=119全通过。
|
2026-07-02 09:20:41 +08:00 |
|
hjhan
|
fb0ab3e948
|
test(swap): ClearSwapPositions重收盘清理合成测试(78751f0a覆盖)
验证78751f0a的核心修复:重收盘清理自动互换资金记录时排除手动互换。
4个测试场景:
- CSW_001: 自动互换资金记录被正确选中删除
- CSW_002: 手动互换资金记录被排除(manualClientCashIds排除逻辑)
- CSW_003: 已在excludedClientCashIds中的记录不重复选中
- CSW_004: 预付金返息记录也参与清理(手动被排除)
Stub override 3个虚方法注入内存数据:
FindFlowEventsByEventIds/FindManualClientCashIds/FindClientCashRecords
至此4个最近修复全部有合成测试覆盖:
①复利consumedInterest(✅) ②eod InterestIncomeSum(✅)
③重收盘误删资金(✅) ④分红重复计算(✅)
验证: 111+4=115全通过。
|
2026-07-02 09:11:38 +08:00 |
|
hjhan
|
eaa4ed735a
|
test(swap): DealFloatPositions分红场景测试(盯市盈亏+分红+增值税)
扩展StubEodService override 3个外部依赖虚方法:
- GetUnderlyingPrice: 注入固定标的价格
- GetUnderlyingData: 注入标的缓存(增值税率)
- CalcBondPayment: 注入固定债券付息
新增3个分红场景测试:
- DF_005: CopyEodPosition盯市盈亏=(price-grossPrice)×qty×方向
- DF_006: 分红计算 TdPosiDividend=payment/(1+tax)×(1-tax)
- DF_007: 增值税调整(tax=6%): 100/1.06×0.94≈88.68
覆盖了cf2f8b6e分红重复计算修复所在的浮动腿归档链路。
验证: 108+3=111全通过。
|
2026-07-02 09:02:43 +08:00 |
|
hjhan
|
fee2203d6e
|
test(swap): DealFloatPositions浮动腿归档合成测试(testable迁移)
新增4个浮动腿归档场景测试:
- DF_001: 空持仓返回空列表
- DF_002: 首日无eod走SaveCurrentEodInitalPosi分支
- DF_003: SaveCurrentEodInitalPosi纯计算字段验证(数量/均价/类型)
- DF_004: 有eod无平仓走CopyEodPosition分支(分支选择验证)
DealFloatPositions和子方法无直接DB调用(数据从参数传入),
但CopyEodPosition/UpdateEodPosition依赖外部数据源
(DataCacheProvider/UnderlyingCodePrice/BondPaymentService),
值验证需后续加接缝。当前覆盖分支选择+首日初始化值验证。
验证: 104+4=108全通过。
|
2026-07-02 08:49:50 +08:00 |
|
hjhan
|
7f0529bbed
|
test(swap): ComposePage流水合成持仓合成测试(testable迁移)
新增4个ComposePage场景测试(参考testable分支ComposePageScenarioTest):
- CP_001: 空事件→不创建持仓
- CP_002: 单条开仓→创建1条持仓,均价=开仓价
- CP_003: 两条开仓(同标的)→加权均价
- CP_004: 开仓+平仓→平仓扣减数量+产生资金记录
改动(SwapEodPositionService.cs):
- SaveEodPosition改为protected virtual(可override绕过UpdateSwapPosition连库)
- SaveEodPosition内部DbContext.Add替换为PersistEodSwapPosition
StubEodPositionService override 12个虚方法:
FindTrade/FindTradeExtend/FindEodSwapPositions/FindSwapPositions/
FindEodSwap/AddSwapEvent/AddClientCash/SaveEodSwapRecord/
ClearSwapPositionsForCompose/PersistEodSwapPosition/SaveAllChanges/
GetCurrencyRate + SaveEodPosition
验证: 100+4=104全通过(T0/T1=89+DealInterests=7+ConsumedInterest=4+ComposePage=4)。
|
2026-07-02 08:39:39 +08:00 |
|
hjhan
|
f501ee95a7
|
test(swap): 复利consumedInterest扣除合成测试(补c6adb3bb覆盖缺口)
c6adb3bb加的复利consumedInterest扣除此前无任何测试覆盖。
现在用4个合成测试完整验证:
改动(SwapDealService.cs):
- GetConsumedInterest加virtual关键字(测试可override注入内存值)
新增(ConsumedInterestScenarioTest.cs):
- StubSwapDealService override TryGetFloatRate+GetConsumedInterest
(模仿T0/T1的StubSwapDealService模式)
- CI_001: 基线(consumedInterest=0)拿到全程复利利息
- CI_002: 注入consumedInterest后利息=基线-consumed(直接验证cs:793)
- CI_003: 守恒(consumed+利息=基线)×3组不同consumed值
- CI_004: 全部已结(consumed=基线)平仓≈0不为负(防双重扣减)
关键发现:测试必须传settment:false走盘中平仓路径(CalcUnwindInterest),
settment:true(默认)走收盘归档路径(CalcEodInterest)不传consumedInterest。
验证: 89(T0/T1)+7(DealInterests)+4(ConsumedInterest)=100全通过。
|
2026-07-01 18:40:48 +08:00 |
|
hjhan
|
be88442c91
|
test(swap): 扩展DealInterests测试-多次互换守恒+预付金ratio翻转
新增2个测试场景:
- DI_SWAP_MULTI_001: 攒10天→互换结清→再攒5天→再互换结清
守恒约束: RealizedInterest+InterestIncomeSum=全程利息(17天)
验证多次互换结算后利息不丢失/不重复
- DI_MARGIN_001: 预付金腿(初始预付金,marginTypes)互换结清后
RealizedInterest应为负(ratio翻转:收取→-1→支付方向)
验证cs:789-793的marginTypes ratio翻转逻辑
验证: 89(T0/T1)+7(DealInterests)=96全通过,无回归。
|
2026-07-01 18:25:44 +08:00 |
|
hjhan
|
775d7a5881
|
test(swap): 阶段3 扩展DealInterests测试-普通日归档值+多日连续守恒
依赖阶段1c的CalcSwapInterests虚方法接缝,现在普通日分支(copy)
也可纯内存测试。
新增/改进的测试:
- DI_BRANCH_001: 改为真正的普通日归档值验证(InterestIncomeSum
前日+1天新计=2天利息),不再是Inconclusive
- DI_MULTI_001: 连续5天收盘归档,验证InterestIncomeSum线性递增
(每天+1天利息,5天后=5×DailyInterest)
StubEodPositionService扩展:
- override CalcSwapInterests(用真实SwapDealService算固定利率利息)
- ExecuteDealInterests public包装(替代反射调用)
- 删除旧的反射辅助方法
验证: 89(T0/T1)+5(DealInterests)=94全通过,无回归。
|
2026-07-01 18:21:51 +08:00 |
|
hjhan
|
deb831bf3e
|
test(swap): 阶段2 DealInterests利息归档合成测试(testable迁移)
模仿GetInterestsUnitTest_T0风格,纯内存不连库:
- StubEodPositionService继承生产类,override PersistEodSwapPosition/
SaveAllChanges/GetCurrencyRate替换DB调用
- 内存构造trade/position/eod/flowEvent数据
- 独立计算期望值(非循环论证)
4个测试场景:
- DI_SWAP_ZERO_001: 互换结清后InterestIncomeSum=当天新计(非攒的全程)
- DI_SWAP_ZERO_002: 已结清后再互换(只结算当天新计)InterestIncomeSum=0
- DI_BRANCH_001: 普通日走copy分支
- DI_BRANCH_002: 互换日走SaveEodInterestPosition分支
验证: 89(T0/T1)+4(DealInterests)=93全通过,无回归。
注意: fc90636a把公式改回pre+新计-实现(比我之前的pre-实现更好,
保留了当天新计利息),测试断言已据此调整。
|
2026-07-01 17:47:00 +08:00 |
|