R1: Umbau auf Multi-Projekt-Struktur (Vorbild PolytraderSharp)

Kurskorrektur: Vorbild ist PolytraderSharp (C#), nicht die veraltete Python-Version.
Reiner Strukturumbau, Verhalten unveraendert.

- src/IBKRTrader.Core (classlib): Core-Code + UI-Contract (ModuleFormBase, WindowManager)
- src/IBKRTrader.Modules.CongressTrading (classlib, referenziert nur Core)
- Root: IBKRTrader.App (WinExe) referenziert Core + Modul
- tests/IBKRTrader.Tests: Referenzen auf Core + Modul
- Neue .slnx; ungenutztes HtmlAgilityPack entfernt
- docs/ARCHITECTURE.md: korrigierter Ziel-Stand + R-Phasenplan
- Build + 38/38 Tests gruen; App startet

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
This commit is contained in:
Richard
2026-07-27 20:26:25 +02:00
parent 2ad4b55db1
commit c20538c8d8
61 changed files with 171 additions and 129 deletions
+255
View File
@@ -0,0 +1,255 @@
using System.ComponentModel;
using IBKRTrader.Core.Trading;
namespace IBKRTrader.Core.Settings;
// ─── Database ────────────────────────────────────────────────────────────────
[TypeConverter(typeof(ExpandableObjectConverter))]
public class DatabaseSettings
{
[Category("Database")]
[DisplayName("Host")]
[Description("MySQL-Serveradresse (Hostname oder IP)")]
public string Host { get; set; } = "larx.your-database.de";
[Category("Database")]
[DisplayName("Port")]
[Description("MySQL-Port (Standard: 3306)")]
public int Port { get; set; } = 3306;
[Category("Database")]
[DisplayName("Database")]
[Description("Name der MySQL-Datenbank")]
public string Database { get; set; } = "bergisnu_db0";
[Category("Database")]
[DisplayName("User")]
[Description("MySQL-Benutzername")]
public string User { get; set; } = "bergisnu_0";
[Category("Database")]
[DisplayName("Password")]
[Description("MySQL-Passwort")]
[PasswordPropertyText(true)]
public string Password { get; set; } = "o5/A49+f}:Da";
public string BuildConnectionString() =>
$"Server={Host};Port={Port};Database={Database};" +
$"User={User};Password={Password};" +
$"AllowPublicKeyRetrieval=true;SslMode=Preferred;CharSet=utf8mb4;" +
$"ConnectionTimeout=15;DefaultCommandTimeout=30;";
public override string ToString() => $"{User}@{Host}:{Port}/{Database}";
}
// ─── IBKR TWS/Gateway (Socket API) ───────────────────────────────────────────
[TypeConverter(typeof(ExpandableObjectConverter))]
public class IBKRSettings
{
[Category("IBKR Gateway")]
[DisplayName("Host")]
[Description("Adresse des IBKR Gateway (Standard: 127.0.0.1)")]
public string Host { get; set; } = "127.0.0.1";
[Category("IBKR Gateway")]
[DisplayName("Port")]
[Description("IBKR Gateway Port (Paper: 4002, Live: 4001)")]
public int Port { get; set; } = 4001;
[Category("IBKR Gateway")]
[DisplayName("Client ID")]
[Description("Eindeutige Client-ID für die API-Verbindung")]
public int ClientId { get; set; } = 1;
public override string ToString() => $"{Host}:{Port} (Client {ClientId})";
}
// ─── IBKR Web API (Client Portal Gateway) ────────────────────────────────────
[TypeConverter(typeof(ExpandableObjectConverter))]
public class IBKRWebApiSettings
{
[Category("IBKR Web API")]
[DisplayName("Aktiviert")]
[Description("Aktiviert die IBKR Web API Marktdaten-Worker")]
public bool Enabled { get; set; } = false;
[Category("IBKR Web API")]
[DisplayName("Gateway URL")]
[Description("URL des Client Portal Gateway (Standard: https://localhost:5000)")]
public string GatewayUrl { get; set; } = "https://localhost:5000";
[Category("IBKR Web API")]
[DisplayName("History-Zeitraum")]
[Description("Zeitraum für den ersten historischen Import (z.B. 2Y, 5Y, 1Y)")]
public string HistoryPeriod { get; set; } = "2Y";
[Category("IBKR Web API")]
[DisplayName("Max Requests/Sek")]
[Description("Maximale API-Anfragen pro Sekunde (IBKR-Limit: 10, empfohlen: 5)")]
public int MaxRequestsPerSecond { get; set; } = 5;
public override string ToString() => Enabled ? $"Aktiv {GatewayUrl}" : "Deaktiviert";
}
// ─── Logging ─────────────────────────────────────────────────────────────────
[TypeConverter(typeof(ExpandableObjectConverter))]
public class LoggingSettings
{
[Category("Logging")]
[DisplayName("Log Level")]
[Description("Minimales Log-Level: Info, Warn oder Error")]
public string Level { get; set; } = "Info";
[Category("Logging")]
[DisplayName("Max. Dateigröße (MB)")]
[Description("Maximale Größe einer Log-Datei in Megabyte")]
public int MaxFileSizeMb { get; set; } = 10;
[Category("Logging")]
[DisplayName("Aufbewahrung (Tage)")]
[Description("Anzahl Tage, nach denen Log-Dateien gelöscht werden")]
public int RetentionDays { get; set; } = 30;
public override string ToString() => $"Level: {Level}";
}
// ─── Webserver ───────────────────────────────────────────────────────────────
[TypeConverter(typeof(ExpandableObjectConverter))]
public class WebserverSettings
{
[Category("Webserver")]
[DisplayName("Port")]
[Description("Port des internen Webservers (Web-UI)")]
public int Port { get; set; } = 5001;
[Category("Webserver")]
[DisplayName("Aktiviert")]
[Description("Webserver und REST-API beim Start aktivieren")]
public bool Enabled { get; set; } = false;
public override string ToString() => Enabled ? $"Aktiv auf Port {Port}" : "Deaktiviert";
}
// ─── Workers ─────────────────────────────────────────────────────────────────
[TypeConverter(typeof(ExpandableObjectConverter))]
public class WorkerSchedule
{
[Category("Worker")]
[DisplayName("Aktiviert")]
public bool Enabled { get; set; } = true;
[Category("Worker")]
[DisplayName("Interval (Minuten)")]
public int IntervalMinutes { get; set; } = 30;
public override string ToString() => Enabled ? $"alle {IntervalMinutes} min" : "Deaktiviert";
}
[TypeConverter(typeof(ExpandableObjectConverter))]
public class WorkerSettings
{
[Category("Workers")]
[DisplayName("BackupWorker")]
[Description("Zeitplan für den automatischen Backup-Worker")]
public WorkerSchedule BackupWorker { get; set; } = new();
[Category("Workers")]
[DisplayName("IBKR Instrument-Sync")]
[Description("Zeitplan für die IBKR Stammdaten-Synchronisation (alle 30 Tage)")]
public WorkerSchedule InstrumentSyncWorker { get; set; } = new() { IntervalMinutes = 43200 }; // 30 Tage
[Category("Workers")]
[DisplayName("IBKR Preishistorie")]
[Description("Zeitplan für den täglichen IBKR Preishistorie-Abruf")]
public WorkerSchedule PriceHistoryWorker { get; set; } = new() { IntervalMinutes = 1440 }; // 24h
public override string ToString() => "Worker-Konfiguration";
}
// ─── Trading ─────────────────────────────────────────────────────────────────
[TypeConverter(typeof(ExpandableObjectConverter))]
public class TradingSettings
{
[Category("Trading")]
[DisplayName("Modus")]
[Description("Handelsmodus: Paper (Test-Account, Port 4002) oder Live (Port 4001)")]
public string Mode { get; set; } = "Paper";
[Category("Trading")]
[DisplayName("Trading aktiv")]
[Description("Globaler Hauptschalter. Nur wenn aktiv werden Orders ausgeführt.")]
public bool TradingEnabled { get; set; } = false;
[Category("Trading")]
[DisplayName("Max. je Trade (%)")]
[Description("Maximaler Nominalwert einer einzelnen Position in % des Kontowerts")]
public double MaxTradePercent { get; set; } = 5.0;
[Category("Trading")]
[DisplayName("Max. je Modul (%)")]
[Description("Maximaler Gesamt-Nominalwert aller Positionen eines Moduls in % des Kontowerts")]
public double MaxPositionPercentPerModule { get; set; } = 20.0;
[Category("Trading")]
[DisplayName("Max. Slippage (%)")]
[Description("Maximal erlaubte Abweichung zwischen Limit-Preis und aktuellem Kurs")]
public double MaxSlippagePercent { get; set; } = 5.0;
[Category("Trading")]
[DisplayName("Gewinnziel (%)")]
[Description("Ziel-Gewinn einer Position in Prozent (für spätere Exit-Logik)")]
public double ProfitTargetPercent { get; set; } = 50.0;
/// <summary>Parst den Modus in das Enum (Fallback: Paper).</summary>
public TradingMode ParsedMode =>
Enum.TryParse<TradingMode>(Mode, true, out var m) ? m : TradingMode.Paper;
public override string ToString() => $"{Mode} {(TradingEnabled ? "aktiv" : "inaktiv")}";
}
// ─── Root ────────────────────────────────────────────────────────────────────
public class AppSettings
{
[Category("Database")]
[DisplayName("Datenbank")]
[Description("MySQL-Verbindungseinstellungen")]
public DatabaseSettings Database { get; set; } = new();
[Category("IBKR Gateway")]
[DisplayName("IBKR")]
[Description("Interactive Brokers Gateway-Verbindung (Socket API)")]
public IBKRSettings IBKR { get; set; } = new();
[Category("IBKR Web API")]
[DisplayName("IBKR Web API")]
[Description("Client Portal Gateway für Marktdaten")]
public IBKRWebApiSettings IBKRWebApi { get; set; } = new();
[Category("Logging")]
[DisplayName("Logging")]
[Description("Log-Level und Datei-Einstellungen")]
public LoggingSettings Logging { get; set; } = new();
[Category("Webserver")]
[DisplayName("Webserver")]
[Description("Interner HTTP-Server und REST-API")]
public WebserverSettings Webserver { get; set; } = new();
[Category("Workers")]
[DisplayName("Worker-Einstellungen")]
[Description("Zeitpläne der einzelnen Core-Worker")]
public WorkerSettings WorkerSettings { get; set; } = new();
[Category("Trading")]
[DisplayName("Trading")]
[Description("Handelsmodus und Risiko-Parameter")]
public TradingSettings Trading { get; set; } = new();
}