refactor(return-leg): 抽取 PositionValueCalc 持仓价值汇总

SwapEodPositionService 8处 SwapPositionValue inline 公式替换:
- 4处 InterestProfitSum * ratio + PosiProfitSum → PositionValueCalc.Calc(带ratio)
- 4处 InterestProfitSum + PosiProfitSum → PositionValueCalc.Calc(默认ratio=1)

持仓价值 = 利息端收益 + 浮动端收益, 8处副本→1个纯函数。
这是最后一个高性价比的纯函数提取。

验证: 编译0错误, 全量513测试7失败(基线一致)。
This commit is contained in:
hjhan
2026-08-11 16:50:21 +08:00
parent 744f1ae448
commit 16c44d3b50
3 changed files with 48 additions and 8 deletions
@@ -0,0 +1,25 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using YLErp.Modules.SwapModule.ReturnLegs;
namespace UnitTestProject.Modules.SwapModule.ReturnLegs
{
[TestClass]
public class PositionValueCalcTest
{
[TestMethod]
public void _利息加浮动()
=> Assert.AreEqual(1500m, PositionValueCalc.Calc(1000m, 500m));
[TestMethod]
public void _利息乘1()
=> Assert.AreEqual(1500m, PositionValueCalc.Calc(1000m, 500m, 1m));
[TestMethod]
public void _利息乘负1()
=> Assert.AreEqual(-500m, PositionValueCalc.Calc(1000m, 500m, -1m));
[TestMethod]
public void _等于浮动端()
=> Assert.AreEqual(500m, PositionValueCalc.Calc(0m, 500m));
}
}
@@ -0,0 +1,15 @@
namespace YLErp.Modules.SwapModule.ReturnLegs;
/// <summary>
/// 持仓价值(SwapPositionValue)汇总。
///
/// SwapPositionValue = 利息端收益 + 浮动端收益。
/// 利息端可能带方向因子(收取/支付),浮动端不含方向因子。
/// 原代码在 SwapEodPositionService 8处重复此公式(1115/1258/1519/1647/1746/1830/1938/2113)。
/// </summary>
public static class PositionValueCalc
{
/// <summary>持仓价值 = 利息端 × 方向因子 + 浮动端。</summary>
public static decimal Calc(decimal interestProfitSum, decimal posiProfitSum, decimal ratio = 1m)
=> interestProfitSum * ratio + posiProfitSum;
}
@@ -1112,7 +1112,7 @@ namespace YLErp.Modules.SwapModule
}
newEodPayPosition.InterestProfitSum = newEodPayPosition.InterestIncomeSum + newEodPayPosition.InterestFeeSum;
//持仓价值
newEodPayPosition.SwapPositionValue = newEodPayPosition.InterestProfitSum * ratio + newEodPayPosition.PosiProfitSum;
newEodPayPosition.SwapPositionValue = PositionValueCalc.Calc(newEodPayPosition.InterestProfitSum, newEodPayPosition.PosiProfitSum, ratio);
//累计已实现
newEodPayPosition.RealizedInterest = eodPayPosition.RealizedInterest + newEodPayPosition.TdCloseInterest * ratio;
@@ -1255,7 +1255,7 @@ namespace YLErp.Modules.SwapModule
: RoundEodInterest(eodPayPosition.InterestFeeSum + newEodPayPosition.TdInterestFee - newEodPayPosition.TdCloseInterestFee);
newEodPayPosition.InterestProfitSum = newEodPayPosition.InterestIncomeSum + newEodPayPosition.InterestFeeSum;
//持仓价值
newEodPayPosition.SwapPositionValue = newEodPayPosition.InterestProfitSum * ratio + newEodPayPosition.PosiProfitSum;
newEodPayPosition.SwapPositionValue = PositionValueCalc.Calc(newEodPayPosition.InterestProfitSum, newEodPayPosition.PosiProfitSum, ratio);
//累计已实现
newEodPayPosition.RealizedInterest = eodPayPosition.RealizedInterest + newEodPayPosition.TdCloseInterest * ratio;
@@ -1516,7 +1516,7 @@ namespace YLErp.Modules.SwapModule
// InterestProfitSum 是利息腿待实现总额,包含利息和费用;无费用时等于 InterestIncomeSum。
newEodPayPosition.InterestProfitSum = newEodPayPosition.InterestIncomeSum + newEodPayPosition.InterestFeeSum;
//持仓价值
newEodPayPosition.SwapPositionValue = newEodPayPosition.InterestProfitSum * ratio + newEodPayPosition.PosiProfitSum;
newEodPayPosition.SwapPositionValue = PositionValueCalc.Calc(newEodPayPosition.InterestProfitSum, newEodPayPosition.PosiProfitSum, ratio);
Log.Info($"InterestIncomeSum is {eodPayPosition.InterestIncomeSum},TdInterestIncome is {newEodPayPosition.TdInterestIncome}" +
$",TdCloseInterest is {newEodPayPosition.TdCloseInterest}");
@@ -1644,7 +1644,7 @@ namespace YLErp.Modules.SwapModule
newEodPayPosition.InterestFeeSum = eodPayPosition.InterestFeeSum + newEodPayPosition.TdInterestFee - newEodPayPosition.TdCloseInterestFee;
newEodPayPosition.InterestProfitSum = newEodPayPosition.InterestIncomeSum + newEodPayPosition.InterestFeeSum;
//持仓价值
newEodPayPosition.SwapPositionValue = newEodPayPosition.InterestProfitSum * ratio + newEodPayPosition.PosiProfitSum;
newEodPayPosition.SwapPositionValue = PositionValueCalc.Calc(newEodPayPosition.InterestProfitSum, newEodPayPosition.PosiProfitSum, ratio);
//累计已实现
newEodPayPosition.RealizedInterest = eodPayPosition.RealizedInterest + newEodPayPosition.TdCloseInterest * ratio;
@@ -1743,7 +1743,7 @@ namespace YLErp.Modules.SwapModule
newEodPayPosition.PosiProfitSum = newEodPayPosition.PosiMtmPnL + newEodPayPosition.PosiDividendSum + newEodPayPosition.PosiFeePending;
//持仓价值
newEodPayPosition.SwapPositionValue = newEodPayPosition.InterestProfitSum + newEodPayPosition.PosiProfitSum;
newEodPayPosition.SwapPositionValue = PositionValueCalc.Calc(newEodPayPosition.InterestProfitSum, newEodPayPosition.PosiProfitSum);
//累计已实现
newEodPayPosition.RealizedFee = closeFee;
newEodPayPosition.RealizedMtmPnL = newEodPayPosition.TdCloseMtmPnl;
@@ -1827,7 +1827,7 @@ namespace YLErp.Modules.SwapModule
, seekPreday: true, currencyRateType: curretEod.PosiDirection == (int)SwapDirectionEnum. ? CurrencyRateType.Buy : CurrencyRateType.Sell);
curretEod.TdCurrency = Convert.ToDecimal(currencyRate);
//持仓价值
curretEod.SwapPositionValue = curretEod.InterestProfitSum + curretEod.PosiProfitSum;
curretEod.SwapPositionValue = PositionValueCalc.Calc(curretEod.InterestProfitSum, curretEod.PosiProfitSum);
UpdateDbOption(curretEod);
curretEod.Invalid = false;
if (curretEod.id == 0)
@@ -1935,7 +1935,7 @@ namespace YLErp.Modules.SwapModule
, seekPreday: true, currencyRateType: curretEod.PosiDirection == (int)SwapDirectionEnum. ? CurrencyRateType.Buy : CurrencyRateType.Sell);
curretEod.TdCurrency = Convert.ToDecimal(currencyRate);
//持仓价值
curretEod.SwapPositionValue = curretEod.InterestProfitSum + curretEod.PosiProfitSum;
curretEod.SwapPositionValue = PositionValueCalc.Calc(curretEod.InterestProfitSum, curretEod.PosiProfitSum);
UpdateDbOption(curretEod);
curretEod.Invalid = false;
if (curretEod.id == 0)
@@ -2110,7 +2110,7 @@ namespace YLErp.Modules.SwapModule
curretEod.PosiNotionalValue = 0;
}
//持仓价值
curretEod.SwapPositionValue = curretEod.InterestProfitSum + curretEod.PosiProfitSum;
curretEod.SwapPositionValue = PositionValueCalc.Calc(curretEod.InterestProfitSum, curretEod.PosiProfitSum);
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, td.StartDate.Value
, seekPreday: true, currencyRateType: curretEod.PosiDirection == (int)SwapDirectionEnum. ? CurrencyRateType.Buy : CurrencyRateType.Sell);
curretEod.TdCurrency = Convert.ToDecimal(currencyRate);