Skip to main content

Smoke tests : cycle bout en bout par exchange/paire

Les positions créées en isTest servent de jeu de données d’une phase à l’autre. Le cleanup (suppression des positions isTest) est isolé à la fin du run, une fois tout le cycle validé.

Phases à couvrir

PhaseObjectifDonnées d’entrée / déclencheur
1. NEWCréation position (BUY1 placé, statut NEW)POST /webhooks/tradingview (payload isTest par exchange/paire)
2. Transition NEW → RUNNINGBUY1 considéré exécuté → calculs TP1/TP2, statut RUNNINGMême webhook (nouvelle bougie) une fois BUY1 fermé côté exchange, ou endpoint dédié (avancement contrôlé)
3. RUNNINGVérifier état RUNNING (BUY2, TP1, TP2, PnL)Lecture des positions isTest (GET ou endpoint de validation)
4. Transition RUNNING → CLOSEDFermeture (tendance ou SL) → statut CLOSEDWebhook avec bougie “changement tendance”, ou endpoint dédié pour forcer processClose sur isTest
5. CLOSEDVérifier position fermée, coûts/frais finauxLecture des positions isTest
6. CleanupSupprimer toutes les positions isTestGET /tests/cleanup-test-positions (Bearer) — une seule fois à la fin

Deux approches possibles

A. Tout via webhook (conditions réelles, timing dépendant)

  • Phase 1 : un POST par paire (comme aujourd’hui) → positions NEW.
  • Phase 2 : re-POST même paire, nouvelle bougie (SMOKETIME + offset) : le flux traite la position existante ; si BUY1 est déjà fermé côté exchange, transition NEW → RUNNING.
  • Phase 3 : pas d’appel HTTP dédié ; on considère que le rapport de la phase 2 (ou un GET de santé) suffit, ou on ajoute un GET /tests/smoke/validate qui retourne l’état des positions isTest (NEW / RUNNING / CLOSED par exchange/paire).
  • Phase 4 : re-POST avec une bougie qui déclenche le changement de tendance (wma50 vs wma50_htf) pour que swingPositions appelle processClose → CLOSED.
  • Phase 5 : même GET de validation ou rapport phase 4.
  • Phase 6 : cleanup (GET cleanup-test-positions).
Intérêt : aucun code métier spécifique “test”, tout passe par le vrai webhook.
Inconvénient : dépend de l’exécution réelle des ordres (BUY1 peut ne pas être fermé entre deux runs) et du timing des bougies.

B. Endpoints dédiés “smoke” (contrôlé, recommandé pour CI) — implémenté

Exposer de petits endpoints protégés (Bearer CI_TEST_SECRET) qui enchaînent la logique métier sur les positions isTest uniquement :
EndpointRôle
POST /webhooks/tradingview (existant)Phase 1 : création NEW (payload isTest par paire).
POST /tests/smoke/advance-to-runningPhase 2 : pour chaque position isTest en NEW, simuler “BUY1 fermé” en base puis checkBuy1Completed → passage RUNNING.
GET /tests/smoke/statusPhases 3 et 5 : retourne pour chaque position isTest : exchange, paire, status, orderSide, ids des ordres (buy1, buy2, tp1, tp2, close).
POST /tests/smoke/advance-to-closedPhase 4 : pour les positions isTest en RUNNING, mise à jour DB uniquement (status CLOSED, closedAt, closedReason TEST_NEW) — pas d’appel exchange.
GET /tests/cleanup-test-positions (existant)Phase 6 : cleanup unique en fin de run.
La CI enchaînerait :
check-exchangesPhase 1 (N curls webhook) → Phase 2 (POST advance-to-running) → Phase 3 (GET status, vérifier RUNNING) → Phase 4 (POST advance-to-closed) → Phase 5 (GET status, vérifier CLOSED) → Phase 6 (GET cleanup-test-positions) → génération rapports/badges.
Intérêt : exécution déterministe, pas de dépendance au remplissage des ordres en temps réel.

Implémentation actuelle (option B)

  • GET /tests/smoke/status : implémenté ; réponse { success, positions: [{ id, exchange, pair, status, orderSide, buy1OrderId, … }], generatedAt }.
  • POST /tests/smoke/advance-to-running : implémenté ; réponse { success, phase, advanced, errors, generatedAt } (207 si au moins une erreur).
  • POST /tests/smoke/advance-to-closed : implémenté ; mise à jour DB seule (closedReason TEST_NEW).
  • GET /tests/cleanup-test-positions : existant ; à appeler une seule fois en fin de cycle.

Comportement en CI

Le nombre de positions créées en Phase 1 (et donc advanced en Phase 2, deletedCount en Phase 6) peut être inférieur au nombre de requêtes webhook : la création d’une position exige une previousCandle en base pour la paire/timeframe et le respect des conditions LONG/SHORT (wma50 vs wma50_htf, rangeFilter). Chaque webhook renvoie 200 avec eptProcessed: 1 dès que la bougie et les EPT sont traités ; seules les paires qui ont déjà une bougie “précédente” et les conditions remplies déclenchent processBuy1. Le cycle (NEW → RUNNING → CLOSED → cleanup) s’applique à toutes les positions isTest créées lors du run.

Rapport unique “cycle” (optionnel)

Un même fichier docs/reports/webhook-smoke/cycle-report.json pourrait agréger :
  • phase1 : résultat des POST webhook par paire (déjà en place).
  • phase2 : résultat de l’avancement vers RUNNING (par paire ou global).
  • phase3 : extrait du GET status (positions RUNNING).
  • phase4 : résultat de l’avancement vers CLOSED.
  • phase5 : extrait du GET status (positions CLOSED).
  • phase6 : résultat du cleanup (deletedCount).
Cela permet d’avoir un seul artefact “cycle bout en bout par exchange/paire” et de lier les badges ou la doc à ce rapport.