refactor(swap): 优化基金公司行为处理逻辑 - finished001

- 修改 FindFundCorporateActions 方法以支持查询跨日期范围的公司行为记录
- 实现按生效日期和ID顺序稳定排序的多条公司行为记录处理
- 更新平仓时基金基线恢复逻辑以正确处理跨多个生效日的场景
- 在测试类中重写 FindFundCorporateActions 方法以支持单元测试验证
- 添加完整的跨非交易日公司行为恢复功能测试用例
This commit is contained in:
张名锐
2026-08-20 16:10:56 +08:00
parent b2f4e16782
commit ff7e540084
4 changed files with 78 additions and 6 deletions
@@ -198,6 +198,41 @@ namespace YLErp.Modules.SwapModule
"Fund 份额缩小为 0.01 倍时,直接平仓期初价应为 100 / 0.01 = 10000");
}
[TestMethod]
public void FCA_UW_009_登记日跨非交易日到生效日按范围恢复基金基线()
{
var eodDate = new DateTime(2026, 7, 12);
var effectiveDate = new DateTime(2026, 7, 13);
var unwindDate = new DateTime(2026, 7, 17);
var realtime = CreateRealtimeFundPosition();
var eod = CreateEod(eodDate, 1000m, 100m);
var service = CreateService(SwapDealTestFactory.CreateTrade(), realtime, eod, hasCompletedFlow: false);
service.ExDividendInfos.Add(new ex_dividend_info
{
id = 1,
UnderlyingCode = "FUND.TEST",
// 7/10 登记,7/13 生效;7/11、7/12 虽无交易但仍可能存在未除权 EOD 快照。
ExDividendDate = new DateTime(2026, 7, 10),
EffectiveDate = effectiveDate,
// 生产数据口径:1 拆 2 直接存 Split=2GiveShareAmount 不参与该拆分。
GiveShareAmount = 0m,
Split = 2m,
ValidStatus = true
});
var unwindData = CreateFullCloseUnwindData();
unwindData.ValueDate = unwindDate;
unwindData.UnwindDate = unwindDate;
Assert.IsTrue(service.RestoreEffectiveFundPositionForTest(unwindData, unwindDate));
Assert.AreEqual(2000m, realtime.PosiQuantity,
"7 月 17 日平仓应补应用 7 月 13 日生效的 Split=2,公司行为不能只按平仓日命中");
Assert.AreEqual(50m, realtime.PosiGrossPrice);
Assert.AreEqual(2000m, unwindData.PositionQty);
Assert.AreEqual(2000m, unwindData.CloseQty);
Assert.AreEqual(50m, unwindData.FlowEvents.Single().PosiGrossPrice);
}
[TestMethod]
public void FCA_UW_003_正式平仓按FundEod基线重算PnL和现金()
{
@@ -60,6 +60,20 @@ namespace YLErp.Modules.SwapModule
&& x.UnderlyingCode == underlyingCode
&& x.EffectiveDate == valueDate.Date);
protected override List<ex_dividend_info> FindFundCorporateActions(
string underlyingCode,
DateTime eodDate,
DateTime valueDate)
=> ExDividendInfos
.Where(x => x.ValidStatus
&& x.UnderlyingCode == underlyingCode
&& x.EffectiveDate.HasValue
&& x.EffectiveDate.Value.Date > eodDate.Date
&& x.EffectiveDate.Value.Date <= valueDate.Date)
.OrderBy(x => x.EffectiveDate)
.ThenBy(x => x.id)
.ToList();
protected override decimal GetFundCorporateActionClosePrice(
ex_dividend_info dividendInfo,
decimal fallbackPrice)