diff --git a/src/PolyTrader.Web/Endpoints/DashboardEndpoints.cs b/src/PolyTrader.Web/Endpoints/DashboardEndpoints.cs index 9296338..cd0fc4d 100644 --- a/src/PolyTrader.Web/Endpoints/DashboardEndpoints.cs +++ b/src/PolyTrader.Web/Endpoints/DashboardEndpoints.cs @@ -78,6 +78,45 @@ namespace PolyTrader.Web.Endpoints return Results.BadRequest(new { error = "Ungültiger Modus oder Parametertyp." }); }); + // Trading beenden (#563) - das WebUI-Gegenstueck zu "Beenden" im Desktop, beschraenkt auf das + // Trading. Ein Ende der ganzen Anwendung naehme den Webserver mit; danach waere das WebUI nicht + // mehr erreichbar, und nur ein Zugang zur Maschine braechte es zurueck. + // + // Beide Modi auf Inaktiv und die Pause an: Damit halten CopyTrading (Engine, Monitor, + // Verkaufsleitern) und ResolutionFarming (#569) an, wie beim Ende der Anwendung. Offene Orders + // an der Boerse werden bewusst NICHT storniert. Das tut auch das Beenden der App nicht, und + // ein Eingriff in die CLOB-Integration gehoert nicht in einen Notschalter. Wieder + // aufgenommen wird nur ausdruecklich ueber die Modus-Schalter. + // + // "confirmed" ist Pflicht: Ein Aufruf ohne Absicht, etwa aus einem alten Skript oder einem + // doppelt abgeschickten Formular, soll das Trading nicht beenden. + group.MapPost("/stop-trading", (StopTradingRequest? req, TradingState state, TerminalLogger logger) => + { + if (req?.Confirmed != true) + return Results.BadRequest(new { error = "Bestätigung fehlt – das Trading wurde nicht beendet." }); + + string liveBefore = state.LiveTradingMode.ToString(); + string demoBefore = state.DemoTradingMode.ToString(); + bool pausedBefore = state.GlobalTradingPaused; + + state.LiveTradingMode = TradingMode.Inactive; + state.DemoTradingMode = TradingMode.Inactive; + state.GlobalTradingPaused = true; + + logger.Warning($"🛑 WebUI: Trading beendet (Live {liveBefore} → Inactive, Demo {demoBefore} → Inactive, " + + $"Pause {(pausedBefore ? "war schon an" : "an")}). Anwendung und WebUI laufen weiter; " + + "offene Orders an der Börse bleiben stehen."); + + return Results.Ok(new + { + success = true, + liveTradingMode = state.LiveTradingMode.ToString(), + demoTradingMode = state.DemoTradingMode.ToString(), + globalTradingPaused = state.GlobalTradingPaused, + stoppedAt = DateTime.UtcNow + }); + }); + group.MapGet("/overview-widgets", (IServiceProvider sp) => { var tradeLog = sp.GetService(); @@ -251,5 +290,7 @@ namespace PolyTrader.Web.Endpoints return routes; } + + public record StopTradingRequest(bool Confirmed); } } diff --git a/src/PolyTrader.Web/wwwroot/index.html b/src/PolyTrader.Web/wwwroot/index.html index e31700f..b0c8db6 100644 --- a/src/PolyTrader.Web/wwwroot/index.html +++ b/src/PolyTrader.Web/wwwroot/index.html @@ -104,6 +104,11 @@ + + @@ -1176,6 +1181,38 @@ Wähle ein Profil und stelle mir eine Frage zu deinen Positionen, Risiken oder d + + + +