Phase 0.2: Fee-Modell-Fundament (FeeModel + MarketData.TakerFeeBps + BUY-Fee-Log)
- FeeModel (pure, getestet): Kategorie-Fallback-Bps (Sports 75 / Politics-Finance 100 / Crypto 180 / Geopolitics 0 / Default 100) + FeeUsd(notional, bps). - MarketData.TakerFeeBps (Core) + Migration AddMarketTakerFeeBps (auf MySQL angewendet). Speichert den echten API-Satz, sobald verfuegbar; 0 = Fallback. - CopyTradingEngine loggt beim BUY die erwartete Taker-Fee (TakerFeeBps aus MarketCache, sonst Kategorie-Fallback) -> Akzeptanz "Fee im TradeReasoning". - FeeModelTests (Kategorie-Mapping case-insensitive, FeeUsd, 0-Faelle). 183 Tests gruen. Build/Smoke gruen. OFFEN (API-abhaengig, erst im Zielland verifizierbar): echtes fee_rate_bps-Feld aus der CLOB/Gamma-API lesen; Fee-basierter Edge-Discard; PnL-Fee-Korrektur. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
395caad11a
commit
cda5b055aa
@@ -0,0 +1,44 @@
|
||||
using PolyTrader.Modules.CopyTrading.Logic;
|
||||
using Xunit;
|
||||
using static PolyTrader.Modules.CopyTrading.Logic.FeeModel;
|
||||
|
||||
namespace PolyTrader.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Sicherheitsnetz für die Fee-Logik (Phase 0.2): Kategorie-Fallback + Fee-Berechnung.
|
||||
/// </summary>
|
||||
public class FeeModelTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Sports", 75)]
|
||||
[InlineData("SPORTS", 75)] // case-insensitive
|
||||
[InlineData("Crypto", 180)]
|
||||
[InlineData("Geopolitics", 0)]
|
||||
[InlineData("Politics", 100)]
|
||||
[InlineData("Finance", 100)]
|
||||
[InlineData("Economics", 100)]
|
||||
[InlineData("Weird-Unknown", 100)] // konservativer Default
|
||||
[InlineData("", 100)]
|
||||
[InlineData(null, 100)]
|
||||
public void FallbackBps_maps_category(string? category, int expected)
|
||||
{
|
||||
Assert.Equal(expected, FallbackBps(category));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FeeUsd_is_notional_times_bps()
|
||||
{
|
||||
Assert.Equal(1.0m, FeeUsd(100m, 100)); // 1,0 % von 100
|
||||
Assert.Equal(0.9m, FeeUsd(50m, 180)); // 1,8 % von 50
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(100, 0)] // kein Satz
|
||||
[InlineData(0, 100)] // kein Notional
|
||||
[InlineData(-5, 100)] // negatives Notional
|
||||
public void FeeUsd_zero_cases(double notional, int bps)
|
||||
{
|
||||
Assert.Equal(0m, FeeUsd((decimal)notional, bps));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user