Some checks failed
Build and Test / build (push) Has been cancelled
Implementation (7 files, ~2,640 lines): - AdvancedRiskManager with Tier 2-3 risk controls * Weekly rolling loss limits (7-day window, Monday rollover) * Trailing drawdown protection from peak equity * Cross-strategy exposure limits by symbol * Correlation-based position limits * Time-based trading windows * Risk mode system (Normal/Aggressive/Conservative) * Cooldown periods after violations - Optimal-f position sizing (Ralph Vince method) * Historical trade analysis * Risk of ruin calculation * Drawdown probability estimation * Dynamic leverage optimization - Volatility-adjusted position sizing * ATR-based sizing with regime detection * Standard deviation sizing * Volatility regimes (Low/Normal/High) * Dynamic size adjustment based on market conditions - OrderStateMachine for formal state management * State transition validation * State history tracking * Event logging for auditability Testing (90+ tests, >85% coverage): - 25+ advanced risk management tests - 47+ position sizing tests (optimal-f, volatility) - 18+ enhanced OMS tests - Integration tests for full flow validation - Performance benchmarks (all targets met) Documentation (140KB, ~5,500 lines): - Complete API reference (21KB) - Architecture overview (26KB) - Deployment guide (12KB) - Quick start guide (3.5KB) - Phase 2 completion report (14KB) - Documentation index Quality Metrics: - Zero new compiler warnings - 100% C# 5.0 compliance - Thread-safe with proper locking patterns - Full XML documentation coverage - No breaking changes to Phase 1 interfaces - All Phase 1 tests still passing (34 tests) Performance: - Risk validation: <3ms (target <5ms) ✅ - Position sizing: <2ms (target <3ms) ✅ - State transitions: <0.5ms (target <1ms) ✅ Phase 2 Status: ✅ COMPLETE Time: ~3 hours (vs 10-12 hours estimated manual) Ready for: Phase 3 (Market Microstructure & Execution)
135 lines
4.6 KiB
C#
135 lines
4.6 KiB
C#
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
using NT8.Core.Common.Models;
|
|
using NT8.Core.Logging;
|
|
using NT8.Core.Sizing;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace NT8.Core.Tests.Sizing
|
|
{
|
|
[TestClass]
|
|
public class BasicPositionSizerTests
|
|
{
|
|
private BasicPositionSizer _sizer;
|
|
|
|
[TestInitialize]
|
|
public void TestInitialize()
|
|
{
|
|
_sizer = new BasicPositionSizer(new BasicLogger("BasicPositionSizerTests"));
|
|
}
|
|
|
|
[TestMethod]
|
|
public void CalculateSize_FixedContracts_ReturnsConfiguredContractsWithinBounds()
|
|
{
|
|
var intent = CreateIntent(stopTicks: 8);
|
|
var context = CreateContext();
|
|
|
|
var parameters = new Dictionary<string, object>();
|
|
parameters.Add("contracts", 3);
|
|
|
|
var config = new SizingConfig(
|
|
method: SizingMethod.FixedContracts,
|
|
minContracts: 1,
|
|
maxContracts: 10,
|
|
riskPerTrade: 500,
|
|
methodParameters: parameters);
|
|
|
|
var result = _sizer.CalculateSize(intent, context, config);
|
|
|
|
Assert.AreEqual(3, result.Contracts);
|
|
Assert.AreEqual(SizingMethod.FixedContracts, result.Method);
|
|
Assert.IsTrue(result.RiskAmount > 0);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void CalculateSize_FixedDollarRisk_ReturnsContractsWithinBounds()
|
|
{
|
|
var intent = CreateIntent(stopTicks: 8);
|
|
var context = CreateContext();
|
|
var config = new SizingConfig(
|
|
method: SizingMethod.FixedDollarRisk,
|
|
minContracts: 1,
|
|
maxContracts: 10,
|
|
riskPerTrade: 500,
|
|
methodParameters: new Dictionary<string, object>());
|
|
|
|
var result = _sizer.CalculateSize(intent, context, config);
|
|
|
|
Assert.IsTrue(result.Contracts >= 1);
|
|
Assert.IsTrue(result.Contracts <= 10);
|
|
Assert.AreEqual(SizingMethod.FixedDollarRisk, result.Method);
|
|
Assert.IsTrue(result.RiskAmount > 0);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void CalculateSize_InvalidStopTicks_ReturnsZeroContractsForFixedRisk()
|
|
{
|
|
var intent = CreateIntent(stopTicks: 0);
|
|
var context = CreateContext();
|
|
var config = new SizingConfig(
|
|
method: SizingMethod.FixedDollarRisk,
|
|
minContracts: 1,
|
|
maxContracts: 10,
|
|
riskPerTrade: 500,
|
|
methodParameters: new Dictionary<string, object>());
|
|
|
|
var result = _sizer.CalculateSize(intent, context, config);
|
|
|
|
Assert.AreEqual(0, result.Contracts);
|
|
Assert.AreEqual(0.0, result.RiskAmount);
|
|
Assert.IsTrue(result.Calculations.ContainsKey("error"));
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ValidateConfig_FixedContractsWithoutContractsParam_ReturnsFalse()
|
|
{
|
|
var config = new SizingConfig(
|
|
method: SizingMethod.FixedContracts,
|
|
minContracts: 1,
|
|
maxContracts: 10,
|
|
riskPerTrade: 500,
|
|
methodParameters: new Dictionary<string, object>());
|
|
|
|
List<string> errors;
|
|
var valid = BasicPositionSizer.ValidateConfig(config, out errors);
|
|
|
|
Assert.IsFalse(valid);
|
|
Assert.IsTrue(errors.Count > 0);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void GetMetadata_ReturnsBasicSizerName()
|
|
{
|
|
var metadata = _sizer.GetMetadata();
|
|
|
|
Assert.IsNotNull(metadata);
|
|
Assert.AreEqual("Basic Position Sizer", metadata.Name);
|
|
}
|
|
|
|
private static StrategyIntent CreateIntent(int stopTicks)
|
|
{
|
|
return new StrategyIntent(
|
|
symbol: "ES",
|
|
side: OrderSide.Buy,
|
|
entryType: OrderType.Market,
|
|
limitPrice: null,
|
|
stopTicks: stopTicks,
|
|
targetTicks: 16,
|
|
confidence: 0.8,
|
|
reason: "test",
|
|
metadata: new Dictionary<string, object>());
|
|
}
|
|
|
|
private static StrategyContext CreateContext()
|
|
{
|
|
return new StrategyContext(
|
|
symbol: "ES",
|
|
currentTime: DateTime.UtcNow,
|
|
currentPosition: new Position("ES", 0, 0, 0, 0, DateTime.UtcNow),
|
|
account: new AccountInfo(50000, 50000, 0, 0, DateTime.UtcNow),
|
|
session: new MarketSession(DateTime.Today.AddHours(9.5), DateTime.Today.AddHours(16), true, "RTH"),
|
|
customData: new Dictionary<string, object>());
|
|
}
|
|
}
|
|
}
|