Initial commit: IBKRTrader

.NET WinForms-Anwendung (Core, Modules/CongressTrading, UI).
Enthaelt .gitignore und settings.example.json als Konfigurationsvorlage.
Echte settings.json mit Zugangsdaten ist bewusst ausgeschlossen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-07-26 18:19:47 +02:00
co-authored by Claude Opus 4.8
commit ebeb035e92
47 changed files with 4527 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
namespace IBKRTrader.Core.Logging;
public enum AppLogLevel
{
Info = 0,
Warn = 1,
Error = 2
}
+10
View File
@@ -0,0 +1,10 @@
namespace IBKRTrader.Core.Logging;
/// <summary>Immutable log entry wird in Datei und RichTextBox geschrieben.</summary>
public sealed record LogEntry(
DateTime Timestamp,
AppLogLevel Level,
string Module,
string Message,
Exception? Exception = null
);
+105
View File
@@ -0,0 +1,105 @@
using System.Runtime.CompilerServices;
namespace IBKRTrader.Core.Logging;
/// <summary>
/// Thread-sicherer Logging-Service.
/// Schreibt farbig in die RichTextBox (UI-Thread-safe via BeginInvoke)
/// Schreibt in Logs\{Module}\{Level}-dd-MM-yy.txt
/// </summary>
public class LoggingService
{
private RichTextBox? _rtb;
private AppLogLevel _minLevel = AppLogLevel.Info;
private readonly object _fileLock = new();
private static readonly string LogBaseDir =
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
// ─── Konfiguration ────────────────────────────────────────────────────────
public void AttachRichTextBox(RichTextBox rtb) => _rtb = rtb;
public void SetMinLevel(AppLogLevel level) => _minLevel = level;
// ─── Öffentliche API ─────────────────────────────────────────────────────
public void Info (string module, string message, Exception? ex = null)
=> Write(AppLogLevel.Info, module, message, ex);
public void Warn (string module, string message, Exception? ex = null)
=> Write(AppLogLevel.Warn, module, message, ex);
public void Error(string module, string message, Exception? ex = null)
=> Write(AppLogLevel.Error, module, message, ex);
public void Write(AppLogLevel level, string module, string message, Exception? ex = null)
{
if (level < _minLevel) return;
var entry = new LogEntry(DateTime.Now, level, module, message, ex);
WriteToFile(entry);
WriteToRtb(entry);
}
// ─── Datei ────────────────────────────────────────────────────────────────
private void WriteToFile(LogEntry e)
{
try
{
var dir = Path.Combine(LogBaseDir, e.Module);
Directory.CreateDirectory(dir);
var file = Path.Combine(dir, $"{e.Level}-{e.Timestamp:dd-MM-yy}.txt");
var line = $"[{e.Timestamp:HH:mm:ss}] {e.Message}";
if (e.Exception != null)
line += $"\r\n {e.Exception}";
lock (_fileLock)
File.AppendAllText(file, line + "\r\n");
}
catch { /* Logging darf niemals abstürzen */ }
}
// ─── RichTextBox ──────────────────────────────────────────────────────────
private static readonly Color ColorInfo = Color.FromArgb(150, 210, 150);
private static readonly Color ColorWarn = Color.FromArgb(255, 190, 60);
private static readonly Color ColorError = Color.FromArgb(255, 80, 80);
private void WriteToRtb(LogEntry e)
{
if (_rtb == null) return;
try
{
var color = e.Level switch
{
AppLogLevel.Warn => ColorWarn,
AppLogLevel.Error => ColorError,
_ => ColorInfo
};
var text = $"[{e.Timestamp:HH:mm:ss}] [{e.Level.ToString().ToUpper(),-5}] [{e.Module}] {e.Message}";
if (e.Exception != null)
text += $"\r\n {e.Exception.Message}";
text += "\r\n";
if (_rtb.InvokeRequired)
_rtb.BeginInvoke(() => AppendColored(text, color));
else
AppendColored(text, color);
}
catch { }
}
private void AppendColored(string text, Color color)
{
if (_rtb == null) return;
_rtb.SelectionStart = _rtb.TextLength;
_rtb.SelectionLength = 0;
_rtb.SelectionColor = color;
_rtb.AppendText(text);
_rtb.SelectionColor = _rtb.ForeColor;
if (_rtb.TextLength > 0)
_rtb.ScrollToCaret();
}
}