Netto-Rechnung aus den ECHTEN Steuer-Buchungen statt geschaetzt
Der seit 05.08. dokumentierte Defekt ist behoben. _add_net rechnete net_pnl = total_pnl - gross_win * 26,375 % und unterstellte, die Quellensteuer sei endgueltig verloren. Sie wird aber taeglich per "Tax settlement" erstattet - real zu 99 %. all: vorher net_pnl -2.449,95 EUR, jetzt +181,00 (total +209,93, echte Steuerlast +28,93). Verzerrung rund 2.630 EUR - sie machte aus einem profitablen Konto ein verlustreiches. Die Schaetzung der EINBEHALTENEN Summe war fast exakt; falsch war allein die Annahme, sie bleibe weg. trader.steuer_buchungen() liest die WHT-/Tax-Deals direkt (position_id == 0, sauber von Trade-Deals getrennt), unter mt5_lock, 5 min gecacht. Fail-safe: ohne MT5 Rueckfall auf die Schaetzung, das Feld wht_quelle sagt welche Zahl drinsteht. Kurze Zeitraeume bleiben verzerrt, in BEIDE Richtungen - die Erstattung kommt am Folgetag. Bei "today" ist wht sogar negativ, weil die Erstattung von gestern heute einging. Ehrlich benannt, nicht kaschiert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
d8839ef7c5
commit
5819a9df21
@@ -20,6 +20,7 @@ Aktuell (Schritt 1): nur Read-only-Endpoints.
|
||||
GET /api/snapshot → kompletter Live-Zustand (Markt/Position/Analyse/Agent)
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import time
|
||||
import asyncio
|
||||
import contextlib
|
||||
import secrets
|
||||
@@ -151,20 +152,49 @@ def logs(lines: int = 200):
|
||||
return {"error": str(e), "lines": []}
|
||||
|
||||
|
||||
def _add_net(stats: dict, rate: float) -> dict:
|
||||
def _add_net(stats: dict, rate: float, trader=None) -> dict:
|
||||
"""Ergänzt eine stats_overview-Periode um Netto-Werte nach Quellensteuer.
|
||||
WHT wird nur auf die Gewinnseite (gross_win) erhoben, Verluste bleiben voll."""
|
||||
|
||||
⚠⚠ SEIT 2026-08-12 AUS DEN **ECHTEN** BUCHUNGEN, nicht mehr geschätzt.
|
||||
Die alte Rechnung war `net_pnl = total_pnl − gross_win × 26,375 %` und
|
||||
unterstellte, die WHT sei endgültig verloren. Sie wird aber täglich per
|
||||
`Tax settlement` erstattet — gemessen über 90 Tage zu **99 %**
|
||||
(einbehalten −2.625,89 €, erstattet +2.608,83 €, verblieben −17,06 €).
|
||||
Die Schätzung sagte −2.619,93 € und machte damit aus **+153 € rund
|
||||
−2.450 €**. ✅ Die Schätzung der EINBEHALTENEN Summe war fast exakt —
|
||||
falsch war allein die Annahme, sie bleibe weg.
|
||||
⚠ Fällt der Broker aus, wird auf die alte Schätzung zurückgefallen; das Feld
|
||||
`wht_quelle` sagt, welche Zahl gerade drinsteht („echt" / „geschätzt").
|
||||
⚠ KURZE ZEITRÄUME sind naturgemäss pessimistisch: die Erstattung kommt erst
|
||||
am Folgetag. Für „today" fehlt sie also meist — deshalb `wht_lag`.
|
||||
"""
|
||||
if not stats or stats.get("error"):
|
||||
return stats
|
||||
gw = stats.get("gross_win", 0.0) or 0.0
|
||||
gl = stats.get("gross_loss", 0.0) or 0.0
|
||||
wht = gw * rate
|
||||
net_gw = gw - wht
|
||||
tp = stats.get("total_pnl", 0.0) or 0.0
|
||||
echt = None
|
||||
if trader is not None:
|
||||
try:
|
||||
echt = trader.steuer_buchungen(int(stats.get("since") or 0),
|
||||
int(stats.get("until") or time.time()))
|
||||
except Exception:
|
||||
echt = None
|
||||
if echt and echt.get("n"):
|
||||
wht = -float(echt["netto"]) # netto ist negativ → Last positiv
|
||||
stats["wht_quelle"] = "echt"
|
||||
stats["wht_brutto"] = echt["wht"]
|
||||
stats["wht_erstattet"] = echt["tax"]
|
||||
stats["wht_lag"] = bool(echt["tax"] == 0 and echt["wht"] < 0)
|
||||
else:
|
||||
wht = gw * rate
|
||||
stats["wht_quelle"] = "geschätzt"
|
||||
stats["wht_pct"] = round(rate * 100, 3)
|
||||
stats["wht"] = wht
|
||||
stats["net_pnl"] = (stats.get("total_pnl", 0.0) or 0.0) - wht
|
||||
stats["net_profit_factor"] = (net_gw / gl) if gl > 0 else None
|
||||
stats["net_avg_win"] = (stats.get("avg_win", 0.0) or 0.0) * (1 - rate)
|
||||
stats["wht"] = round(wht, 2)
|
||||
stats["net_pnl"] = round(tp - wht, 2)
|
||||
stats["net_profit_factor"] = ((gw - wht) / gl) if gl > 0 else None
|
||||
stats["net_avg_win"] = (stats.get("avg_win", 0.0) or 0.0) * (
|
||||
1 - (wht / gw if gw > 0 else 0.0))
|
||||
return stats
|
||||
|
||||
|
||||
@@ -187,7 +217,8 @@ def stats():
|
||||
out: dict = {"wht_pct": round(rate * 100, 3)}
|
||||
for period in ("today", "week", "all"):
|
||||
try:
|
||||
out[period] = _add_net(eng.history.stats_overview(period), rate)
|
||||
out[period] = _add_net(eng.history.stats_overview(period), rate,
|
||||
getattr(eng, "trader", None))
|
||||
except Exception as e:
|
||||
out[period] = {"error": str(e)}
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user