feat(bond): 添加公司行为现金分红标识并优化付息计算逻辑

- 在 BondPayment 模型中添加 IsCorporateActionCashDividend 属性用于区分不同数据来源
- 修改 BondPaymentService 中的 CalcPayment 方法,按每条记录来源分别处理金额单位转换
- 更新单元测试以验证混合债券付息和公司行为分红的正确计算
- 移除不再需要的 useBondPriceScale 参数简化方法接口
- 修正注释说明以反映新的按记录类型分别计算的逻辑
This commit is contained in:
张名锐
2026-08-21 16:51:55 +08:00
parent 02da9d78a3
commit 392e36a820
5 changed files with 55 additions and 46 deletions
@@ -2156,18 +2156,13 @@ namespace YLErp.Modules.SwapModule
int shortRatio = DirectionRatio.LongShort(flowEvent.PositionType);
int directionRatio = DirectionRatio.ReceivePay(flowEvent.PayDirection);
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(flowEvent.UnderlyingCode);
// 债券付息按每百元票息存储,继续走 BondPriceConverterStock/Fund 的公司行为
// 现金分红按每 10 份金额存储,实际现金 = payment_interest * qty / 10,不能 /100
// 标的资料缺失时保持旧债券口径,避免未知标的的历史平仓金额被放大。
var useBondPriceScale = um == null
|| !SwapEodPositionService.IsCorporateActionInstrument(um.UnderlyingInstrumentType);
// + 付息日>上日日终且小于等于平仓日期的分红数据
// 期间付息和公司行为现金分红可能同时命中;BondPaymentService 逐条按来源单位换算,
// 原生 bond_payment_info 记录按每 100 份,公司行为表补充记录按每 10 份
var dividendIn = servie.CalcPayment(
payments,
unwindQty,
shortRatio,
directionRatio,
useBondPriceScale);
directionRatio);
decimal tax = um?.ValueAddedTax ?? 0;
dividendIn = DividendCalc.AfterTaxRaw(dividendIn, tax);
@@ -342,25 +342,19 @@ namespace YLErp.Modules.SwapModule
/// <summary>
/// 计算期间现金流(生产: BondPaymentService;测试: 返回固定值)。
/// BondPaymentService 的默认仍是债券百分比价格口径;TRS Stock/Fund 的公司行为
/// 分红按每 10 份金额入库,因此必须显式关闭 BondPriceConverter 的 /100 换算。
/// 标的资料缺失时沿用债券口径,避免把未知历史数据放大 100 倍
/// BondPaymentService 会按每条付款记录的数据来源换算:bond_payment_info 原生期间付息
/// 按每 100 份,公司行为表补充的现金分红按每 10 份。不能只按 Fund/Stock 标的类型
/// 选择一个统一除数,否则两类记录同时命中时会错算
/// </summary>
protected virtual decimal CalcBondPayment(string underlyingCode, DateTime fromDate, DateTime toDate, decimal qty, int shortRatio, int directionRatio)
{
var underlying = GetUnderlyingData(underlyingCode);
// 本期现金分红只覆盖 TRS Stock/Fund。其他非债券(期货、期权等)虽然也不属于
// 债券,但尚未接入本现金分红表,继续使用默认债券换算,避免扩大改造范围。
var useBondPriceScale = underlying == null
|| !IsCorporateActionInstrument(underlying.UnderlyingInstrumentType);
return new BondPaymentService(UserInfo).CalcPayment(
underlyingCode,
fromDate,
toDate,
qty,
shortRatio,
directionRatio,
useBondPriceScale);
directionRatio);
}
// ---- SwapPositionCompose 路径专用 seam(借鉴 testable 分支)----