Commit Graph
1372 Commits
Author SHA1 Message Date
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 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
hjhan 67d7733ed6 docs(margin): 修正 CalcMarginInterest remarks——SwapIntervalList 单段是保证金本性而非限制
第2点措辞修正:原写"SwapIntervalList 必须单段(多段会漏分段)"误导,把业务本性误述成代码限制。
实际:保证金=固定利率(业务定义),SwapIntervalList 多段是融资腿 FR007 概念与保证金无关;
CalcMarginInterest 只消费 rate(GetFixedRate 已处理分段),不直接读 SwapIntervalList,
单段 segmentRates 是对固定利率的正确建模。纯注释,零行为变化。
2026-08-14 08:14:32 +08:00
hjhan 692b8d753b docs(margin): 补强 CalcMarginInterest 隐式假设/契约注释 + SwapEodPositionService orginPv 冗余说明
- CalcMarginInterest 加 <remarks>:显性化 4 点——InterestType 必须单利、SwapIntervalList 必须单段(违反静默算错、无 assert,前端保证)、方向须调用方翻转、preEod 首日就地修改;附定位指引(SwapCalcTrace 反推 accrualBasis)
- SwapEodPositionService 三处 FixedAmountAndMargin 的 orginPv 赋值加注释:仅固定值腿(mode 1)生效,保证金(5/6)被 CalcMarginInterest 忽略

纯注释,零代码行为变化;全量 SwapModule 524/524 通过。
2026-08-13 18:32:22 +08:00
tengyufan 8afd449c40 feat(ClientBlack): 新增客户黑名单审批流程
- 黑名单新增、删除、批量导入、批量移出在配置审批节点后,审批通过才生效
- 新增黑名单待提交后可提交审批;仅首节点未审批时可撤回,进入后续节点禁止撤回
- 增加黑名单审批列表、审批弹窗、审批操作日志及状态筛选
- 支持审批配置中的“黑名单审批”流程及对应菜单、模块权限、操作权限
- 黑名单审批中禁止同名记录覆盖备注;已在黑名单中的同名导入会明确提示本次将修改备注
- 未配置审批节点时保持原有直接生效行为
- 增加黑名单审批状态机单测,39/39 通过
- 修正撤回全部失败时仍提示“撤回审批成功”的问题
2026-08-13 17:21:04 +08:00
hjhan 9df39491da fix(dividend): 分红按债权登记日(reg_date)口径计提,手动互换读取当日EOD快照 (GLMS-20260105-0006)
- BondPayment 实体补映射 reg_date(债权登记日,对应 bond_payment_info.reg_date 列)
- BondPaymentService.GetBondPayments 改按 reg_date 过滤(原错用 pay_date_PL/支付日;pay_date_PL 是理论付息日,仍属支付日,非登记日)
- SwapDealService.GetPreEodPositionByDate 由 ValueDate < dealDate 改 <=,登记日当天手动互换读当日EOD分红而非T-1
- 新增 GLMS20260105_0006_RegisterDateDividendTest 回归测试(手工合成内存,先RED复现后GREEN 2/2)

根因:bond_payment_info 表仅有 pay_date_PL(理论付息日)/pay_date_act(实际付息日) 两个支付日,缺登记日;
代码用支付日判定票息归属,且手动互换只读 T-1 EOD 快照;登记日≠支付日(恰差一工作日)时缺陷被掩盖,
导致对话框分红收益显示 0。
2026-08-13 12:31:45 +08:00
张名锐 04f4468be5 refactor(trade): 优化除权信息处理逻辑和数据查询策略
- 在 FindExDividendByBusinessKey 方法中添加注释说明业务唯一键按"标的 + 自然日"定义
- 实现字段独立合并策略,当前值非零时覆盖旧值,为零时保留旧值
- 保存前统一截断时间部分,确保同一天不同时间能命中同一个自然日业务键
- 先在当前批次内按业务键归并,避免重复行生成多条数据库记录
- 除权数据查询时不使用 SQL 左连接,防止重复行扩增影响风险计算
- 使用不区分大小写的 UnderlyingCode 匹配,兼容代码大小写差异
- 除权记录不参与 SQL 左连接,先完成基础关联再内存查找唯一记录
- 风险对象的除权 Pv 重算规则与持仓处理保持一致,仅在股票交易类型下执行
2026-08-13 11:09:50 +08:00
hjhan dea9c4cba5 docs(margin): 修复保证金计息重构后的过时文档与注释
按最新代码(CalcMarginInterest 已接生产、orginPv hack 已删、MarginAccount 未接线、保证金精度=12)修正:
- 删除 orginPv 维度重映射的孤儿 summary(方法已删)
- SwapDealService 注释:去掉 orginPv(InitSwapDealInterest)/保证金腿 引用
- SwapInterest/AccrualContext/InterestRate:去掉 Precision=11 是"保证金腿"、"保证金场景"等错误归因(保证金实际跑精度12)
- MarginAccount/MarginBalance:标注"尚未接线",生产入口指向 CalcMarginInterest,去掉"余额×利率×天数"过度简化
- 测试注释:去掉"无 orginPv/差分"(盘中保留差分)、"提交2 待切换"(已完成)

仅文档/注释,零代码行为变化。
2026-08-13 10:58:47 +08:00
张名锐 5a51d66970 refactor(dividend): 优化除权除息计算逻辑并改进数据类型精度
- 将除权除息相关数值字段从 double 类型改为 decimal 类型以提高精度
- 重构了红利比率计算方法 GetRatio,新增 GetRatioDecimal 方法使用 decimal 计算
- 修改价格和持仓数量计算逻辑,统一使用 decimal 进行高精度运算
- 更新数据库查询逻辑,将篮子标的判断从 IsBasket() 方法改为 CommodityCode 条件
- 优化 AddDividendInfos 方法中的批量处理逻辑,增加业务键冲突检测
- 添加数据源标识字段 DataSource 和来源更新时间字段 SourceUpdatedAt
- 新增 FindExDividendByBusinessKey 和 MergeNonZeroDividendValues 辅助方法
- 更新结算服务中除权除息信息的获取方式,使用字典查找替代 LINQ JOIN
- 修复前端保存除权信息时的响应处理逻辑
- 为基金类型也开放除权功能,不仅限于股票类型
- 添加单元测试验证篮子标的查询翻译逻辑的正确性
2026-08-13 10:53:57 +08:00
hjhan 9b29211d3c refactor(margin): 保证金计息切换到 CalcMarginInterest + 删 orginPv 外部维度 hack
- GetInterests 保证金分支(5/6)切到 CalcMarginInterest,不再走融资腿通用 CalcEodInterest/CalcUnwindInterest
- 删除 InitSwapDealInterest 的保证金 orginPv 维度 hack(保证金已不走该方法,成为死代码)
- CalcMarginInterest 修正三处与旧管线的对齐(全量回归发现):
  · 加 endDate 参数(盘中用 InitInterestDate 的 endDate,否则少算天数)
  · calcLast 合并 newCalcLast(与 CalcUnwindInterest 一致,算尾)
  · 盘中保留 accrualBasis 差分(posiPrincipal 对齐状态路径相关,单一本金变量无法覆盖;orginPv 内部按 PreviousBalance 算,消除外部维度 hack)
- 更新 Shadow/GoldenReplay 测试调用点(加 endDate)

修正说明:盘中“消除差分”不可行——SPC_006(position 已对齐) 与 PrepaidPrincipalCloseTrace(position 未对齐) 期望相反,差分 accrualBasis 经 orginPv 自适应两种状态。CalcMarginInterest 真实收益收敛为:保证金领域独立 + orginPv 内聚 + 消除浮动/分段/复利死分支,而非消除差分。EOD 路径无差分(用昨日终本金)。

验证:全量 SwapModule 522/522 通过(0 失败);真实库黄金回放 60 条 0 差异。
2026-08-13 10:39:03 +08:00
hjhan 7243684839 test(margin): 新增真实库黄金回放验证——96库60条EOD逐日比对,新旧管线0差异
- MarginInterestGoldenReplayTest:连 192.168.2.96 测试库,对真实保证金交易(GLMS-20260701-0008/-0013/-0006)逐日 EOD 比对旧管线 GetInterests(settment=true) vs 新方法 CalcMarginInterest
- 结果:60 条腿×日比对,InterestAmount/TdInterestAmount 严格一致(容差1e-6),0 不一致
- 覆盖真实边界:追加预付金多行(base 135555/200000 各自计息)、InterestProfitSum 累计滚动、跨 EOD 续接
- 为提交2(切换生产+删 orginPv hack)建立真实数据安全网
2026-08-13 09:59:48 +08:00
hjhan af1b4fd27f refactor(longshort): 全量移除多空组合(StructType)子系统死代码(无入口/无存量,按需求重写优于维护) 2026-08-13 09:50:25 +08:00
hjhan a86b496f87 test(margin): 新增 CalcMarginInterest 影子对账——保证金计息消除 orginPv/差分,与旧管线数值一致
- 新增 CalcMarginInterest(SwapDealService):保证金专属计息,复用 SimpleInterestAccrual 纯函数,notional 直接取保证金余额(EOD=昨日终本金/盘中=今日本金),消除融资腿差分公式 accrualBasis=TdInterestPrincipal+posiPrincipal-orginPv 与 orginPv 维度 hack(对保证金 accrualBasis 恒等于 posiPrincipal,差分冗余)
- 保留累计语义(priorAccrued+增量),满足下游 SwapEodPositionService 字段契约
- 新增 MarginInterestShadowTest:5 场景对账(EOD 续接/首日、盘中全平/部分平仓/互换),新旧 InterestAmount/TdInterestAmount 严格一致
- 本提交仅影子对账,生产路径未改(GetInterests 仍走 CalcEodInterest/CalcUnwindInterest);下一步提交2 切换生产 + 删 orginPv hack

零生产风险;编译 0 错误;影子对账 5/5 + 现有保证金/利息回归 60/60 通过。
2026-08-13 09:37:42 +08:00
hjhan 905bd407e2 refactor(frontend): 清理已删除利息模式 7/8 的前端死分支
后端 InterestModeEnum 已删除 mode 7/8(无历史数据),前端对应分支恒不成立。
移除 swaptrade 下 6 个 JS 文件中的 ==7/==8 死分支,并精简仅校验 mode7/8
唯一性的 checkSwapRateList(保留 changeInterestMode 方法签名以对齐 cshtml 绑定)。
2026-08-13 09:05:58 +08:00
hjhan 70550af29a refactor(funding-leg): 清理CalcNotional死参数posiLong/posiShort+修正过时InterestMode注释
- 删除 IFundingLegStrategy.CalcNotional 的 posiLong/posiShort 死参数(多空存续腿界面已禁用,三个实现均不读取),同步三个实现签名、SwapDealService 唯一调用点、FundingLegStrategyTest 7 处调用
- 修正 SwapPosition/SwapFlowEvent/EodSwapPosition 的 InterestMode 字段注释(去掉已删的 3/4,补全 5/6/9)
- 重写 SwapUnwindFloatingLegDiagnosticTdd 过时类注释

零行为变化;编译 0 错误;FundingLegStrategyTest 11/11 通过。
2026-08-13 08:51:21 +08:00
hjhan beb13ff52f docs: 删除不适用的利息部分平仓尾差缺陷分析文档
该文档分析的几个 bug 结论不正确,已不再适用,移除。
2026-08-13 08:38:51 +08:00
hjhan 50bc6562da chore: 删除误提交的 TdCarryInCharacterizationTest 占位测试(沙箱漂移产生的无意义文件) 2026-08-12 18:29:51 +08:00
hjhan dfdc890749 test: 补全 SaveAutoSwapDeal 的测试 seam——修复6个AS_*测试失败
- SwapEodPositionService: AddSwapEvent 虚方法(已存在)替换 line 741 的 new SwapEventService 直调

- SwapEodPositionService: 新增 PersistFlowEvent 虚方法,替换 line 749/760 的 DbContext.swap_flow_event.Add 直调

- TestableSwapEodPositionService: PersistFlowEvent 改为 override

- BondTrsAutoSwapScenarioTest.AutoSwapEodService: override PersistFlowEvent 同步到 PersistedFlowEvents

测试: 511→517 通过,7→0 失败
2026-08-12 18:23:51 +08:00
hjhan 84820a3203 test: 修复预存在测试失败-AddClientCashInCashOut no-op override + FR007取价失败兜底
- TestableSwapEodPositionService: override AddClientCashInCashOut 与 AddClientCash 同构 no-op,修复6个AS_*测试客户信息未找到异常

- GLMS20260805ClosePercentDiffDiagnoseTest: FR007取价失败走 Inconclusive(与连不上库同语义,外部数据依赖不应判为测试失败)

AS_* 仍有深层失败(自动互换未触发,interestList=0),属预存在的测试数据问题,需单独排查
2026-08-12 18:08:47 +08:00
hjhan f1f7cae832 refactor(accrual): 抽取BuildSegmentRates共享分段取率+清理needPrice死参数
- 抽取 BuildSegmentRates:统一单利/复利分段取率循环,参数化 fetchAfterDate (单利传 ValueDate 仅取新段,复利传 null 全程取)

- 修复 BuildSegmentRates static→instance:访问实例属性 IndexFixer

- 清理 CalcDaily 层 needPrice 死参数:4个 CalcDaily* 方法签名移除 needPrice;上层 CalcSwapInterests/GetInterests 保留 (virtual seam/位置参数兼容)

- 修复 6 处调用点 needPrice 参数传递

- 新增影子测试:单利+FR007浮动+部分平仓+历史归档,验证 segmentRates 一致

- 新增 TdCarryInCharacterizationTest:钉死部分平仓 TdInterestAmount carry-in 行为

测试: 511通过 / 7预存在失败(数据依赖) / 9跳过
2026-08-12 18:02:36 +08:00
hjhan c412f918d9 refactor(swap): Phase3 提取ClosePercentMath共享模块
SwapDealService的4个public static ClosePercent方法body搬到ClosePercentMath.cs:
- ResolveUnwindPreviousNotional (上一日终浮动端名义本金)
- ToRemainingClosePercent (A→B 占期初→占剩余)
- ToOriginalClosePercent (B→A 逆转换)
- CalcDefaultInitClosePercent (默认占期初比例)

DealService保留4个一行转发壳, 外部调用(含6+测试文件)零改动
核实EodService内联closePercent公式与此不同, 非重复, 不替换
SwapModule零回归(7基线/510通过)
2026-08-12 17:31:39 +08:00
hjhan 69295f31ce refactor(eod): Phase2 提取EodPnlCalculator——11个static方法搬出SwapEodPositionService
SwapEodPositionService的static纯计算方法搬到EodPnlCalculator.cs:
- private→internal: RoundMoney/RoundEodInterest/NormalizeEodPositionForStorage/SetFloatingRealizedPnl/FillPositionLegSummary/SumInterestPnL/CalculateWeightedMarginRate
- public留转发壳: CalculateSwapRealizedPnl/NormalizeInterestSignForReport/CalculateWeightedMarginInterest/SetFixedLegRealizedPnl

SwapEodPositionService内所有调用点加EodPnlCalculator前缀
SwapModule零回归(7基线/510通过)
2026-08-12 16:46:13 +08:00
hjhan 40756a28b3 refactor(accrual): BuildLegRate/BuildEodPolicy移到各自类型(Phase1补完)
BuildLegRate → FundingLegRate.Build(position, spread, float) — 利率值对象的自然工厂
BuildEodPolicy → AccrualPolicy.BuildEod(position, annualDays, isCompound) — 计息政策的自然工厂

SwapDealService删除2个private static定义, 4处调用点改用类型方法
SwapModule零回归(7基线/510通过)
2026-08-12 16:32:04 +08:00
hjhan b9362ea700 refactor(swap): Phase1 提取UnwindNormalizer+TradingFeeCalc出SwapDealService
SwapDealService的10个private static纯逻辑方法搬到两个新文件:
- UnwindNormalizer.cs: NormalizeNotionalValues/FullCloseRequest/Recalculate/IsFullClose/SettledInterestAmounts/EventUnwindDate (6个)
- TradingFeeCalc.cs: CalcInitTradingFee/CalcInitTradingFeePending (2个)

SwapDealService内21处调用点加类名前缀, 反射测试改为直接调用(public)
SwapModule零回归(7基线/510通过)
2026-08-12 16:26:12 +08:00
hjhan 89eae7555f docs: 任务4 EOD续接风险分析 + SwapDealService方向比例收口
新增 docs/eod-continuation-proposal.md:
- 记录4个风险(并本金起点/consumedInterest语义/resetCarry/全平重放)
- 记录验证方案(6场景影子测试)
- 标注待立项,不混入日常重构

SwapDealService 收尾: 3处内联方向比例→DirectionRatio.ReceivePay
- line389: PosiDirection收取?-1:1 → -ReceivePay
- line1104/1235: InterestDirection==1?1:-1 → ReceivePay

SwapModule零回归(7基线/510通过)
2026-08-12 15:24:15 +08:00
张名锐 304e04d60a Merge remote-tracking branch 'origin/glms/feature/1.4.2' into glms/feature/1.4.2 2026-08-12 15:10:06 +08:00
hjhan 8419d53421 refactor(eod): MtmCalc.BlendPrice提取加权均价混合(候选J)
4处内联 (prevPrice*prevQty + sum) / total → MtmCalc.BlendPrice(...)
SwapModule零回归(7基线/510通过)

候选K(单点TdRealizedPnL)/L(2处guard差InterestType)/M(2处guard)/N(单点)为低频,
提取收益不足以抵消新增方法的开销, 暂不提取
2026-08-12 15:03:00 +08:00