Phase 5.2: TradingState-Split (Core-State vs. CopyTradingState)

- Core TradingState (in Core): globale Schalter, Accounts, MarketCache, GlobalPnl.
- Neuer CopyTradingState (im Modul): Traders, MasterTraderPositions,
  TraderAnalyticsCache, TotalCopyTrades/GetNextTradeId, PendingOrderTimestamps,
  SixSharesMinimum.
- 10 Konsumenten umgestellt (Program, frm_main, CopyTradingEngine,
  TraderMonitor, Alchemy, WSS, Snapshot, StartupHydration, beide Analytics-Jobs):
  Modul-Felder von _state.* auf _copyState.* umgeleitet, CopyTradingState via DI.
- Rein mechanische Feld-Umleitung, keine Logikänderung. Build 0 Fehler.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-07-01 20:09:50 +02:00
co-authored by Claude Opus 4.8
parent 55050a19e5
commit f8d395b2a3
13 changed files with 174 additions and 127 deletions
@@ -0,0 +1,47 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using PolyTraderSharp.Models;
namespace PolyTraderSharp
{
/// <summary>
/// In-Memory Hot-Path State des Copytrading-Moduls.
/// Enthält den copytrading-spezifischen Zustand: kopierte Master-Trader, deren
/// Positions-Tracking, Analytics-Cache, Copy-Trade-Zähler und Order-Timestamps.
/// Der modulübergreifende Zustand (Accounts, MarketCache, globale Schalter) liegt
/// im Core-<see cref="TradingState"/>.
/// </summary>
public class CopyTradingState
{
// Copytrading-Risk-Regel: mindestens 6 Shares pro Order erzwingen.
public bool SixSharesMinimum { get; set; } = true;
// Kopierte Master-Trader (TraderId -> TrackedTrader)
public ConcurrentDictionary<int, TrackedTrader> Traders { get; } = new();
private int _totalCopyTrades = 0;
public int TotalCopyTrades
{
get => _totalCopyTrades;
set => _totalCopyTrades = value;
}
public int GetNextTradeId()
{
return Interlocked.Increment(ref _totalCopyTrades);
}
// Analytics Cache (AccountId -> List<TraderAnalyticsResult>)
public ConcurrentDictionary<int, List<TraderAnalyticsResult>> TraderAnalyticsCache { get; } = new();
// Tracks when live orders were placed for stale order cleanup.
// Key: "AccountId_TokenId", Value: (PlacedAt, SourceTraderId)
public ConcurrentDictionary<string, (DateTime PlacedAt, int SourceTraderId)> PendingOrderTimestamps { get; } = new();
// Master Trader Position Tracker (Key: "{TraderId}_{TokenId}", Value: (Shares, LastUpdated))
// Entscheidet, ob ein SELL-Signal ein Teilverkauf (ignorieren) oder ein Voll-Exit (kopieren) ist.
public ConcurrentDictionary<string, (decimal Shares, DateTime LastUpdated)> MasterTraderPositions { get; } = new();
}
}