Files
zszq-trs/UnitTestProject/Modules/SwapModule/Margin/MarginLegTest.cs
T
hjhan 47422b9024 feat(margin): MarginAccount 加计息入口 AccrueInterest
保证金账户现在具备独立计息能力:
AccrueInterest(rate, start, end, boundary, annualDays)
委托 SwapInterest.AccrueSimple(余额×利率×天数/年化)。

保证金利息是券商对客户保证金存款付息, 方向与融资腿相反。
Margin 模块现在完全独立于 CalcNotionalByMode——
有自己的余额管理 + 计息入口, 不依赖融资腿框架。

测试: 3个计息用例(7天/零余额/释放后减半)。
CalcNotionalByMode 的 mode 5/6 case 仍在(下游路径共用),
待 EOD 归档改走 Margin 路径后再删。
验证: 编译0错误, 全量511测试7失败(基线一致)。
2026-08-11 13:03:38 +08:00

122 lines
4.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using YLErp.Derivatives.Interest;
using YLErp.Modules.SwapModule.Margin;
namespace UnitTestProject.Modules.SwapModule.Margin
{
/// <summary>
/// 保证金账户(MarginAccount)单测。验证余额变动(追加/释放/返还)。
/// 保证金就是保证金——有余额、有利率、有利息,不存在"计息基数/Notional"概念。
/// </summary>
[TestClass]
public class MarginLegTest
{
private const decimal Opening = 2_000_000m;
#region MarginAccount 余额变动
[TestMethod]
public void 账户_初始余额等于期初保证金()
{
var account = new MarginAccount(new MarginBalance(Opening));
Assert.AreEqual(Opening, account.Balance.Balance);
}
[TestMethod]
public void 账户_追加保证金_余额增加()
{
var account = new MarginAccount(new MarginBalance(Opening));
account.Deposit(500_000m);
Assert.AreEqual(2_500_000m, account.Balance.Balance);
}
[TestMethod]
public void 账户_释放保证金_余额减少()
{
var account = new MarginAccount(new MarginBalance(Opening));
account.Withdraw(800_000m);
Assert.AreEqual(1_200_000m, account.Balance.Balance);
}
[TestMethod]
public void 账户_释放超过余额_不低于零()
{
var account = new MarginAccount(new MarginBalance(Opening));
account.Withdraw(3_000_000m);
Assert.AreEqual(0m, account.Balance.Balance, "保证金余额不低于零");
}
#endregion
#region 三种保证金形态解析器
[TestMethod]
public void 三种形态解析器_各自返回正确Form和余额()
{
IMarginResolver cash = new CashMargin();
IMarginResolver credit = new CreditMargin();
IMarginResolver guarantee = new GuaranteeMargin();
Assert.AreEqual(MarginForm.Cash, cash.Form);
Assert.AreEqual(MarginForm.Credit, credit.Form);
Assert.AreEqual(MarginForm.Guarantee, guarantee.Form);
Assert.AreEqual(Opening, cash.Resolve(Opening).Balance);
Assert.AreEqual(Opening, credit.Resolve(Opening).Balance);
Assert.AreEqual(Opening, guarantee.Resolve(Opening).Balance);
}
#endregion
#region MarginAccount 计息
[TestMethod]
public void 计息_单利7天_余额200万年化3pct()
{
var account = new MarginAccount(new MarginBalance(2_000_000m));
// 200万 × 3% / 365 × 7天 = 1150.68...
var r = account.AccrueInterest(
rate: 0.03m,
startDate: new System.DateTime(2026, 5, 4),
endDate: new System.DateTime(2026, 5, 11),
boundary: AccrualBoundary.StartOnly,
annualDays: 365);
Assert.IsTrue(r.Accrued > 0, "7天利息应大于0");
System.Console.WriteLine($"保证金7天利息={r.Accrued}");
}
[TestMethod]
public void 计息_零余额_利息为零()
{
var account = new MarginAccount(new MarginBalance(0m));
var r = account.AccrueInterest(0.03m,
new System.DateTime(2026, 5, 4), new System.DateTime(2026, 5, 11),
AccrualBoundary.StartOnly, 365);
Assert.AreEqual(0m, r.Accrued);
}
[TestMethod]
public void 计息_释放后余额减少_利息相应减少()
{
var full = new MarginAccount(new MarginBalance(2_000_000m));
var half = new MarginAccount(new MarginBalance(2_000_000m));
half.Withdraw(1_000_000m);
var rFull = full.AccrueInterest(0.03m,
new System.DateTime(2026, 5, 4), new System.DateTime(2026, 5, 11),
AccrualBoundary.StartOnly, 365);
var rHalf = half.AccrueInterest(0.03m,
new System.DateTime(2026, 5, 4), new System.DateTime(2026, 5, 11),
AccrualBoundary.StartOnly, 365);
Assert.IsTrue(rHalf.Accrued < rFull.Accrued, "释放后利息应更少");
Assert.IsTrue(System.Math.Abs(rFull.Accrued - rHalf.Accrued * 2m) < 0.01m,
"余额减半, 利息也应减半");
}
#endregion
}
}