refactor(return-leg): 新增 DividendCalc 分红增值税后计算 + 修复 MtmCalc 参数类型
DividendCalc: 增值税后票息 = payment/(1+tax)*(1-tax), 原 SwapEodPositionService 4处重复此公式(1804/1894/1906/2095)。 本次先建纯函数+测试, 4处inline替换下次做。 附带修复: MtmCalc shortRatio 参数从 decimal 改为 int (原代码6处声明中5处是int, 仅1696是decimal, 统一为int)。 1696行 shortRatio 声明同步改为 int。 验证: 编译0错误, DividendCalc 4个测试全过, 全量507测试7失败(基线一致)。
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace YLErp.Modules.SwapModule.ReturnLegs;
|
||||
|
||||
/// <summary>
|
||||
/// 标的端分红(票息)计算。
|
||||
///
|
||||
/// 增值税后票息 = 税前票息 / (1+税率) × (1-税率)
|
||||
/// 原代码在 SwapEodPositionService 4处重复此公式(1804/1894/1906/2095)。
|
||||
/// </summary>
|
||||
public static class DividendCalc
|
||||
{
|
||||
/// <summary>增值税后票息,四舍五入到 2 位。</summary>
|
||||
public static decimal AfterTax(decimal payment, decimal tax)
|
||||
=> Math.Round(payment / (1 + tax) * (1 - tax), 2);
|
||||
|
||||
/// <summary>增值税后票息(不四舍五入,供中间计算用)。</summary>
|
||||
public static decimal AfterTaxRaw(decimal payment, decimal tax)
|
||||
=> payment / (1 + tax) * (1 - tax);
|
||||
}
|
||||
@@ -10,11 +10,13 @@ namespace YLErp.Modules.SwapModule.ReturnLegs;
|
||||
/// </summary>
|
||||
public static class MtmCalc
|
||||
{
|
||||
/// <summary>标的市值。多头为正、空头为负。</summary>
|
||||
/// <summary>标的市值。多头为正、空头为负。shortRatio: 多头=1, 空头=-1。</summary>
|
||||
public static decimal MarketValue(decimal price, decimal qty, decimal contractSize, int shortRatio)
|
||||
=> price * qty * contractSize * shortRatio;
|
||||
|
||||
/// <summary>盯市未实现盈亏 = (标的价 - 成本全价) × 数量 × 合约乘数 × 多空 × 收付。</summary>
|
||||
/// <param name="shortRatio">多头=1, 空头=-1。</param>
|
||||
/// <param name="ratio">收取=1, 支付=-1。</param>
|
||||
public static decimal UnrealizedPnl(decimal price, decimal costGrossPrice, decimal qty, decimal contractSize, int shortRatio, decimal ratio)
|
||||
=> (price - costGrossPrice) * qty * contractSize * shortRatio * ratio;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user