> ## Documentation Index
> Fetch the complete documentation index at: https://docs.poihunter.com/llms.txt
> Use this file to discover all available pages before exploring further.

# État CLOSED

> Conditions et processus de fermeture de position

# État CLOSED - Fermeture de Position

{/* Ne pas modifier manuellement, ils sont mis à jour automatiquement après chaque commit */}

## 📊 Statut des Tests

### Tests Frontend (Checkly)

[![checkly-frontend no-tests](https://img.shields.io/badge/checkly--frontend-no--tests-lightgrey)](https://app.checklyhq.com/checks)

### Tests Backend (Vitest)

[![vitest-backend failing](https://img.shields.io/badge/vitest--backend-failing-red)](https://docs.poihunter.com/docs/reports/vitest/specs/swing-positions-etat-closed.json)

***

## 🔗 Avant cette étape

* **[Transition RUNNING → CLOSED](/docs/specifications/swing-positions/transition-running-to-closed)** — Comment on passe de RUNNING à CLOSED.

## 🎯 Vue d'ensemble

L'état **CLOSED** correspond à une position fermée. Une position peut être fermée pour deux raisons principales : changement de tendance ou Stop Loss touché.

## 🔄 Transition RUNNING → CLOSED

### Conditions de fermeture

1. **Changement de tendance :**
   * LONG : `candle.wma50 < wma50_htf`
   * SHORT : `candle.wma50 > wma50_htf`

2. **Stop Loss touché :**
   * SL de BUY2 touché (BUY2 fermé) → Fermeture complète
   * Note : SL de BUY1 touché (BUY2 non fermé) → Position reste en RUNNING

**Note :** Le Stop Loss est désormais géré par `sharkModeCron.ts` qui surveille les bougies 1m et met à jour le SL de manière agressive basé sur le Heikin Ashi. La fermeture par SL est gérée directement via `processClose()` qui crée l'ordre Close, puis la position passe en `CLOSED` après l'exécution de l'ordre.

### Actions lors de la fermeture

* Annulation des ordres TP1/TP2 ouverts
* Création d'un ordre de fermeture (market)
* Après l'exécution de l'ordre Close : `status = CLOSED`
* Calcul des coûts finaux (`finalBuyCost`, `finalSellCost`)
* Calcul des frais finaux (`finalBuyFee`, `finalSellFee`)
* Notification envoyée

### Ordre de fermeture (processClose)

**Calcul du montant à fermer selon le contexte :**

1. **SL touché + BUY2 non fermé :**
   ```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
   amountToClose = min(calculateRelativeAmount(position), buy1Amount - reserveAmount)
   // Pas de soustraction des fees pour SL
   ```

2. **SL touché + BUY2 fermé :**
   ```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
   amountToClose = calculateRelativeAmount(position) + reserveAmount
   // Pas de soustraction des fees pour SL
   ```

3. **Fermeture normale (changement de tendance) :**
   ```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
   amountToClose = calculateRelativeAmount(position) + reserveAmount - totalBaseAssetFees
   ```

**Vérification préalable :**

* Si `calculateRelativeAmount(position) <= 0` : Ne pas créer d'ordre Close, passer directement en CLOSED

> La valeur `relativeAmount` stockée en base est conservée pour debug/audit,
> mais la logique de fermeture doit se baser sur le calcul dynamique.

**Note :** Pour les fermetures par SL (touché ou sécurité), les frais ne sont pas soustraits du montant à fermer car ils sont gérés séparément lors de l'exécution de l'ordre.

## 📋 Variantes de Fermeture

### Variante 1 : Fermeture par changement de tendance

**Séquence** :

```
Position RUNNING → Nouvelle bougie → Changement tendance détecté → Annulation TP1/TP2 → Ordre Close → CLOSED
```

**Comportement attendu** :

* Détection du changement de tendance via le **Range Filter** : `trend` **bull** / **bear** sur le webhook (plus de condition de clôture basée sur WMA50 LTF vs HTF pour ce déclencheur).
* Annulation des ordres TP1/TP2 ouverts
* Création d'un ordre Close (market) pour vendre `relativeAmount + reserveAmount - totalBaseAssetFees`
* Après exécution de l'ordre Close : `status = CLOSED`, `closedReason = TREND_CHANGED`
* Calcul des coûts et frais finaux
* Notification envoyée

### Variante 2 : Fermeture par Stop Loss (SL\_BUY2)

**Séquence** :

```
Position RUNNING → BUY2 fermé → SL touché (SL_BUY2) → Ordre Close → CLOSED
```

**Comportement attendu** :

* SL de BUY2 touché (BUY2 fermé)
* `slMode = SL_BUY2` défini
* Création d'un ordre Close pour vendre `relativeAmount + reserveAmount`
* Après exécution de l'ordre Close : `status = CLOSED`, `closedReason = REACHED_STOP_LOSS`
* Fermeture complète de la position
* Calcul des coûts et frais finaux
* Notification envoyée

### Variante 3 : SL de BUY1 touché (position reste RUNNING)

**Séquence** :

```
Position RUNNING → BUY2 non fermé → SL de BUY1 touché → Ordre Close → Position reste RUNNING
```

**Comportement attendu** :

* SL de BUY1 touché (BUY2 non fermé)
* `slMode = SL_BUY1` défini
* Création d'un ordre Close pour vendre seulement `relativeAmount` (pas `reserveAmount`)
* Après exécution de l'ordre Close : **Position reste en RUNNING** (pas CLOSED)
* `relativeAmount` mis à jour à 0
* La position continue d'être traitée pour permettre l'exécution future de BUY2
* La position ne sera fermée que si :
  * BUY2 est exécuté puis son SL est touché (passage en SL\_BUY2)
  * La tendance change (création d'un ordre Close)

**Note importante :** Cette variante ne ferme PAS la position, elle vend seulement le montant de BUY1. La position reste active pour permettre l'exécution de BUY2.

## 🔍 Logique de Fermeture Détaillée

### Après exécution de l'ordre Close

La fermeture de la position après l'exécution de l'ordre Close est déterminée par `slMode` et le `status`, pas par `calculatedRelativeAmount`.

#### **Cas 1 : SL\_BUY2 (SL de BUY2 touché)**

* **Condition :** `slMode === 'SL_BUY2'` ET `closeOrder.status === 'closed'`
* **Comportement :**
  * ✅ **Fermeture complète de la position** (l'ordre Close a vendu `relativeAmount + reserveAmount`)
  * ✅ `status = CLOSED`
  * ✅ `closedReason = REACHED_STOP_LOSS`
  * ✅ `closedAt = new Date()`
  * ✅ `relativeAmount = 0`
  * ✅ Calcul des coûts finaux (`finalBuyCost`, `finalSellCost`)
  * ✅ Calcul des frais finaux (`finalBuyFee`, `finalSellFee`)
  * ✅ Notification envoyée

#### **Cas 2 : SL\_BUY1 (SL de BUY1 touché, BUY2 non fermé)**

* **Condition :** `slMode === 'SL_BUY1'` ET `buy2IsClosed === false` ET `closeOrder.status === 'closed'`
* **Comportement :**
  * ✅ **La position reste en RUNNING** même après l'exécution de l'ordre Close
  * ✅ L'ordre Close a vendu seulement `relativeAmount` (pas `reserveAmount`)
  * ✅ `relativeAmount` est mis à jour à 0
  * ✅ La position continue d'être traitée par `swingPositions` pour permettre l'exécution future de BUY2
  * ✅ La position ne sera fermée que si :
    * BUY2 est exécuté puis son SL est touché (passage en SL\_BUY2)
    * La tendance change (création d'un ordre Close)

#### **Cas 3 : Fermeture normale (changement de tendance)**

* **Condition :** `closeOrder.status === 'closed'` ET `slMode !== 'SL_BUY1'` (ou `slMode === null`)
* **Comportement :**
  * ✅ `status = CLOSED`
  * ✅ `closedReason = TREND_CHANGED`
  * ✅ `closedAt = new Date()`
  * ✅ Calcul des coûts finaux (`finalBuyCost`, `finalSellCost`)
  * ✅ Calcul des frais finaux (`finalBuyFee`, `finalSellFee`)
  * ✅ Notification envoyée

## 📊 Calculs Finaux

### Coûts finaux

```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
finalBuyCost = (buy1Amount * buy1Price) + (buy2Amount * buy2Price)
finalSellCost = (tp1Amount * tp1Price) + (tp2Amount * tp2Price) + (closeAmount * closePrice)
```

### Frais finaux

```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
finalBuyFee = (buy1Order.fee?.cost || 0) + (buy2Order.fee?.cost || 0)
finalSellFee = totalTpFees + (closeOrder.fee?.cost || 0)
```

### PnL final

```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
pnl = finalSellCost - finalBuyCost - finalBuyFee - finalSellFee
```

## 🧪 Tests

### Tests Frontend

Les tests frontend vérifient l'affichage des positions fermées et l'historique.

**Fichiers de tests** : `features/positions/closed-position.spec.ts`

**Configuration Checkly** :

```typescript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
// @checkly frequency: 10min
// @checkly locations: paris, new-york
// @checkly alertChannels: linear
// @checkly tags: production, positions
```

### Tests Backend

Les tests backend valident la logique de fermeture et les différents scénarios.

**Fichiers de tests** : `packages/functions/src/tests/positions/closed-state.test.ts`

**Exécution** :

```bash theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
npm run test -- closed-state
```

## 🔗 Navigation

* **[Vue d'ensemble](../swing-positions/index)** : Retour à la vue d'ensemble
* **[État NEW](etat-new)** : Création de position
* **[État RUNNING](etat-running)** : Gestion des ordres
