From bd04642735b295836b201d7797a48049a3ad8616 Mon Sep 17 00:00:00 2001 From: Richard Date: Fri, 4 Sep 2026 15:33:51 +0200 Subject: [PATCH] Bargeld je Waehrung: $LEDGER:ALL statt $LEDGER, und melden was ankam Beim ersten echten Order-Nachweis gegen das Paper-Konto (#293) lehnte Schicht C jeden Kauf mit "Waehrungsdeckung [USD]: benoetigt 344, verfuegbar 0" ab, obwohl das Konto Bargeld hat. Ursache: das nackte "$LEDGER" liefert nur die Zusammenfassung in Kontobasiswaehrung, und die traegt als Waehrungskennung "BASE" - also genau den Wert, den die Auswertung ueberspringen muss, damit dasselbe Geld nicht zweimal zaehlt. Die Aufschluesselung blieb dadurch leer, und eine leere Aufschluesselung heisst fuer Schicht C bewusst "Deckung unbekannt, also ablehnen". Mit ":ALL" kommen die Bestaende je Waehrung. Dazu eine Logzeile mit dem, was der Broker gemeldet hat. Ohne sie ist eine Ablehnung durch Schicht C von aussen nicht von einem echten Geldmangel zu unterscheiden - man sieht "verfuegbar 0" und weiss nicht, ob kein Geld da ist oder keine Auskunft kam. Genau diese Stunde hat der Fund gekostet. Gemessen am Paper-Konto DUR371528: EUR 91.832,22 / USD -3.751,01. Co-Authored-By: Claude Opus 5 --- .../Trading/Ibkr/IbkrConnection.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/IBKRTrader.Core/Trading/Ibkr/IbkrConnection.cs b/src/IBKRTrader.Core/Trading/Ibkr/IbkrConnection.cs index 0aca3b1..d32385b 100644 --- a/src/IBKRTrader.Core/Trading/Ibkr/IbkrConnection.cs +++ b/src/IBKRTrader.Core/Trading/Ibkr/IbkrConnection.cs @@ -346,11 +346,17 @@ internal sealed class IbkrConnection : DefaultEWrapper, IDisposable _accounts[id] = slot; try { - // $LEDGER liefert zusaetzlich die Bargeldbestaende je Waehrung. Sie werden fuer die + // $LEDGER:ALL liefert die Bargeldbestaende JE WAEHRUNG. Sie werden fuer die // Waehrungsdeckung gebraucht (Kapitalmodell ยง4 Schicht C): ein Kauf in X darf nur aus // Cash in X finanziert werden, sonst entsteht ein Sollsaldo in X - ein Margin-Kredit, // auch wenn das Konto in Summe positiv aussieht. - _socket.reqAccountSummary(id, "All", "NetLiquidation,AvailableFunds,TotalCashValue,$LEDGER"); + // + // ":ALL" ist noetig und nicht kosmetisch. Das nackte "$LEDGER" liefert nur die + // Zusammenfassung in Kontobasiswaehrung, und die traegt als Waehrungskennung "BASE" - + // also genau den Wert, den die Auswertung ueberspringen muss, damit dasselbe Geld nicht + // zweimal zaehlt. Ergebnis war eine leere Aufschluesselung und damit eine Ablehnung + // jedes Kaufs durch Schicht C (am 2026-09-04 gegen das Paper-Gateway beobachtet). + _socket.reqAccountSummary(id, "All", "NetLiquidation,AvailableFunds,TotalCashValue,$LEDGER:ALL"); if (!await WaitAsync(slot.Done.Task, timeout, ct).ConfigureAwait(false)) { @@ -363,6 +369,16 @@ internal sealed class IbkrConnection : DefaultEWrapper, IDisposable return null; } + // Was der Broker an Waehrungen gemeldet hat, gehoert ins Log: ohne diese Zeile ist eine + // Ablehnung durch Schicht C ("verfuegbar 0") von aussen nicht von einem echten + // Geldmangel zu unterscheiden. + _logger.Info(LogModule, slot.Cash.Count == 0 + ? "Konto: keine Bargeldaufschluesselung je Waehrung erhalten - Schicht C lehnt Kaeufe " + + "deshalb ab. Antwortet das Gateway nicht auf $LEDGER:ALL?" + : "Konto: Bargeld je Waehrung " + string.Join(", ", + slot.Cash.Select(kv => string.Create(CultureInfo.InvariantCulture, + $"{kv.Key} {kv.Value:N2}"))) + "."); + return new AccountState( ReadDecimal(slot.Values, "NetLiquidation"), ReadDecimal(slot.Values, "AvailableFunds"),