refactor(swap-eod): 抽出期末头寸纯函数并放宽可见性
SetFixedLegRealizedPnl 替换4处复制粘贴(清理L1296双分号); NormalizeInterestSignForReport 替换16行内联报表分支; CalculateWeightedMarginInterest private->public static。均为纯静态无实例依赖,配套无库单测锁定行为。
This commit is contained in:
@@ -1023,7 +1023,7 @@ namespace YLErp.Modules.SwapModule
|
||||
//累计已实现
|
||||
newEodPayPosition.RealizedInterest = eodPayPosition.RealizedInterest + newEodPayPosition.TdCloseInterest * ratio;
|
||||
newEodPayPosition.RealizedInterestFee = eodPayPosition.RealizedInterestFee + newEodPayPosition.TdCloseInterestFee;
|
||||
newEodPayPosition.RealizedPnl = newEodPayPosition.RealizedInterest + newEodPayPosition.RealizedInterestFee;
|
||||
SetFixedLegRealizedPnl(newEodPayPosition);
|
||||
var currencyRate = GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, valueDate, true,
|
||||
position.InterestDirection == (int)SwapDirectionEnum.收取 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
|
||||
newEodPayPosition.TdCurrency = Convert.ToDecimal(currencyRate);
|
||||
@@ -1157,7 +1157,7 @@ namespace YLErp.Modules.SwapModule
|
||||
//累计已实现
|
||||
newEodPayPosition.RealizedInterest = eodPayPosition.RealizedInterest + newEodPayPosition.TdCloseInterest * ratio;
|
||||
newEodPayPosition.RealizedInterestFee = eodPayPosition.RealizedInterestFee + newEodPayPosition.TdCloseInterestFee;
|
||||
newEodPayPosition.RealizedPnl = newEodPayPosition.RealizedInterest + newEodPayPosition.RealizedInterestFee;
|
||||
SetFixedLegRealizedPnl(newEodPayPosition);
|
||||
var currencyRate = GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, valueDate, true,
|
||||
position.InterestDirection == (int)SwapDirectionEnum.收取 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
|
||||
newEodPayPosition.TdCurrency = Convert.ToDecimal(currencyRate);
|
||||
@@ -1293,7 +1293,7 @@ namespace YLErp.Modules.SwapModule
|
||||
//累计已实现
|
||||
newEodPayPosition.RealizedInterest = eodPayPosition.RealizedInterest + newEodPayPosition.TdCloseInterest * ratio;
|
||||
newEodPayPosition.RealizedInterestFee = eodPayPosition.RealizedInterestFee + newEodPayPosition.TdCloseInterestFee;
|
||||
newEodPayPosition.RealizedPnl = newEodPayPosition.RealizedInterest + newEodPayPosition.RealizedInterestFee; ;
|
||||
SetFixedLegRealizedPnl(newEodPayPosition);
|
||||
var currencyRate = GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, valueDate, true,
|
||||
position.InterestDirection == (int)SwapDirectionEnum.收取 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
|
||||
newEodPayPosition.TdCurrency = Convert.ToDecimal(currencyRate);
|
||||
@@ -1415,7 +1415,7 @@ namespace YLErp.Modules.SwapModule
|
||||
//累计已实现
|
||||
newEodPayPosition.RealizedInterest = eodPayPosition.RealizedInterest + newEodPayPosition.TdCloseInterest * ratio;
|
||||
newEodPayPosition.RealizedInterestFee = eodPayPosition.RealizedInterestFee + newEodPayPosition.TdCloseInterestFee;
|
||||
newEodPayPosition.RealizedPnl = newEodPayPosition.RealizedInterest + newEodPayPosition.RealizedInterestFee;
|
||||
SetFixedLegRealizedPnl(newEodPayPosition);
|
||||
var currencyRate = GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, valueDate, true,
|
||||
eodPayPosition.InterestDirection == (int)SwapDirectionEnum.收取 ? CurrencyRateType.Buy : CurrencyRateType.Sell);
|
||||
newEodPayPosition.TdCurrency = Convert.ToDecimal(currencyRate);
|
||||
@@ -2087,6 +2087,28 @@ namespace YLErp.Modules.SwapModule
|
||||
+ position.RealizedInterestFee;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 风险报表符号归一化:把历史两种符号口径的 TdCloseInterest/RealizedInterest
|
||||
/// 统一按"绝对金额 × 业务方向"重写。普通利息腿收取为正、支付为负;
|
||||
/// 预付金腿利息方向与保证金本金方向相反。随后重算 RealizedPnl。
|
||||
/// 抽为 public static 纯函数以支持无库单测(见 SwapReportInterestSignNormalizeTest)。
|
||||
/// 仅当 InterestDirection > 0 时执行(与原内联逻辑等价)。
|
||||
/// </summary>
|
||||
public static void NormalizeInterestSignForReport(eod_swap_position position)
|
||||
{
|
||||
if (position.InterestDirection <= 0) return;
|
||||
|
||||
var interestRatio = position.InterestDirection == (int)SwapDirectionEnum.收取 ? 1m : -1m;
|
||||
if (ConsTrade.InterestMarginModels.Contains(position.InterestMode))
|
||||
{
|
||||
interestRatio = -interestRatio;
|
||||
}
|
||||
position.TdCloseInterest = Math.Abs(position.TdCloseInterest) * interestRatio;
|
||||
position.RealizedInterest = Math.Abs(position.RealizedInterest) * interestRatio;
|
||||
// 兼容修复前已落库的利息腿:当时只累计了明细字段,未同步写入 RealizedPnl。
|
||||
position.RealizedPnl = position.RealizedInterest + position.RealizedInterestFee;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取多空组合 平仓详细
|
||||
/// </summary>
|
||||
@@ -2179,22 +2201,9 @@ namespace YLErp.Modules.SwapModule
|
||||
item.eodPosition.PosiNetFeePrice *= multiplier;
|
||||
item.eodPosition.PosiNetNoFeePrice *= multiplier;
|
||||
item.eodPosition.UnderlyingPrice *= multiplier;
|
||||
if (item.eodPosition.InterestDirection > 0)
|
||||
{
|
||||
// 历史数据的 TdCloseInterest、RealizedInterest 存在两种符号口径,
|
||||
// 风险报表统一按绝对金额和业务方向还原:普通利息腿收取为正、支付为负,
|
||||
// 预付金腿的利息方向与保证金本金方向相反。
|
||||
var interestRatio = item.eodPosition.InterestDirection == (int)SwapDirectionEnum.收取 ? 1m : -1m;
|
||||
if (ConsTrade.InterestMarginModels.Contains(item.eodPosition.InterestMode))
|
||||
{
|
||||
interestRatio = -interestRatio;
|
||||
}
|
||||
item.eodPosition.TdCloseInterest = Math.Abs(item.eodPosition.TdCloseInterest) * interestRatio;
|
||||
item.eodPosition.RealizedInterest = Math.Abs(item.eodPosition.RealizedInterest) * interestRatio;
|
||||
// 兼容修复前已落库的利息腿:当时只累计了明细字段,未同步写入 RealizedPnl。
|
||||
item.eodPosition.RealizedPnl = item.eodPosition.RealizedInterest
|
||||
+ item.eodPosition.RealizedInterestFee;
|
||||
}
|
||||
// 历史数据的 TdCloseInterest、RealizedInterest 存在两种符号口径,
|
||||
// 风险报表统一按绝对金额和业务方向还原,并重算 RealizedPnl。
|
||||
NormalizeInterestSignForReport(item.eodPosition);
|
||||
}
|
||||
return retListResult;
|
||||
|
||||
@@ -2630,12 +2639,24 @@ namespace YLErp.Modules.SwapModule
|
||||
/// <summary>
|
||||
/// 计算预付金利息金额。InterestIncomeSum 已是各腿利息金额,
|
||||
/// 按收取为正、支付为负直接轧差求和,不做本金加权。
|
||||
/// 抽为 public static 纯函数以支持无库单测(见 SwapWeightedMarginInterestTest)。
|
||||
/// </summary>
|
||||
private static decimal CalculateWeightedMarginInterest(IEnumerable<eod_swap_position> margins)
|
||||
public static decimal CalculateWeightedMarginInterest(IEnumerable<eod_swap_position> margins)
|
||||
{
|
||||
return margins.Sum(x =>
|
||||
x.InterestIncomeSum * (x.InterestDirection == (int)SwapDirectionEnum.收取 ? 1 : -1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 固定利息腿的累计已实现盈亏 = 累计已实现利息 + 累计已实现利息费用。
|
||||
/// 4 处 SaveAutoEodInterestPosition/SaveEodInterestPosition 路径口径一致,
|
||||
/// 抽为 public static 纯函数以支持无库单测(见 SwapFixedLegRealizedPnlTest),
|
||||
/// 并消除复制粘贴带来的笔误风险(如 L1296 历史双分号)。
|
||||
/// </summary>
|
||||
public static void SetFixedLegRealizedPnl(eod_swap_position position)
|
||||
{
|
||||
position.RealizedPnl = position.RealizedInterest + position.RealizedInterestFee;
|
||||
}
|
||||
/// <summary>
|
||||
/// 将数据库中以公司/交易簿记方向保存的日终字段转换为客户视角。
|
||||
/// 该转换必须在拆分浮动收益、费用和期间付息/分红之前完成,
|
||||
|
||||
Reference in New Issue
Block a user