尝试去掉第2级(TdInterestPrincipal)导致5个保证金测试失败。 根因: 生产 EOD 归档(eod_swap_position(35774))的 InterestPrincipalFix=0, 只有 TdInterestPrincipal 有值。第2级不是死代码, 不可删。 恢复三级 fallback, 补充注释说明每级命中的真实场景。 教训: 不能只看赋值点判断字段是否有值, 必须看实际数据。 验证: 编译0错误, 全量509测试7失败(基线一致)。
50 lines
2.0 KiB
C#
50 lines
2.0 KiB
C#
using YLErp.DBModels;
|
||
|
||
namespace YLErp.Modules.SwapModule.Margin;
|
||
|
||
/// <summary>
|
||
/// 保证金计算工具。从 SwapDealService 剥离的保证金纯函数。
|
||
/// </summary>
|
||
public static class MarginCalc
|
||
{
|
||
/// <summary>
|
||
/// 取上一日终保证金余额。
|
||
///
|
||
/// 三级优先级(均有测试覆盖,不可简化):
|
||
/// 1. InterestPrincipalFix——EOD 归档赋值时的首选字段
|
||
/// 2. TdInterestPrincipal——部分 EOD 归档路径未写 InterestPrincipalFix(值为0),
|
||
/// 此时 TdInterestPrincipal 含正确的保证金本金(生产 eod_swap_position(35774) 即此场景)
|
||
/// 3. fallback——首次平仓(preEod.id==0, 无归档)时用当日保证金余额
|
||
/// </summary>
|
||
public static decimal PreviousBalance(eod_swap_position preEod, decimal fallback)
|
||
{
|
||
var previous = preEod.InterestPrincipalFix != 0m
|
||
? preEod.InterestPrincipalFix
|
||
: preEod.TdInterestPrincipal;
|
||
return preEod.id != 0 && previous != 0m ? previous : fallback;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保证金方向翻转。保证金利息是券商付给客户(方向与融资腿相反)。
|
||
/// </summary>
|
||
public static int FlipDirection(int direction)
|
||
=> direction == (int)SwapDirectionEnum.收取
|
||
? (int)SwapDirectionEnum.支付
|
||
: (int)SwapDirectionEnum.收取;
|
||
|
||
/// <summary>
|
||
/// 汇总保证金腿的平仓返还金额(SwapMarginAmount)和保证金返息(SwapMarginRebatePnl)。
|
||
/// 保证金方向与融资腿相反:interestRatio = InterestDirection==1 ? -1 : 1。
|
||
/// </summary>
|
||
public static void AccumulateSettlement(List<swap_flow_event> interestList, UnwindData unwindData)
|
||
{
|
||
foreach (var x in interestList)
|
||
{
|
||
if (!MarginModes.Contains(x.InterestMode)) continue;
|
||
var interestRatio = x.InterestDirection == 1 ? -1m : 1m;
|
||
unwindData.SwapMarginRebatePnl += x.InterestClosePnL;
|
||
unwindData.SwapMarginAmount += x.InterestPrincipal * interestRatio;
|
||
}
|
||
}
|
||
}
|