Files
zszq-trs/YLErpDAL/Modules/SwapModule/InterestCalcRequest.cs
T
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

92 lines
5.5 KiB
C#
Raw 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.
namespace YLErp.Modules.SwapModule;
/// <summary>
/// GetInterests 参数对象(2026-08 参数显式化)。
///
/// 动机:原 GetInterests 20 个位置参数中,名义本金簇(posiNotionalValue/closePosiNotionalValue/closePercent
/// 在【盘中平仓】与【EOD 平仓后收盘】两类场景下语义相反(详见 GetInterests "根因位置"注释与
/// GetInterestsEntrySemanticsTest 的口径留档),位置参数无法表达该约束。
///
/// 用法:只能经两个场景工厂构造——工厂形参名即该场景语义(平仓前剩余 / 平仓后剩余 / 实际平掉额),
/// 物理上防止两套语义混传。needPrice/grossPrice 为原方法死参数(体内零消费),本对象不承载。
/// </summary>
public sealed class InterestCalcRequest
{
public trade Td { get; }
public trade_extend TradeExtend { get; }
public DateTime ValueDate { get; }
public DateTime UnwindDate { get; }
public List<eod_swap_position> EodPositions { get; }
public List<swap_position> Positions { get; }
/// <summary>当日适用名义本金。语义随场景:盘中=平仓【前】剩余;EOD平仓后收盘=平仓【后】剩余;EOD增量=当前剩余。</summary>
public decimal PosiNotionalValue { get; }
public decimal PosiLongNotionalValue { get; }
public decimal PosiShortNotionalValue { get; }
/// <summary>本次实际平掉本金(两场景恒同义)。mode2 无条件覆盖 / mode9 全平兜底的输入。</summary>
public decimal ClosePosiNotionalValue { get; }
/// <summary>平仓比例。语义随场景:盘中=实际比例(B 占剩余);EOD平仓后收盘=恒1(全额结息)。</summary>
public decimal ClosePercent { get; }
public int EventType { get; }
public bool TdClose { get; }
public decimal OrginPv { get; }
public bool Add { get; }
public bool NewCalcLast { get; }
public List<swap_flow_event> CloseList { get; }
private InterestCalcRequest(
trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate,
List<eod_swap_position> eodPositions, List<swap_position> positions,
decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue,
decimal closePosiNotionalValue, decimal closePercent,
int eventType, bool tdClose, decimal orginPv,
bool add, bool newCalcLast, List<swap_flow_event> closeList)
{
Td = td; TradeExtend = tradeExtend; ValueDate = valueDate; UnwindDate = unwindDate;
EodPositions = eodPositions; Positions = positions;
PosiNotionalValue = posiNotionalValue; PosiLongNotionalValue = posiLongNotionalValue;
PosiShortNotionalValue = posiShortNotionalValue; ClosePosiNotionalValue = closePosiNotionalValue;
ClosePercent = closePercent; EventType = eventType; TdClose = tdClose; OrginPv = orginPv;
Add = add; NewCalcLast = newCalcLast; CloseList = closeList;
}
/// <summary>
/// 【盘中平仓/互换结息】场景(→ GetIntradayUnwindInterestssettment:false 盘中重放)。
/// </summary>
/// <param name="preCloseNotional">平仓【前】实时剩余本金(原 GetUnwindInterests.stockEqvNotional)。</param>
/// <param name="closedNotional">本次实际平掉本金(= preCloseNotional × closePercentRemaining)。</param>
/// <param name="closePercentRemaining">平仓比例,B 语义【占剩余】(前端传 A 占期初须先经 ToRemainingClosePercent 转换)。</param>
public static InterestCalcRequest IntradayUnwind(
trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate,
List<eod_swap_position> eodPositions, List<swap_position> positions,
decimal preCloseNotional, decimal preCloseLongNotional, decimal preCloseShortNotional,
decimal closedNotional, decimal closePercentRemaining,
int eventType, bool tdClose, decimal orginPv,
bool add, bool newCalcLast, List<swap_flow_event> closeList)
=> new(td, tradeExtend, valueDate, unwindDate, eodPositions, positions,
preCloseNotional, preCloseLongNotional, preCloseShortNotional,
closedNotional, closePercentRemaining,
eventType, tdClose, orginPv, add, newCalcLast, closeList);
/// <summary>
/// 【EOD 当日有平仓后的收盘结息】场景(→ CalcEodPostCloseSettleInterestssettment:false 全额结息)。
/// 该场景触发 GetInterests 内 mode2 无条件覆盖 / mode9 全平兜底(见其"根因位置"注释,勿删)。
/// </summary>
/// <param name="remainingNotionalAfterClose">平仓【后】剩余本金(GetInterests.posiNotionalValue 形参位)。</param>
/// <param name="closedNotional">本次实际平掉本金。</param>
public static InterestCalcRequest EodPostCloseSettle(
trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate,
List<eod_swap_position> eodPositions, List<swap_position> positions,
decimal remainingNotionalAfterClose, decimal remainingLongNotional, decimal remainingShortNotional,
decimal closedNotional,
int eventType, bool tdClose, decimal orginPv,
bool add, bool newCalcLast)
=> new(td, tradeExtend, valueDate, unwindDate, eodPositions, positions,
remainingNotionalAfterClose, remainingLongNotional, remainingShortNotional,
closedNotional, 1m, // 恒1:本次事件全额结息(非 closeNational / 期初比例)
eventType, tdClose, orginPv, add, newCalcLast, closeList: null);
}