Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -455,9 +455,38 @@ def run_judge_api():
|
|
| 455 |
try:
|
| 456 |
with sqlite3.connect(DB_NAME, timeout=10) as conn:
|
| 457 |
conn.row_factory, cursor = sqlite3.Row, conn.cursor()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 458 |
cursor.execute("SELECT * FROM signals WHERE status = 'EN_COURS' AND confirmed = 1")
|
| 459 |
trades = cursor.fetchall()
|
| 460 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 461 |
closed_trades = []
|
| 462 |
for t in trades:
|
| 463 |
try:
|
|
@@ -474,17 +503,36 @@ def run_judge_api():
|
|
| 474 |
|
| 475 |
sl_dyn, peak = t['sl'], t['peak_price']
|
| 476 |
new_peak = max(peak, current_price) if t['direction'] == 'HAUSSIER' else min(peak, current_price)
|
| 477 |
-
|
|
|
|
|
|
|
|
|
|
| 478 |
|
| 479 |
nouveau_sl = sl_dyn
|
|
|
|
|
|
|
|
|
|
| 480 |
if t['direction'] == 'HAUSSIER':
|
| 481 |
-
if progression >= 0.75:
|
| 482 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 483 |
else:
|
| 484 |
-
if progression >= 0.75:
|
| 485 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 486 |
|
| 487 |
cursor.execute("UPDATE signals SET peak_price = ?, sl = ? WHERE id = ?", (new_peak, nouveau_sl, t['id']))
|
|
|
|
| 488 |
outcome, reward = None, 0
|
| 489 |
if t['direction'] == 'HAUSSIER':
|
| 490 |
if current_price >= t['tp']: outcome, reward = "GAGNÉ ✅", 3
|
|
@@ -497,7 +545,9 @@ def run_judge_api():
|
|
| 497 |
mutate_agent(t['symbol'], t['timeframe'], t['regime'], success=(reward>0))
|
| 498 |
cursor.execute("UPDATE signals SET status=? WHERE id=?", (outcome, t['id']))
|
| 499 |
closed_trades.append({"symbol": t['symbol'], "id": t['id']})
|
| 500 |
-
except:
|
|
|
|
|
|
|
| 501 |
conn.commit()
|
| 502 |
return {"status": "updates", "data": closed_trades} if closed_trades else {"status": "waiting"}
|
| 503 |
except Exception as e: return {"status": "error", "message": str(e)}
|
|
|
|
| 455 |
try:
|
| 456 |
with sqlite3.connect(DB_NAME, timeout=10) as conn:
|
| 457 |
conn.row_factory, cursor = sqlite3.Row, conn.cursor()
|
| 458 |
+
|
| 459 |
+
# ==============================================================
|
| 460 |
+
# 🧹 1. PURGE DES SIGNAUX ORPHELINS (Le Bras était éteint)
|
| 461 |
+
# ==============================================================
|
| 462 |
+
cursor.execute("SELECT id, date, timeframe FROM signals WHERE status = 'EN_COURS' AND confirmed = 0")
|
| 463 |
+
orphelins = cursor.fetchall()
|
| 464 |
+
current_time = datetime.now(timezone.utc)
|
| 465 |
+
max_age_minutes = {"1m": 15, "5m": 20, "15m": 30, "1h": 60}
|
| 466 |
+
|
| 467 |
+
for o in orphelins:
|
| 468 |
+
try:
|
| 469 |
+
date_str = o['date'].replace('Z', '+00:00')
|
| 470 |
+
signal_time = datetime.fromisoformat(date_str)
|
| 471 |
+
age_minutes = (current_time - signal_time).total_seconds() / 60.0
|
| 472 |
+
max_age = max_age_minutes.get(o['timeframe'], 60)
|
| 473 |
+
|
| 474 |
+
if age_minutes > max_age:
|
| 475 |
+
cursor.execute("UPDATE signals SET status = 'EXPIRÉ ⏰' WHERE id = ?", (o['id'],))
|
| 476 |
+
print(f"🧹 [PURGE] Signal ID {o['id']} ({o['timeframe']}) annulé. Âge: {int(age_minutes)}m > Limite: {max_age}m.")
|
| 477 |
+
except Exception:
|
| 478 |
+
pass
|
| 479 |
+
|
| 480 |
+
# ==============================================================
|
| 481 |
+
# ⚖️ 2. JUGEMENT DES TRADES ACTIFS (Trailing Stop Complet)
|
| 482 |
+
# ==============================================================
|
| 483 |
cursor.execute("SELECT * FROM signals WHERE status = 'EN_COURS' AND confirmed = 1")
|
| 484 |
trades = cursor.fetchall()
|
| 485 |
+
|
| 486 |
+
if not trades:
|
| 487 |
+
conn.commit()
|
| 488 |
+
return {"status": "waiting"}
|
| 489 |
+
|
| 490 |
closed_trades = []
|
| 491 |
for t in trades:
|
| 492 |
try:
|
|
|
|
| 503 |
|
| 504 |
sl_dyn, peak = t['sl'], t['peak_price']
|
| 505 |
new_peak = max(peak, current_price) if t['direction'] == 'HAUSSIER' else min(peak, current_price)
|
| 506 |
+
|
| 507 |
+
# Calcul de la progression (0 à 1)
|
| 508 |
+
dist_totale = abs(t['tp'] - t['price'])
|
| 509 |
+
progression = abs(current_price - t['price']) / dist_totale if dist_totale > 0 else 0
|
| 510 |
|
| 511 |
nouveau_sl = sl_dyn
|
| 512 |
+
dist_sl_initial = abs(t['price'] - sl_dyn)
|
| 513 |
+
|
| 514 |
+
# 🛡️ LOGIQUE DU TRAILING STOP À 4 PALIERS
|
| 515 |
if t['direction'] == 'HAUSSIER':
|
| 516 |
+
if progression >= 0.75:
|
| 517 |
+
nouveau_sl = max(sl_dyn, t['price'] + (dist_totale * 0.60)) # Sécurise 60% du gain
|
| 518 |
+
elif progression >= 0.50:
|
| 519 |
+
nouveau_sl = max(sl_dyn, t['price'] + (dist_totale * 0.25)) # Sécurise 25% du gain
|
| 520 |
+
elif progression >= 0.30:
|
| 521 |
+
nouveau_sl = max(sl_dyn, t['price'] + (dist_totale * 0.05)) # Breakeven + frais
|
| 522 |
+
elif progression >= 0.10:
|
| 523 |
+
nouveau_sl = max(sl_dyn, t['price'] - (dist_sl_initial * 0.50)) # Réduit le risque de 50%
|
| 524 |
else:
|
| 525 |
+
if progression >= 0.75:
|
| 526 |
+
nouveau_sl = min(sl_dyn, t['price'] - (dist_totale * 0.60))
|
| 527 |
+
elif progression >= 0.50:
|
| 528 |
+
nouveau_sl = min(sl_dyn, t['price'] - (dist_totale * 0.25))
|
| 529 |
+
elif progression >= 0.30:
|
| 530 |
+
nouveau_sl = min(sl_dyn, t['price'] - (dist_totale * 0.05))
|
| 531 |
+
elif progression >= 0.10:
|
| 532 |
+
nouveau_sl = min(sl_dyn, t['price'] + (dist_sl_initial * 0.50))
|
| 533 |
|
| 534 |
cursor.execute("UPDATE signals SET peak_price = ?, sl = ? WHERE id = ?", (new_peak, nouveau_sl, t['id']))
|
| 535 |
+
|
| 536 |
outcome, reward = None, 0
|
| 537 |
if t['direction'] == 'HAUSSIER':
|
| 538 |
if current_price >= t['tp']: outcome, reward = "GAGNÉ ✅", 3
|
|
|
|
| 545 |
mutate_agent(t['symbol'], t['timeframe'], t['regime'], success=(reward>0))
|
| 546 |
cursor.execute("UPDATE signals SET status=? WHERE id=?", (outcome, t['id']))
|
| 547 |
closed_trades.append({"symbol": t['symbol'], "id": t['id']})
|
| 548 |
+
except Exception:
|
| 549 |
+
pass
|
| 550 |
+
|
| 551 |
conn.commit()
|
| 552 |
return {"status": "updates", "data": closed_trades} if closed_trades else {"status": "waiting"}
|
| 553 |
except Exception as e: return {"status": "error", "message": str(e)}
|