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
| Phase | Objectif | Données d’entrée / déclencheur |
|---|---|---|
| 1. NEW | Création position (BUY1 placé, statut NEW) | POST /webhooks/tradingview (payload isTest par exchange/paire) |
| 2. Transition NEW → RUNNING | BUY1 considéré exécuté → calculs TP1/TP2, statut RUNNING | Même webhook (nouvelle bougie) une fois BUY1 fermé côté exchange, ou endpoint dédié (avancement contrôlé) |
| 3. RUNNING | Vérifier état RUNNING (BUY2, TP1, TP2, PnL) | Lecture des positions isTest (GET ou endpoint de validation) |
| 4. Transition RUNNING → CLOSED | Fermeture (tendance ou SL) → statut CLOSED | Webhook avec bougie “changement tendance”, ou endpoint dédié pour forcer processClose sur isTest |
| 5. CLOSED | Vérifier position fermée, coûts/frais finaux | Lecture des positions isTest |
| 6. Cleanup | Supprimer toutes les positions isTest | GET /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
swingPositionsappelleprocessClose→ CLOSED. - Phase 5 : même GET de validation ou rapport phase 4.
- Phase 6 : cleanup (GET cleanup-test-positions).
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 :| Endpoint | Rôle |
|---|---|
| POST /webhooks/tradingview (existant) | Phase 1 : création NEW (payload isTest par paire). |
| POST /tests/smoke/advance-to-running | Phase 2 : pour chaque position isTest en NEW, simuler “BUY1 fermé” en base puis checkBuy1Completed → passage RUNNING. |
| GET /tests/smoke/status | Phases 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-closed | Phase 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. |
check-exchanges → Phase 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 doncadvanced 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 fichierdocs/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).