test(swap): EQD-6968 补不算头不算尾(00)组合——CalcFirst=false 零覆盖盲区
- Red_Compound_NoHeadNoTail:00+缺平仓日价 → 放行(calcLast 同 false,与 10 同口径) - CalcFirst_Simple_NoHeadDropsExactlyStartDayInterest:单利下 00 与 10 利息差 恰好=开始日一天利息(精确断言,钉 CalcFirst 回归)。closeRate 取 7/6 定盘同值, 免疫既有取价细节——排查中发现:无日终快照+00 时 fetchAfter=interestStart-1 会 跳过开始日取价、首段利率用种子(GetFloatRate 回写的尾日定盘),与 10 的 fetchAfter=开始日-1 不同(FIX 日志可复现,niche 场景:首个日终前平仓)。 Run 运行器扩参:settment / exerciseDate(供后续 EOD 与到期日用例)。 验证:GLMS20260817Fr007UnwindMorningTest 25/25 内存全绿
This commit is contained in:
@@ -97,7 +97,7 @@ namespace YLErp.Modules.SwapModule
|
||||
private static OptUserInfo MakeOptUser() =>
|
||||
new(0, nameof(GLMS20260817Fr007UnwindMorningTest), OptUserFrom.UnitTest);
|
||||
|
||||
private static trade BuildTrade(DateTime closeDate, string calcMode = "10")
|
||||
private static trade BuildTrade(DateTime closeDate, string calcMode = "10", DateTime? exerciseDate = null)
|
||||
{
|
||||
var extend = new trade_extend
|
||||
{
|
||||
@@ -117,7 +117,7 @@ namespace YLErp.Modules.SwapModule
|
||||
TradeType = "债券TRS",
|
||||
TradeDate = TradeDate,
|
||||
StartDate = StartDate,
|
||||
ExerciseDate = closeDate.AddDays(1),
|
||||
ExerciseDate = exerciseDate ?? closeDate.AddDays(1),
|
||||
TradeStatus = "已平仓",
|
||||
ValidState = "Valid",
|
||||
trade_extend = extend
|
||||
@@ -183,7 +183,9 @@ namespace YLErp.Modules.SwapModule
|
||||
int interestRule = 0,
|
||||
bool newCalcLast = false,
|
||||
Dictionary<DateTime, double> market = null,
|
||||
DateTime? omitDate2 = null)
|
||||
DateTime? omitDate2 = null,
|
||||
bool settment = false,
|
||||
DateTime? exerciseDate = null)
|
||||
{
|
||||
var cd = closeDate ?? CloseDate;
|
||||
var omit = new HashSet<DateTime>();
|
||||
@@ -195,7 +197,7 @@ namespace YLErp.Modules.SwapModule
|
||||
else if (!includeCloseDate) omit.Add(cd.Date);
|
||||
|
||||
var svc = new StubSwapDealService(MakeOptUser(), omit, closeRate, market);
|
||||
var td = BuildTrade(cd, calcMode);
|
||||
var td = BuildTrade(cd, calcMode, exerciseDate);
|
||||
var position = BuildPosition(interestType, cd, restDays, interestRule);
|
||||
var eodList = preEod == null
|
||||
? new List<eod_swap_position>()
|
||||
@@ -207,7 +209,7 @@ namespace YLErp.Modules.SwapModule
|
||||
new List<swap_position> { position },
|
||||
Notional, Notional, closePrecent,
|
||||
(int)SwapEventTypeEnum.平仓, false, Notional,
|
||||
false, settment: false, newCalcLast: newCalcLast, closeList: null);
|
||||
false, settment: settment, newCalcLast: newCalcLast, closeList: null);
|
||||
Assert.AreEqual(1, interests.Count, "应返回恰好 1 条利息事件");
|
||||
return new Outcome { Fe = interests[0] };
|
||||
}
|
||||
@@ -421,5 +423,35 @@ namespace YLErp.Modules.SwapModule
|
||||
preEod: BuildPreEod(new DateTime(2026, 7, 13))),
|
||||
"单利 算尾(11)+当日非重置日+当日缺价 → 应放行");
|
||||
}
|
||||
|
||||
// ── 不算头不算尾(calcMode="00"):CalcFirst=false 组合 ──
|
||||
// 对尾日 FR007 行为与"10"一致(calcLast 同 false);另以单利精确断言钉 CalcFirst 语义——
|
||||
// "00" 比"10"恰好少计开始日一天的利息(单利无基数效应,差值可精确到分毫)。
|
||||
|
||||
[TestMethod]
|
||||
public void Red_Compound_NoHeadNoTail_WithoutCloseDateFr007_Succeeds()
|
||||
{
|
||||
AssertNoThrow(Run(InterestTypeEnum.复利, includeCloseDate: false, calcMode: "00",
|
||||
preEod: BuildPreEod(new DateTime(2026, 7, 13))),
|
||||
"不算头不算尾(00)+缺平仓日价 → 应放行(与10同口径,尾日不参与计息)");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CalcFirst_Simple_NoHeadDropsExactlyStartDayInterest()
|
||||
{
|
||||
// closeRate=0.0142 与 7/6 定盘相同:使"00"首段种子利率与"10"首段取价利率一致,
|
||||
// 断言只对"少计开始日一天"敏感,免疫无日终快照时 fetchAfter=interestStart-1
|
||||
// 跳过 7/6 取价、首段用种子利率的既有取价细节。
|
||||
var w10 = Run(InterestTypeEnum.单利, includeCloseDate: true, calcMode: "10", closeRate: 0.0142);
|
||||
var w00 = Run(InterestTypeEnum.单利, includeCloseDate: true, calcMode: "00", closeRate: 0.0142);
|
||||
Assert.IsFalse(w10.Threw, "10 不应抛:" + w10.Ex?.Message);
|
||||
Assert.IsFalse(w00.Threw, "00 不应抛:" + w00.Ex?.Message);
|
||||
// 开始日 7/6 属首段:all-in = spread(-0.0155) + 定盘(0.0142) = -0.0013;
|
||||
// 单利下 00 与 10 的利息差 = 恰好首日一天利息(年化 A365)。
|
||||
var expectedStartDayInterest = Notional * (Spread + 0.0142m) / AnnualDays;
|
||||
Assert.AreEqual(expectedStartDayInterest, w10.Fe.InterestAmount - w00.Fe.InterestAmount, 0.0000001m,
|
||||
"不算头(00)应恰好少计开始日一天利息(CalcFirst 回归锚)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user