Riy777 commited on
Commit
f2021cb
·
verified ·
1 Parent(s): 4ad3fe1

Update trade_manager.py

Browse files
Files changed (1) hide show
  1. trade_manager.py +63 -26
trade_manager.py CHANGED
@@ -18,6 +18,18 @@ class TradeManager:
18
 
19
  async def open_trade(self, symbol, decision, current_price):
20
  try:
 
 
 
 
 
 
 
 
 
 
 
 
21
  portfolio_state = await self.r2_service.get_portfolio_state_async()
22
  available_capital = portfolio_state.get("current_capital_usd", 0)
23
 
@@ -43,7 +55,7 @@ class TradeManager:
43
  "status": "OPEN",
44
  "stop_loss": decision.get("stop_loss"),
45
  "take_profit": decision.get("take_profit"),
46
- "trade_type": decision.get("trade_type"),
47
  "position_size_usd": available_capital,
48
  "expected_target_minutes": expected_target_minutes,
49
  "expected_target_time": expected_target_time,
@@ -65,11 +77,11 @@ class TradeManager:
65
  "symbol": symbol,
66
  "position_size": available_capital,
67
  "expected_minutes": expected_target_minutes,
68
- "trade_type": decision.get("trade_type", "LONG"),
69
  "strategy": strategy
70
  })
71
 
72
- print(f"✅ تم فتح صفقة جديدة لـ {symbol} باستراتيجية {strategy}")
73
  return new_trade
74
 
75
  except Exception as e:
@@ -91,7 +103,8 @@ class TradeManager:
91
 
92
  entry_price = trade_to_close['entry_price']
93
  position_size = trade_to_close['position_size_usd']
94
- trade_type = trade_to_close.get('trade_type', 'LONG')
 
95
  strategy = trade_to_close.get('strategy', 'unknown')
96
 
97
  pnl = 0.0
@@ -99,12 +112,13 @@ class TradeManager:
99
 
100
  if entry_price and entry_price > 0 and close_price and close_price > 0:
101
  try:
102
- if trade_type == 'LONG':
103
- pnl_percent = ((close_price - entry_price) / entry_price) * 100
104
- pnl = position_size * (pnl_percent / 100)
105
- elif trade_type == 'SHORT':
106
- pnl_percent = ((entry_price - close_price) / entry_price) * 100
107
- pnl = position_size * (pnl_percent / 100)
 
108
 
109
  except (TypeError, ZeroDivisionError) as calc_error:
110
  pnl = 0.0
@@ -153,7 +167,7 @@ class TradeManager:
153
  "new_capital": new_capital,
154
  "strategy": strategy,
155
  "position_size": position_size,
156
- "trade_type": trade_type,
157
  "reason": reason
158
  })
159
 
@@ -193,6 +207,7 @@ class TradeManager:
193
  trade_to_update['strategy'] = original_strategy
194
  trade_to_update['decision_data'] = re_analysis_decision
195
  trade_to_update['is_monitored'] = True
 
196
 
197
  open_trades = await self.r2_service.get_open_trades_async()
198
  for i, trade in enumerate(open_trades):
@@ -304,7 +319,6 @@ class TradeManager:
304
 
305
  # الحصول على السعر الحالي مع مهلة زمنية
306
  try:
307
- # ✅ الإصلاح: استخدام await بشكل صحيح مع دالة get_latest_price_async
308
  current_price = await asyncio.wait_for(
309
  self.data_manager.get_latest_price_async(symbol),
310
  timeout=10
@@ -324,43 +338,55 @@ class TradeManager:
324
  entry_price = trade['entry_price']
325
  stop_loss = trade.get('stop_loss')
326
  take_profit = trade.get('take_profit')
 
 
327
  should_close, close_reason = False, ""
328
 
329
- # التحقق من شروط الإغلاق
330
  if stop_loss and current_price <= stop_loss:
331
- should_close, close_reason = True, f"وصول وقف الخسارة: {current_price} <= {stop_loss}"
332
  elif take_profit and current_price >= take_profit:
333
- should_close, close_reason = True, f"وصول جني الأرباح: {current_price} >= {take_profit}"
334
 
335
- # تحديث وقف الخسارة الديناميكي
336
  if not should_close and current_price > entry_price:
337
- dynamic_stop = current_price * 0.98
338
- if dynamic_stop > (stop_loss or 0):
339
- trade['stop_loss'] = dynamic_stop
 
 
 
 
340
 
341
  # إغلاق الصفقة إذا لزم الأمر
342
  if should_close:
343
  if self.r2_service.acquire_lock():
344
  try:
345
- await self.immediate_close_trade(symbol, current_price, close_reason)
 
 
 
 
 
346
  except Exception as close_error:
347
  print(f"❌ فشل الإغلاق التلقائي لـ {symbol}: {close_error}")
348
  finally:
349
  self.r2_service.release_lock()
350
 
351
- break
352
 
353
  # إعادة تعيين عداد الأخطاء عند النجاح
354
  if symbol in self.monitoring_errors:
355
  self.monitoring_errors[symbol] = 0
356
 
357
  # التحقق من وقت المراقبة الطويل
358
- monitoring_duration = time.time() - start_time
359
  if monitoring_duration > max_monitoring_time:
360
- print(f"🕒 انتهى وقت مراقبة الصفقة {symbol}")
 
361
  break
362
 
363
- await asyncio.sleep(15)
364
 
365
  except Exception as error:
366
  error_count = self._increment_monitoring_error(symbol)
@@ -374,11 +400,22 @@ class TradeManager:
374
  "error_count": error_count,
375
  "error": str(error)
376
  })
377
- break
 
 
 
 
 
378
 
379
- await asyncio.sleep(30)
380
 
381
  print(f"🛑 توقيف مراقبة الصفقة: {symbol}")
 
 
 
 
 
 
382
 
383
  def _increment_monitoring_error(self, symbol):
384
  if symbol not in self.monitoring_errors:
 
18
 
19
  async def open_trade(self, symbol, decision, current_price):
20
  try:
21
+ # ✅ الإصلاح: التحقق من نوع الصفقة ومنع صفقات SHORT
22
+ trade_type = decision.get("trade_type", "LONG") # الافتراضي هو LONG
23
+ if trade_type == "SHORT":
24
+ print(f"⚠️ تم رفض فتح صفقة SHORT لـ {symbol}. النظام مصمم لـ SPOT فقط.")
25
+ await self.r2_service.save_system_logs_async({
26
+ "trade_open_rejected": True,
27
+ "reason": "SHORT trade not allowed for SPOT system",
28
+ "symbol": symbol,
29
+ "llm_decision": decision
30
+ })
31
+ return None # لا تفتح الصفقة
32
+
33
  portfolio_state = await self.r2_service.get_portfolio_state_async()
34
  available_capital = portfolio_state.get("current_capital_usd", 0)
35
 
 
55
  "status": "OPEN",
56
  "stop_loss": decision.get("stop_loss"),
57
  "take_profit": decision.get("take_profit"),
58
+ "trade_type": "LONG", # ✅ الإصلاح: فرض LONG دائماً لـ SPOT
59
  "position_size_usd": available_capital,
60
  "expected_target_minutes": expected_target_minutes,
61
  "expected_target_time": expected_target_time,
 
77
  "symbol": symbol,
78
  "position_size": available_capital,
79
  "expected_minutes": expected_target_minutes,
80
+ "trade_type": "LONG", # تم فرض LONG
81
  "strategy": strategy
82
  })
83
 
84
+ print(f"✅ تم فتح صفقة جديدة (LONG) لـ {symbol} باستراتيجية {strategy}")
85
  return new_trade
86
 
87
  except Exception as e:
 
103
 
104
  entry_price = trade_to_close['entry_price']
105
  position_size = trade_to_close['position_size_usd']
106
+ # الإصلاح: بما أن النظام SPOT فقط، نفترض دائماً LONG لحساب PnL
107
+ trade_type = "LONG" # trade_to_close.get('trade_type', 'LONG')
108
  strategy = trade_to_close.get('strategy', 'unknown')
109
 
110
  pnl = 0.0
 
112
 
113
  if entry_price and entry_price > 0 and close_price and close_price > 0:
114
  try:
115
+ # الإصلاح: استخدام معادلة LONG فقط
116
+ # if trade_type == 'LONG':
117
+ pnl_percent = ((close_price - entry_price) / entry_price) * 100
118
+ pnl = position_size * (pnl_percent / 100)
119
+ # elif trade_type == 'SHORT': # <-- إزالة هذا القسم
120
+ # pnl_percent = ((entry_price - close_price) / entry_price) * 100
121
+ # pnl = position_size * (pnl_percent / 100)
122
 
123
  except (TypeError, ZeroDivisionError) as calc_error:
124
  pnl = 0.0
 
167
  "new_capital": new_capital,
168
  "strategy": strategy,
169
  "position_size": position_size,
170
+ "trade_type": trade_type, # سيظل LONG دائماً
171
  "reason": reason
172
  })
173
 
 
207
  trade_to_update['strategy'] = original_strategy
208
  trade_to_update['decision_data'] = re_analysis_decision
209
  trade_to_update['is_monitored'] = True
210
+ trade_to_update['trade_type'] = "LONG" # ✅ الإصلاح: التأكد من بقائها LONG
211
 
212
  open_trades = await self.r2_service.get_open_trades_async()
213
  for i, trade in enumerate(open_trades):
 
319
 
320
  # الحصول على السعر الحالي مع مهلة زمنية
321
  try:
 
322
  current_price = await asyncio.wait_for(
323
  self.data_manager.get_latest_price_async(symbol),
324
  timeout=10
 
338
  entry_price = trade['entry_price']
339
  stop_loss = trade.get('stop_loss')
340
  take_profit = trade.get('take_profit')
341
+ # ✅ الإصلاح: نفترض LONG دائماً عند التحقق من الإغلاق لـ SPOT
342
+ trade_type = "LONG"
343
  should_close, close_reason = False, ""
344
 
345
+ # التحقق من شروط الإغلاق (مع افتراض LONG)
346
  if stop_loss and current_price <= stop_loss:
347
+ should_close, close_reason = True, f"وصول وقف الخسارة (LONG): {current_price} <= {stop_loss}"
348
  elif take_profit and current_price >= take_profit:
349
+ should_close, close_reason = True, f"وصول جني الأرباح (LONG): {current_price} >= {take_profit}"
350
 
351
+ # تحديث وقف الخسارة الديناميكي (Trailing Stop Loss) لصفقات LONG
352
  if not should_close and current_price > entry_price:
353
+ # مثال بسيط: تحديد وقف خسارة عند 2% تحت السعر الحالي إذا كان أعلى من وقف الخسارة الأصلي
354
+ potential_new_stop = current_price * 0.98
355
+ current_stop_loss = trade.get('stop_loss', 0) or 0 # التعامل مع None
356
+ if potential_new_stop > current_stop_loss:
357
+ trade['stop_loss'] = potential_new_stop
358
+ print(f"📈 {symbol}: تم تحديث وقف الخسارة الديناميكي إلى {potential_new_stop:.6f}")
359
+ # ملاحظة: هذا التحديث محلي للمهمة، قد تحتاج لحفظه في R2 إذا أردت استمراره
360
 
361
  # إغلاق الصفقة إذا لزم الأمر
362
  if should_close:
363
  if self.r2_service.acquire_lock():
364
  try:
365
+ # قبل الإغلاق، تأكد من جلب أحدث نسخة من الصفقة من R2
366
+ latest_trade_data = await self.r2_service.get_trade_by_symbol_async(symbol)
367
+ if latest_trade_data and latest_trade_data['status'] == 'OPEN':
368
+ await self.immediate_close_trade(symbol, current_price, close_reason)
369
+ else:
370
+ print(f"⚠️ الصفقة {symbol} لم تعد مفتوحة أو غير موجودة، تم إلغاء الإغلاق.")
371
  except Exception as close_error:
372
  print(f"❌ فشل الإغلاق التلقائي لـ {symbol}: {close_error}")
373
  finally:
374
  self.r2_service.release_lock()
375
 
376
+ break # الخروج من حلقة المراقبة بعد محاولة الإغلاق
377
 
378
  # إعادة تعيين عداد الأخطاء عند النجاح
379
  if symbol in self.monitoring_errors:
380
  self.monitoring_errors[symbol] = 0
381
 
382
  # التحقق من وقت المراقبة الطويل
383
+ monitoring_duration = time.time() - self.monitoring_tasks[symbol]['start_time'] # استخدام وقت البدء الأصلي
384
  if monitoring_duration > max_monitoring_time:
385
+ print(f"🕒 انتهى وقت مراقبة الصفقة {symbol} ({monitoring_duration:.0f}s > {max_monitoring_time}s)")
386
+ # يمكنك إضافة منطق هنا لإغلاق الصفقة إذا طالت مدتها، أو تركها لإعادة التحليل
387
  break
388
 
389
+ await asyncio.sleep(15) # انتظار 15 ثانية بين كل فحص
390
 
391
  except Exception as error:
392
  error_count = self._increment_monitoring_error(symbol)
 
400
  "error_count": error_count,
401
  "error": str(error)
402
  })
403
+ # اختياري: محاولة إغلاق الصفقة كإجراء أخير
404
+ # current_price_fallback = await self.data_manager.get_latest_price_async(symbol)
405
+ # if current_price_fallback and self.r2_service.acquire_lock():
406
+ # try: await self.immediate_close_trade(symbol, current_price_fallback, "Forced close due to monitoring errors")
407
+ # finally: self.r2_service.release_lock()
408
+ break # الخروج من الحلقة بسبب الأخطاء
409
 
410
+ await asyncio.sleep(30) # انتظار أطول بعد الخطأ
411
 
412
  print(f"🛑 توقيف مراقبة الصفقة: {symbol}")
413
+ # التأكد من إزالة المهمة عند الخروج من الحلقة
414
+ if symbol in self.monitoring_tasks:
415
+ del self.monitoring_tasks[symbol]
416
+ if symbol in self.monitoring_errors:
417
+ del self.monitoring_errors[symbol]
418
+
419
 
420
  def _increment_monitoring_error(self, symbol):
421
  if symbol not in self.monitoring_errors: