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跳过,与基线逐位一致。
This commit is contained in:
@@ -147,7 +147,7 @@ namespace YLErp.Modules.SwapModule
|
||||
|
||||
var eodPostClose = CreateService().GetInterests(td, td.trade_extend, UnwindDate, UnwindDate,
|
||||
eodPositions, positions, Remaining, Remaining, 0m, Closed, 1m,
|
||||
(int)SwapEventTypeEnum.平仓, tdClose: false, needPrice: true, grossPrice: 1m, orginPv: PreClose,
|
||||
(int)SwapEventTypeEnum.平仓, tdClose: false, orginPv: PreClose,
|
||||
add: true, settment: false, newCalcLast: false, closeList: null);
|
||||
|
||||
Assert.AreEqual(1, intraday.Count);
|
||||
@@ -182,7 +182,7 @@ namespace YLErp.Modules.SwapModule
|
||||
|
||||
var eodPostClose = CreateService().GetInterests(td, td.trade_extend, UnwindDate, UnwindDate,
|
||||
eodPositions, positions, Remaining, Remaining, 0m, Closed, 1m,
|
||||
(int)SwapEventTypeEnum.平仓, tdClose: false, needPrice: true, grossPrice: 1m, orginPv: PreClose,
|
||||
(int)SwapEventTypeEnum.平仓, tdClose: false, orginPv: PreClose,
|
||||
add: true, settment: false, newCalcLast: false, closeList: null);
|
||||
|
||||
Assert.AreEqual(1, intraday.Count);
|
||||
@@ -210,7 +210,7 @@ namespace YLErp.Modules.SwapModule
|
||||
// 全平:剩余=0,平掉=全部 1000
|
||||
var result = CreateService().GetInterests(td, td.trade_extend, UnwindDate, UnwindDate,
|
||||
eodPositions, positions, 0m, 0m, 0m, PreClose, 1m,
|
||||
(int)SwapEventTypeEnum.平仓, tdClose: false, needPrice: true, grossPrice: 1m, orginPv: PreClose,
|
||||
(int)SwapEventTypeEnum.平仓, tdClose: false, orginPv: PreClose,
|
||||
add: true, settment: false, newCalcLast: false, closeList: null);
|
||||
|
||||
Assert.AreEqual(1, result.Count);
|
||||
@@ -218,5 +218,90 @@ namespace YLErp.Modules.SwapModule
|
||||
Assert.IsTrue(result[0].InterestAmount != 0m,
|
||||
"mode9 全平时 posi=0,兜底必须以 closePosiNotionalValue(实际平掉额) 为结息本金,结息额非零(兜底钉子)");
|
||||
}
|
||||
|
||||
#region CalcEodPostCloseSettleInterests 接缝映射钉子
|
||||
|
||||
/// <summary>
|
||||
/// 参数捕获 stub:拦下 CalcSwapInterests 的全部实参,不触库、不真算。
|
||||
/// </summary>
|
||||
private sealed class CalcSwapInterestsCapture : TestableSwapEodPositionService
|
||||
{
|
||||
public CalcSwapInterestsCapture() : base(nameof(GetInterestsEntrySemanticsTest)) { }
|
||||
|
||||
public List<swap_flow_event> CapturedCloseList = null;
|
||||
public bool CapturedTdClose;
|
||||
public int CapturedEventType;
|
||||
public decimal CapturedPosiNotional;
|
||||
public decimal CapturedClosePosiNotional;
|
||||
public decimal CapturedClosePercent;
|
||||
public decimal CapturedOrginPv;
|
||||
public bool CapturedAdd;
|
||||
public bool CapturedSettment;
|
||||
public bool CapturedNewCalcLast;
|
||||
public int CallCount;
|
||||
|
||||
protected override List<swap_flow_event> CalcSwapInterests(
|
||||
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 closePrecent,
|
||||
int eventType, bool tdClose,
|
||||
decimal orginPv,
|
||||
bool add = false, bool settment = true, bool newCalcLast = false,
|
||||
List<swap_flow_event> closeList = null)
|
||||
{
|
||||
CallCount++;
|
||||
CapturedTdClose = tdClose; CapturedEventType = eventType;
|
||||
CapturedPosiNotional = posiNotionalValue; CapturedClosePosiNotional = closePosiNotionalValue;
|
||||
CapturedClosePercent = closePrecent; CapturedOrginPv = orginPv;
|
||||
CapturedAdd = add; CapturedSettment = settment; CapturedNewCalcLast = newCalcLast;
|
||||
CapturedCloseList = closeList;
|
||||
return new List<swap_flow_event>();
|
||||
}
|
||||
|
||||
public List<swap_flow_event> ExposedEodPostCloseSettle(InterestCalcRequest req)
|
||||
=> CalcEodPostCloseSettleInterests(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 钉死 InterestCalcRequest.EodPostCloseSettle 工厂 → CalcEodPostCloseSettleInterests →
|
||||
/// CalcSwapInterests 的位置参数转发契约。这段转发是位置传参最易错位的环节
|
||||
/// (posiNotionalValue/closePosiNotionalValue/orginPv 三个相邻同型 decimal,编译器不查错位),
|
||||
/// 任何映射改动(含将来删 needPrice/grossPrice 死参数)都必须保持本断言绿。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void EOD平仓后收盘_工厂到接缝_参数映射钉死()
|
||||
{
|
||||
var td = CreateTrade();
|
||||
var position = CreatePosition(InterestModeEnum.合约名义本金规模, InterestTypeEnum.单利);
|
||||
var preEod = CreatePreEod(interestSum: 0.05m, principal: PreClose);
|
||||
var positions = new List<swap_position> { position };
|
||||
|
||||
var stub = new CalcSwapInterestsCapture();
|
||||
var req = InterestCalcRequest.EodPostCloseSettle(
|
||||
td, td.trade_extend, UnwindDate, UnwindDate,
|
||||
new List<eod_swap_position> { preEod }, positions,
|
||||
remainingNotionalAfterClose: Remaining, remainingLongNotional: Remaining, remainingShortNotional: 0m,
|
||||
closedNotional: Closed,
|
||||
eventType: (int)SwapEventTypeEnum.平仓, tdClose: false,
|
||||
orginPv: PreClose, add: true, newCalcLast: false);
|
||||
|
||||
stub.ExposedEodPostCloseSettle(req);
|
||||
|
||||
Assert.AreEqual(1, stub.CallCount, "默认实现应恰好调用一次 CalcSwapInterests(虚接缝兼容既有测试替身)");
|
||||
Assert.AreEqual(Remaining, stub.CapturedPosiNotional, "posiNotionalValue 位 = 平仓后剩余(700)——语义核心,错位即红");
|
||||
Assert.AreEqual(Closed, stub.CapturedClosePosiNotional, "closePosiNotionalValue 位 = 实际平掉额(300)");
|
||||
Assert.AreEqual(1m, stub.CapturedClosePercent, "closePrecent 恒 1(全额结息)");
|
||||
Assert.AreEqual((int)SwapEventTypeEnum.平仓, stub.CapturedEventType);
|
||||
Assert.IsFalse(stub.CapturedTdClose);
|
||||
Assert.AreEqual(PreClose, stub.CapturedOrginPv, "orginPv 位 = 上一日终本金——与相邻 decimal 最易错位处");
|
||||
Assert.IsTrue(stub.CapturedAdd);
|
||||
Assert.IsFalse(stub.CapturedSettment, "settment=false:走盘中重放算法(EOD平仓后收盘复用重放)");
|
||||
Assert.IsFalse(stub.CapturedNewCalcLast);
|
||||
Assert.IsNull(stub.CapturedCloseList, "该场景不传 closeList");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user