Files
PolyTraderSharp/src/PolyTrader.Modules.CopyTrading/CopyTradingModule.cs
T
RichardandClaude Opus 4.8 e22a6e3091 Phase 0.1: SELL-Eskalationsleiter statt Market-Dump (CLOB-kritisch)
Behebt die April-Verlustquelle: SELLs wurden als Market-Order mit 0.01-Limit ins
oft leergeraeumte Orderbuch geworfen -> wir wurden zur Exit-Liquidity. Jetzt:
GTC-Limit nahe am Master-Exit, stufenweises Nachpreisen bis zum Floor.

- Position.ExitPending (runtime-only, EF-ignoriert): Position wird bei SELL NICHT
  mehr optimistisch entfernt, sondern als ExitPending zurueckgestellt (kein
  Doppel-SELL, Limits rechnen korrekt; Sync schliesst nach bestaetigtem Fill).
- CopyTradingState.ExitLadders + ExitLadderState (transienter Leiter-Zustand).
- SellLogic (pure, getestet): FirstLimit (HF-fest/prozentual), Floor (SellFloorPct),
  NextPrice (relative Stufe, auf Floor geclamped), IsAtFloor, LadderStepPct (3%),
  LadderIntervalSeconds (HF 20s / sonst 120s).
- SellLadderService (BackgroundService): senkt offene Exit-Limits stufenweise
  (cancel via CancelConflictingOrdersAsync -> tiefer neu platzieren), am Floor ohne
  Fill Position halten + Threema-Benachrichtigung. Fills erkennt der bestehende Sync.
- CopyTradingEngine SELL-Live-Pfad ruft die Leiter; Demo-Pfad unveraendert.
  Doppel-SELL-Guard ueber ExitPending. Umfangreiches Logging (kein Live-Test moeglich).

163 Tests gruen. Build/Smoke gruen. Backup-Rollback: Commit 1dffc9e.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 17:40:40 +02:00

98 lines
4.4 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;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Channels;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using PolyTrader.Core.Configuration;
using PolyTrader.Core.Modularity;
using PolyTrader.Core.Streaming;
using PolyTrader.Modules.CopyTrading.Persistence;
using PolyTrader.Modules.CopyTrading.Persistence.Ef;
using PolyTrader.Modules.CopyTrading.Ui;
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-Persistenz: EF Core / Pomelo / MySQL (thread-safer DbContextFactory).
var conn = configuration["Database:MySqlConnectionString"] ?? string.Empty;
services.AddDbContextFactory<CopyTradingDbContext>(o => o.UseMySql(conn, DatabaseServerVersion.Value));
services.AddSingleton<ICopyTradeLogRepository, EfCopyTradeLogRepository>();
services.AddSingleton<ICopyTradingAccountSettingsRepository, EfCopyTradingAccountSettingsRepository>();
services.AddSingleton<ITrackedTraderRepository, EfTrackedTraderRepository>();
services.AddSingleton<IMasterTraderHistoryRepository, EfMasterTraderHistoryRepository>();
// WSS-Infrastruktur (Core) wird nur vom Copytrading-Blockchain-Listener genutzt.
services.AddSingleton<IBlockchainWssClientFactory, AlchemyWssClientFactory>();
// Modul-Services (Signalquelle, Ausführung, Analytics)
services.AddSingleton<TraderMonitorService>();
services.AddHostedService(sp => sp.GetRequiredService<TraderMonitorService>());
services.AddHostedService<CopyTradingEngine>();
services.AddHostedService<TraderAnalyticsJob>();
services.AddHostedService<MasterTraderAnalyticsJob>();
// Persistiert die geschlossenen Copytrades (Modul-Channel -> Modul-Log + Core-Log).
services.AddHostedService<PersistenceService>();
// WSS-Listener des Moduls: Blockchain (Alchemy → Master-Trader-Wallets) und
// Polymarket-Markt-WSS (Auto-Redeem nach Copytrading-Settings).
services.AddHostedService<AlchemyWebsocketService>();
services.AddHostedService<PolymarketWssClient>();
// Phase 0.1: SELL-Eskalationsleiter (preist offene Exit-Limits stufenweise nach).
services.AddHostedService<SellLadderService>();
}
public void RegisterUi(IModuleUiHost host, IServiceProvider services)
{
// EIN Fenster fürs ganze Modul: die einzelnen Ansichten sind Tabs im
// CopyTradingMainForm (Master-Trader / geschlossene Trades / Account-Einstellungen).
// So bleibt der Launcher schlank ein Button je Modul statt je View.
host.RegisterView(new ModuleView
{
Id = "copytrading.main",
Title = "Copytrading",
Group = "CopyTrading",
Order = 100,
CreateForm = () =>
{
var form = new CopyTradingMainForm();
form.Initialize(services);
return form;
}
});
}
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
}