diff --git a/UnitTestProject/Modules/SwapModule/ReturnLegs/DividendCalcTest.cs b/UnitTestProject/Modules/SwapModule/ReturnLegs/DividendCalcTest.cs
new file mode 100644
index 00000000..20a842ad
--- /dev/null
+++ b/UnitTestProject/Modules/SwapModule/ReturnLegs/DividendCalcTest.cs
@@ -0,0 +1,37 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using YLErp.Modules.SwapModule.ReturnLegs;
+
+namespace UnitTestProject.Modules.SwapModule.ReturnLegs
+{
+ [TestClass]
+ public class DividendCalcTest
+ {
+ [TestMethod]
+ public void AfterTax_零税率_等于原值()
+ {
+ Assert.AreEqual(1000m, DividendCalc.AfterTax(1000m, 0m));
+ }
+
+ [TestMethod]
+ public void AfterTax_6pct增值税()
+ {
+ // 1000 / 1.06 * 0.94 = 886.79...
+ Assert.AreEqual(886.79m, DividendCalc.AfterTax(1000m, 0.06m));
+ }
+
+ [TestMethod]
+ public void AfterTax_负票息()
+ {
+ // -500 / 1.06 * 0.94 = -443.40
+ Assert.AreEqual(-443.40m, DividendCalc.AfterTax(-500m, 0.06m));
+ }
+
+ [TestMethod]
+ public void AfterTaxRaw_不四舍五入()
+ {
+ var raw = DividendCalc.AfterTaxRaw(1000m, 0.06m);
+ Assert.AreNotEqual(886.79m, raw, "Raw 版本不四舍五入");
+ Assert.IsTrue(raw > 886.79m && raw < 886.80m);
+ }
+ }
+}
diff --git a/YLErpDAL/Modules/SwapModule/ReturnLegs/DividendCalc.cs b/YLErpDAL/Modules/SwapModule/ReturnLegs/DividendCalc.cs
new file mode 100644
index 00000000..1b9f898f
--- /dev/null
+++ b/YLErpDAL/Modules/SwapModule/ReturnLegs/DividendCalc.cs
@@ -0,0 +1,18 @@
+namespace YLErp.Modules.SwapModule.ReturnLegs;
+
+///
+/// 标的端分红(票息)计算。
+///
+/// 增值税后票息 = 税前票息 / (1+税率) × (1-税率)
+/// 原代码在 SwapEodPositionService 4处重复此公式(1804/1894/1906/2095)。
+///
+public static class DividendCalc
+{
+ /// 增值税后票息,四舍五入到 2 位。
+ public static decimal AfterTax(decimal payment, decimal tax)
+ => Math.Round(payment / (1 + tax) * (1 - tax), 2);
+
+ /// 增值税后票息(不四舍五入,供中间计算用)。
+ public static decimal AfterTaxRaw(decimal payment, decimal tax)
+ => payment / (1 + tax) * (1 - tax);
+}
diff --git a/YLErpDAL/Modules/SwapModule/ReturnLegs/MtmCalc.cs b/YLErpDAL/Modules/SwapModule/ReturnLegs/MtmCalc.cs
index 482fbe90..82701e11 100644
--- a/YLErpDAL/Modules/SwapModule/ReturnLegs/MtmCalc.cs
+++ b/YLErpDAL/Modules/SwapModule/ReturnLegs/MtmCalc.cs
@@ -10,11 +10,13 @@ namespace YLErp.Modules.SwapModule.ReturnLegs;
///
public static class MtmCalc
{
- /// 标的市值。多头为正、空头为负。
+ /// 标的市值。多头为正、空头为负。shortRatio: 多头=1, 空头=-1。
public static decimal MarketValue(decimal price, decimal qty, decimal contractSize, int shortRatio)
=> price * qty * contractSize * shortRatio;
/// 盯市未实现盈亏 = (标的价 - 成本全价) × 数量 × 合约乘数 × 多空 × 收付。
+ /// 多头=1, 空头=-1。
+ /// 收取=1, 支付=-1。
public static decimal UnrealizedPnl(decimal price, decimal costGrossPrice, decimal qty, decimal contractSize, int shortRatio, decimal ratio)
=> (price - costGrossPrice) * qty * contractSize * shortRatio * ratio;
}
diff --git a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
index af4a85bc..5a4b46e8 100644
--- a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
+++ b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs
@@ -1693,7 +1693,7 @@ namespace YLErp.Modules.SwapModule
{
payQty = Math.Abs(payQty);
decimal ratio = eventFlow.PayDirection == (int)SwapDirectionEnum.收取 ? 1 : -1;//收取为正,支付为负
- decimal shortRatio = newEodPayPosition.PositionType == (int)PositionTypeFlag.Long ? 1 : -1;//多空方向
+ int shortRatio = newEodPayPosition.PositionType == (int)PositionTypeFlag.Long ? 1 : -1;//多空方向
newEodPayPosition.ValueDate = eventFlow.PayDate.Value;
newEodPayPosition.PositionId = eventFlow.PositionId;
newEodPayPosition.ClientId = td.ClientId;