Slice 1 (Fable-Fixes): Leiter-Ownership – K1/H2/H1
Wer darf die ruhende Leiter-Order anfassen? Nur die Leiter selbst. - H1 (Race): StartLadderAsync macht ZUERST einen atomaren Claim (ExitLadders.TryAdd). Master-SELL (Engine) und Profit-Target (Sync) sind damit idempotent – kein Doppel-GTC / keine Fehlerkaskade. Verliert ein Aufrufer den Claim, wird die (evtl. von der Engine entfernte) Position als ExitPending zurueckgestellt – kein Waise. Order-Fehler gibt den Claim zurueck. - K1a (Floor-Deadlock): CleanupStaleOpenOrdersAsync ueberspringt Keys mit aktiver Leiter (ExitLadders.ContainsKey) – cancelt die Floor-Order nicht mehr. - K1b (Floor-Robustheit): ProcessLadderAsync prueft am Floor via GetOpenOrders, ob die SELL-Order noch ruht; falls nicht (Cleanup/extern/Teil-Fill), neu platzieren statt bis zum Neustart unverkaeuflich zu haengen. - H2 (Engine-Cancel): Pre-Signal-CancelConflictingOrders wird uebersprungen, wenn fuer den Markt eine Leiter aktiv ist – zerschiesst die Leiter-Order nicht. Tests: 8 neue Integrationstests (SellLadderService ueber gemockten IClobClient): atomarer/paralleler Claim, Waisen-Schutz, Claim-Rueckgabe, Floor-Neuplatzierung, Floor-Halten bei ruhender Order, Leiter-Ende bei gefuellter Position. Verifikation: Build 0 Fehler, 215 Tests gruen, --smoke-ui ok. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
ad8f7b0d03
commit
0200a726e7
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using PolyTrader.Core.Persistence;
|
||||
using PolyTraderSharp.Models;
|
||||
|
||||
namespace PolyTrader.Tests.Fakes
|
||||
{
|
||||
/// <summary>
|
||||
/// Minimaler In-Memory-Stub für <see cref="IPositionRepository"/>. Die Leiter-Tests brauchen nur,
|
||||
/// dass UpsertLive nicht crasht; die eigentliche Persistenz ist hier irrelevant.
|
||||
/// </summary>
|
||||
public sealed class FakePositionRepository : IPositionRepository
|
||||
{
|
||||
public List<(int AccountId, string TokenId)> UpsertedLive { get; } = new();
|
||||
|
||||
public List<Position> GetLive(int accountId) => new();
|
||||
public List<Position> GetDemo(int accountId) => new();
|
||||
public Position? FindLive(int accountId, string tokenId) => null;
|
||||
public Position? FindDemo(int accountId, string tokenId) => null;
|
||||
public void UpsertLive(int accountId, Position position) => UpsertedLive.Add((accountId, position.TokenId));
|
||||
public void UpsertDemo(int accountId, Position position) { }
|
||||
public void DeleteLive(int accountId, string tokenId) { }
|
||||
public void DeleteDemo(int accountId, string tokenId) { }
|
||||
public void DropDemo(int accountId) { }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user