fix(swap): 修复债券结息价差盈亏计算逻辑
- 将价差盈亏计算从使用CloseNotionalValue改为使用PositionQty和ContractSize - 更新前端JavaScript代码中的计算公式,按持仓数量和合约乘数计算价差盈亏 - 在UnwindInput模型中添加PositionQty和ContractSize字段 - 修正后台计算服务中的数据映射逻辑 - 添加FC_009测试用例验证债券价差按数量计算的正确性 - 更新现有测试用例的输入参数以匹配新的计算方式
This commit is contained in:
@@ -156,9 +156,9 @@ namespace YLErp.Modules.SwapModule
|
||||
|
||||
/// <summary>
|
||||
/// [FC_006] 结息-债券多头-全量结算(基线)
|
||||
/// income 用 CloseNotionalValue 而非 CloseQty,无 longRatio
|
||||
/// EntryPrice=1.02, TradingAmountAvg=105(×100形态), CloseNotionalValue=10000
|
||||
/// MarkClosePnl = 10000×(105×0.01−1.02)×1 = 10000×0.03 = 300
|
||||
/// income 使用持仓数量和合约乘数,无 longRatio
|
||||
/// EntryPrice=1.02, TradingAmountAvg=105(×100形态), PositionQty=10000, ContractSize=1
|
||||
/// MarkClosePnl = 10000×1×(105×0.01−1.02)×1 = 10000×0.03 = 300
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void FC_006_结息_债券多头_全量结算()
|
||||
@@ -166,7 +166,9 @@ namespace YLErp.Modules.SwapModule
|
||||
var input = new UnwindInput
|
||||
{
|
||||
Multiplier = 100, PosiGrossPrice = 1.02m, TradingAmountAvg = 105m,
|
||||
CloseNotionalValue = 10000, // income 用名义本金
|
||||
PositionQty = 10000,
|
||||
ContractSize = 1,
|
||||
CloseNotionalValue = 10200, // 与数量刻意不同,守卫 income 不再误用名义本金
|
||||
CloseQty = 0, // income 不用数量
|
||||
PayDirection = 1, PositionType = 1,
|
||||
TradingFee = "0", TradingFeePending = "0", DividendIn = "0"
|
||||
@@ -188,7 +190,8 @@ namespace YLErp.Modules.SwapModule
|
||||
var input = new UnwindInput
|
||||
{
|
||||
Multiplier = 100, PosiGrossPrice = 1.02m, TradingAmountAvg = 110m,
|
||||
CloseNotionalValue = 10000, CloseQty = 0,
|
||||
PositionQty = 10000, ContractSize = 1,
|
||||
CloseNotionalValue = 10200, CloseQty = 0,
|
||||
PayDirection = 1, PositionType = 1,
|
||||
TradingFee = "0", TradingFeePending = "0", DividendIn = "0"
|
||||
};
|
||||
@@ -209,7 +212,8 @@ namespace YLErp.Modules.SwapModule
|
||||
var input = new UnwindInput
|
||||
{
|
||||
Multiplier = 100, PosiGrossPrice = 1.02m, TradingAmountAvg = 105m,
|
||||
CloseNotionalValue = 10000, CloseQty = 0,
|
||||
PositionQty = 10000, ContractSize = 1,
|
||||
CloseNotionalValue = 10200, CloseQty = 0,
|
||||
PayDirection = 1, PositionType = 1,
|
||||
TradingFee = "0", TradingFeePending = "0", DividendIn = "0"
|
||||
};
|
||||
@@ -225,6 +229,35 @@ namespace YLErp.Modules.SwapModule
|
||||
Console.WriteLine($"FC_008: SwapRealizedPnL={result.SwapRealizedPnL}, SwapMarginRebatePnl={result.SwapMarginRebatePnl} ✅");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [FC_009] 结息-债券支付端:价差盈亏必须按数量计算,不能按期初名义本金计算。
|
||||
/// 纯价差 = 30000000×1×(80%−98%)×(−1) = 5400000;加分红-45000后合计5355000。
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void FC_009_结息_债券价差按数量计算()
|
||||
{
|
||||
var input = new UnwindInput
|
||||
{
|
||||
Multiplier = 100,
|
||||
PosiGrossPrice = 0.98m,
|
||||
TradingAmountAvg = 80m,
|
||||
PositionQty = 30000000m,
|
||||
ContractSize = 1m,
|
||||
CloseNotionalValue = 29400000m,
|
||||
CloseQty = 0m,
|
||||
PayDirection = 2,
|
||||
PositionType = 1,
|
||||
TradingFee = "0",
|
||||
TradingFeePending = "0",
|
||||
DividendIn = "-45000"
|
||||
};
|
||||
|
||||
var result = FrontendCalcReference.CalcIncome(input);
|
||||
|
||||
AssertDecimalEqual(5400000m, result.MarkClosePnl, 0.01m, "income MarkClosePnl按数量计算");
|
||||
AssertDecimalEqual(5355000m, result.FloatPnlSum, 0.01m, "income FloatPnlSum包含分红");
|
||||
}
|
||||
|
||||
private static void AssertDecimalEqual(decimal expected, decimal actual, decimal tolerance, string message = "")
|
||||
{
|
||||
Assert.IsTrue(Math.Abs(expected - actual) <= tolerance,
|
||||
|
||||
Reference in New Issue
Block a user