Testnetz: geldkritische Trade-Mathematik extrahiert (TradeMath) + getestet

- Neue pure Klasse TradeMath (Logic/): ExitValue, RealizedPnl, PnlPercent
  (Null-Guard), WeightedAverageEntryPrice (Div-durch-0-Schutz).
- CopyTradingEngine ruft sie jetzt im Demo-Close-PnL und bei der Positions-
  Aufstockung (Demo + Live, gewichteter Einstiegspreis) – verhaltensneutral.
- TradeMathTests (6 Faelle: Gewinn/Verlust, %-Basis, 0-Kapital/0-Size-Guards).

Gesamt 160 Tests gruen. Build/Smoke gruen. (Phase-0.1-SELL-Wiring weiterhin
bewusst zurueckgestellt bis zum Server-Test; pure Leiter liegt getestet bereit.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-07-07 11:09:41 +02:00
co-authored by Claude Opus 4.8
parent 581755029a
commit 1dffc9e253
3 changed files with 85 additions and 5 deletions
@@ -497,7 +497,7 @@ namespace PolyTraderSharp.Services
{
old.Size += pos.Size;
old.AmountUsd += pos.AmountUsd;
old.EntryPrice = old.AmountUsd / old.Size; // weighted average
old.EntryPrice = TradeMath.WeightedAverageEntryPrice(old.AmountUsd, old.Size); // weighted average
return old;
});
@@ -541,7 +541,7 @@ namespace PolyTraderSharp.Services
{
old.Size += pos.Size;
old.AmountUsd += pos.AmountUsd;
old.EntryPrice = old.AmountUsd / old.Size;
old.EntryPrice = TradeMath.WeightedAverageEntryPrice(old.AmountUsd, old.Size);
return old;
});
@@ -612,8 +612,8 @@ namespace PolyTraderSharp.Services
{
_positionRepo.DeleteDemo(account.AccountId, signal.TokenId);
decimal exitUsd = openPos.Size * signal.Price;
decimal realizedPnl = exitUsd - openPos.AmountUsd;
decimal exitUsd = TradeMath.ExitValue(openPos.Size, signal.Price);
decimal realizedPnl = TradeMath.RealizedPnl(openPos.Size, signal.Price, openPos.AmountUsd);
_state.GlobalPnl += realizedPnl;
account.UpdateBalance(account.AvailableBalance + exitUsd);
@@ -633,7 +633,7 @@ namespace PolyTraderSharp.Services
ExitPrice = signal.Price,
Size = openPos.Size,
RealizedPnl = realizedPnl,
PnlPercent = openPos.AmountUsd > 0 ? (realizedPnl / openPos.AmountUsd * 100m) : 0m,
PnlPercent = TradeMath.PnlPercent(realizedPnl, openPos.AmountUsd),
OpenedAt = openPos.OpenedAt,
ClosedAt = DateTime.UtcNow,
ExitReason = signal.Reason