- DemoModel (pure, getestet): ExitFillPrice (Signalpreis minus halber Spread, geclamped) + CloseWithFees (Erlös zum Fill-Preis minus Round-Trip-Fee). - CopyTradingEngine Demo-Close nutzt es: ExitPrice = realistischer Fill statt Signalpreis, RealizedPnl netto nach Fees, ClosedTrade.TotalFees befuellt. -> Demo-PnL ist nicht mehr systematisch geschoent (Master-Validierung brauchbar). - DemoModelTests (Fill-Clamping, Round-Trip-Fee, 0-Fee). 207 Tests gruen. Build/Smoke gruen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
49 lines
1.8 KiB
C#
49 lines
1.8 KiB
C#
using PolyTrader.Modules.CopyTrading.Logic;
|
|
using Xunit;
|
|
using static PolyTrader.Modules.CopyTrading.Logic.DemoModel;
|
|
|
|
namespace PolyTrader.Tests
|
|
{
|
|
/// <summary>
|
|
/// Sicherheitsnetz für den realistischeren Demo-Modus (Phase 4.2): Exit-Slippage + Fees.
|
|
/// </summary>
|
|
public class DemoModelTests
|
|
{
|
|
[Fact]
|
|
public void ExitFillPrice_is_below_signal_by_half_spread()
|
|
{
|
|
Assert.Equal(0.495m, ExitFillPrice(0.50m, 0.005m));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0.011, 0.005, 0.01)] // Clamp Untergrenze
|
|
[InlineData(0.20, 0.30, 0.01)] // stark negativ -> Untergrenze
|
|
[InlineData(0.90, 0.005, 0.895)] // normal im Band
|
|
[InlineData(0.999, 0.005, 0.99)] // Clamp Obergrenze (0.994 -> 0.99)
|
|
public void ExitFillPrice_clamps_to_valid_range(double signal, double half, double expected)
|
|
{
|
|
Assert.Equal((decimal)expected, ExitFillPrice((decimal)signal, (decimal)half));
|
|
}
|
|
|
|
[Fact]
|
|
public void CloseWithFees_subtracts_slippage_and_roundtrip_fee()
|
|
{
|
|
// size 100, signal 0.60 -> exit 0.595, exitUsd 59.5
|
|
// fees = 1% von 50 (Entry) + 1% von 59.5 (Exit) = 0.5 + 0.595 = 1.095
|
|
// pnl = 59.5 - 50 - 1.095 = 8.405
|
|
var (exitUsd, pnl, fees) = CloseWithFees(size: 100m, signalPrice: 0.60m, entryAmountUsd: 50m, feeBps: 100, halfSpread: 0.005m);
|
|
Assert.Equal(59.5m, exitUsd);
|
|
Assert.Equal(1.095m, fees);
|
|
Assert.Equal(8.405m, pnl);
|
|
}
|
|
|
|
[Fact]
|
|
public void CloseWithFees_zero_fee_only_slippage()
|
|
{
|
|
var (exitUsd, pnl, fees) = CloseWithFees(100m, 0.60m, 50m, feeBps: 0, halfSpread: 0.005m);
|
|
Assert.Equal(0m, fees);
|
|
Assert.Equal(exitUsd - 50m, pnl);
|
|
}
|
|
}
|
|
}
|