#EQD-7194 估值报告页面:追报金额,可取资金,可用资金不正确

This commit is contained in:
锦麟 王
2026-08-28 10:58:47 +08:00
parent 5f951d33f6
commit 2d7f23f637
4 changed files with 134 additions and 51 deletions
@@ -3,9 +3,11 @@ using YLErp.Modules.SwapModule.Margin;
namespace YLErp.Modules.SwapModule
{
/// <summary>
/// R2 阶段三 §3.2 可用资金公式测试(需求拆分 R2 口径,实时/EOD/报告三处共用 SwapSpanBalanceCalc):
/// 客户维度 = Max(现金结存 + 授信 − 已使用授信 + 初始保证金 − 维持保证金, 0);
/// 合约维度 = Max(现金结存 + 授信 − 已使用授信 交易维度追加保证金合计, 0)。
/// R2 阶段三 §3.2 可用资金/追保/可取资金公式测试(定稿 2026-08-28 口径,实时/EOD/报告三处共用 SwapSpanBalanceCalc):
/// 客户维度可用 = Max(现金结存 + 授信 − 已使用授信 + 初始保证金 − 维持保证金, 0);
/// 合约维度可用 = Max(现金结存 + 授信 − 已使用授信, 0)(定稿删除"−交易维度追加保证金",避免与现金结存/已使用授信双重扣减);
/// 追保金额两维度均 Max(...,0) 截断、恒 ≥ 0(只追不退);
/// 可取资金只算现金部分:合约维度 = Max(现金结存 + min(持仓盈亏,0), 0),客户维度 = Max(现金结存 + 初始 − 维持 + min(持仓盈亏,0), 0)。
/// 授信额度为 credit.Credit 合计(保存时已折算比例),现金结存=期末结存(阶段二起授信不进资金)。
/// </summary>
[TestClass]
@@ -35,40 +37,27 @@ namespace YLErp.Modules.SwapModule
cashBalance: 20, totalCredit: 100, usedCredit: 20, initialMargin: 100, maintenanceMargin: 130), 1e-6);
}
/// <summary>
/// 合约维度可用资金(定稿 2026-08-28):Max(现金结存 + 授信 − 已使用授信, 0),不再减交易维度追加保证金。
/// </summary>
[TestMethod]
public void SB_004_合约维度_按交易追加合计扣减()
public void SB_004_合约维度_可用资金()
{
//现金20 + 授信100 已使用20 追加合计30 = 70
Assert.AreEqual(70, SwapSpanBalanceCalc.CalcContractDimensionAvailable(
cashBalance: 20, totalCredit: 100, usedCredit: 20, tradeAdditionalMarginSum: 30), 1e-6);
//现金20 + 授信100 已使用20 = 100
Assert.AreEqual(100, SwapSpanBalanceCalc.CalcContractDimensionAvailable(
cashBalance: 20, totalCredit: 100, usedCredit: 20), 1e-6);
}
[TestMethod]
public void SB_005_合约维度_扣尽截断为0()
{
//现金20 + 授信0 已使用30 = 10 → 0
Assert.AreEqual(0, SwapSpanBalanceCalc.CalcContractDimensionAvailable(
cashBalance: 20, totalCredit: 0, usedCredit: 0, tradeAdditionalMarginSum: 30), 1e-6);
cashBalance: 20, totalCredit: 0, usedCredit: 30), 1e-6);
}
/// <summary>
/// 阶段三口径一致性:无追加保证金流水时(阶段四前),两维度公式数值一致——
/// 交易追加合计 = Σ(维持−累计) = 维持 − 初始,与客户维度的 (初始−维持) 项互相抵消。
/// </summary>
[TestMethod]
public void SB_006_阶段三两维度数值一致()
{
var cash = 20d;
var credit = 100d;
var used = 20d;
var initial = 100d;
var maintenance = 130d;
var clientDimension = SwapSpanBalanceCalc.CalcClientDimensionAvailable(cash, credit, used, initial, maintenance);
var contractDimension = SwapSpanBalanceCalc.CalcContractDimensionAvailable(cash, credit, used, maintenance - initial);
Assert.AreEqual(clientDimension, contractDimension, 1e-9);
}
/// <summary>
/// 阶段四 §4.2 客户维度双向追保:正数=需追保,不以 0 截断。
/// 客户维度追保金额(定稿 2026-08-28Max(...,0) 截断,恒 ≥ 0,只追不退)。
/// </summary>
[TestMethod]
public void SB_010_客户维度追保金额_正数需追保()
@@ -79,15 +68,15 @@ namespace YLErp.Modules.SwapModule
}
[TestMethod]
public void SB_011_客户维度追保金额_负数可返还()
public void SB_011_客户维度追保金额_盈余截断为0()
{
//差额 (维持130−初始100)=30,资金 20+10020=100 → 追保 = 30 100 = 70(可返还,不截断为 0
Assert.AreEqual(-70, SwapSpanBalanceCalc.CalcClientDimensionCallMargin(
//差额 (维持130−初始100)=30,资金 20+10020=100 → 30 100 = 70 → 截断为 0(资金富余不展示负数
Assert.AreEqual(0, SwapSpanBalanceCalc.CalcClientDimensionCallMargin(
cashBalance: 20, totalCredit: 100, usedCredit: 20, initialMargin: 100, maintenanceMargin: 130), 1e-6);
}
/// <summary>
/// 客户维度追保金额与可用资金公式互为反向( Max 截断):追保 = −(未截断可用资金)。
/// 客户维度追保金额与可用资金公式互为反向(各加 Max 截断):追保 = Max((未截断可用资金), 0)
/// </summary>
[TestMethod]
public void SB_012_客户维度追保与可用资金反向一致()
@@ -100,7 +89,7 @@ namespace YLErp.Modules.SwapModule
var available = SwapSpanBalanceCalc.CalcClientDimensionAvailable(cash, credit, used, initial, maintenance);
var callMargin = SwapSpanBalanceCalc.CalcClientDimensionCallMargin(cash, credit, used, initial, maintenance);
var availableUnfloored = cash + credit - used + initial - maintenance;
Assert.AreEqual(-availableUnfloored, callMargin, 1e-9);
Assert.AreEqual(Math.Max(-availableUnfloored, 0), callMargin, 1e-9);
//可用资金被 0 截断时追保为正(需追保),两者不矛盾
if (availableUnfloored < 0)
{
@@ -127,5 +116,42 @@ namespace YLErp.Modules.SwapModule
Assert.AreEqual(0, SwapSpanBalanceCalc.CalcContractDimensionCallMargin(
cashBalance: 50, totalCredit: 100, usedCredit: 20), 1e-6);
}
/// <summary>
/// 可取资金(定稿 2026-08-28):只算现金部分(授信不可取现);min(持仓盈亏,0) 只扣浮亏、浮盈不放行。
/// </summary>
[TestMethod]
public void SB_015_客户维度可取资金_浮亏扣减()
{
//现金200 + 初始100 维持150 + min(30,0) = 120
Assert.AreEqual(120, SwapSpanBalanceCalc.CalcClientDimensionDesirableFund(
cashBalance: 200, initialMargin: 100, maintenanceMargin: 150, positionPnl: -30), 1e-6);
}
[TestMethod]
public void SB_016_客户维度可取资金_浮盈不放行()
{
//现金200 + 初始100 维持150 + min(50,0)=0 → 150
Assert.AreEqual(150, SwapSpanBalanceCalc.CalcClientDimensionDesirableFund(
cashBalance: 200, initialMargin: 100, maintenanceMargin: 150, positionPnl: 50), 1e-6);
}
[TestMethod]
public void SB_017_客户维度可取资金_截断为0()
{
//现金20 + 初始100 维持150 + min(40,0) = 70 → 0
Assert.AreEqual(0, SwapSpanBalanceCalc.CalcClientDimensionDesirableFund(
cashBalance: 20, initialMargin: 100, maintenanceMargin: 150, positionPnl: -40), 1e-6);
}
[TestMethod]
public void SB_018_合约维度可取资金()
{
//Max(100 + min(30,0), 0) = 70;浮亏超过现金时截断为 0
Assert.AreEqual(70, SwapSpanBalanceCalc.CalcContractDimensionDesirableFund(cashBalance: 100, positionPnl: -30), 1e-6);
Assert.AreEqual(0, SwapSpanBalanceCalc.CalcContractDimensionDesirableFund(cashBalance: 20, positionPnl: -50), 1e-6);
//浮盈不放行:Max(100 + min(80,0), 0) = 100
Assert.AreEqual(100, SwapSpanBalanceCalc.CalcContractDimensionDesirableFund(cashBalance: 100, positionPnl: 80), 1e-6);
}
}
}