Commit Graph
1397 Commits
Author SHA1 Message Date
hjhan b94cce68ee chore(cleanup): 删除裁决文档与 saga 注释——保留技术事实,剥离过程叙事(零逻辑改动)
删除 项目文档/双入口口径裁决-复利mode2部分平仓-20260816.md:
四轮状态改写的过程文档,终态有价值的技术事实已转移到代码注释与测试锚点。

保留的技术事实(新家):
- SwapEodPositionService:1325:恒1重算中间值不进结算现金流;系统端到端结果由
  DI_EXCEL_SCENARIO4 家族对账确认书公式保障(最终全平=剩余额×∏利率,2026-08-18
  手算复核);改动口径前必读该测试家族——破坏 ∏ 恒等式的调整会被其拦截
- ContractReferenceOracleTest:13:Excel 金标准期望值亦符合确认书公式(复核记录)
- EntrySemanticsTest 手算锚点 0.036165 保留(公式自含,去文档引用)

清理的 saga 痕迹:契约修复/裁决文档/暂缓/证伪 等过程性话语全部移除,
测试方法名与注释改为中性事实描述;[EOD平仓后收盘结息] 日志文案
'恒1全额结息(历史行为,契约修复暂缓)'→'全额结息(恒1惯例)'。

验证:编译 0 错误;EntrySemantics+Oracle 16/16 绿;全量 928=145/771/12
与基线逐位一致——纯注释/文档/日志文案改动,零逻辑变更。
2026-08-17 13:30:10 +08:00
hjhan fc4c93c47a docs(adjudication): 手算完成 Excel↔确认书对账——两者等同;修正封案推理
以 20260421-0004 输入按确认书公式 ∏(1+(FR007i+利差)×di/365)−1 精确手算:
- BL(部分平仓)=平掉额×利率(4/22→5/11)=-37,119.14,与 Excel 完全一致(差0.00)
- BN(最终全平)=剩余额×利率(4/22→5/19)=-123,280.18,与 Excel 差0.01(分步舍入)
=> Excel 金标准就是确认书公式本身;系统旧链端到端结果(BL/BN)已契约精确正确。

修正 2026-08-17 封案推理:分叉破坏的是实现不变量(最终全平须 reconcile 到
剩余×∏利率),而非修复方向被证伪——251,355 是被丢弃的中间值,不在结果链上。
结果层已无契约偏差可修,§六仅剩内部卫生价值,终局不修;未来动此链(含罚息)
硬性验收=DI_EXCEL_SCENARIO4 全绿+∏恒等式不变(手算模板已留文档)。
2026-08-17 13:08:11 +08:00
hjhan 55363e9f51 EQD-6968: 重命名 FR007 不计尾放宽取率参数为准确语义命名,提升可读性
纯改名与化简:BuildSegmentRates 的 includeEnd 别名->calcLast、exclusionEndDate->relaxedFixingFromDate(语义=从该日起放宽定盘缺失拦截而非排除某日);GetFloatRate 不算尾回退改正向结构;GetInterests 抽出 effectiveCalcLast 替代重复 calcLast||newCalcLast。计息逻辑不变,12 用例内存单测全绿。
2026-08-17 13:00:08 +08:00
hjhan 56c9a0652b docs(adjudication): 终局封禁——§六方案被 Excel 金标准证伪(验收门实证)
2026-08-17 实施§六(autoSwap分叉)并执行全量验收门:DI_EXCEL_SCENARIO4 家族
(20260421-0001~0012,业务 Excel BL/BN 列)失败——0004 最终全平期望 -123280.17(Excel BN)
vs 修复后 -120922.50(差-2357.67);DI_MANUAL_PARTIAL_CLOSE 语义钉子同破。已回滚,
基线 145/771/12 恢复(含 FR007 新套件全绿)。

根因认知升级:恒1重算直接金额虽被丢弃,但其快照种子链是 20260421 系列调优到与
业务 Excel 精确一致的整体——动一环破全局。'恒1无契约依据'仅对直接金额成立。

未来根治前置条件升级:先完成 Excel 模型↔确认书公式 reconcile 并经业务书面确认;
罚息等新需求触及该链时同样必须过 Excel 金标准。
2026-08-17 12:31:17 +08:00
hjhan 305f8a0322 EQD-6968: 补强 FR007 不算尾平仓误拦截回归套件(单利Red/数值一致性/非整倍数边界,重构为 Run 运行器) 2026-08-17 11:42:41 +08:00
hjhan bc401bd687 EQD-6968: 不算尾计息不再因平仓日FR007未发布误拦平仓(缺价回退上一重置日利率,有价仍取新利率) 2026-08-17 11:22:37 +08:00
hjhan feee779994 docs(adjudication): §六封案——条件触发默认不修(终局定性)
终局查实危害边界:分歧(251,355 无契约依据)止于【零结算现金流 + 单个内部页面
(日终持仓风险)两列展示字段】,不进结算书/对账单,客户不可见;TdInterestPrincipal
种子链被 20260421 特判块转换兜住。修复属高危区卫生项,单独立项风险大于收益。

触发条件(满足其一才执行§六):①罚息需求落地时顺手修正(同一计息路径同一验收);
②内部风控页展示列被业务投诉;③20260421 类事故复发。
§六方案与回归网作为触发时现成材料封存,勿删。
2026-08-17 10:57:27 +08:00
tengyufan 35096b8726 Merge remote-tracking branch 'origin/glms/feature/1.4.2' into glms/feature/1.4.2 2026-08-17 10:52:54 +08:00
hjhan 97aff02e1d test(infra): P0——ModuleInitializer 初始化段容错,测试库不可达不再连坐全部测试
问题(2026-08-16 栈实证):M1→AppManager.Initialize→InitializePsConfig→
InnerAppConfigService.ConfigDic 读 AppConfig 表→ServerVersion.AutoDetect 连库,
库不可达时 ModuleInitializer 抛异常→903 个测试全部'Unable to create instance'全红,
DB 断网期间阻塞全部开发(本周实证两天)。

修复:初始化段(AppManager.Initialize + DataCacheManager.UpdateOnce)包 try-catch,
失败降级为醒目警告(Console+NLog),纯内存测试照常可跑;依赖配置/缓存/库的测试
以各自连接错误失败(与降级前一致,不再伪装成类创建失败)。
完全跳过初始化仍用 YLErp_UNIT_TEST_SKIP_INITIALIZATION=1。
仅测试工程 Program.cs,零生产代码改动。

验证(库不可达、不开逃生门):修复前 0/17 类创建全失败;修复后 17/17 通过;
扩大集 48/48 通过(147ms)。常量类不受影响已证(ConsTrade.InterestMarginModels
为编译期常量,MarginModesTest 离线绿)。
2026-08-17 10:00:09 +08:00
tengyufan 4f68233f14 Merge remote-tracking branch 'origin/glms/feature/1.4.2' into glms/feature/1.4.2
# Conflicts:
#	UnitTestProject/Modules/SwapModule/DividendEodNoDoubleCountTest.cs
2026-08-17 10:00:00 +08:00
hjhan 97c6dc6bb6 docs(adjudication): 修正§1.1③快照影响表述——重算结果非完全丢弃,accrual字段确被改写
复核修正(代码级验证,行号为9efaa1b5):
- '不进快照'过宽:TdInterestIncome 四分支中三分支(!hasPreviousEod/全平/默认)直接写
  重算值,仅'有历史已结且算尾'分支被 DailyAccrual 干净覆盖;复利mode2/9的
  TdInterestPrincipal 取重算值(次日复利种子);FloatRate 同
- '零生产资金后果'严格=【零结算现金流后果】(TdCloseInterest/autoSettled不受影响成立)
- 新增落地审查清单:关联 GLMS-20260421-0004(同方法本金反推膨胀~2.3倍历史事故),
  :1413+复利部分平仓特判块消费 InterestPrincipal,§六实施时须验证两请求形状下
  反推链路等价,accrual 字段改写须进黄金回放 diff 白名单
2026-08-16 15:50:12 +08:00
hjhan 9efaa1b5cc chore(swap)+test: 删分红EOD历史死代码 + 补计算过程常驻日志(零行为语义变更);契约修复转为暂缓
死代码删除(SwapEodPositionService.UpdateEodPosition,论证+实证链完整):
- todayConsumedDividend/originNotional/totalPayment/totalInterest 自 0910969e(7/2 改递推式)
  起计算结果从未被消费,仅残留全历史 CalcBondPayment 只读查询+日志副作用,且构成
  脏数据(OriginalStockEqvNotional=null/PosiNetPrice=0)下 EOD 崩溃点(除零,实测复现)
- 配套边界测试 DividendEodNoDoubleCountTest.脏数据边界_*:删除前红(崩溃)→删除后绿
  (不抛异常+四输出字段与正常数据逐字段一致);stash 基线对比确认离线套件无其他差异
- 止血预案:git revert 本提交即回到已验证态

计算过程常驻日志(快速定位,纯增):
- [EOD平仓后收盘结息]:口径/autoSwap/平仓前/剩余/平掉额——排障第一入口
- [分红-EOD计提Copy/Update]:窗口/qty/税率/当日新计/账面前值→后值——与
  [分红-登记日口径]窗口命中日志构成分红计算全链
- [利息-全平专属分支]:全平分支触发标记,兼作契约修复落地后的验证哨兵

契约修复(EOD传真实比例)转为暂缓:影响快照种子,黄金回放验收门因96库网络未恢复
无法执行,按风险优先级撤回行为变更;方案+回归网(同形状等价oracle)+落地哨兵已
全部就绪并留档于裁决文档,DB恢复后可直接落地。
2026-08-16 15:47:09 +08:00
hjhan c9f44d4fde revert(test-infra): 测试库连接超时回退 2s→30s(恢复 8/14 前配置)
04b52061 将 Connection Timeout 30→2 属离线排障场景的急速失败配置,
对正常连库环境过紧(慢网/高延迟下秒死,且 ModuleInitializer 预热失败
拖垮整个测试程序集)。经实证:恢复 30s 后本机仍无法连库(秒败,
Unable to connect to any of the specified MySQL hosts),确认超时配置
非本次全红根因——根因为本机到 192.168.2.96 网络不可达(TCP/ICMP/ARP
三重验证)。2s 改动本身仍应回退以免放大慢网故障。.runsettings 为
opt-in(仅 --settings 显式启用)保留不动。
2026-08-16 13:25:50 +08:00
hjhan eb9591e212 chore(build): nuget.config 内网 Nexus HTTP 源补 allowInsecureConnections,修复 NU1302
NuGet 新版(VS 设计时 restore / SDK 7+)强制 HTTPS 源,内网
git.yiliantech.com/nexus 仅有 HTTP,导致 YLErp.Resources/MailKit/Security/Cache/Core
还原报 NU1302。按官方指定开关显式放行该源;nuget.org 仍走 HTTPS 不受影响。
验证:dotnet restore --force 真实触源成功,全解决方案编译 0 错误。
2026-08-16 12:57:06 +08:00
hjhanandClaude Opus 4.7 07764e7e3f test(swap): 契约参考实现落地,引擎主力族盘中重放首次对齐确认书公式 oracle
ContractReferenceCalc 独立实现 §8a 确认书公式(∏/重置期切分/末段收口/
利率确定日=重置日上一营业日),禁止引用生产计息类防同源;4 例手算锚点
自验证(真实规模 5000万/2.05%/90天=75999.04 与玩具锚点)。

引擎对照首批 3 例全绿:mode9/mode2 × 复利 × "10" × T+0 部分平仓30%,
盘中重放与契约 oracle 容差 0.01 元内逐分吻合——盘中口径=确认书公式
自此有机器强制,后续补格直接复用 oracle 供给(TEST-MATRIX §7.5 已登记)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-16 12:19:28 +08:00
hjhanandClaude Opus 4.7 f596bd80bc docs(adjudication): 影响面最终关闭——EOD重算结果被丢弃,零生产后果
DealInterests hasClose 分支未接收 SaveAutoEodWithCloseInterestPosition 返回值,
UpdateDbOption 仅打审计字段不落库,快照滚动盘中实结金额——错误的251,355
只存在于内存与日志。内网查证与数据修正清单取消,修复定性为重构卫生项。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-16 11:53:15 +08:00
hjhanandClaude Opus 4.7 a5684022fa docs(adjudication): 裁定资金面无影响——EOD重算不动钱,修复性质降为排雷
代码级核查:当日平仓后的EOD重算路径(autoSwap=false)无AddClientCash调用,
快照当日结出与累计已结均滚动盘中实落库金额,剩余待实现亦正确;
错误金额仅存在于重算写入的利息流水记录。撤回"双重结算敞口"表述,
内网查询目的改为确认流水记录无消费方+生成数据修正清单。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-16 11:48:52 +08:00
hjhanandClaude Opus 4.7 f75792b45b docs(adjudication): 裁决材料升级为确认书生产参数规模并钉清触发链
- 分歧表新增真实规模复算(5000万/2.05%/7天重置/90天):应结75,999 vs 现结251,355,
  单笔多结175,356(3.3倍);玩具参数降级为可复现实测锚点
- 新增触发链一节:EOD平仓后收盘=收盘归档对当日平仓事件的重算(非自动平仓本身),
  人工/自动平仓当下结息均正确,分歧仅在当晚归档重算
- TEST-MATRIX §9 增补规则5:oracle与裁决材料一律用生产参数,玩具参数仅限字符化钉子

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-16 11:26:42 +08:00
hjhanandClaude Opus 4.7 5a92709c42 docs(swap): 双入口口径分歧裁决申请——复利mode2部分平仓(EOD多结63%)
- 契约验算:盘中口径0.036165=确认书∏复利公式手算值(3.7e-7舍入差)
- 机制定位:SwapDealService:1220 closePrecent==1 分支是全平专属设计,
  但EOD入口传参惯例percent恒1→EOD部分平仓30%掉进全平分支,
  剩余100%持仓待实现利息被一次结走
- 待业务裁决两项:部分平仓应结口径(推荐=契约公式/盘中口径)、全平维持现公式
- 裁决后修复方案已就绪:EOD传真实比例+1220分支回归全平专属+2035e1df粘合退役
- 附生产影响面查证建议(EOD自动部分平仓×复利mode2/9存量事件比对)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-16 11:18:15 +08:00
hjhan c94a3e8c97 test(swap): 铺 §7-1 守恒不变量护栏,守 EOD平仓后收盘×部分平仓 裸格(§6 空洞1)
新增 4 个免库纯内存测试(GetInterestsEntrySemanticsTest):①部分平仓 剩余持仓前递且 期初=剩余+平掉;②全平 剩余前递=0;③两次部分平仓 逐日守恒 期初-剩余前递=平掉;④ClosePercentMath 多次平仓累计比例=1-∏(1-各次剩余口径)纯数学。

守恒断言落在 preEod.PosiNotionalValue(剩余前递)而非 InterestPrincipal——后者在 InitSwapDealInterest:1164 后被利息算法重赋值(1197 复利特判/1266 单利路径),语义随入口/模式变,非稳健观测点;剩余前递由 CalcUnwindInterest:1084 在 preEod.id==0 时写入,与利息算法无关,最稳健。

用途:作为 GetInterests 早路由(Tier A)合入的前置护栏——funding-leg(mode2)不触发早路由 continue,故本类任何回归都直接暴露早路由对 EOD平仓后收盘路径的破坏。验证:YLErp_UNIT_TEST_SKIP_INITIALIZATION=1 dotnet test --filter Name~守恒 全过;整类仅 2 个旧复利测试因无 96 库失败,与本次无关。
2026-08-16 11:17:37 +08:00
hjhanandClaude Opus 4.7 73264a30e2 docs(swap): 新增融资腿计息测试矩阵 TEST-MATRIX.md
- 主力族(mode9×FR007×复利×算头不算尾)7 维矩阵 + 4 入口枚举 + 近 6 周 fix 热力图定位
  (全部落在 CalcUnwindInterest 与 SaveAutoEodWithCloseInterestPosition 两个带)
- 确认书契约公式提取为 oracle:∏[1+(FR007i+利差)×di/365]−1、重置期含首不含尾、
  利率确定日=重置日上一营业日、末段 di 按实际日历日收口(来源 GuoLian 插件 4 份模板)
- 生产参数定格:重置频率 7 天/年化 365,唯一组合
- 保证金 5/6 声明不在矩阵内(独立余额模型+专属黄金回放护栏)
- 4 条合入硬规则:失败测试先行/扫兄弟格/黄金回放门禁/断言投影优先

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-16 11:03:21 +08:00
hjhanandClaude Opus 4.7 db447aa584 refactor(swap): 保证金腿在 GetInterests 循环入口提前路由,融资腿分支树去除 MarginModes 依赖
- 保证金腿(5/6)在最外层路由并 continue:本金(InterestPrincipalFix×closePrecent)、
  方向翻转、CalcMarginInterest 收口一处;newClosePercent 在保证金腿恒等于
  closePrecent,直接传参
- 融资腿(1/2/9)分支树内 3 处 MarginModes.Contains 归零,后续融资腿改动与保证金解耦
- GetFixedRate 前移为两路共用(纯读函数,已验证无副作用)
- 有意跳过 GetFloatRate:CalcMarginInterest 纯固定利率(FundingLegRate.Fixed/
  FloatRate 恒 0),浮动取价对保证金无意义;脏数据 FloatRateUnderlyingCode
  缺价时不再阻断保证金结算(唯一行为变化,方向更安全)
- 验证:SwapModule 537 用例 A/B(带改/不带改)摘要完全一致(71F/459P/7S),
  失败项均为本机无库环境失败;内网全量单测待跑

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-16 11:03:11 +08:00
hjhan 44e24b3172 refactor(margin): MarginModes 反转依赖 ConsTrade.InterestMarginModels 并删除 premiumModes 硬编码副本
- MarginModes.All/ForLinq/FixedAmountAndMargin 改为由框架常量 ConsTrade.InterestMarginModels 派生,消除 DAL 层独立重写集合(单一真源在 Core 层,本类退化为形态包装,避免新增保证金形态时口径分裂)
- SwapEodPositionService.premiumModes 局部 new List 字面量替换为 MarginModes.ForLinq(DAL 内部冗余副本消除)
- 重写 MarginModes.cs 过时的“复制 6 次/待收敛”注释,改为记录依赖方向与收敛历史;ForLinq 注释改为“派生自框架常量,仅做形态适配”
- 更新 MarginModesTest 类注释与一致性测试注释以反映派生关系
- 验证:YLErpDAL/UnitTestProject 编译 0 错误;MarginModesTest 5/5 通过
2026-08-16 10:47:45 +08:00
hjhan 04b5206134 test(infra): 缩短测试库连接超时 30s→2s 并加入 MSTest 并行 .runsettings
UnitTestProject/appsettings.json: 四个连接串 Connection Timeout=30→2,无库环境连不上 2 秒即失败,避免逐个 DB 测试 30s 空转;有库时 LAN 连接<1s 不受影响。新增 .runsettings: Workers=0(自动取 CPU 核数)+Scope=TestClass 类级并行,opt-in(仅 --settings 生效);共享静态单例(LogFactory/DataCacheManager/YLServiceLocator)启用前先跑串行基线确认无交叉污染。
2026-08-16 10:30:39 +08:00
hjhan 1d9bac4dd6 refactor(swap): 提取 EodSwapPositionQueries.ActiveByTradeAndDate 收口日终有效持仓查询
将 eod_swap_position 上'SwapTradeId + ValueDate + !Invalid'的 5 处重复谓词
(SwapEodPositionService.cs:2133/2195/2246/2487、ConfirmationGenerateContext.cs:2868)
收口到 EodSwapPositionQueries.ActiveByTradeAndDate(tradeId, valueDate),
与 SwapPositionQueries.ActiveByTrade 同构,零逻辑变更。
2026-08-15 13:44:53 +08:00
hjhan 3505e40c7e build(nuget): 新增仓库级 nuget.config 注册 Nexus 私有源
仓库此前无 nuget.config,全局 NuGet.Config 仅含 nuget.org,
导致沙箱/CI/新机器 dotnet restore 因找不到 Qdp.Pricing.*、YieldChain.Core
等带 -glms 后缀私有包而 NU1101。注册 Nexus nuget-group(v3, 匿名可读)
源后 build 可在任意环境复现。
2026-08-15 13:38:08 +08:00
hjhan f2c2f6052c refactor(swap): 提取 SwapPositionQueries.ActiveByTrade 收口有效持仓查询
- 新增 SwapPositionQueries.ActiveByTrade 静态扩展,收口 'SwapTradeId==X && !Invalid' 规则到单一真相
- 替换 SwapDealService/SwapEodPositionService/SwapTradeService 共 7 处纯重复谓词
- 仅返回 IQueryable,不调 SaveChanges,不动 FindTrade seam / 事务边界;行为保持等价
2026-08-15 12:48:44 +08:00
hjhan 9d91134789 docs(cleanup): 新增多租户死代码清理执行计划
- 量化衡泰对接/保证金其他家分支/其他家BizLogic/浙商定制/前端公司分支的死代码规模与门控方式
- 明确零风险清理 vs 需确认 GLMS 部署开关的中风险项(衡泰 HedgingSource/接回执开关、监管报表 DataSource 门控)
- 给出分阶段执行顺序与删除前编译验证 checklist
2026-08-15 10:49:40 +08:00
hjhan 1c19d2f7c5 fix(EQD-7049): 新建空白期权定价页跳过空标的默认查询,避免'标的信息缺失'弹窗
- 页面初始化时 updateUnderlying 以空 UnderlyingCode/InstrumentType/VarietyId 发起 /pricing/AjaxGetUnderlying,后端三者皆空返回 JsonError('标的信息缺失') 并自动弹窗
- 前端守卫:三者皆空时仅重置空 underlying 并 return,不再发请求,与后端 AjaxGetUnderlying(PricingController.cs:398-414) 判定精确对应
- 不影响正常路径:选类型(InstrumentType)/品种(VarietyId>0)/具体标的(UnderlyingCode) 仍照常查询
- 同步修改东莞定制版 structure_dz.js
2026-08-14 17:49:59 +08:00
hjhan ebc6070543 docs(swap): 删除 GetInterests 过期 XML 文档注释 posiLong/ShortNotionalValue
- 这两个形参已在 posiLong/posiShort 合并重构中移除,残留 <param> 注释具误导性

- 纯文档改动,零逻辑风险
2026-08-14 17:47:51 +08:00
hjhan ef37c8e71d refactor(swap): 合并多空名义本金参数为单一 posiTotalNotional 并加固测试
- DealInterests 的 posiLongNotionalValue + posiShortNotionalValue 合并为 posiTotalNotional(调用点以 posiLongNotional+posiShortNotional 求和传入),净减一个参数

- SwapDealService / SwapEodPositionService / InterestCalcRequest 同步收敛多空死管道参数

- 19 个测试调用点适配新签名

- SwapEodPositionServiceIntegrationTest 参数计数断言由裸数字改为参数名集合断言(CollectionAssert.AreEquivalent,对增删/重排/改名敏感)
2026-08-14 17:30:46 +08:00
hjhan fdf6357c4f fix(EQD-7049): 期权定价页标的下拉改为服务端搜索,移除全量标的下载
- vueUnderlying.lookup 不再遍历全量 ylotc.underlyings(债券十几万量级导致 29s 下载/页面卡死),改为调用 /frontdata/AjaxGetUnderlyingSelect 按关键词服务端搜索
- 默认预拉 20 条(后端 MaxShowLength 硬截断),输入时异步搜索并刷新缓存(乱序响应由 token 丢弃)
- 移除 BasicDataJs 的 标的Live 参数消除全量标的下载;IsCombined 由 IsSynthetic||IsBasket 映射,保留期权黑名单护栏(BlackLimit=1)
- 同步修改东莞定制版 Structure_DZ
2026-08-14 17:06:08 +08:00
hjhan 4a3fee9292 refactor(swap)+test: 删 GetInterests/CalcSwapInterests 死参数 needPrice/grossPrice;补工厂→接缝映射钉子
死参数收口(另一半):
- SwapDealService.GetInterests 删 needPrice/grossPrice(体内零消费,2026-08 验证);
  InitSwapDealInterest.needPrice 同为死参数一并删
- SwapEodPositionService.CalcSwapInterests 签名+转发同步;两个 EOD 生产调用点
  (SaveAutoEodInterestPosition/SaveEodInterestPositionCopy) 重排实参;
  CalcEodPostCloseSettleInterests/GetIntradayUnwindInterests 委托同步
- 14 个测试文件 ~44 处直调点机械更新(8 处 override 签名 + 36 处调用实参)
- 注意:EOD 编排链(DealInterests→Save*家族)的 grossPrice(期初不含费价)有真实用途,保留未动

新增钉子:CalcEodPostCloseSettleInterests 工厂→接缝参数映射测试——
CalcSwapInterestsCapture 捕获 stub 断言 EodPostCloseSettle 的完整转发契约
(posi=平仓后剩余/closePosi=平掉额/恒1/settment:false/orginPv 等 11 项)。
该段位置转发含三个相邻同型 decimal,编译器不查错位,此测试兜底。

验证:定向 241 测试通过(含 T0/T1 Excel 验证期望值、EntrySemantics 精确值钉子——
任何 decimal 错位即红);全量 903=145失败/746通过/12跳过,与基线逐位一致。
2026-08-14 16:57:56 +08:00
hjhan 018d7e777f refactor(swap): InterestCalcRequest 参数对象——GetInterests 双显式入口收敛为单参数
新增 InterestCalcRequest(SwapModule 根):
- 承载 GetInterests 全部有效入参(needPrice/grossPrice 死参数不承载),私有构造;
- 仅两个场景工厂可构造:IntradayUnwind(平仓前剩余/实际平掉额/B语义比例)、
  EodPostCloseSettle(平仓后剩余/实际平掉额/恒1全额结息)——工厂形参名即场景语义,
  物理上防止两套名义本金语义混传(6fdc7d80 错账的温床);
- GetIntradayUnwindInterests / CalcEodPostCloseSettleInterests 签名收敛为单参数 req,
  生产调用点(GetUnwindInterests / SaveAutoEodWithCloseInterestPosition)改工厂构造;
- 原 20 参 GetInterests / 19 参 CalcSwapInterests 保留为底层实现与测试兼容层(十余处测试直调,不动)。

验证:定向 140 测试通过;全量 902(+3 字符化测试)= 145失败/745通过/12跳过,
与基线逐位一致,零回归。
2026-08-14 15:57:52 +08:00
hjhan b01b485ee4 test(swap): GetInterests 双入口语义字符化测试——并实测发现复利口径分歧
钉住三组现状(Step3 特判降级的前置回归网):
- 复利×mode2×部分平仓30%:盘中=0.036164835616(closePosi=平掉额300 全程重放);
  EOD=0.059041913305(preEod待实现0.05 + 平掉额末段增量0.009042,closePercent==1 分支)
  ⚠️ 两值不等=同一经济事件两种结息额的口径分歧,已留档待业务裁决(勿当既定正确)
- 单利×mode2:双入口数值留档(Console),断言非零
- 复利×mode9 全平(posi=0):兜底覆盖生效,结息额非零(兜底钉子)

基建复用 GetInterestsUnitTest_T0 口径(T+0、4/27起息、11算头算尾、FR007内存取价stub)。
2026-08-14 15:52:52 +08:00
hjhan 01447ffe04 refactor(swap): GetInterests 传参语义显式化——盘中/EOD平仓后收盘拆双显式入口
问题:GetInterests 同名参数在两类调用方下语义相反,约定只存在于注释(2035e1df 固化):
  盘中(:489链)                EOD平仓后收盘(:1311链)
  posiNotionalValue  平仓前剩余本金  vs  平仓后剩余本金
  closePercent       实际平仓比例(B)  vs  恒1(全额结息)
  均走 settment:false 盘中重放算法。6fdc7d80 修的错账即两语义混用产物,
  mode2 无条件覆盖/mode9 全平兜底是粘合补丁。

改动(纯机械,零行为变化):
- SwapDealService 新增 GetIntradayUnwindInterests(preCloseNotional/closedNotional/
  closePercentRemaining 具名),GetUnwindInterests 切换调用;needPrice/grossPrice 为
  GetInterests 死参数(体内零消费),新入口不再暴露
- SwapEodPositionService 新增虚接缝 CalcEodPostCloseSettleInterests
  (remainingNotionalAfterClose/closedNotional/恒1),默认实现经 CalcSwapInterests
  转发——既有测试替身对该接缝的拦截不变;SaveAutoEodWithCloseInterestPosition 切换调用
- 原 GetInterests/CalcSwapInterests 签名与行为不动(测试直调兼容);EOD 增量路径
  (:1148/:1563, settment:true, closePosi=posi 同值) 语义自洽,本次不动

验证:全量 899 测试 145失败/742通过/12跳过——与 e2431e9d 基线逐位一致,零回归。
2026-08-14 15:39:44 +08:00
hjhan e2431e9d44 refactor(accrual): 计息类型整体迁入 DAL——新增 Accrual/InterestMath,删 Core 未接线孤儿
搬迁(算法体逐字未动,仅换命名空间与归属):
- SwapInterest.Round/AccrualDays/FundingLegPrecision + AccrualBoundary/InterestResult
  → YLErpDAL/Modules/SwapModule/Accrual/InterestMath.cs
- AccrualTrace → Accrual/AccrualTrace.cs(被迫同迁:其 MarkStart 引用 AccrualBoundary,
  Core 不能反向依赖 DAL)
- 引用切换:Simple/CompoundInterestAccrual、AccrualPolicy、SwapCalcTrace、SwapDealService
  (保留 using YLErp.Derivatives.Interest——IIndexFixer/IndexFixerBase 留 Core)

删除(零生产引用,孤儿清零):
- Core:SwapInterest.cs 算法方法(AccrueSimple/AccrueCompoundInArrears/ApplyUnwind/
  AccrueUnrealized/ToInterestRate,未接线且与 DAL 生产实现舍入/rollover 口径已分叉)、
  AccrualContext.cs、InterestRate.cs
- DAL:AccrualState.cs(零引用死类)
- 测试:SwapInterest_CompoundInArrears_RolloverTimingTests.cs(仅测已删原语)

验证:两解决方案 Rebuild 0 错误;磁盘 SwapInterest. 残留 0;影子/分红/场景 86/86 通过
(含 Accrual 3 影子对账、Margin 影子、divPower 新增 AutoUnwindMultiPartial)。
注:AccrualContext 默认精度 11 与生产 12 的分叉隐患随删除一并消除;
已删原语若将来重建须先补对账测试,勿凭记忆复原(ARCHITECTURE.md 已留警告)。
2026-08-14 15:31:04 +08:00
hjhan c0ac749e5b refactor(swap): 删除未接线的衡泰平仓消费死链 AutoSwapUnwindFromConsumer
- 移除 SwapDealService.AutoSwapUnwindFromConsumer 及其私有辅助
  GetUnwindInterestsByHT(全仓零调用方,随山证 v2.3.0 拷贝引入后从未接线)
- git rm 删除仅被该死链引用的 HengTaiModel/SwapUnwindReq.cs(全仓零引用)
- 修正 UnderlyingEntryFullPriceLeg.cs 中指向已删方法的文档注释
- 保留真实平仓路径 DealUnwind / CalcCloseAmount 等共享活代码
2026-08-14 15:14:09 +08:00
张名锐 11a7aabce5 Merge branch 'glms/feature/0812_zmr_divPower' into glms/feature/1.4.2 2026-08-14 14:51:56 +08:00
hjhan 58bd27c596 test(EQD-7004): 补自动平仓路径多次部分平仓不重复计入的实证测试——驱动真实 BondPaymentService.CalcPayment(reg_date 口径×当次平仓量 unwindQty),验证总额按登记日持仓分摊、不自洽多算 2026-08-14 14:24:23 +08:00
hjhan 896a5c3dcc test(EQD-7004): DividendEodNoDoubleCountTest 的 EodSvcStub.CalcBondPayment 由线性假公式改为桥接真实 BondPaymentService(reg_date 口径),使登记日全平/盘中互换端到端测试真正跑生产票息计算 2026-08-14 13:37:52 +08:00
hjhan 6a25e4a2d8 test(EQD-7004): 补 reg_date 口径端到端测试——EOD引擎按债权登记日计提,登记日T+1全平/部分平仓经GetPreEodDividendSum正确读取 2026-08-14 13:13:17 +08:00
hjhan fffdea4526 fix(EQD-7004): 分红关键链路日志 Debug 提升为 Info(生产可见,k8s console 可输出)
bdba5fbe 中加的分红日志原为 Debug 级;但生产 NLog minlevel=Info,k8s console 打不出来。

- 按决策改为 Info 级(5 处): BondPaymentService.GetBondPayments(reg_date 过滤区间+命中条数)、SwapDealService.GetPreEodPositionByDate(EOD 定位+回退)、GetPreEodDividendSum(取EOD日期+PosiDividendSum)、方案C 平仓预览/收益结算两处 DividendIn 赋值

此后日志一律不使用 Debug 级(生产不可见)。任务编号 EQD-7004。
2026-08-14 12:53:39 +08:00
hjhan 37b889c3bf test(dividend): 补全平端到端测试——登记日全平按交易场所规定不享有当日分红
全平场景端到端测试(DividendIn 由 GetPreEodDividendSum 真实算,非喂常量)。
登记日当日全平(盘中平仓→收盘持仓0),按各交易场所规定不享有登记日当日分红(股权登记日以收盘在册为准)。
系统行为正确:①DividendIn 读 T-1(=T日前待实现,正确不含当日);②EOD 全平 PosiQuantity=0 不计提当日。
断言:应得(T日前待实现)==实拿(DividendIn)(不享有当日符合规定)+ EOD 不计提当日。

合并原 d9a55fd1 + 830c72c4:前者误判'丢失缺陷',后者按业务规则修正为'不享有、系统正确'。
2026-08-14 12:49:45 +08:00
hjhan 830c72c485 test(dividend): 修正全平测试——登记日全平按交易场所规定不享有当日分红(系统行为正确)
业务澄清:登记日(股权登记日)以收盘在册为准,盘中全平→收盘持仓0→不在册→不享有当日分红。
系统行为(DividendIn 读T-1不含当日 + EOD PosiQuantity=0不计提当日)是正确的,非丢失非bug。

修正:全平测试从"特征化·已知缺陷 lost=10"改为"验证正确行为(不享有当日)"。
应得=T日前待实现累计(不含登记日当日);实拿=DividendIn;断言相等(不享有当日符合规定)+ EOD不计提当日。
2026-08-14 10:50:24 +08:00
hjhan d9a55fd11a test(dividend): 补全平特征化测试——登记日盘中全平当日分红丢失10(已知缺陷)
全平端到端测试(DividendIn 由 GetPreEodDividendSum 真实算)暴露:登记日盘中全平,当日分红丢失 10。
根因:①盘中 DividendIn 读 T-1(当日 EOD 未生成,漏当日新计);②EOD 全平 PosiQuantity=0 → TdPosiDividend=0(不计提当日)+ PosiDividendSum=0。当日分红既没进 DividendIn、也没进 PosiDividendSum,彻底丢失。

与收益互换(不扣持仓)对比:收益互换不丢失(当日新计挂 PosiDividendSum);全平丢失(扣持仓后 EOD 不计提)。
特征化断言 lost=10(锁定现状,CI 绿),注释待修复方向,修复后改回断言 lost=0。
2026-08-14 10:35:05 +08:00
hjhan 9bc6344f18 test(dividend): 补端到端测试——盘中互换DividendIn真实算+保存+EOD,验证不重复不丢失
填补 MU_001 缺口:MU_001 的互换 DividendIn 是测试喂的常量,本测试由生产方法 GetPreEodDividendSum 真实算出(读 EOD 快照),再喂给 EOD——覆盖"预览算 DividendIn + EOD 扣减"完整链路。

验证:盘中收益互换(不扣持仓) → DividendIn=GetPreEodDividendSum(读T-1) → 保存 → EOD:TdCloseDividend 扣减 DividendIn(不重复) + 当日新计进 PosiDividendSum(不丢失) + 守恒(全程新计-全程实现=末尾PosiDividendSum)。

内存 stub(DealSvcStub+EodSvcStub),不连库,进 CI。
2026-08-14 10:28:10 +08:00
hjhan bdba5fbecd fix(EQD-7004): 补全分红登记日口径修复的多次付息累计测试与Trace日志
原修复 9df39491 仅覆盖单次登记日(4/3)的两个单点修复,本次补全 EQD-7004 的完整验证与排查手段:

- 测试 GLMS20260105_0006 新增 4 个场景:5 期 reg_date 过滤口径各自命中正确子集;五期票息累计=5x36160=180800;auto 实现归0后下次登记日重新累加;4 期挂账累计读 144640

- 分红读取关键链路加 Debug 级日志(生产可关):BondPaymentService.GetBondPayments(reg_date 过滤区间+命中条数)、SwapDealService.GetPreEodPositionByDate(EOD 定位+回退)、GetPreEodDividendSum(取EOD日期+PosiDividendSum)、方案C 平仓预览/收益结算两处 DividendIn 赋值

实跑 dotnet test 全 GREEN(6/6)。任务编号 EQD-7004。
2026-08-14 10:05:01 +08:00
hjhan b2cbbff9e7 refactor(margin): 删除未接线的保证金死代码预留抽象
- 删除 MarginAccount 整类、IMarginResolver 子树(MarginForm/CashMargin/CreditMargin/GuaranteeMargin)、MarginBalance 只读 struct:全仓零生产实例化,结构上无法适配 CalcMarginInterest 的盘中差分模型。

- 删除仅覆盖上述死代码的 MarginLegTest(不损失活代码覆盖率)。

- 保留被 CalcMarginInterest 实际使用的 MarginCalc/MarginModes 活代码。

- 同步修剪 ARCHITECTURE.md 树图与对账表,清理 AccrualContext.cs 过期注释。
2026-08-14 08:55:37 +08:00
hjhan 909111ad2c docs(margin): 修正 CalcMarginInterest remarks——SwapIntervalList 是互换观察日排期而非FR007
第三次修正(前两次基于错误理解)。查证代码后准确描述:
- SwapIntervalList 是"互换观察日排期"(阶梯利率表 + 结息日历),非 FR007 浮动(浮动由 FloatRateUnderlyingCode + interest_rest_days 独立驱动);保证金前端亦开放分段录入
- rate 来自 GetFixedRate(SwapIntervalList 取 Date≤unwindDate 最近段)
- 盘中用该 rate 全程,与旧 CalcDailySimpleInterest 完全一致(BuildSegmentRates 的 spread 也是 GetFixedRate 单一值全程,不按 SwapIntervalList 切段)——阶梯利率盘中半路变更的精细处理是既有未覆盖口径,非本次引入;EOD 因每日重取 GetFixedRate 能正确反映阶梯
纯注释,零行为变化。
2026-08-14 08:22:49 +08:00