hjhan
|
5dc8bdbf9e
|
refactor(interest): 计息 trace 命名对齐业界最佳实践
- InterestTrace → AccrualTrace:追踪对象是"计息过程"而非泛指的 Interest,与仓库
既有的 SwapCalcTrace(-Trace 后缀约定) 及 AccrualContext/AccrualBoundary/AccrualPolicy
家族一致;AccrualTrace 经 SwapCalcTrace.Write 常驻落盘,二者职责分清(收集器 vs 落盘通道)。
- InterestStep → AccrualTraceEvent、InterestTraceEntry → AccrualTraceEntry:
条目类别对应 QuantLib/Strata 的"事件"概念(AccrualTraceEvent),命名自描述。
- SwapCalcTrace.Persist → Write:"Persist" 易误读为落库持久化;此处只是写入日志通道,
且类内已有私有 Record(string),故用 Write 避免歧义。
纯改名、数值逻辑零改动;YLErpDAL + UnitTestProject 编译 0 错。
|
2026-08-12 07:05:41 +08:00 |
|
hjhan
|
be3be877ec
|
refactor(interest): 引入 AccrualContext 并将 AccrueCompound 重命名为 AccrueCompoundInArrears
1. 新增 AccrualContext 只读值对象,把 annualDays/precision/trace 三个"与金额利率无关"
的横向参数打包为上下文成员。计息纯函数只吃一个 ctx,签名去噪、可读性提升;
ctx 为只读值对象(非类的实例/静态字段),不破坏纯函数(线程安全、可重入、可测)。
trace 因此成为"传入上下文的成员"而非散落参数,满足"默认成员而非参数"的诉求。
2. AccrueCompound → AccrueCompoundInArrears:精确表达 OIS/SOFR/FR007 的
compounded-in-arrears 语义(每子区间取定盘、段末滚入本金),与
InterestRate.Compounding.Compounded 闭式分支(TRS 下死路径)一刀两断、不再混淆。
纯增量、数值逻辑不变;YLErpDAL + UnitTestProject 编译 0 错 0 警;FR007 两段切换场景
实跑 trace 与旧版数值完全一致。
|
2026-08-12 06:13:38 +08:00 |
|
hjhan
|
fcf52a305e
|
feat(interest): 融资腿计息接入 trace 并常驻落盘
FundingLegAccrual.AccrueSimpleEod 接 InterestTrace;SwapCalcTrace 新增 Persist
把收集器条目经 Critical 无条件落盘(与开关无关);已迁移的 EOD 单利适配器
CalcDailySimpleInterestByEod 创建并 Persist trace。纯增量、数值逻辑不变。
|
2026-08-12 06:05:02 +08:00 |
|
hjhan
|
63bfc8ca8f
|
refactor(interest): SwapDealService 接入 FundingLegRate 工厂并复用 FundingLegPrecision
取率处改用 Fixed/Floating 工厂;InterestCalculationPrecision 引用
SwapInterest.FundingLegPrecision,消除重复常量定义。
|
2026-08-12 05:36:02 +08:00 |
|
hjhan
|
dee491b8d0
|
refactor(interest): FundingLegAccrual 删除危险骨架,仅保留纯函数 AccrueSimpleEod
移除标注"切勿在未迁移前接入生产"的 AccrueDay/AccruePeriod 骨架(含 IIndexFixer/
Func 取价),保留与旧实现逐字对齐的纯函数,消除两套计息逻辑并存的隐患。
|
2026-08-12 05:36:02 +08:00 |
|
hjhan
|
e7514a2d84
|
cleanup(interest): 删除 AccrualPolicy 未使用的 FromLegacy 工厂与冗余 using
FromLegacy 无调用方;移除 YLErp.DBModels using 后 InterestTypeEnum 仅存于注释。
|
2026-08-12 05:36:02 +08:00 |
|
hjhan
|
4e67af52e8
|
refactor(interest): FundingLegRate 瘦身为单一 all-in 利率值对象
固定/浮动腿的区别是取率环节的事,计息只认一个数;以 Fixed/Floating 工厂
取代原 4 字段构造,不再为腿型背负多余字段。
|
2026-08-12 05:36:01 +08:00 |
|
hjhan
|
0c447ff5ff
|
refactor: 提取融资腿计息领域模型 (AccrualPolicy/FundingLegRate/AccrualState/FundingLegAccrual) - 将 CalcDailySimpleInterestByEod 纯数学下沉至 FundingLegAccrual.AccrueSimpleEod, 消除 double 往返转换, 引入值对象收敛散落参数
|
2026-08-11 22:37:19 +08:00 |
|
hjhan
|
246392b665
|
cleanup: 删除 SwapInterestAdapter 半成品, 回退 SwapInterest 未提交改动
SwapInterestAdapter + SwapInterest 增强(annualized/segmentRates/
resetCarryInterest) + 配套测试 是半成品, 有G7/G8已知边界,
且破坏现有测试。按审查建议回退, 作为独立PR后续处理。
当前工作区只剩 BondIndex/RateYield 到期日修复。
验证: 编译0错误, 全量513测试7失败(基线一致)。
|
2026-08-11 19:23:21 +08:00 |
|
hjhan
|
dafc06793e
|
refactor: AddClientCashInCashOut 加 virtual + 修正架构文档
AddClientCashInCashOut 从 public 改为 public virtual,
使测试可 override, 消除 RecordMarginCashFlow 迁出的阻塞。
AddClientCash 已是 virtual, 这是统一两者。
修正 ARCHITECTURE.md: 保证金有余额和返息(非'没有计息基数')。
验证: 编译0错误, 全量513测试7失败(基线一致)。
|
2026-08-11 17:09:13 +08:00 |
|
hjhan
|
7cea09d976
|
docs: 新增 SwapModule ARCHITECTURE.md 架构说明
记录重构后的三大限界上下文结构:
- FundingLegs(融资腿) / Margin(保证金) / ReturnLegs(标的端)
- 命名规则(防歧义): Funding/Return/Margin/FloatRate
- Core 层纯函数库(SwapInterest + IIndexFixer)
- 已消除的 inline 重复清单
- 方向因子类型规范(int)
- 待后续改造的接缝预留
不改原有文档(corp-action-*.md 仍准确)。
|
2026-08-11 17:03:44 +08:00 |
|
hjhan
|
5a7869e0c9
|
fix(return-leg): PositionValueCalc.ratio 改为 int, 统一方向因子类型
ratio(收取=1/支付=-1)是方向因子, 应该是 int。
和 MtmCalc/DirectionRatio/MarginCalc 的 int 保持一致。
调用点(SwapEodPositionService 4处)原 ratio 是 decimal,
加 (int) 显式转换(值恒为 1或-1, 零精度损失)。
排查确认: 这是唯一的类型不一致, 其他纯函数参数类型均已统一。
验证: 编译0错误, 全量513测试7失败(基线一致)。
|
2026-08-11 16:59:22 +08:00 |
|
hjhan
|
16c44d3b50
|
refactor(return-leg): 抽取 PositionValueCalc 持仓价值汇总
SwapEodPositionService 8处 SwapPositionValue inline 公式替换:
- 4处 InterestProfitSum * ratio + PosiProfitSum → PositionValueCalc.Calc(带ratio)
- 4处 InterestProfitSum + PosiProfitSum → PositionValueCalc.Calc(默认ratio=1)
持仓价值 = 利息端收益 + 浮动端收益, 8处副本→1个纯函数。
这是最后一个高性价比的纯函数提取。
验证: 编译0错误, 全量513测试7失败(基线一致)。
|
2026-08-11 16:50:21 +08:00 |
|
hjhan
|
7e169dd53f
|
fix(margin): 回退 PreviousBalance 简化, 恢复三级 fallback
尝试去掉第2级(TdInterestPrincipal)导致5个保证金测试失败。
根因: 生产 EOD 归档(eod_swap_position(35774))的 InterestPrincipalFix=0,
只有 TdInterestPrincipal 有值。第2级不是死代码, 不可删。
恢复三级 fallback, 补充注释说明每级命中的真实场景。
教训: 不能只看赋值点判断字段是否有值, 必须看实际数据。
验证: 编译0错误, 全量509测试7失败(基线一致)。
|
2026-08-11 15:46:28 +08:00 |
|
hjhan
|
6fe5d81917
|
refactor(margin): 3个保证金纯函数迁入 MarginCalc, 改正命名
从 SwapDealService 剥离到 Margin/MarginCalc.cs:
- PreviousBalance: 取上一日终保证金余额(原 ResolveMarginOrginPv, 改正命名)
- FlipDirection: 保证金方向翻转(原 FlipMarginDirection)
- AccumulateSettlement: 平仓汇总(原 AccumulateMarginSettlement)
命名修正: orginPv 是融资腿概念, 保证金没有; 改为 PreviousBalance。
SwapDealService 里删掉这3个private方法, 调用点改用 MarginCalc.XXX。
RecordMarginCashFlow 暂留(依赖实例方法 AddClientCash)。
保证金纯函数现在全部在 Margin 模块, SwapDealService 只保留
RecordMarginCashFlow(资金记录, 需要实例上下文)。
验证: 编译0错误, 全量509测试7失败(基线一致)。
|
2026-08-11 14:35:42 +08:00 |
|
hjhan
|
2fbffcceb4
|
refactor(margin): 3处散落保证金资金记录收敛到 RecordMarginCashFlow
RecordMarginCashFlow 加委托重载, 统一 AddClientCash(virtual)和
AddClientCashInCashOut(非virtual)两条路径。
替换3处 inline:
- :1663 SwapUnwind 平仓(AddClientCash, 只有应付预付金)
- :1979 DealUnwind(AddClientCashInCashOut, 只有应付预付金)
- :2128 SwapIncome 互换(AddClientCash, 只有预付金返息)
- :2195 自动互换(AddClientCash, 只有应付预付金, swapEvent.unwindData)
注释掉的返息代码(//if SwapMarginRebatePnl)同步清理——
通过传 marginRebate:0 表达'不写返息', 不再留注释代码。
SwapDealService 保证金资金记录 inline: 4处 → 0。
全部走 RecordMarginCashFlow 的 2 个重载。
验证: 编译0错误, 全量509测试7失败(基线一致)。
|
2026-08-11 14:26:29 +08:00 |
|
hjhan
|
11923e11b7
|
refactor(margin): 抽取 RecordMarginCashFlow 保证金资金记录
SwapLongShortUnwind 里 inline 的保证金资金记录
(应付预付金 + 预付金返息)抽成独立方法。
SwapDealService 内保证金方法清单(待整体迁入Margin):
- ResolveMarginOrginPv 维度重映射
- FlipMarginDirection 方向翻转
- AccumulateMarginSettlement 平仓汇总
- RecordMarginCashFlow 资金记录(新)
验证: 编译0错误, 全量509测试7失败(基线一致)。
|
2026-08-11 13:48:06 +08:00 |
|
hjhan
|
870cd337f6
|
refactor(margin): 抽取 AccumulateMarginSettlement 保证金平仓汇总
把 SwapUnwind 里 inline 的保证金汇总逻辑(SwapMarginRebatePnl +
SwapMarginAmount)抽成独立方法, 与融资腿汇总分离。
原循环里保证金和融资腿混在一起, 现在保证金走
AccumulateMarginSettlement, 融资腿汇总留在主循环。
待迁入 Margin 模块。
验证: 编译0错误, 全量509测试7失败(基线一致)。
|
2026-08-11 13:18:20 +08:00 |
|
hjhan
|
29df4c480d
|
refactor: 删除 CalcNotionalByMode, 保证金/融资腿计息基数内联到调用点
CalcNotionalByMode 已完成历史使命:
- 融资腿(1/2/9)迁入 FundingLegStrategyFactory
- 保证金(5/6)迁入 MarginModes.Contains 分支
- 死代码(3/4/7/8)已删
调用点(GetInterests:843)现在内联两条路径:
- 保证金: closePrincipal = Fix × closePercent (用 MarginModes.Contains 判断)
- 融资腿: FundingLegStrategyFactory.Get(mode).CalcNotional(...)
删除:
- CalcNotionalByMode 方法(含注释)
- 2个用反射调私有方法的诊断测试(验证的逻辑已被FundingLegStrategyTest覆盖)
验证: 编译0错误, 全量509测试7失败(基线一致)。
|
2026-08-11 13:13:32 +08:00 |
|
hjhan
|
47422b9024
|
feat(margin): MarginAccount 加计息入口 AccrueInterest
保证金账户现在具备独立计息能力:
AccrueInterest(rate, start, end, boundary, annualDays)
委托 SwapInterest.AccrueSimple(余额×利率×天数/年化)。
保证金利息是券商对客户保证金存款付息, 方向与融资腿相反。
Margin 模块现在完全独立于 CalcNotionalByMode——
有自己的余额管理 + 计息入口, 不依赖融资腿框架。
测试: 3个计息用例(7天/零余额/释放后减半)。
CalcNotionalByMode 的 mode 5/6 case 仍在(下游路径共用),
待 EOD 归档改走 Margin 路径后再删。
验证: 编译0错误, 全量511测试7失败(基线一致)。
|
2026-08-11 13:03:38 +08:00 |
|
hjhan
|
e9b54bdcf6
|
cleanup: 删除死代码枚举 mode 3/4/7/8 及相关引用
mode 3(持仓名义本金)/4(持仓市值): 零引用死代码
mode 7/8(多空存续名义本金): 界面已禁用, 无历史数据(用户确认)
删除:
- InterestModeEnum: 移除 持仓名义本金/持仓市值/多头存续名义本金/空头存续名义本金
枚举值保持显式(1/2/5/6/9), DB契约不变
- CalcNotionalByMode: 移除 mode 7/8 的 case
- ConsTrade.InterestModels/InterestNotionalModels: 移除 mode 7/8
- 删除3个 mode 7/8 相关测试方法(场景已不存在)
CalcNotionalByMode 现在只剩 mode 5/6(保证金)的 case,
待 Margin 独立计息入口建成后整体删除。
验证: 编译0错误, 全量508测试7失败(基线一致)。
|
2026-08-11 13:00:52 +08:00 |
|
hjhan
|
ed7b9102d4
|
docs: CalcNotionalByMode 补充过渡期注释, 说明保留原因
回应命名评审: 确认 FundingLegs 目录无旧文件残留(5个新文件),
旧类名/命名空间零引用。CalcNotionalByMode 有意保留:
- mode 5/6(保证金)待 Margin 独立入口建成后迁出
- mode 7/8(多空存续)界面已禁用, 保留为防御性兜底
待 mode 5/6 迁出后本方法可整体删除。
|
2026-08-11 12:55:02 +08:00 |
|
hjhan
|
cbe5b58577
|
refactor: 新增 DirectionRatio 方向因子纯函数, 替换7处三元式
多空方向(PositionType==Long?1:-1)和收付方向(xxx==收取?1:-1)
在两个上帝类里重复 15+处, +1/-1 写反是常见 bug 源。
新增 ReturnLegs/DirectionRatio.cs:
- LongShort(positionType): 多头=+1, 空头=-1
- ReceivePay(direction): 收取=+1, 支付=-1
替换:
- SwapEodPositionService: 6处 shortRatio 三元式(含注释1处)
- SwapDealService: 1处 shortRatio + 1处 directionRatio
验证: 编译0错误, 全量511测试7失败(基线一致)。
|
2026-08-11 12:30:53 +08:00 |
|
hjhan
|
e35a738d2e
|
refactor(funding-leg): 修复2个类名+补DividendCalc注释
采纳命名审查建议(优先级最高的2项):
1. UnderlyingFullPriceLeg → UnderlyingEntryFullPriceLeg
补齐'期初(Entry)'——建仓时点全价, 非当前全价, 金融上是不同计息口径
2. FixedNotionalLeg → FixedAmountLeg
去掉误导性的Notional——'固定值'是合同写死的数额, 不一定是名义本金,
避免与ContractNotionalLeg的Notional概念撞车
3. DividendCalc 补充注释: 业务含义(债券票息+股票分红统一用Dividend)、
税务口径(还原不含税再扣税)、命名保持理由
验证: 编译0错误, 全量507测试7失败(基线一致)。
|
2026-08-11 11:24:05 +08:00 |
|
hjhan
|
d61ff742de
|
refactor(return-leg): SwapDealService 增值税公式替换为 DividendCalc
SwapDealService:1806 inline 的 dividendIn/(1+tax)*(1-tax) 替换为
DividendCalc.AfterTaxRaw(中间计算不四舍五入)。
全库 payment/(1+tax)*(1-tax) inline 公式: 5处(SwapEod 4 + SwapDeal 1) → 0。
全部收敛到 DividendCalc.AfterTax / AfterTaxRaw。
验证: 编译0错误, 全量507测试7失败(基线一致)。
|
2026-08-11 11:18:56 +08:00 |
|
hjhan
|
c52d439469
|
refactor(return-leg): 4处增值税inline公式替换为 DividendCalc
SwapEodPositionService 4处 payment/(1+tax)*(1-tax) inline 替换:
- 1804/1906/2094: Math.Round(...) → DividendCalc.AfterTax(payment, tax)
- 1893: 中间计算(不四舍五入) → DividendCalc.AfterTaxRaw(total, tax)
修复 MtmCalcTest: UnrealizedPnl 第6参数 ratio 从 1m 改为 1(int)。
(1+tax) inline 公式出现次数: 4 → 0。
验证: 编译0错误, 全量507测试7失败(基线一致)。
|
2026-08-11 11:12:15 +08:00 |
|
hjhan
|
939d6a4271
|
fix(return-leg): MtmCalc.UnrealizedPnl ratio 参数改为 int
ratio(收取=1/支付=-1)和 shortRatio 一样是 int, 不是 decimal。
1695行 ratio 声明同步从 decimal 改为 int。
C# decimal*int 自动提升为 decimal, 不影响计算结果。
验证: 编译0错误, 全量507测试7失败(基线一致)。
|
2026-08-11 11:05:55 +08:00 |
|
hjhan
|
963f7a04e5
|
refactor(return-leg): 新增 DividendCalc 分红增值税后计算 + 修复 MtmCalc 参数类型
DividendCalc: 增值税后票息 = payment/(1+tax)*(1-tax),
原 SwapEodPositionService 4处重复此公式(1804/1894/1906/2095)。
本次先建纯函数+测试, 4处inline替换下次做。
附带修复: MtmCalc shortRatio 参数从 decimal 改为 int
(原代码6处声明中5处是int, 仅1696是decimal, 统一为int)。
1696行 shortRatio 声明同步改为 int。
验证: 编译0错误, DividendCalc 4个测试全过,
全量507测试7失败(基线一致)。
|
2026-08-11 11:04:08 +08:00 |
|
hjhan
|
946cbbb66d
|
refactor: InterestLeg 改名 FundingLeg(业界标准 Financing Leg)
命名: InterestLeg→FundingLeg, 消除'interest'与通用'利息'歧义。
Funding精确表达'融资成本'(客户付券商的杠杆成本 spread+FR007)。
改名清单:
- IInterestLegStrategy → IFundingLegStrategy
- InterestLegStrategyFactory → FundingLegStrategyFactory
- InterestLegStrategyTest → FundingLegStrategyTest
- 命名空间 InterestLegs → FundingLegs
- 目录 InterestLegs/ → FundingLegs/
- SwapDealService 引用同步更新
验证: 编译0错误, 全量503测试7失败(基线一致)。
|
2026-08-11 10:52:04 +08:00 |
|
hjhan
|
a26f848287
|
refactor(return-leg): 抽取 MtmCalc 标的端盯市计算
把 SwapEodPositionService 4处重复的 UnderlyingMarketValue 公式和
4处 PosiMtmPnL 公式抽成 MtmCalc 纯函数:
- MarketValue(price, qty, contractSize, shortRatio): 标的市值
- UnrealizedPnl(price, costGrossPrice, qty, contractSize, shortRatio, ratio): 盯市未实现盈亏
原代码4处副本(1731/1813/1898/2101 + 1741/1814/1899/2102)全部替换。
验证: 编译0错误, 全量503测试7失败(基线一致)。
|
2026-08-11 10:45:43 +08:00 |
|
hjhan
|
59651b802e
|
refactor(return-leg): QuantityRollforward 改名 QtyRollforward
代码里统一用 Qty 表示数量, 命名更简洁。
文件/类/测试类同步改名: Quantity→Qty。
|
2026-08-11 10:40:17 +08:00 |
|
hjhan
|
279c640345
|
refactor(return-leg): 抽取 QuantityRollforward 标的端数量递推
把 SwapEodPositionService:1980 inline 的数量递推公式抽成独立纯函数:
qty = 上一日终数量 + 开仓 - 平仓 + 公司行为调整
新增第4参数 corpActionDeltaQty(默认0,当前不影响行为),
预留给公司行为改造(送股/拆股/配股)。
原代码硬编码'数量只因交易变动'假设,改造时填入非零值即可。
ReturnLegs/QuantityRollforward.cs: 纯函数, 不依赖任何实例状态
ReturnLegs 测试: 8个(无交易/开仓/平仓/全平/超额/送股/拆股)
SwapEodPositionService: inline 2行 → QuantityRollforward.Calc() 1行
验证: 编译0错误, 全量497测试7失败(基线一致)。
|
2026-08-11 10:36:38 +08:00 |
|
hjhan
|
82fb5e5916
|
refactor(margin): SwapDealService 5处保证金判断收敛到 MarginModes
把 5 处 inline 的 InterestModeEnum==5||6 判断改为 MarginModes.Contains:
- :99 前端参考计算分流(MarginLegs vs InterestLegs)
- :680 ResolveInterestLegPositions 持仓对齐
- :716 ResolveInterestLegPositionsAsOf 未来持仓 LINQ Where
- :722 ResolveInterestLegPositionsAsOf if 判断
- :2023 平仓 SwapMarginAmount 汇总
- :2441 UpdateInitalPosition 平仓递减
仅剩 CalcNotionalByMode 的 case 标签(switch case 须常量,无法用 Contains)。
SwapDealService 内 InterestModeEnum.初始预付金/追加预付金 引用: 10处→2处(case标签)。
验证: 编译0错误, 全量489测试7失败(基线一致)。
|
2026-08-11 10:30:44 +08:00 |
|
hjhan
|
a868f3eb15
|
refactor(margin): 抽取 FlipMarginDirection 保证金方向翻转方法
2处 inline 的保证金方向翻转(收取↔支付)抽成独立方法 FlipMarginDirection。
保证金利息是券商付给客户, 方向与融资腿相反。
- GetInterests 路径(854行): if(5||6) → MarginModes.Contains + FlipMarginDirection
- 衡泰路径(1934行): 同上, 保留 _closePosiNotionalValue=0
判断从 InterestModeEnum==5||6 改为 MarginModes.Contains(统一口径)。
纯提取, 行为零变化。
验证: 编译0错误, 全量489测试7失败(基线一致)。
|
2026-08-11 10:27:18 +08:00 |
|
hjhan
|
ae4af111f3
|
refactor(margin): 抽取 ResolveMarginOrginPv 保证金维度重映射方法
把 InitSwapDealInterest 里 8 行 inline 的 orginPv 重映射逻辑抽成独立方法
ResolveMarginOrginPv(position, preEodPosition, fallback)。
保证金腿被迫走融资腿差分公式(dynomicPrincipal = TdPrincipal + posi - orginPv),
但 orginPv 对融资腿是'交易名义本金',对保证金腿须对齐到'保证金余额',
否则维度不匹配算出巨负值。提取后 InitSwapDealInterest 更干净,
且新方法待迁入 Margin 模块。
判断从 InterestModeEnum==5||6 改为 MarginModes.Contains(统一口径)。
纯提取, 行为零变化。
验证: 编译0错误, 全量489测试7失败(基线一致)。
|
2026-08-11 10:23:22 +08:00 |
|
hjhan
|
e73272042a
|
refactor(return-leg): 新增 ReturnLegSummary 标的端值对象
标的端(Total Return Leg)归档产出的汇总值: 多空名义本金/平仓名义本金/含费全价。
对应原 SwapPositionCompose 里 DealFloatPositions 传给 DealInterests 的4个标量。
命名说明(防歧义):
- 用 ReturnLeg(业界标准 Total Return Leg), 不用 FloatLeg
- 'float'在金融里首要含义是'浮动利率'(如FR007), 用于标的端会产生歧义
- 标的端 = 标的资产的总回报(价格涨跌+票息分红), 与浮动利率无关
纯新增骨架, 零生产改动。
验证: 编译0错误, 3个单测全过, 全量489测试7失败(基线一致)。
|
2026-08-11 10:15:20 +08:00 |
|
hjhan
|
b7469be104
|
refactor(margin): 保证金去除'计息基数'错误概念, 改用余额建模
保证金就是保证金——有余额、有利率、有利息, 不存在'计息基数/Notional'概念。
现有代码把保证金塞进 InterestPrincipalFix 当计息腿处理是错误建模。
修正:
- 删除 MarginLeg.cs(CalcBalance/accrualFactor 是融资腿的概念, 不该用在保证金)
- 新增 MarginAccount.cs: 管理余额变动(Deposit追加/Withdraw释放), 不含计息
- MarginBalance: 注释去掉'计息基数', 改为'保证金余额'
- IMarginResolver.Resolve: 去掉 accrualFactor 参数(融资腿比例, 非保证金概念)
- CashMargin/CreditMargin/GuaranteeMargin: 同步去掉 accrualFactor
- 枚举注释: '计息余额' → '余额'
保证金利息由 SwapInterest 纯函数按 余额×利率×天数/年化 计算,
MarginAccount 只提供余额, 不掺计息逻辑。
验证: sln编译0错误, 全量486测试7失败(基线一致,零回归)。
|
2026-08-11 10:06:27 +08:00 |
|
hjhan
|
22f22bc9c5
|
refactor(margin): ConsTrade.InterestMarginModels 4处引用收敛到 MarginModes
上次失败根因: EodClientBalanceCalc:134 是 EF Core LINQ 表达式,
HashSet.Contains 无法翻译成 SQL, 导致场景3/4 全红。
修正: MarginModes 新增 ForLinq(List<int>) 供 EF Core 翻译用。
- SwapEodPositionService 2处纯函数(非LINQ): 用 MarginModes.Contains
- EodClientBalanceCalc LINQ表达式: 用 MarginModes.ForLinq.Contains
- RealTimeClientBanlanceService(已ToList,内存集合): 用 MarginModes.Contains
ConsTrade.InterestMarginModels 产品代码引用: 4处 → 0(只剩定义+注释)。
保证金mode判断 {初始预付金,追加预付金} 现在统一由 MarginModes 提供。
验证: sln编译0错误, 全量485测试7失败(基线一致,零回归)。
|
2026-08-11 09:57:20 +08:00 |
|
hjhan
|
ef1a126b8f
|
refactor(margin): 4处散落marginTypes收敛到MarginModes
SwapEodPositionService: 删除 marginTypes 字段(13处.Contains全改MarginModes.Contains)
SwapEventEmailService: marginTypes 字段改为 MarginModes.All.ToList()
EodClientBalanceCalc: 删除未使用的 marginTypes 局部变量(死代码)
ClientBalanceUtility: 删除未使用的 marginTypes 局部变量(死代码)
收敛后 {初始预付金,追加预付金} 集合只在 MarginModes.All 一处定义,
消除6处副本口径分裂风险。
验证: sln编译0错误, 全量485测试7失败(基线一致,零回归)。
注: 上次27失败是stash残留导致的状态不一致,本次从干净状态逐步改。
|
2026-08-11 09:40:48 +08:00 |
|
hjhan
|
553e3d4c6d
|
refactor(margin): 新增 MarginModes 统一保证金mode判断口径
现状: 同一集合{初始预付金,追加预付金}在代码里复制了至少6次
(ConsTrade.InterestMarginModels + 5处局部marginTypes/premiumModes)。
任何一处漏改(如新增保证金形态)都会导致口径分裂。
本次: Margin 模块新增 MarginModes 静态类, 作为单一判断来源。
- IReadOnlyCollection<int> All: 保证金mode集合
- bool Contains(int): 判断mode是否属于保证金
后续逐个替换散落的marginTypes/premiumModes/InterestMarginModels。
纯新增, 零生产代码改动。
验证: 5个单测全过, 全量485测试7失败(基线一致)。
|
2026-08-11 09:27:25 +08:00 |
|
hjhan
|
30ae93b8ca
|
fix(interest): SwapDealIndexFixer 改用委托, 修复 CS0122 编译错误
问题: SwapDealIndexFixer(internal)访问 SwapDealService.TryGetFloatRate
(protected) 报 CS0122, 因非嵌套类无权访问 protected 成员。
修复: SwapDealIndexFixer 改为接受 Func<DateTime,string,(bool,double)> 委托,
SwapDealService.IndexFixer 属性传入 TryGetFloatRate 的包装。
- 无需访问 protected 成员
- SwapDealIndexFixer 保持独立文件(clean code)
- virtual 接缝仍保留(测试 override TryGetFloatRate 仍生效)
验证: YLErpDAL.csproj 编译 0 错误, 全量480测试7失败(基线一致,零回归),
CI_007/CI_008 通过。
|
2026-08-11 09:23:01 +08:00 |
|
hjhan
|
59c16aabc1
|
refactor(interest): SwapDealService 6处取价收敛到 IIndexFixer
修正上次尝试的失败: 静态 Fr007IndexFixer.Instance 绕过了
TryGetFloatRate(virtual)接缝, 导致测试 stub 失效(CI_007/CI_008失败)。
本次方案: 新增 SwapDealIndexFixer(实例级, 委托 TryGetFloatRate):
- SwapDealService.IndexFixer 属性 lazy 初始化, 包 SwapDealIndexFixer
- 6处 GetNonHolidayDefore+TryGetFloatRate 全部替换为 IndexFixerBase+IndexFixer
- TryGetFloatRate(protected virtual)保留不动, 测试 stub 机制完全不受影响
验证: CI_007/CI_008 从失败转为通过, 全量480测试7失败(与基线一致,零回归)。
SwapDealService 内 GetNonHolidayDefore 出现次数: 6 → 0(全部收敛到 IndexFixerBase)。
|
2026-08-11 09:17:42 +08:00 |
|
hjhan
|
7d0397fc44
|
refactor(interest): CalcNotionalByMode 融资腿委托策略工厂
融资腿(mode 1固定值/2合约名义本金/9标的期初全价)改由
InterestLegStrategyFactory.Get(mode).CalcNotional(...) 计算,
不再走原 switch 的 case。
保证金(mode 5/6)和多空存续(mode 7/8)暂保留原 switch 逻辑,
待 Margin 上下文接入后再迁出。
行为等价: 全量480测试, 改动前后失败数一致(7个, 全为无库环境问题),
零回归。
|
2026-08-11 09:13:26 +08:00 |
|
hjhan
|
55284fb76b
|
refactor(margin): 抽出独立 Margin 限界上下文,移除 PrepayLeg 错误继承
- 新建 YLErp.Modules.SwapModule.Margin:MarginBalance / MarginLeg / IMarginResolver(Cash/Credit/Guarantee)
- MarginLeg 不继承 IInterestLegStrategy,与利息腿完全解耦(保证金是客户存款/担保,非互换腿)
- 删除 PrepayLeg,工厂不再注册 mode 5/6 预付金
- 预付金用例迁入 MarginLegTest,旧 InterestLegStrategyTest 改为断言预付金已非利息腿
|
2026-08-10 22:09:09 +08:00 |
|
hjhan
|
aca834d8dc
|
refactor(interest): 新增预付金腿策略 + 策略工厂
新增(零生产改动):
- InterestLegs/PrepayLeg.cs
mode 5 初始预付金 / mode 6 追加预付金 共用。
计息基数=InterestPrincipalFix, 平仓本金=Fix×closePercent。
构造时校验mode合法性(只接受5/6)。
方向翻转/orginPv重映射等独有逻辑后续单独抽。
- InterestLegs/InterestLegStrategyFactory.cs
按InterestMode返回对应策略, 收敛switch分发。
死代码mode 3/4/7/8不注册, 传入会抛ArgumentException。
测试(14个全过):
- 预付金: 部分平仓/全平/非法mode构造
- 工厂: 各活跃mode返回正确类型/未注册mode抛异常/int重载等价
fixing接入尝试(已回退):
- 尝试用Fr007IndexFixer.Instance替换SwapDealService的6处取价
- 发现问题: 静态Instance绕过TryGetFloatRate(virtual)接缝,
破坏测试stub机制(CI_007/CI_008失败)
- 已回退, 下次改用实例级IIndexFixer(委托TryGetFloatRate)方式接入
|
2026-08-10 18:40:04 +08:00 |
|
hjhan
|
79e9304114
|
refactor(interest): 新增利息腿策略接口 + 3个活跃mode实现
为拆三类腿做准备,按 Strategy 模式封装 CalcNotionalByMode 的 switch。
本次零生产代码改动,全部为新增小文件,每个类单一职责<50行。
新增(策略接口+值对象):
- InterestLegs/IInterestLegStrategy.cs
NotionalResult 值对象(closePrincipal/posiPrincipal/closePercent)
+ IInterestLegStrategy 接口(每个mode一个实现)
新增(3个活跃利息腿mode):
- InterestLegs/FixedNotionalLeg.cs mode 1 固定值
计息基数恒=InterestPrincipalFix, 不随平仓比例变化(合同写死的固定值)
- InterestLegs/ContractNotionalLeg.cs mode 2 合约名义本金规模
平仓本金=posiNotional×closePercent, 按比例线性缩放
- InterestLegs/UnderlyingFullPriceLeg.cs mode 9 标的期初全价
主路径公式同mode2, 差异在衡泰路径grossPrice折算+EOD复利反推
确认现状:
- 界面实际只有3个活跃利息腿mode(1/2/9), TradeView.cshtml:330-349
- mode 3(持仓名义本金)/4(持仓市值) 零引用=死代码, 本次不实现
- mode 7/8(多空存续) 界面已注释掉, 本次不实现
- mode 5/6(预付金) 属保证金维度, 后续单独做PrepayLeg
新增测试(8个,全过):
- InterestLegStrategyTest.cs 覆盖各mode的部分平仓/全平/零平仓场景
验证策略行为与现有CalcNotionalByMode switch完全一致
|
2026-08-10 18:32:17 +08:00 |
|
hjhan
|
a0bca2858f
|
Merge branch 'glms/feature/1.4.2' of http://git.yiliantech.com/gitlab/otc-dev/zszq-trs into glms/feature/1.4.2
|
2026-08-10 18:02:01 +08:00 |
|
hjhan
|
250c41b925
|
refactor(interest): 抽取 IIndexFixer 取价接缝 + 清理固定值腿错误测试
为后续拆三类腿做准备,新增 FR007 取价的独立接口层(参考 QuantLib IborIndex
分层),本次零生产代码改动,全部为新增小文件。
新增文件(取价接缝,供后续 SwapDealService 6 处 inline 取价迁移用):
- Framework/YLErp.Core/Interest/IIndexFixer.cs
接口定义:给定取价日和标的代码返回当日利率,取价与计息解耦
- Framework/YLErp.Core/Interest/IndexFixerBase.cs
取价日计算工具:收敛原散落 6 处的 GetNonHolidayDefore(date.AddDays(rule))
- YLErpDAL/Modules/SwapModule/Fr007IndexFixer.cs
生产实现 + GetFixingOrThrow 辅助方法,独立文件便于单测
测试清理(删除基于错误假设的测试):
- 删除 SwapFixedInterestLegClosePercentBugTest.cs 整个文件
该文件假设'固定值腿利息应随平仓比例线性缩放',但固定值是合同写死的、
永远不随平仓比例变化。d1badfe4 的'修复'本身才是错的,当前分支已正确回退
- 修正 SwapUnwindPrepayPrincipalBugTdd.cs 固定值测试方法
断言从'应=Fix×0.5'改为'恒=Fix不随比例变化',对齐正确的业务定义
已知失败(非本次引入,留待后续与拆腿一起修):
- BondTrsAutoSwapScenarioTest 的 AS_001/004/008/009/010/011 共 6 个
原因:SaveAutoSwapDeal 直接调 AddClientCashInCashOut(非virtual)绕过
AddClientCash(virtual)封装,无库环境抛'客户信息未找到'。
从 096d2609 引入时即失败,需 AddClientCashInCashOut 加 virtual + 客户数据
mock,与拆腿那次可测性改造一起做
|
2026-08-10 18:01:37 +08:00 |
|
张名锐
|
8fdf2417f4
|
fix(swap): 修复日终持仓风险_互换 利息金额方向处理逻辑
|
2026-08-10 17:59:30 +08:00 |
|
张名锐
|
54445c1e38
|
Merge remote-tracking branch 'origin/glms/feature/zmr-0808' into glms/feature/1.4.2
# Conflicts:
# YLErpDAL/Modules/SwapModule/SwapDealService.cs
# YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
|
2026-08-10 10:56:34 +08:00 |
|