Files
IBKRTrader/Core/Settings/AppSettings.cs
T
Richard 2ad4b55db1 @
Phase 3: Trading-Kern (Risk, Execution, Portfolio) mit sicherem Broker-Default

- Core/Trading/TradingModels: Signal, Order(Request/Result), RiskContext/Decision,
  Account, Position, Quote, ExecutionResult, Enums (Side/OrderType/Mode)
- IBrokerClient + NullBrokerClient (sicherer Default, handelt NIE bis IBKR-Adapter verifiziert)
- RiskService (+IRiskService): Sizing nach MaxTrade%, Modul-Limit, Slippage; Buy/Sell
- PortfolioService (+IPortfolioService): core_position + core_trade_history + core_budget
- ExecutionService (+IExecutionService): Signal -> Kurs -> Konto -> Risiko -> Order -> Buchung
- TradingSettings in AppSettings (Paper/Live, TradingEnabled, Risikoparameter)
- CoreMigrations: core_position; DI-Registrierung der Trading-Services
- Tests: RiskService (11) + ExecutionService (6, NSubstitute) -> 38/38 gruen

Offen (bewusst gekapselt): echter IbkrBrokerClient gegen Client-Portal-Gateway (manuell verifizieren).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-07-27 11:33:59 +02:00

256 lines
9.9 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 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();
}