Combo fatal = Rate Limit 429 continu sur l'API TopStep (12 min de silence sur /Order/searchOpen + /Position/searchOpen) + logique _reset_cycle aveugle qui émet un Market Buy/Sell des "contrats résiduels" sans vérifier qu'une position réelle existe côté exchange.
Pendant le blackout, la position SHORT 5 cts (avg 27097.17) a été fermée côté TopStep (safety TP hit probable, ou ordre parasite). À la reconnexion, le bot voyait encore 5 cts dans son état interne alors que l'exchange affichait 0. Le reset_cycle a alors envoyé un Market Buy x5 @ 27120 pour "nettoyer" — sauf qu'il a ouvert un LONG 5 cts au sommet. Ce long s'est ensuite dissous via la re-entry SHORT 1 ct + des ordres SO/safety qui ont mangé la différence en slippage + fees.
| Métrique | Valeur | Commentaire |
|---|---|---|
| Cumul bot interne (5 cycles) | +$192.50 | ne voit QUE les 5 TP trail gagnants |
| PnL net today TopStep | −$64.70 | 25 trades · WR 28% · PF 0.72 |
| Delta bug | ≈ −$257 | écart entre réalité bot et compte |
| Worst trade today | −$132.48 | vraisemblablement le LONG 5cts débouclé |
| Max DD today | −$251.64 | 0.503% du compte · loin du daily limit $1,200 |
| Max consec losses | 7 | contre 4 la veille en condition normale |
| Fees today | $21.70 | ratio élevé pour 25 trades (ordre Market Buy 5cts) |
_reset_cycle
Fichier : strategies/dca_loop_strategy.py · méthode _reset_cycle()
Comportement actuel (buggé) :
Correction proposée :
_reset_cycle — vérif authoritative exchange avant émission d'ordre./Order/searchOpen, et backoff exponentiel cappé à 30s au lieu de 8s qui fait ré-essayer trop vite.
client/topstep_client.py
topstepx.com/trades · account EXPRESS-V2-CT-46786-78909733
RECONCILE doit afficher un badge rouge persistant sur le dashboard 50K jusqu'à validation manuelle. Aujourd'hui l'incident est passé silencieux jusqu'à ce que l'utilisateur voie la divergence sur TopStep.
web/nq-looper.html + endpoint API pour exposer le nb de reconciles
bot_state.qty != exchange_qty ET exchange_qty == 0, le bot s'arrête et attend validation humaine. Cohérent avec la philo "Auto-stop sur SL = volontaire" (cf. feedback).
position_manager couvrirait les 3 bots (50K / 150K / dynamit).