Fruehjahrsputz: toter Code, ungenutzte Symbole, Dokumentenstand
Alles Entfernte war nachweislich ohne Aufrufer. Build, 198/198 Tests, Smoke-UI
und Daemon-Prueflauf sind vor und nach jedem Schritt gruen.
Code:
- AIModelService: Platzhalter, der immer 0.5 lieferte. Im DI registriert,
aber nie irgendwo injiziert. Ordner Core/AI faellt mit weg.
- CtApiWrapper + CtMeta: JSON-Modelle fuer einen {data,meta}-Umschlag, den
CapitolTrades nicht mehr liefert. Der Scraper deserialisiert seit laengerem
direkt List<CtTrade>.
- IBKRGatewayService: DisconnectAsync, InitBrokerageSessionAsync und
SearchStocksBySymbolAsync. Der Dienst selbst bleibt - er versorgt
Instrument-Sync, Kurshistorie und den Watchdog-Heartbeat.
- Je eine Methode ohne Aufrufer: BudgetService.GetAvailableBudgetAsync,
TradeHistoryService.GetRecentTradesAsync, CongressRepository.
GetAllTradeIdsAsync und .ResetHistoryImportAsync, IbkrMapping.DefaultPortFor,
SecretProtection.IsEncrypted.
- CongressRepository bekam damit einen LoggingService injiziert, den es nicht
mehr benutzt - Abhaengigkeit samt Konstruktorparameter raus.
Ressourcen:
- 17 Symbole der WinForms-Oberflaeche entfernt. Das Wildcard-Muster im csproj
nahm sie in die Binaerdatei auf, ViewIcons.cs bildet aber nur sieben
Schluessel ab. Resources/ enthaelt jetzt genau die sieben.
NuGet-Allowlist:
- Dapper und HtmlAgilityPack sind seit R3 bzw. R1 aus dem Projekt raus,
Microsoft.WindowsDesktop.* seit L5. Muster entfernt.
- MySqlConnector und Newtonsoft.Json stehen NUR transitiv in den
Projektdateien und wurden zuerst mitentfernt - ein Restore in einen leeren
Paket-Ordner scheiterte darauf mit NU1100. Beide wieder aufgenommen, jetzt
mit Begruendung, damit der naechste Aufraeumlauf nicht dieselbe Falle tritt.
Dokumente an den tatsaechlichen Stand angeglichen:
- ARCHITECTURE: R2 fuehrte die Umstellung auf IHostedService als offen, obwohl
R4 sie erledigt hat. L6 und die Deploymentcenter-Phase fehlten ganz.
- DC-Konzept: Schritte 0-8 standen auf "dieser Durchlauf", sind aber umgesetzt.
Jetzt je Schritt der wirkliche Stand - inklusive der beiden Halbfertigen:
Update-PRUEFUNG laeuft, das Anwenden hat keinen Aufrufer; die
Release-Pipeline steht, ist aber nie gelaufen. P5 ist eingetreten.
- Accounting und Supervisor trugen keinen Umsetzungsvermerk, obwohl beide
Module gebaut sind. Vermerk nach dem Muster des Linux-Konzepts ergaenzt,
mit dem, was jeweils offen bleibt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -44,7 +44,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Die Symbole der bisherigen Oberfläche unverändert weiterverwenden (siehe Shell/ViewIcons.cs). -->
|
||||
<!-- Resources/ enthält genau die Symbole, die Shell/ViewIcons.cs auf einen Schlüssel abbildet.
|
||||
Der Ordner trug bis 2026-08-23 zusätzlich 17 Symbole der WinForms-Oberfläche mit, die das
|
||||
Wildcard-Muster mit in die Binärdatei nahm, ohne dass sie je aufgelöst wurden. Kommt ein
|
||||
neuer Schlüssel dazu, gehört das PNG hierher – eine Datei ohne Eintrag in ViewIcons nicht. -->
|
||||
<AvaloniaResource Include="..\..\Resources\*.png" Link="Assets\%(Filename)%(Extension)" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
using IBKRTrader.Core.Logging;
|
||||
|
||||
namespace IBKRTrader.Core.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Platzhalter für KI-Modell-Integration.
|
||||
/// Wird in einer späteren Phase mit echten ML-Modellen ersetzt.
|
||||
/// </summary>
|
||||
public class AIModelService
|
||||
{
|
||||
private readonly LoggingService _logger;
|
||||
|
||||
public AIModelService(LoggingService logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>Platzhalter: Gibt immer 0.5 zurück (keine echte Vorhersage).</summary>
|
||||
public Task<double> PredictAsync(string symbol, object features)
|
||||
{
|
||||
_logger.Warn("AI", $"AIModelService ist ein Platzhalter – keine echte Vorhersage für {symbol}.");
|
||||
return Task.FromResult(0.5);
|
||||
}
|
||||
}
|
||||
@@ -19,13 +19,6 @@ public class BudgetService
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<decimal> GetAvailableBudgetAsync(string module)
|
||||
{
|
||||
await using var db = await _dbf.CreateDbContextAsync();
|
||||
var b = await db.Budgets.FindAsync(module);
|
||||
return b is null ? 0m : b.TotalBudget - b.UsedBudget;
|
||||
}
|
||||
|
||||
public async Task ReserveBudgetAsync(string module, decimal amount)
|
||||
{
|
||||
await using var db = await _dbf.CreateDbContextAsync();
|
||||
|
||||
@@ -119,26 +119,6 @@ public class IBKRGatewayService
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialisiert die Brokerage-Session über den Gateway.
|
||||
/// </summary>
|
||||
public async Task<bool> InitBrokerageSessionAsync(CancellationToken ct = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await RateLimitAsync(ct);
|
||||
var body = new StringContent("{\"publish\":true,\"compete\":true}",
|
||||
System.Text.Encoding.UTF8, "application/json");
|
||||
var response = await _http.PostAsync("iserver/auth/ssodh/init", body, ct);
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn("IBKR", $"Brokerage-Session-Init fehlgeschlagen: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Contract Search ─────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
@@ -198,33 +178,6 @@ public class IBKRGatewayService
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sucht Aktien-Contracts nach Symbolen.
|
||||
/// GET /trsrv/stocks?symbols=AAPL,MSFT
|
||||
/// </summary>
|
||||
public async Task<Dictionary<string, List<IBKRStockContract>>?> SearchStocksBySymbolAsync(
|
||||
string symbols, CancellationToken ct = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await RateLimitAsync(ct);
|
||||
var response = await _http.GetAsync($"trsrv/stocks?symbols={Uri.EscapeDataString(symbols)}", ct);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
_logger.Warn("IBKR", $"Stock-Suche fehlgeschlagen: HTTP {(int)response.StatusCode}");
|
||||
return null;
|
||||
}
|
||||
|
||||
return await response.Content.ReadFromJsonAsync<Dictionary<string, List<IBKRStockContract>>>(JsonOpts, ct);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error("IBKR", $"Stock-Suche fehlgeschlagen: {ex.Message}", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Historical Market Data ──────────────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
@@ -263,12 +216,4 @@ public class IBKRGatewayService
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Disconnect ──────────────────────────────────────────────────────────
|
||||
|
||||
public Task DisconnectAsync()
|
||||
{
|
||||
IsConnected = false;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,10 +92,6 @@ public static class SecretProtection
|
||||
return Encoding.UTF8.GetString(pt);
|
||||
}
|
||||
|
||||
/// <summary>True, wenn der Wert bereits im verschlüsselten Format vorliegt.</summary>
|
||||
public static bool IsEncrypted(string? value) =>
|
||||
!string.IsNullOrEmpty(value) && value!.StartsWith(Prefix, StringComparison.Ordinal);
|
||||
|
||||
private static byte[] DeriveKey(string raw)
|
||||
{
|
||||
// 32-Byte-Key als Base64?
|
||||
|
||||
@@ -33,10 +33,6 @@ internal static class IbkrMapping
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>Der zum Handelsmodus passende Gateway-Port.</summary>
|
||||
public static int DefaultPortFor(TradingMode mode) =>
|
||||
mode == TradingMode.Live ? GatewayLivePort : GatewayPaperPort;
|
||||
|
||||
/// <summary>US-Aktie über die SMART-Route – der einzige Instrumententyp, den die Module handeln.</summary>
|
||||
public static Contract Stock(string symbol) => new()
|
||||
{
|
||||
|
||||
@@ -42,13 +42,4 @@ public class TradeHistoryService
|
||||
|
||||
_logger.Info(module, $"Trade gespeichert: {action} {quantity}x {symbol} @ {price:F2}");
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<CoreTrade>> GetRecentTradesAsync(int limit = 100)
|
||||
{
|
||||
await using var db = await _dbf.CreateDbContextAsync();
|
||||
return await db.TradeHistory
|
||||
.OrderByDescending(t => t.TradedAt)
|
||||
.Take(limit)
|
||||
.ToListAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using IBKRTrader.Core.AI;
|
||||
using IBKRTrader.Core.Budget;
|
||||
using IBKRTrader.Core.Configuration;
|
||||
using IBKRTrader.Core.DependencyInjection;
|
||||
@@ -166,7 +165,6 @@ public static class AppHostBuilder
|
||||
|
||||
services.AddSingleton<BudgetService>();
|
||||
services.AddSingleton<TradeHistoryService>();
|
||||
services.AddSingleton<AIModelService>();
|
||||
|
||||
// Datenfundament für Analyse/Forensik (Supervisor): Entscheidungsjournal + Order-Events.
|
||||
services.AddSingleton<IDecisionJournal, EfDecisionJournal>();
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using IBKRTrader.Core.Logging;
|
||||
using IBKRTrader.Core.Settings;
|
||||
using IBKRTrader.Modules.CongressTrading.Models;
|
||||
using IBKRTrader.Modules.CongressTrading.Persistence.Ef;
|
||||
@@ -14,16 +13,13 @@ public class CongressRepository
|
||||
{
|
||||
private readonly IDbContextFactory<CongressTradingDbContext> _dbf;
|
||||
private readonly CoreSettingsService _settings;
|
||||
private readonly LoggingService _logger;
|
||||
|
||||
public CongressRepository(
|
||||
IDbContextFactory<CongressTradingDbContext> dbf,
|
||||
CoreSettingsService settings,
|
||||
LoggingService logger)
|
||||
CoreSettingsService settings)
|
||||
{
|
||||
_dbf = dbf;
|
||||
_settings = settings;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
// ─── CongressMember ───────────────────────────────────────────────────────
|
||||
@@ -71,13 +67,6 @@ public class CongressRepository
|
||||
return await db.Trades.AnyAsync(t => t.TradeId == tradeId);
|
||||
}
|
||||
|
||||
public async Task<HashSet<string>> GetAllTradeIdsAsync()
|
||||
{
|
||||
await using var db = await _dbf.CreateDbContextAsync();
|
||||
var ids = await db.Trades.Select(t => t.TradeId).ToListAsync();
|
||||
return ids.ToHashSet();
|
||||
}
|
||||
|
||||
/// <summary>Fügt einen Trade ein, sofern die TradeId noch nicht existiert.</summary>
|
||||
public async Task InsertTradeAsync(CongressTrade trade, bool detailsFetched = true)
|
||||
{
|
||||
@@ -133,19 +122,4 @@ public class CongressRepository
|
||||
public Task<string?> GetSettingAsync(string key) => _settings.GetAsync(key);
|
||||
public Task SetSettingAsync(string key, string v) => _settings.SetAsync(key, v);
|
||||
public Task DeleteSettingAsync(string key) => _settings.DeleteAsync(key);
|
||||
|
||||
// ─── Reset ────────────────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>Löscht alle CT-Fortschritts-Flags und alle CT-Daten aus der DB.</summary>
|
||||
public async Task ResetHistoryImportAsync()
|
||||
{
|
||||
await DeleteSettingAsync("ct.history_import_done");
|
||||
await DeleteSettingAsync("ct.history_import_page");
|
||||
await DeleteSettingAsync("ct.history_import_total");
|
||||
|
||||
await using var db = await _dbf.CreateDbContextAsync();
|
||||
await db.Trades.ExecuteDeleteAsync();
|
||||
await db.Members.ExecuteDeleteAsync();
|
||||
_logger.Warn("CT", "History-Import-Reset durchgeführt – alle CT-Daten gelöscht.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,20 +9,6 @@ namespace IBKRTrader.Modules.CongressTrading.Scraper;
|
||||
|
||||
// ─── JSON-Modelle (exakte Feldnamen aus dem RSC-Stream) ──────────────────────
|
||||
|
||||
internal class CtApiWrapper
|
||||
{
|
||||
[JsonPropertyName("data")] public List<CtTrade>? Data { get; set; }
|
||||
[JsonPropertyName("meta")] public CtMeta? Meta { get; set; }
|
||||
}
|
||||
|
||||
internal class CtMeta
|
||||
{
|
||||
[JsonPropertyName("totalPages")] public int TotalPages { get; set; }
|
||||
[JsonPropertyName("pageSize")] public int PageSize { get; set; }
|
||||
[JsonPropertyName("totalCount")] public int TotalCount { get; set; }
|
||||
[JsonPropertyName("page")] public int Page { get; set; }
|
||||
}
|
||||
|
||||
internal class CtTrade
|
||||
{
|
||||
[JsonPropertyName("_txId")] public long TxId { get; set; }
|
||||
|
||||
Reference in New Issue
Block a user