Neues Modul PolyTrader.Modules.Accounting (IPolyTraderModule, acc_-Praefix, nur Core-Referenz, KEIN Handel). Konzept: docs/konzepte/KONZEPT-Modul-Accounting.md, Phase A-1. Buchungsgrundlage ausschliesslich aus unabhaengigen Polymarket-/On-Chain-Abrufen (nie unsere Trading-DB), append-only, prueffaehig: - Modelle: LedgerEntry (+ LedgerEventType), IngestRun (mit Balance-Anker), RawSnapshot, RawActivity/RawTransfer (normalisierte Eingaben, entkoppeln pure Logik von der API-Feldbenennung). - AccountingClassifier (Logic/, pur+getestet): Activity->Buchungssatz (Typ/Vorzeichen: BUY=Cash raus inkl. Fee, SELL=Cash rein minus Fee, Redeem/Reward +, Split/Merge/Conversion geldneutral), stabiler Idempotency-Key; Transfer-Klassifikation trennt intern (System-Contract-Whitelist) von externen Deposits/Withdrawals. SumNet fuer den Balance-Anker-Abgleich. - AccountingDbContext (acc_ledger append-only + Unique-Index Idempotency, acc_ingest_runs, acc_raw; Autoincrement-PKs). Migration InitialAccounting generiert UND angewendet. Repos mit idempotentem Upsert (true=neu/false=Duplikat). - AccountingIngestService (BackgroundService): testbarer IngestAccountAsync - Activity + On-Chain- Transfers klassifizieren + idempotent buchen, Rohschnappschuss ablegen, Lauf inkl. Balance-Anker- Delta protokollieren; Backfill vs. inkrementell (Lookback-Ueberlappung gegen API-Lag). - Quellen hinter Interfaces (IActivitySource/ITransferSource/IBalanceAnchorSource) mit Null-Stubs: Modul laeuft offline und bucht korrekt nichts. Live-Abruf + System-Contract-Whitelist = Zielland. - UI designerfaehig (partial + .Designer.cs): Tabs Ledger (filterbar) + Abruf/Status (Ingest-Laeufe, Balance-Anker, manueller Backfill/Inkrement). - Program.cs (beide Modul-Listen) + sln + App/Tests-Referenzen. A-2 (Abrechnung/BWA/FX), A-3 (US-Steuerschicht FIFO/Form-8949), A-4 (CSV/PDF via PDFsharp/MigraDoc) folgen. Tests: +12 (Klassifikation, intern/extern-Transfer, Ingest-Idempotenz, Balance-Anker, Inkrement-Fenster). Build 0 Fehler, 379 Tests gruen, --smoke-ui alle 6 Views gruen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
17 KiB
Konzept: Modul „Accounting" (Steuer-/Buchhaltungs-Reporting aller Live-Accounts)
Stand: 2026-07-14 Ziel: Vollständige, unabhängig von unserer Trading-DB erhobene, buchhalterisch korrekte Erfassung ALLER Transaktionen aller Live-Polymarket-Accounts. Periodische (meist monatliche), vor einer Steuerbehörde nachvollziehbare Abrechnungen — je einzelnem Account ODER über alle Accounts, für frei wählbare Zeiträume. BWA-artige Kennzahlen-Übersicht in der UI. Export als CSV und PDF. Reihenfolge: unabhängig, jederzeit baubar (kein Live-Trading nötig — rein lesende API-Abrufe). Kein Handel; reines Ingest-/Reporting-Modul.
Entscheidungen Richard (2026-07-14):
- Währung: USDC nativ + USD + EUR (jede Transaktion in allen drei ausgewiesen).
- Abrechnung: neutrale prüfbare Aufstellung UND konkrete US-Steuerberechnung — Zielland USA, Florida LLC (Florida ohne State Income Tax → nur Federal). Als dokumentierte, vom CPA prüfbare Rechenschicht, nicht als Steuerberatung (Disclaimer, §4a).
- Umfang v1: inkl. On-Chain-Ein-/Auszahlungen von Anfang an (vollständige Kapitalsicht).
0. Leitprinzipien
- Unabhängige Quelle = Polymarket, NICHT unsere DB. Das Modul erhebt die Buchungsgrundlage ausschließlich über eigene, regelmäßige Abrufe direkt bei Polymarket und speichert sie roh + normalisiert in eigenen Tabellen. Unsere eigenen Trade-Logs (Copytrading/ResolutionFarming/Core) werden nur für den optionalen Abgleich (§7) herangezogen, nie als Buchungsgrundlage.
- Nachvollziehbarkeit / Audit. Jeder Buchungssatz führt auf einen konkreten, prüfbaren Nachweis zurück (Transaktions-Hash, Activity-/Trade-ID, Abruf-Zeitpunkt, Rohdaten-Snapshot). Der Roh-Ingest ist unveränderlich (append-only); Abrechnungen sind daraus reproduzierbar ableitbar.
- Zwei Ebenen: neutraler Ledger + prüfbare US-Steuerschicht. Unten liegt eine vollständige, länderneutrale Transaktions-/Ledger-Aufstellung + Kennzahlen (belastbare Basis). Darauf setzt eine konfigurierbare, dokumentierte US-Steuer-Rechenschicht (Florida LLC, §4a) — mit klaren, im Export ausgewiesenen Annahmen, die der US-CPA prüft/bestätigt. Das Tool rechnet; es berät nicht (Disclaimer, §4a). Der neutrale Ledger bleibt auch bei anderer steuerlicher Einordnung gültig.
- Lesend / idempotent. Keine Orders, keine On-Chain-Writes. Überlappende Wiederholungs-Abrufe dürfen nichts doppelt buchen (stabile Idempotenz-Schlüssel, Upsert statt Insert).
1. Architektur-Einbettung
Neues Projekt src/PolyTrader.Modules.Accounting/ als IPolyTraderModule
(Name = "Accounting", DbPrefix = "acc_"), Registrierung in Program.cs. Referenziert nur den
Core. Eigener AccountingDbContext (acc_-Tabellen), eigene UI (ein Fenster mit Tabs), eigene
Settings-Sektion.
- Nutzt den bestehenden
PolymarketApiService(Data-API/activity,/positions,GetUsdcBalanceAsync(wallet)) und für On-Chain-Ein-/Auszahlungen die vorhandene Alchemy-Anbindung. - Betrifft ALLE Live-Accounts (aus
TradingState.Accountsbzw.IAccountRepository;!IsDemo, mit gesetzterWalletAddress). - Hinweis Ist-Stand:
PolymarketApiService.GetTraderActivityAsyncfiltert heute hart auftype=TRADE. Fürs Accounting brauchen wir ALLE Activity-Typen → entweder den Filter parametrisieren oder eine eigene, accounting-spezifische Abruf-Methode (schlanker, ohne Copytrading-Annahmen).
2. Datenbeschaffung (der Kern: der unabhängige Abruf)
2.1 Ledger-Quellen bei Polymarket
- Data-API
/activity?user=<wallet>= primäres Kontobuch. Enthält (Feldnamen/Typen bei Umsetzung zwingend aus https://docs.polymarket.com verifizieren) u. a.:TRADE(BUY/SELL-Fills): Preis, Size, USDC, Fee, Token/Market, txHash, Timestamp, Side.REDEEM(Resolution-Auszahlung: Gewinner-Shares → USDC).SPLIT/MERGE/CONVERSION(CTF-/NegRisk-Operationen; meist geldneutral, aber bestandsrelevant).REWARD(Liquidity Rewards) / Maker-Rebates — Einnahmen.
- On-Chain USDC-Ein-/Auszahlungen (Deposits/Withdrawals ins/aus dem Wallet): sind nicht Teil
der Trading-Activity. Quelle: Polygon/Alchemy (ERC-20-Transfer-Logs USDC ↔ Wallet).
- Adresse ist vorhanden: Polymarket nutzt Gnosis-Safe-Proxy-Wallets — genau die Adresse, die
wir bereits als
AccountState.WalletAddressfür Balance- und Activity-Abrufe verwenden. Sie ist also die Watch-Adresse für USDC-Transfers (keine zusätzliche Beschaffung nötig). - Die eigentliche Arbeit ist die Klassifikation: Die USDC-Transfers des Safes enthalten SOWOHL
trading-interne Bewegungen (Safe ↔ Polymarket-Contracts: CTF/Exchange/NegRisk — bereits in
/activityals Trades/Redeems erfasst) ALS AUCH echte Ein-/Auszahlungen (Safe ↔ EXTERNE Adressen). Nur letztere sind Deposits/Withdrawals. Klassifikation über eine Whitelist der Polymarket-System-Contracts (die CTF-Adresse0x4D97…6045liegt bereits im Code — Exchange/NegRisk-Adapter/USDC ergänzen, aus docs verifizieren). Alternativ als Kreuzprobe: ΔSafe-Balance − Σ(interne Activity) = externe Netto-Ein-/Auszahlung. - ⚠️ Gnosis-Safe-Nuance: Transfers laufen ggf. als Safe-
execTransaction; die ERC-20-Transfer-Logs (from/to = Safe) bleiben aber die maßgebliche, prüfbare Quelle.
- Adresse ist vorhanden: Polymarket nutzt Gnosis-Safe-Proxy-Wallets — genau die Adresse, die
wir bereits als
- Balance-Anker:
GetUsdcBalanceAsync(wallet)je Abruf als Kontrollpunkt (End-Saldo Soll-Ist).
2.2 Vollständigkeit & Idempotenz
- Backfill + Inkrementell: Erstlauf lädt die volle Historie je Account (paginiert,
offset/limit; Rate-Limits beachten — Activity 1000/10 s, Positions 150/10 s, bereits im ApiService limitiert). Danach nur neue Ereignisse ab dem letzten bekannten Zeitpunkt, mit Sicherheits-Lookback-Überlappung gegen API-Lag. - Idempotenz-Schlüssel je Buchungssatz: stabile Kombination
txHash + logIndex/assetId + type→ überlappende Abrufe buchen nicht doppelt (Unique-Constraint + Upsert). - Lückenerkennung: Timestamp-Kontinuität + Seiten-Vollständigkeit prüfen; fehlende Bereiche gezielt nachladen und markieren.
- Rohdaten-Snapshot: die JSON-Rohantwort je Abruf-Batch speichern (Nachweis + Reproduzierbarkeit), zusätzlich zu den normalisierten Sätzen.
2.3 Abruf-Steuerung
AccountingIngestJob : BackgroundService(JobManager-registriert, manuell triggerbar), Intervall konfigurierbar (z. B. stündlich inkrementell, täglich Voll-Reconcile). Nutzt die bestehenden Rate-Limiter desPolymarketApiService.
3. Persistenz (acc_-Tabellen, append-only Ledger)
| Tabelle | Inhalt |
|---|---|
acc_ledger |
Normalisierte, unveränderliche Buchungssätze: AccountId, EventType (TRADE_BUY/TRADE_SELL/REDEEM/REWARD/FEE/SPLIT/MERGE/DEPOSIT/WITHDRAWAL), Timestamp, TokenId/Market, Outcome, Size, PriceUsdc, GrossUsdc, FeeUsdc, NetUsdc, TxHash, LogIndex, Source, IngestBatchId, IdempotencyKey (unique) |
acc_ingest_runs |
Abruf-Protokoll: AccountId, Von/Bis, Start/Ende, #Sätze, Ok/Fehler, Balance-Anker (Soll-Ist) |
acc_raw |
Rohdaten-Snapshots (JSON) je Batch (Nachweis) |
acc_fx_rates |
(falls Fiat, §10.1) amtliche Tages-FX-Kurse (z. B. USD→EUR) je Datum |
acc_statements (optional) |
Erzeugte Periodenabrechnungen (Metadaten + Daten-Hash) für Versionierung/Reproduzierbarkeit |
Autoincrement-PKs (Lehre aus dem CopyTrading-TradeId-Problem), Unique-Index auf IdempotencyKey,
Indizes auf (AccountId, Timestamp).
4. Buchhaltungs-Logik (pure, testbar) — AccountingEngine
Wie bei den anderen Modulen liegt die geldkritische Logik pur und unit-getestet in Logic/:
- Klassifikation roher Activity → Buchungssatz-Typ + Vorzeichen (Einnahme/Ausgabe). Rein/testbar.
- Periodenabrechnung (Zeitraum × Account bzw. alle): aggregiert die Ledger-Sätze zu: Anfangssaldo, Einlagen, Entnahmen, Handelsvolumen, realisierte Gewinne/Verluste, Fees, Rewards, Netto-Ergebnis, Endsaldo — mit Soll-Ist gegen den Balance-Anker (Abweichung = Vollständigkeits-Signal).
- Realisierung / Kostenbasis: Gewinn/Verlust wird bei SELL/REDEEM realisiert; Kostenbasis je Position per FIFO (US-Norm für Krypto/Property; Specific-ID als Option, §10.5) — Lot-Matching der BUYs zu jeder Veräußerung, inkl. Haltefristen (short/long term). Pure/testbar. Offene Positionen zum Periodenende optional als Mark-to-Market ausweisen, aber getrennt vom realisierten Ergebnis.
- Währung/FX: jede Transaktion in USDC (nativ), USD und EUR. Umrechnung je Transaktionsdatum:
USDC→USD (Stablecoin, Annahme 1:1 als USD-Äquivalent — im Export dokumentiert; realer USDC/USD-Kurs
optional) und USD→EUR über amtliche Tageskurse (EZB), versioniert in
acc_fx_rates.
4a. US-Steuer-Rechenschicht (Florida LLC) — konfigurierbar, CPA-prüfbar
⚠️ Kein Steuerrat. Diese Schicht rechnet Zahlen nach dokumentierten, konfigurierbaren Annahmen aus und weist diese im Export offen aus. Die steuerliche Einordnung von Prediction-Market-/Event-Contract-Erträgen in den USA ist nicht eindeutig geklärt. Der Output ist zur Prüfung/Bestätigung durch einen US-CPA/Steuerberater gedacht, nicht als endgültige Steuererklärung. Jede Annahme ist im PDF/CSV dokumentiert und in den Settings umstellbar.
Rahmen (Defaults, alle in Settings umstellbar):
- Entität: Florida LLC. Florida erhebt keine State Income Tax → nur Federal. LLC-Typ (single-member = disregarded → Schedule C/D im 1040; vs. multi-member = Partnership 1065 + K-1) bestimmt nur die Ziel-Formulare, nicht die Gewinnermittlung (§10.7).
- Einordnung (Default-Annahme): jede Position = Property-Disposition → realisierter Gewinn/ Verlust je Veräußerung (SELL/REDEEM) im Form-8949/Schedule-D-Stil: Proceeds (USD), Cost Basis (USD), Holding Period (short/long), Gain/Loss. Alternative Einordnungen (ordinary income, gambling, §1256) als umstellbare Annahme vorgesehen — Auswahl trifft der CPA (§10.4).
- USDC: als USD-Äquivalent (1:1) behandelt; USDC-Käufe/-Verkäufe gelten nicht separat als steuerbares Krypto-Event (dokumentierte Vereinfachung; abschaltbar).
- Kostenbasis: FIFO (Default) oder Specific-ID; Lot-genau, mit Haltefristen.
- Wash-Sale: Default-Annahme „nicht anwendbar" auf Event-Contracts/Krypto (Stand 2026) — als Schalter, da Rechtslage im Fluss.
Output der Steuerschicht:
- Form-8949-artige Veräußerungsliste je Account/Zeitraum (Description, Acquired, Sold, Proceeds, Cost Basis, Gain/Loss, Short/Long) — CSV + PDF.
- Schedule-D-artige Zusammenfassung (kurz-/langfristig, Summen) je Account und aggregiert über die LLC.
- Vollständige Methodik-/Annahmen-Seite im Export (Reproduzierbarkeit + Prüfbarkeit).
Die Rechenlogik (FIFO-Lot-Matching, Haltefrist, Gain/Loss, FX-Umrechnung je Datum) liegt pur und
unit-getestet in Logic/ (z. B. UsTaxEngine), getrennt vom neutralen Ledger.
5. UI (WinForms, ein Fenster mit Tabs — Muster wie ResolutionFarming)
- Übersicht / BWA: Kennzahlen-Kacheln für den gewählten Zeitraum + Account(s): Netto-Ergebnis, Handelsvolumen, Fees, Rewards, Einlagen/Entnahmen, Endsaldo, realisiert vs. offen; Monats-/Perioden-Vergleich.
- Ledger: filterbare Transaktionsliste inkl. Nachweisspalten (txHash etc.).
- Steuer (US): Form-8949-artige Veräußerungsliste + Schedule-D-Zusammenfassung je Account/alle, mit ausgewiesenen Annahmen (FIFO, Einordnung, USDC=USD). Werte in USD (und EUR).
- Abrechnungen / Export: Zeitraum-Picker (Monats-Presets + frei), Account-Auswahl (einzeln / alle), Währungswahl (USDC/USD/EUR), Buttons „CSV" und „PDF".
- Abruf / Status: Ingest-Läufe, Vollständigkeits-/Lücken-Status, Balance-Soll-Ist, manueller Trigger.
6. Export (CSV + PDF)
- CSV: vollständiger Ledger + Aggregat je Abrechnung (maschinen-/prüfbar).
- PDF: formatierte Abrechnung — Kopf (Account, Wallet, Zeitraum, Erstellungsdatum), Aggregat-Tabelle, Transaktionsliste, Methodik-/Nachweis-Hinweis. Library PDFsharp/MigraDoc (MIT) — echte, bedingungslose MIT-Lizenz ohne Umsatzschwelle; MigraDoc eignet sich für tabellarische Abrechnungen/Berichte. (QuestPDF bewusst NICHT: dessen „Community"-Lizenz ist kostenlos nur unter 1 Mio USD Jahresumsatz — für eine handelnde LLC ein Lizenzrisiko. Siehe §10.1.)
- Reproduzierbarkeit: jeder Export trägt Zeitraum, Datenstand (letzter Ingest), Zeilenzahl und einen Daten-Hash → gleiche Eingabe ⇒ identische Abrechnung (wichtig für die Prüfbarkeit).
7. Abgleich mit eigener Trade-DB (niedrige Priorität)
Gegenüberstellung Polymarket-Ledger ↔ unsere Modul-/Core-Trade-Logs je Account/Zeitraum: fehlende/ zusätzliche Trades, Preis-/Size-/Fee-Abweichungen, PnL-Differenzen. Rein analytisch — findet Sync-/Buchungsfehler unserer Trading-Seite. Bericht in der UI + Export.
8. Phasen & Akzeptanzkriterien
- A-1 Ingest (read-only), inkl. Ein-/Auszahlungen: Modul + acc_-Persistenz + Activity-Ingest
(ALLE Typen) + On-Chain-USDC-Deposits/Withdrawals + Backfill/Inkrement + Idempotenz + Ingest-Status-UI.
Akzeptanz: volle Historie eines Live-Accounts vollständig & doppelfrei; Balance-Anker Soll-Ist ≈ 0
(inkl. Ein-/Auszahlungen).
✅ UMGESETZT (2026-07-20, Commit folgt):
PolyTrader.Modules.Accounting(acc_-Präfix). PureAccountingClassifier(Typ/Vorzeichen/Idempotenz-Key; intern↔extern-Transfer-Trennung via System-Contract-Whitelist).AccountingDbContext(acc_ledger append-only + Unique-Idempotency, acc_ingest_runs, acc_raw; MigrationInitialAccountingangewendet).AccountingIngestService(BackgroundService, testbarerIngestAccountAsync: idempotenter Upsert + Balance-Anker-Δ + Backfill/Inkrement mit Lookback). Quellen hinter Interfaces (IActivitySource/ITransferSource/IBalanceAnchorSource) mit Null-Stubs — offline lauffähig; Live-Abruf (Polymarket /activity ALLE Typen, Alchemy-USDC-Transfers, GetUsdcBalanceAsync) + System-Contract-Whitelist ist Zielland- Arbeit. UI (designerfähig): Tabs Ledger + Abruf/Status mit manuellem Backfill/Inkrement. 12 Tests. - A-2 Abrechnung + Übersicht + FX:
AccountingEngine+ BWA-UI + Periodenabrechnung je Account/alle, Werte in USDC/USD/EUR (Tageskurse inacc_fx_rates). Akzeptanz: Monatsabrechnung stimmt gegen Balance-Anker; Kennzahlen plausibel; FX nachvollziehbar. - A-3 US-Steuerschicht:
UsTaxEngine(FIFO-Lot-Matching, Haltefristen, Gain/Loss) + Form-8949-/ Schedule-D-Ansicht + Annahmen-Dokumentation. Akzeptanz: Summe realisierter Gain/Loss stimmt gegen die neutrale Abrechnung; Annahmen ausgewiesen. - A-4 Export: CSV + PDF (Abrechnung, Ledger, Form-8949/Schedule-D) mit Zeitraum-/Account-/Währungswahl. Akzeptanz: vollständig, reproduzierbar, prüfbar.
- A-5 Reconciliation (niedrig): Abgleich mit eigener DB.
Die geldkritische Logik (Klassifikation, Aggregation, Realisierung, FX) ist von Anfang an pur + unit-getestet; Ingest/Export werden über Interfaces (Activity-Quelle, PDF-Writer) testbar gehalten — wie bei ResolutionFarming die Live-Anbindung hinter Interfaces liegt.
9. Risiken & Gegenmaßnahmen
| Risiko | Gegenmaßnahme |
|---|---|
| Unvollständige API-Historie / Pagination-Lücken | Balance-Anker-Soll-Ist als Vollständigkeits-Wächter; Lückenerkennung + Nachlad; Rohdaten-Snapshots |
| API-Feld-/Endpoint-Änderungen | Rohdaten speichern; Normalisierung entkoppelt; Feldnamen bei Umsetzung aus docs verifizieren |
| Doppelbuchung bei überlappenden Abrufen | strikte Idempotenz-Schlüssel + Upsert |
| Steuerliche Fehlinterpretation | bewusst neutrale, vollständige Aufstellung statt Steuerberechnung; Methodik im Export dokumentiert |
| FX-Korrektheit | amtliche Tageskurse (z. B. EZB) versioniert in acc_fx_rates |
| Falsche Wallet-Adresse (Proxy vs. Signer) für Deposits | Adress-/Transfer-Semantik je Account verifizieren |
10. Entscheidungen & offene Punkte
Entschieden (2026-07-14):
- ✅ Währung: USDC nativ + USD + EUR (Tageskurse EZB, USDC≈USD dokumentiert).
- ✅ Abrechnung: neutraler Ledger + US-Steuerschicht (Florida LLC), als CPA-prüfbare Rechenschicht.
- ✅ Umfang v1: inkl. On-Chain-Ein-/Auszahlungen.
- ✅ Kostenbasis: FIFO (US-Norm), Specific-ID als Option.
Noch offen / vom CPA zu bestätigen:
- ✅ PDF-Library: PDFsharp/MigraDoc (MIT) — nach Rückfrage bewusst statt QuestPDF: QuestPDFs „Community MIT"-Lizenz ist nur unter 1 Mio USD Jahresumsatz kostenlos (darüber Professional/ Enterprise kostenpflichtig) → für eine handelnde LLC ein Lizenzrisiko. PDFsharp/MigraDoc ist echte MIT ohne Schwelle.
- Steuerliche Einordnung (Default-Annahme): Property-Disposition (Form 8949/Schedule D, Default) vs. ordinary income vs. gambling vs. §1256 — vom US-CPA bestätigen lassen; im Tool umstellbar.
- LLC-Typ: single-member (disregarded) vs. multi-member (Partnership 1065/K-1) — bestimmt nur die Ziel-Formulare/Darstellung, nicht die Gewinnermittlung.
- USDC=USD-Annahme & Wash-Sale-Schalter: Defaults gesetzt (1:1; Wash-Sale n/a) — vom CPA bestätigen.
- ✅ Proxy-Wallets: geklärt. Der Gnosis-Safe (= vorhandene
WalletAddress) ist die Watch-Adresse; zu bauen ist die Transfer-Klassifikation intern (Polymarket-Contracts) vs. extern (Deposit/Withdrawal) über eine System-Contract-Whitelist (CTF-Adresse bereits im Code; Exchange/NegRisk/USDC ergänzen). - FX-Quelle & USDC/USD: EZB-Tageskurse für USD→EUR; USDC→USD als 1:1 (Default) oder realer Kurs?