Phase 5: CopyTrading-Modul-Migration (Services + Modul-Contract)

- TraderMonitorService, CopyTradingEngine, TraderAnalyticsJob physisch ins
  Modul-Projekt (src/PolyTrader.Modules.CopyTrading/Services) verschoben.
- Neu: CopyTradingModule : IPolyTraderModule — registriert CopyTradingState,
  die Signal-/Trade-Channels, ICopyTradeLogRepository und die Modul-Services selbst.
- Program.cs: Modul-Discovery (foreach module.RegisterServices / RegisterUi);
  die entsprechenden Direkt-Registrierungen entfernt. StartupHydration laeuft
  weiterhin als erster HostedService (State-Hydration vor Trading).
- MasterTraderAnalyticsJob bleibt vorerst in der App (nutzt noch den App-Shim
  fuer mt_history -> braucht erst ein History-Repo). RegisterUi noch leer
  (Modul-Views folgen; Copytrading-UI weiter ueber Legacy erreichbar).
- Build 0 Fehler. Launcher zeigt jetzt "Module: 1".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-07-02 12:24:10 +02:00
co-authored by Claude Opus 4.8
parent 4f6c7fdb86
commit ff1db2aea0
5 changed files with 77 additions and 16 deletions
+22 -14
View File
@@ -10,6 +10,8 @@ using Microsoft.Extensions.Options;
using PolyTrader.Core.Configuration;
using PolyTrader.Core.DependencyInjection;
using PolyTrader.Core.Streaming;
using PolyTrader.Core.Modularity;
using PolyTrader.Modules.CopyTrading;
using PolyTrader.Modules.CopyTrading.Persistence;
using PolyTraderSharp.Models;
using PolyTraderSharp.Services;
@@ -25,8 +27,11 @@ internal static class Program
{
ApplicationConfiguration.Initialize();
Channel<CopySignal> copySignalChannel = Channel.CreateUnbounded<CopySignal>();
Channel<ClosedTrade> closedTradeChannel = Channel.CreateUnbounded<ClosedTrade>();
var modules = new System.Collections.Generic.List<IPolyTraderModule>
{
new CopyTradingModule()
};
AppHost = Host.CreateDefaultBuilder().ConfigureServices(delegate(HostBuilderContext context, IServiceCollection services)
{
services.Configure<DatabaseOptions>(context.Configuration.GetSection(DatabaseOptions.SectionName));
@@ -37,15 +42,9 @@ internal static class Program
return client.GetDatabase(dbOptions.DatabaseName);
});
services.AddCorePersistence();
services.AddSingleton<ICopyTradeLogRepository, MongoCopyTradeLogRepository>();
services.AddSingleton<IBlockchainWssClientFactory, AlchemyWssClientFactory>();
services.AddSingleton((IServiceProvider sp) => ServerSettings.Load("server_settings.xml"));
services.AddSingleton<TradingState>();
services.AddSingleton<CopyTradingState>();
services.AddSingleton(copySignalChannel.Writer);
services.AddSingleton(copySignalChannel.Reader);
services.AddSingleton(closedTradeChannel.Writer);
services.AddSingleton(closedTradeChannel.Reader);
services.AddSingleton(delegate(IServiceProvider sp)
{
TerminalLogger requiredService2 = sp.GetRequiredService<TerminalLogger>();
@@ -76,16 +75,21 @@ internal static class Program
services.AddSingleton<MullvadVpnService>();
services.AddSingleton<ThreemaService>();
services.AddSingleton<JobManager>();
services.AddSingleton<TraderMonitorService>();
// MUSS als erster HostedService laufen: hydriert den State, bevor die
// Trading-Services (unten) gegen einen leeren State anlaufen.
// Trading-Services gegen einen leeren State anlaufen.
services.AddHostedService<StartupHydrationService>();
services.AddHostedService((IServiceProvider sp) => sp.GetRequiredService<TraderMonitorService>());
services.AddHostedService<CopyTradingEngine>();
// Module registrieren ihre eigenen Services/Channels/State selbst.
foreach (var module in modules)
{
services.AddSingleton(module);
module.RegisterServices(services, context.Configuration);
}
services.AddHostedService<AlchemyWebsocketService>();
services.AddHostedService<PersistenceService>();
services.AddHostedService<MarketSyncService>();
services.AddHostedService<TraderAnalyticsJob>();
services.AddHostedService<MasterTraderAnalyticsJob>();
services.AddHostedService<PolymarketWssClient>();
services.AddHostedService((IServiceProvider sp) => sp.GetRequiredService<MullvadVpnService>());
@@ -193,7 +197,11 @@ internal static class Program
return view;
}
});
// TODO Phase 5-UI: registrierte IPolyTraderModule durchlaufen und module.RegisterUi(uiHost) aufrufen.
// Modul-UI registrieren (Module steuern ihre Views selbst bei).
foreach (var module in modules)
{
module.RegisterUi(uiHost);
}
var launcher = AppHost.Services.GetRequiredService<PolyTraderSharp.Ui.LauncherForm>();
Application.Run(launcher);
@@ -0,0 +1,55 @@
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Channels;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using PolyTrader.Core.Modularity;
using PolyTrader.Modules.CopyTrading.Persistence;
using PolyTraderSharp;
using PolyTraderSharp.Models;
using PolyTraderSharp.Services;
namespace PolyTrader.Modules.CopyTrading
{
/// <summary>
/// Das Copytrading-Modul: registriert seinen eigenen State, seine Channels, sein
/// Trade-Log-Repository und seine Services selbst. Die App kennt nur den Contract.
/// </summary>
public class CopyTradingModule : IPolyTraderModule
{
public string Name => "CopyTrading";
public string DbPrefix => "ct_";
public void RegisterServices(IServiceCollection services, IConfiguration configuration)
{
// Copytrading-Hot-Path-State
services.AddSingleton<CopyTradingState>();
// Signal-/Trade-Channels des Moduls
var copySignalChannel = Channel.CreateUnbounded<CopySignal>();
var closedTradeChannel = Channel.CreateUnbounded<ClosedTrade>();
services.AddSingleton(copySignalChannel.Writer);
services.AddSingleton(copySignalChannel.Reader);
services.AddSingleton(closedTradeChannel.Writer);
services.AddSingleton(closedTradeChannel.Reader);
// Modul-eigener Trade-Log
services.AddSingleton<ICopyTradeLogRepository, MongoCopyTradeLogRepository>();
// Modul-Services (Signalquelle, Ausführung, Analytics)
services.AddSingleton<TraderMonitorService>();
services.AddHostedService(sp => sp.GetRequiredService<TraderMonitorService>());
services.AddHostedService<CopyTradingEngine>();
services.AddHostedService<TraderAnalyticsJob>();
}
public void RegisterUi(IModuleUiHost host)
{
// TODO: Master-Traders- und Geschlossene-Trades-Views als Modul-UI beisteuern.
}
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
}
@@ -1,7 +1,5 @@
using System;
using MongoDB.Driver;
using PolyTrader.Core.Persistence;
using PolyTraderSharp.Extensions;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;