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;