118 lines
3.9 KiB
C#
118 lines
3.9 KiB
C#
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
using NT8.Core.Common.Models;
|
|
using NT8.Core.Risk;
|
|
|
|
namespace NT8.Core.Tests.Risk
|
|
{
|
|
[TestClass]
|
|
public class PortfolioRiskManagerTests
|
|
{
|
|
private PortfolioRiskManager _manager;
|
|
|
|
[TestInitialize]
|
|
public void TestInitialize()
|
|
{
|
|
_manager = PortfolioRiskManager.Instance;
|
|
}
|
|
|
|
[TestCleanup]
|
|
public void TestCleanup()
|
|
{
|
|
_manager.UnregisterStrategy("strat1");
|
|
_manager.UnregisterStrategy("strat2");
|
|
_manager.UnregisterStrategy("strat3");
|
|
_manager.UnregisterStrategy("strat4");
|
|
_manager.UnregisterStrategy("strat5");
|
|
_manager.PortfolioKillSwitch = false;
|
|
_manager.PortfolioDailyLossLimit = 2000.0;
|
|
_manager.MaxTotalOpenContracts = 6;
|
|
_manager.ResetDaily();
|
|
}
|
|
|
|
[TestMethod]
|
|
public void PortfolioDailyLossLimit_WhenBreached_BlocksNewOrder()
|
|
{
|
|
// Arrange
|
|
_manager.RegisterStrategy("strat1", TestDataBuilder.CreateTestRiskConfig());
|
|
_manager.PortfolioDailyLossLimit = 500;
|
|
_manager.ReportPnL("strat1", -501);
|
|
var intent = TestDataBuilder.CreateValidIntent();
|
|
|
|
// Act
|
|
var decision = _manager.ValidatePortfolioRisk("strat1", intent);
|
|
|
|
// Assert
|
|
Assert.IsFalse(decision.Allow);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void MaxTotalOpenContracts_WhenAtCap_BlocksNewOrder()
|
|
{
|
|
// Arrange
|
|
_manager.RegisterStrategy("strat1", TestDataBuilder.CreateTestRiskConfig());
|
|
_manager.MaxTotalOpenContracts = 2;
|
|
|
|
var fill1 = new OrderFill("ord1", "ES", 1, 5000.0, System.DateTime.UtcNow, 0.0, "exec1");
|
|
var fill2 = new OrderFill("ord2", "ES", 1, 5001.0, System.DateTime.UtcNow, 0.0, "exec2");
|
|
_manager.ReportFill("strat1", fill1);
|
|
_manager.ReportFill("strat1", fill2);
|
|
var intent = TestDataBuilder.CreateValidIntent();
|
|
|
|
// Act
|
|
var decision = _manager.ValidatePortfolioRisk("strat1", intent);
|
|
|
|
// Assert
|
|
Assert.IsFalse(decision.Allow);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void PortfolioKillSwitch_WhenTrue_BlocksAllOrders()
|
|
{
|
|
// Arrange
|
|
_manager.RegisterStrategy("strat1", TestDataBuilder.CreateTestRiskConfig());
|
|
_manager.PortfolioKillSwitch = true;
|
|
var intent = TestDataBuilder.CreateValidIntent();
|
|
|
|
// Act
|
|
var decision = _manager.ValidatePortfolioRisk("strat1", intent);
|
|
|
|
// Assert
|
|
Assert.IsFalse(decision.Allow);
|
|
Assert.IsTrue(decision.RejectReason.ToLowerInvariant().Contains("kill switch"));
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ValidatePortfolioRisk_WhenWithinLimits_Passes()
|
|
{
|
|
// Arrange
|
|
_manager.RegisterStrategy("strat1", TestDataBuilder.CreateTestRiskConfig());
|
|
var intent = TestDataBuilder.CreateValidIntent();
|
|
|
|
// Act
|
|
var decision = _manager.ValidatePortfolioRisk("strat1", intent);
|
|
|
|
// Assert
|
|
Assert.IsTrue(decision.Allow);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ResetDaily_ClearsPnL_UnblocksTrading()
|
|
{
|
|
// Arrange
|
|
_manager.RegisterStrategy("strat1", TestDataBuilder.CreateTestRiskConfig());
|
|
_manager.PortfolioDailyLossLimit = 500;
|
|
_manager.ReportPnL("strat1", -600);
|
|
var intent = TestDataBuilder.CreateValidIntent();
|
|
|
|
// Act
|
|
var blocked = _manager.ValidatePortfolioRisk("strat1", intent);
|
|
_manager.ResetDaily();
|
|
var unblocked = _manager.ValidatePortfolioRisk("strat1", intent);
|
|
|
|
// Assert
|
|
Assert.IsFalse(blocked.Allow);
|
|
Assert.IsTrue(unblocked.Allow);
|
|
}
|
|
}
|
|
}
|