Nexo-S commited on
Commit
1984e8d
·
verified ·
1 Parent(s): 10c4dda

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +27 -35
app.py CHANGED
@@ -752,14 +752,13 @@ def should_send_signal(symbol, timeframe, proba):
752
 
753
  last_signals_sent[key] = (proba, now)
754
  return True
755
- # --- ⚖️ JUDGE API V31 (AUTO-CONFIRMATION & TRAILING STOP) ---
756
  def run_judge_api(live_prices_json="{}"):
757
  try:
758
  import json
759
  try:
760
  raw_prices = json.loads(live_prices_json) if isinstance(live_prices_json, str) else {}
761
  live_prices = {k.lower(): v for k, v in raw_prices.items()}
762
- if live_prices: print(f"📡 [PRIX REÇUS DU BRAS] : {live_prices}")
763
  except:
764
  live_prices = {}
765
 
@@ -767,12 +766,11 @@ def run_judge_api(live_prices_json="{}"):
767
  conn.row_factory = sqlite3.Row
768
  cursor = conn.cursor()
769
 
770
- # 🔥 ON PREND TOUS LES TRADES (Confirmés ou non)
771
  cursor.execute("SELECT * FROM signals WHERE status = 'EN_COURS'")
772
  trades = cursor.fetchall()
773
 
774
  closed_trades = []
775
- watching_info = []
776
  current_time = datetime.now(timezone.utc)
777
  max_age_minutes = {"1m": 5, "5m": 10, "15m": 30, "1h": 60}
778
 
@@ -782,15 +780,12 @@ def run_judge_api(live_prices_json="{}"):
782
  epic = sym_db.replace("/", "").replace("USDT", "USD").lower()
783
  if not epic.endswith("m"): epic += "m"
784
 
785
- # 1. EST-CE QUE LE MT5 A CE TRADE OUVERT ?
786
  is_live = epic in live_prices
787
 
788
- # 🎯 LA MAGIE : Si MT5 a le trade, on l'Auto-Confirme !
789
  if is_live and t['confirmed'] == 0:
790
  cursor.execute("UPDATE signals SET confirmed = 1 WHERE id = ?", (t['id'],))
791
- print(f"✅ [AUTO-CONFIRM] Le Bras trade {epic} (ID: {t['id']}).")
792
 
793
- # 🗑️ Si MT5 NE L'A PAS
794
  if not is_live:
795
  date_str = t['date'].replace('Z', '+00:00')
796
  signal_time = datetime.fromisoformat(date_str)
@@ -798,38 +793,29 @@ def run_judge_api(live_prices_json="{}"):
798
  max_age = max_age_minutes.get(t['timeframe'], 60)
799
 
800
  if t['confirmed'] == 1:
801
- # Il était confirmé mais a disparu de MT5 (TP/SL touché en local)
802
  cursor.execute("UPDATE signals SET status = 'FERMÉ PAR MT5 🛑' WHERE id = ?", (t['id'],))
803
- print(f"🏁 [JUGE] Trade ID {t['id']} fermé nativement par le MT5.")
804
- closed_trades.append({"symbol": t['symbol'], "id": t['id']})
805
  elif age_minutes > max_age:
806
- # Il n'a jamais été pris et il est vieux
807
  cursor.execute("UPDATE signals SET status = 'EXPIRÉ ⏰' WHERE id = ?", (t['id'],))
808
- print(f"🧹 [PURGE] Signal ID {t['id']} expiré.")
809
- continue # On stoppe ici pour ce trade, on passe au suivant
810
 
811
- # ==========================================
812
- # ⚖️ 2. LE TRAILING STOP (Puisque is_live est True)
813
- # ==========================================
814
  current_price = float(live_prices[epic])
815
-
816
  sl_dyn, peak = t['sl'], t['peak_price']
817
  new_peak = max(peak, current_price) if t['direction'] == 'HAUSSIER' else min(peak, current_price)
818
-
819
  dist_totale = abs(t['tp'] - t['price'])
820
 
821
  if t['direction'] == 'HAUSSIER':
822
  mouvement = current_price - t['price']
823
- else: # BAISSIER
824
  mouvement = t['price'] - current_price
825
 
826
  progression = mouvement / dist_totale if (dist_totale > 0 and mouvement > 0) else 0
827
- watching_info.append(f"{sym_db} ({current_price}$) -> Prog: {round(progression*100, 1)}%")
828
 
829
  nouveau_sl = sl_dyn
830
  dist_sl_initial = abs(t['price'] - sl_dyn)
831
 
832
- # LOGIQUE AGRESSIVE DE SÉCURISATION
833
  if t['direction'] == 'HAUSSIER':
834
  if progression >= 0.60: nouveau_sl = max(sl_dyn, t['price'] + (dist_totale * 0.50))
835
  elif progression >= 0.40: nouveau_sl = max(sl_dyn, t['price'] + (dist_totale * 0.20))
@@ -842,13 +828,8 @@ def run_judge_api(live_prices_json="{}"):
842
  elif progression >= 0.10: nouveau_sl = min(sl_dyn, t['price'] + (dist_sl_initial * 0.50))
843
 
844
  cursor.execute("UPDATE signals SET peak_price = ?, sl = ? WHERE id = ?", (new_peak, nouveau_sl, t['id']))
845
- # 🔥 AJOUTE CETTE LIGNE pour envoyer les coordonnées au Bras
846
- watching_info.append({"id": t['id'], "symbol": t['symbol'], "sl": nouveau_sl, "prog": progression})
847
-
848
- # 🚨 ALERTE SI LE SL A BOUGÉ
849
- if nouveau_sl != sl_dyn:
850
- print(f"🛡️ [CLOUD-SL] {t['symbol']} ID {t['id']} | Le SL avance à {round(nouveau_sl, 5)} (Prog: {round(progression*100,1)}%)")
851
 
 
852
  outcome, reward = None, 0
853
  if t['direction'] == 'HAUSSIER':
854
  if current_price >= t['tp']: outcome, reward = "GAGNÉ ✅", 3
@@ -858,19 +839,30 @@ def run_judge_api(live_prices_json="{}"):
858
  elif current_price >= nouveau_sl: outcome, reward = ("GAGNÉ (PARTIEL) 💸", 1) if nouveau_sl < t['price'] else ("PERDU ❌", -5)
859
 
860
  if outcome:
861
- # Si le Juge clôture la position par lui-même
862
  mutate_agent(t['symbol'], t['timeframe'], t['regime'], success=(reward>0))
863
  cursor.execute("UPDATE signals SET status=? WHERE id=?", (outcome, t['id']))
864
- print(f"🏁 [JUGE] Trade ID {t['id']} ({t['symbol']}) clôturé : {outcome}")
865
- closed_trades.append({"symbol": t['symbol'], "id": t['id']})
866
-
 
 
 
 
 
 
 
867
  except Exception as e:
868
  print(f"⚠️ Erreur Trade ID {t['id']}: {e}")
869
-
870
  conn.commit()
871
- return {"status": "updates", "data": closed_trades, "watching": watching_info} if closed_trades else {"status": "waiting", "watching": watching_info}
872
- except Exception as e: return {"status": "error", "message": str(e)}
873
 
 
 
 
 
 
 
 
874
  # --- 📡 LECTURE RADAR OPTIMISÉE ---
875
  def get_active_signals():
876
  try:
 
752
 
753
  last_signals_sent[key] = (proba, now)
754
  return True
755
+ # --- ⚖️ JUDGE API V31 (VERSION NETTOYÉE POUR SL PHYSIQUE) ---
756
  def run_judge_api(live_prices_json="{}"):
757
  try:
758
  import json
759
  try:
760
  raw_prices = json.loads(live_prices_json) if isinstance(live_prices_json, str) else {}
761
  live_prices = {k.lower(): v for k, v in raw_prices.items()}
 
762
  except:
763
  live_prices = {}
764
 
 
766
  conn.row_factory = sqlite3.Row
767
  cursor = conn.cursor()
768
 
 
769
  cursor.execute("SELECT * FROM signals WHERE status = 'EN_COURS'")
770
  trades = cursor.fetchall()
771
 
772
  closed_trades = []
773
+ watching_info = [] # 🎯 Contiendra uniquement des dicts pour le Bras
774
  current_time = datetime.now(timezone.utc)
775
  max_age_minutes = {"1m": 5, "5m": 10, "15m": 30, "1h": 60}
776
 
 
780
  epic = sym_db.replace("/", "").replace("USDT", "USD").lower()
781
  if not epic.endswith("m"): epic += "m"
782
 
 
783
  is_live = epic in live_prices
784
 
 
785
  if is_live and t['confirmed'] == 0:
786
  cursor.execute("UPDATE signals SET confirmed = 1 WHERE id = ?", (t['id'],))
787
+ print(f"✅ [AUTO-CONFIRM] ID: {t['id']}")
788
 
 
789
  if not is_live:
790
  date_str = t['date'].replace('Z', '+00:00')
791
  signal_time = datetime.fromisoformat(date_str)
 
793
  max_age = max_age_minutes.get(t['timeframe'], 60)
794
 
795
  if t['confirmed'] == 1:
 
796
  cursor.execute("UPDATE signals SET status = 'FERMÉ PAR MT5 🛑' WHERE id = ?", (t['id'],))
797
+ closed_trades.append({"symbol": t['symbol'], "id": t['id'], "direction": t['direction']})
 
798
  elif age_minutes > max_age:
 
799
  cursor.execute("UPDATE signals SET status = 'EXPIRÉ ⏰' WHERE id = ?", (t['id'],))
800
+ continue
 
801
 
802
+ # --- CALCUL DU TRAILING ---
 
 
803
  current_price = float(live_prices[epic])
 
804
  sl_dyn, peak = t['sl'], t['peak_price']
805
  new_peak = max(peak, current_price) if t['direction'] == 'HAUSSIER' else min(peak, current_price)
 
806
  dist_totale = abs(t['tp'] - t['price'])
807
 
808
  if t['direction'] == 'HAUSSIER':
809
  mouvement = current_price - t['price']
810
+ else:
811
  mouvement = t['price'] - current_price
812
 
813
  progression = mouvement / dist_totale if (dist_totale > 0 and mouvement > 0) else 0
 
814
 
815
  nouveau_sl = sl_dyn
816
  dist_sl_initial = abs(t['price'] - sl_dyn)
817
 
818
+ # LOGIQUE AGRESSIVE
819
  if t['direction'] == 'HAUSSIER':
820
  if progression >= 0.60: nouveau_sl = max(sl_dyn, t['price'] + (dist_totale * 0.50))
821
  elif progression >= 0.40: nouveau_sl = max(sl_dyn, t['price'] + (dist_totale * 0.20))
 
828
  elif progression >= 0.10: nouveau_sl = min(sl_dyn, t['price'] + (dist_sl_initial * 0.50))
829
 
830
  cursor.execute("UPDATE signals SET peak_price = ?, sl = ? WHERE id = ?", (new_peak, nouveau_sl, t['id']))
 
 
 
 
 
 
831
 
832
+ # --- DÉCISION DE CLÔTURE ---
833
  outcome, reward = None, 0
834
  if t['direction'] == 'HAUSSIER':
835
  if current_price >= t['tp']: outcome, reward = "GAGNÉ ✅", 3
 
839
  elif current_price >= nouveau_sl: outcome, reward = ("GAGNÉ (PARTIEL) 💸", 1) if nouveau_sl < t['price'] else ("PERDU ❌", -5)
840
 
841
  if outcome:
 
842
  mutate_agent(t['symbol'], t['timeframe'], t['regime'], success=(reward>0))
843
  cursor.execute("UPDATE signals SET status=? WHERE id=?", (outcome, t['id']))
844
+ closed_trades.append({"symbol": t['symbol'], "id": t['id'], "direction": t['direction']})
845
+ else:
846
+ # 🎯 ON N'AJOUTE DANS WATCHING QUE SI LE TRADE EST ENCORE OUVERT
847
+ watching_info.append({
848
+ "id": t['id'],
849
+ "symbol": t['symbol'],
850
+ "sl": round(nouveau_sl, 6),
851
+ "prog": round(progression, 4)
852
+ })
853
+
854
  except Exception as e:
855
  print(f"⚠️ Erreur Trade ID {t['id']}: {e}")
856
+
857
  conn.commit()
 
 
858
 
859
+ # Retour propre : data contient les fermetures, watching contient les mises à jour SL
860
+ return {
861
+ "status": "updates" if closed_trades else "waiting",
862
+ "data": closed_trades,
863
+ "watching": watching_info
864
+ }
865
+ except Exception as e: return {"status": "error", "message": str(e)}
866
  # --- 📡 LECTURE RADAR OPTIMISÉE ---
867
  def get_active_signals():
868
  try: