Files
IBKRTrader/src/IBKRTrader.App/ViewModels/Rows.cs
T
RichardandClaude Opus 5 8fd99ee6fa Positionsverwaltung: Herkunft sichtbar, Zuordnung aenderbar, Sperren einstellbar
Erster Teil von #485. Der PositionManager im Core beantwortet drei Fragen, die
sich beim Debuggen sofort stellen: Wem gehoert eine Position, was sagt der Broker
dazu, und was ist gesperrt.

Drei Zugaenge auf denselben Dienst - das Fenster der Shell, --positions und
--reassign im kopflosen Betrieb, GET /api/positions. Der Testbetrieb laeuft als
systemd-Dienst; ein Werkzeug, das nur in der Oberflaeche existiert, fehlt genau
dann, wenn man es braucht.

Entscheidungen, die im Code begruendet stehen:

- BrokerQuantity ist nullable und heisst "nicht bekannt", nicht "null Stueck".
  Ohne Verbindung sieht ein leergeraeumtes Konto genauso aus wie eine Stoerung;
  aus dem einen darf nicht auf das andere geschlossen werden.
- Umbuchen aendert die Zuordnung, nie die Menge. Eine Umbuchung, die eine
  Stueckzahl bewegt, waere ein Handel ohne Order und stuende in keiner Historie.
- Gegen eine entgegengesetzte Position wird abgelehnt: Das waere eine
  Glattstellung und gehoert ueber eine Order gemacht, mit Preis und Historie.
- Das Quellbuch ist Pflicht - Schutz gegen die falsche Zeile -, ebenso eine
  Begruendung, sonst ist der Eingriff spaeter nicht mehr erklaerbar.
- Das Cap des Zielbuchs sperrt NICHT. Die Position existiert bereits; sie zu
  benennen erzeugt kein neues Risiko. Wuerde die Grenze das verhindern, bliebe
  jede zu grosse Position fuer immer in UNASSIGNED.
- Der REST-Endpunkt ist lesend. Der Listener kennt keine Anmeldung; ein
  schreibender Zugriff waere ein Eingriff in die Buecher, den niemand belegen kann.

Beim ersten Testlauf gefunden: (Module, ContractKey) ist der Primaerschluessel
von core_position, das Buch laesst sich in der Zeile nicht ueberschreiben.
Umgebucht wird deshalb durch Loeschen und Neuanlegen.

471 Tests gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 12:41:06 +02:00

61 lines
3.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Avalonia.Media;
namespace IBKRTrader.App.ViewModels;
/// <summary>
/// Zeilentypen für die DataGrids der Core-Ansichten.
///
/// <para>Bewusst benannte Records statt der anonymen Typen, die die WinForms-Fassung an
/// <c>DataGridView.DataSource</c> gehängt hat: Avalonias <c>DataGrid</c> bindet über
/// kompilierte Bindings gegen einen bekannten Typ. Anonyme Typen sind <c>internal</c> und
/// funktionieren dort nur über Reflexion – mit benannten Records bleibt die Spaltendefinition
/// im XAML prüfbar.</para>
/// </summary>
public sealed record ModuleRow(string Name, string Prefix, string Status);
/// <summary>
/// Eine Zeile im Live-Log. Die Farbe hängt am Eintrag statt an einer Selektion – WinForms färbte
/// über <c>SelectionColor</c> der RichTextBox ein, in Avalonia wird je Element gebunden.
/// </summary>
public sealed record LogRow(string Text, IBrush Color);
/// <summary>Eine offene Position im Modul-Fenster.</summary>
public sealed record PositionRow(string Symbol, int Quantity, decimal AvgPrice, decimal Notional);
/// <summary>
/// Eine Zeile der Positionsverwaltung (#485). Zahlen kommen als fertiger Text: Die Formatierung
/// gehoert an eine Stelle, und „Broker“ muss zwischen „null Stück“ und „keine Auskunft“
/// unterscheiden koennen - ein Zahlentyp kann das nicht.
/// </summary>
public sealed record ManagedPositionRow(
string Book, string Origin, string Instrument, string Quantity, string AvgPrice,
string Bound, string Broker, string Restrictions);
/// <summary>Bestand, den der Broker fuehrt und den kein Buch beansprucht.</summary>
public sealed record UnknownPositionRow(
string Symbol, string SecType, string Currency, string Quantity, string AvgCost, string Note);
/// <summary>Eine Zeile der Supervisor-Berichtsliste. Tokens als fertiger Text (Prompt / Completion).</summary>
public sealed record SupervisorReportRow(
DateTime CreatedAt, string Profile, string Model, string Question, int ToolCallCount, string Tokens);
// ─── Accounting ──────────────────────────────────────────────────────────────
// Beträge als bereits formatierter Text: die Umrechnung in die Anzeigewährung passiert beim
// Laden, und das Format ist damit an einer Stelle festgelegt statt in jeder Spaltendefinition.
/// <summary>Eine Monatszeile des Monatsvergleichs (BWA).</summary>
public sealed record MonthlyRow(
string Month, string Opening, string Deposits, string Withdrawals,
string Volume, string Fees, string Result, string Closing);
/// <summary>Eine Buchung im neutralen Ledger.</summary>
public sealed record LedgerRow(
DateTime Time, string AccountId, string EventType, string Side, string Symbol,
string Currency, decimal Quantity, decimal Price,
decimal Gross, decimal Fee, decimal Net, string TransactionId);
/// <summary>Ein Ingest-Lauf des Flex-Query-Abrufs.</summary>
public sealed record IngestRunRow(
string AccountId, DateTime Started, DateTime? Finished, bool Backfill,
int NewEntries, int DuplicateEntries, bool Success, string Delta, string Message);