État RUNNING - Gestion des Ordres
📊 Statut des Tests
Tests Frontend (Checkly)
Tests Backend (Vitest)
🎯 Vue d’ensemble
L’état RUNNING correspond à une position active où le système gère les ordres BUY2, TP1, TP2 et calcule le PnL en temps réel. C’est l’état le plus complexe avec de nombreuses variantes de workflow possibles.🔍 Gestion des Ordres en RUNNING
BUY2 (processBuy2)
Conditions de création/remplacement :buy2Order.status !== 'closed'buy2Ordern’existe pas OU prix différent OU annulé
- À chaque nouvelle bougie, le système vérifie si RANGE_FILTER_LOW/HIGH a changé
- Si le nouveau niveau est différent du prix de l’ordre BUY2 en cours :
- L’ordre BUY2 existant est annulé
- Un nouvel ordre BUY2 est placé au nouveau niveau RANGE_FILTER_LOW/HIGH
- L’activité “BUY2_ORDER_UPDATED” est enregistrée avec l’ancien et nouveau prix
- Cette mise à jour évite que l’ordre BUY2 se retrouve sous le trailing stop
- Si l’ordre BUY2 ne peut pas être annulé (déjà exécuté), la mise à jour est ignorée
- Mise à jour de
buy2Order,buy2Amount,buy2Price - Recalcul de
relativeEntryPrice(moyenne pondérée de BUY1 et BUY2) - Mise à jour de
relativeAmountviacalculateRelativeAmount() - L’activité “BUY2_ORDER_EXECUTED” est enregistrée dans le champ activity avec le prix d’exécution et le montant de l’ordre BUY2
- Si l’ordre TP1 n’est pas clos, on annule l’ordre pour placer nouvel ordre TP1 avec le nouveau montant actif
- Si l’ordre TP2 n’est pas clos, on annule l’ordre pour placer nouvel ordre TP2 avec le nouveau montant actif
TP1 (processTp1)
Conditions de création/remplacement :tp1Order.status !== 'closed'tp1Ordern’existe pas OU montant différent OU annulé
- Si
buy2Order.status === 'closed'ETtp1Order.status !== 'closed':- Recalcul de
tp1Amount = relativeAmount * 0.7(arrondi selon précision exchange) - Recalcul de
tp2Amount = relativeAmount - tp1Amount(après arrondi de TP1)
- Recalcul de
- Archive de TP1 dans
archivedTp1Orders(si nécessaire) - Calcul de
relativeAmountviacalculateRelativeAmount() - Si BUY2 pas encore fermé : ajustement de
buy2Amountpour inclure le montant TP1 vendu
TP2 (processTp2)
Conditions de création/remplacement :tp2Order.status !== 'closed'tp2Ordern’existe pas OU montant différent OU annulé
- Archive de TP2 dans
archivedTp2Orders(si nécessaire) - Calcul de
relativeAmountviacalculateRelativeAmount() - Si BUY2 pas encore fermé : ajustement de
buy2Amountpour inclure le montant TP2 vendu
Gestion des Take Profits
- Le montant actif ÉGALE la somme des quantités achetées avec BUY1 et BUY2 moins une réserve correspondant au montant minimum d’un ordre (+ marge). Ce montant actif détermine les quantités vendues pour TP1 et TP2
- Le prix TP1 correspond à 50% de la moyenne des GAP max des 10 dernières positions et l’activité “TP1_ORDER_PLACED” sont enregistrées dans le champ activity
- Le prix TP2 correspond à 95% de la moyenne des GAP max des 10 dernières positions et l’activité “TP2_ORDER_PLACED” sont enregistrées dans le champ activity
- Les ordres TP sont annulés si la position se ferme et les activités “TP1_ORDER_CANCELED” et “TP2_ORDER_CANCELED” sont enregistrées dans le champ activity
💰 ÉVOLUTION DES PRIX ET CALCULS FINANCIERS
Calcul des Prix TP1/TP2
Les prix TP1 et TP2 sont recalculés à chaque fois querelativeEntryPrice change :
Évolution de relativeEntryPrice
Le prix d’entrée relatif est recalculé à chaque BUY2 fermé :Calcul des Quantités TP
Les quantités TP sont toujours basées surrelativeAmount :
🦈 Gestion du Shark Mode
Le Shark Mode est un mode de gestion agressive du Stop Loss activé automatiquement lorsque le prix évolue favorablement d’au moins 0.5% par rapport au prix d’entrée.Activation du Shark Mode
Conditions :- Position en statut
RUNNINGouNEW - Évolution du prix ≥ 0.5% par rapport au prix d’entrée (
avgEntryPriceourelativeEntryPrice) - Calcul basé sur les bougies Heikin Ashi 1m
sharkModeEnabled = truesharkModeEnabledAt = Date.now()- Ajout d’une activité
SHARK_MODE_ACTIVATEDavec le pourcentage d’évolution
Mise à Jour du Stop Loss en Shark Mode
Fréquence : Chaque minute (cron jobsharkModeCron.ts)
Note importante :
sharkModeCron.tss’exécute chaque minute pour surveiller les positions actives et gérer le SL agressiftradingview.ts(webhook) reçoit les bougies toutes les 5 minutes pour traiter les positions et créer de nouvelles positions- Cette différence de fréquence peut créer des situations où
sharkModeCron.tsdétecte un SL touché et crée un ordre Close avecslMode = 'SL_BUY1', mais le webhook TradingView arrive 5 minutes plus tard et doit respecter ceslModepour ne pas fermer incorrectement la position
- LONG : SL =
haLow(low de la dernière bougie Heikin Ashi) - SHORT : SL =
haHigh(high de la dernière bougie Heikin Ashi) - Le SL ne peut que se rapprocher du prix (monter pour LONG, descendre pour SHORT)
Gestion du SL Touché en Shark Mode
Le système utilise un champslMode pour distinguer le type de SL touché et déterminer le comportement de la position :
SL_BUY1: SL de BUY1 touché (BUY2 non fermé) - Position reste en RUNNINGSL_BUY2: SL de BUY2 touché (BUY2 fermé) - Position passe en CLOSED après l’exécution de l’ordre Close
Cas 1 : SL de BUY1 touché (BUY2 non fermé)
Comportement :- ✅ Le status reste RUNNING (ne pas passer en CLOSED)
- ✅ Définir
slMode = SL_BUY1pour marquer que c’est un SL de BUY1 - ✅ Créer un ordre Close pour vendre
relativeAmount(si > 0) - ✅ Ajouter une activité
BUY1_SL_TOUCHEDavec indication “SL de BUY1” - ✅ Utiliser
processClose()pour créer l’ordre Close (position reste en RUNNING) - ✅ Même après l’exécution de l’ordre Close : La position reste en RUNNING si
slMode === 'SL_BUY1'etbuy2IsClosed === false
Cas 2 : SL de BUY2 touché (BUY2 fermé)
Comportement :- ✅ Définir
slMode = SL_BUY2pour marquer que c’est un SL de BUY2 - ✅ Créer un ordre Close pour vendre
relativeAmount + reserveAmount(si relativeAmount > 0) - ✅ Ajouter une activité
BUY2_SL_TOUCHEDavec indication “SL de BUY2” - ✅ Utiliser
processClose()pour gérer la fermeture (annulation TP1/TP2, création ordre market) - ✅ Après l’exécution de l’ordre Close : La position passe directement en CLOSED (fermeture complète)
📋 Variantes de Workflow
Variante 1 : Workflow Standard (Sans BUY2)
Variante 2 : Workflow Standard avec BUY2
Variante 3 : TP1 fermé avant BUY2
- TP1 archivé dans
archivedTp1Orders buy2Amountajusté avectp1Amount- BUY2 ordre remplacé avec nouveau montant
- Nouveaux TP1/TP2 créés avec montants recalculés
Variante 4 : BUY2 fermé avant TP1/TP2
relativeEntryPricerecalculé (moyenne pondérée)- Nouveaux TP1/TP2 avec montants basés sur
relativeAmount - TP1/TP2 archivés quand fermés
🔧 Fonctions de Vérification
calculateRelativeAmount()
Calcule le montant relatif en prenant en compte tous les ordres :🧪 Tests
Tests Frontend
Les tests frontend vérifient l’affichage et l’interaction avec les positions en RUNNING. Fichiers de tests :features/positions/running-position.spec.ts
Configuration Checkly :
Tests Backend
Les tests backend valident la logique de gestion des ordres en RUNNING et les variantes de workflow. Fichiers de tests :packages/functions/src/tests/positions/running-state.test.ts
Exécution :
🔗 Navigation
- Vue d’ensemble : Retour à la vue d’ensemble
- État NEW : Création de position
- État CLOSED : Conditions de fermeture