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。
This commit is contained in:
@@ -103,6 +103,16 @@ namespace YLErp.Modules.SwapModule
|
||||
DataState = (int)SwapFlowDateStateEnum.完成
|
||||
};
|
||||
|
||||
private static swap_flow_event CloseEvent(decimal qty, decimal dividendIn, DateTime eventDate) => new swap_flow_event
|
||||
{
|
||||
SwapTradeId = SwapTradeId, EventType = (int)SwapFlowEventTypeEnum.平仓,
|
||||
PositionId = PositionId, Quantity = qty, DividendIn = dividendIn,
|
||||
MarkClosePnl = 0m, CloseFee = 0m, TradingFeePending = 0m,
|
||||
TradingAmount = qty * 1.000m,
|
||||
UnwindDate = eventDate, EventDate = eventDate, PayDate = eventDate,
|
||||
DataState = (int)SwapFlowDateStateEnum.完成
|
||||
};
|
||||
|
||||
private static void AssertDecimalEqual(decimal expected, decimal actual, decimal tol, string msg)
|
||||
=> Assert.IsTrue(Math.Abs(expected - actual) <= tol, $"{msg}: expected={expected} actual={actual}");
|
||||
|
||||
@@ -159,5 +169,63 @@ namespace YLErp.Modules.SwapModule
|
||||
Console.WriteLine($"[EOD 后] TdPosiDividend={r2.TdPosiDividend} TdCloseDividend={r2.TdCloseDividend} PosiDividendSum={r2.PosiDividendSum}");
|
||||
Console.WriteLine($"结论:互换实现 {dividendIn} 被扣减(不重复);当日新计 {r2.TdPosiDividend} 挂 PosiDividendSum(不丢失)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 盘中全平(扣持仓→PosiQuantity=0):验证登记日当日分红是否丢失。
|
||||
///
|
||||
/// 全平 vs 收益互换的关键区别:全平扣持仓,EOD 时 PosiQuantity=0 → 当日新计 TdPosiDividend 不计提(:1834 守卫)
|
||||
/// + PosiDividendSum 归 0(:1856 else)。若盘中 DividendIn 读 T-1(漏当日新计),则当日分红
|
||||
/// 既没进 DividendIn、也没进 PosiDividendSum → 丢失。本测试暴露这个风险。
|
||||
///
|
||||
/// 序列(StartDate=1/5,每日 0.01×1000=10):
|
||||
/// D1=1/6 无事件 Copy:PosiDividendSum=10
|
||||
/// D2=1/7 盘中全平:DividendIn=GetPreEodDividendSum(读 D1)=10(漏 D2 当日);EOD:PosiQuantity=0→TdPosiDividend=0, PosiDividendSum=0
|
||||
/// 应得(登记日持仓享当日)= D1累计(10) + D2当日(10) = 20;实拿 = DividendIn(10) + PosiDividendSum(0) = 10 → 丢失 10
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void 特征化_登记日全平_当日分红丢失10_已知缺陷待修复()
|
||||
{
|
||||
var eodSvc = new EodSvcStub();
|
||||
var td = CreateTrade();
|
||||
var position = CreatePosition();
|
||||
var initialEod = CreateInitialEod();
|
||||
|
||||
// D1=1/6 无事件 EOD
|
||||
var d1 = new DateTime(2026, 1, 6);
|
||||
var r1 = eodSvc.ExecuteCopyEodPosition(initialEod, td, d1, StartDate);
|
||||
AssertDecimalEqual(10m, r1.PosiDividendSum, 0.01m, "D1 PosiDividendSum");
|
||||
|
||||
// D2=1/7 盘中全平:DividendIn 由生产方法真实算(读 D1 EOD,当日 EOD 未生成)
|
||||
var d2 = new DateTime(2026, 1, 7);
|
||||
var dealSvc = new DealSvcStub(
|
||||
new List<eod_swap> { new eod_swap { SwapTradeId = SwapTradeId, ValueDate = d1 } },
|
||||
new List<eod_swap_position> { r1 });
|
||||
decimal dividendIn = dealSvc.ExposeGetPreEodDividendSum(SwapTradeId, PositionId, d2);
|
||||
AssertDecimalEqual(10m, dividendIn, 0.01m, "全平 DividendIn=读T-1(D1)=10(漏 D2 当日新计)");
|
||||
|
||||
// 全平事件(扣全部持仓)
|
||||
var closeEvent = CloseEvent(InitialQty, dividendIn, d2);
|
||||
|
||||
// D2=1/7 EOD(UpdateEodPosition,全平→PosiQuantity=0)
|
||||
var r2 = eodSvc.ExecuteUpdateEodPosition(position, r1, td, d2, d1, new List<swap_flow_event> { closeEvent });
|
||||
|
||||
// 登记日持仓应享当日分红:D1累计 + D2当日(若持仓>0 本应计提 = 1天×0.01×1000=10)
|
||||
decimal d2AccrualIfHeld = DailyRatePerUnit * 1 * InitialQty;
|
||||
decimal expectedTotal = r1.PosiDividendSum + d2AccrualIfHeld; // 应得 = 10 + 10 = 20
|
||||
decimal actualGot = dividendIn + r2.PosiDividendSum; // 实拿 = DividendIn + 末尾挂着
|
||||
decimal lost = expectedTotal - actualGot;
|
||||
|
||||
Console.WriteLine($"[全平] D1累计={r1.PosiDividendSum}, D2当日(若计提)={d2AccrualIfHeld}, 应得={expectedTotal}");
|
||||
Console.WriteLine($"[全平] DividendIn={dividendIn}, EOD:TdPosiDividend={r2.TdPosiDividend} PosiDividendSum={r2.PosiDividendSum} PosiQuantity={r2.PosiQuantity}");
|
||||
Console.WriteLine($"[全平] 实拿={actualGot}, 丢失={lost}");
|
||||
|
||||
// 【特征化·已知缺陷】登记日盘中全平,当日分红丢失 10(D2当日新计既没进 DividendIn 也没进 PosiDividendSum)。
|
||||
// 根因:①盘中 DividendIn=GetPreEodDividendSum 读 T-1(当日 EOD 未生成,漏当日新计);
|
||||
// ②EOD 全平 PosiQuantity=0 → TdPosiDividend=0(:1834 不计提当日)+ PosiDividendSum=0(:1856)。
|
||||
// 待修复:GetPreEodDividendSum 当日 EOD 不存在时补算当日分红,或全平 EOD 按登记日持仓计提。
|
||||
// 修复后改回 AssertDecimalEqual(0m, lost, ...)(不丢失)。
|
||||
AssertDecimalEqual(10m, lost, 0.01m,
|
||||
$"【已知缺陷】登记日盘中全平当日分红丢失={lost}(应得{expectedTotal}, 实拿{actualGot})。待修复。");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user