Riy777 commited on
Commit
4871cfe
·
1 Parent(s): 49edbc8

Update helpers.py

Browse files
Files changed (1) hide show
  1. helpers.py +89 -43
helpers.py CHANGED
@@ -1,63 +1,44 @@
1
- import os, re
2
  from datetime import datetime
3
 
4
  def safe_float_conversion(value, default=0.0):
5
  try:
6
- if value is None:
7
- return default
8
- if isinstance(value, (int, float)):
9
- return float(value)
10
  if isinstance(value, str):
11
- cleaned = ''.join(character for character in value if character.isdigit() or character in '.-')
12
  return float(cleaned) if cleaned else default
13
  return default
14
- except (ValueError, TypeError):
15
- return default
16
 
17
  def _apply_patience_logic(decision, hold_minutes, trade_data, processed_data):
18
  action = decision.get('action')
19
-
20
  if action == "CLOSE_TRADE" and hold_minutes < 20:
21
  current_price = processed_data.get('current_price', 0)
22
  entry_price = trade_data.get('entry_price', 0)
23
-
24
- try:
25
- profit_loss_percent = ((current_price - entry_price) / entry_price) * 100
26
- except (TypeError, ZeroDivisionError):
27
- profit_loss_percent = 0
28
-
29
  if profit_loss_percent < 2:
30
- print(f"Blocked premature selling! Only {hold_minutes:.1f} minutes held, PnL: {profit_loss_percent:.2f}%")
31
- decision['action'] = "HOLD"
32
- decision['reasoning'] = f"Patience Filter: Blocked premature sell. Held for {hold_minutes:.1f}m. Giving trade more time."
33
- return decision
34
-
35
  return decision
36
 
37
  def parse_json_from_response(response_text: str):
38
- """استخراج JSON من رد النموذج"""
39
  try:
40
  json_match = re.search(r'```json\n(.*?)\n```', response_text, re.DOTALL)
41
- if json_match:
42
- return json_match.group(1).strip()
43
-
44
  json_match = re.search(r'\{.*\}', response_text, re.DOTALL)
45
- if json_match:
46
- return json_match.group()
47
-
48
- return None
49
- except Exception:
50
  return None
 
51
 
52
  def validate_required_fields(data_dict: dict, required_fields: list) -> bool:
53
- """التحقق من وجود الحقول المطلوبة"""
54
  return all(field in data_dict for field in required_fields)
55
 
56
  def format_technical_indicators(advanced_indicators):
57
- """تنسيق المؤشرات الفنية"""
58
- if not advanced_indicators:
59
- return "No data for advanced indicators."
60
-
61
  summary = []
62
  for timeframe, indicators in advanced_indicators.items():
63
  if indicators:
@@ -65,20 +46,85 @@ def format_technical_indicators(advanced_indicators):
65
  if 'rsi' in indicators: parts.append(f"RSI: {indicators['rsi']:.2f}")
66
  if 'macd_hist' in indicators: parts.append(f"MACD Hist: {indicators['macd_hist']:.4f}")
67
  if 'volume_ratio' in indicators: parts.append(f"Volume: {indicators['volume_ratio']:.2f}x")
68
- if parts:
69
- summary.append(f"{timeframe}: {', '.join(parts)}")
70
-
71
  return "\n".join(summary) if summary else "Insufficient indicator data."
72
 
73
  def format_strategy_scores(strategy_scores, recommended_strategy):
74
- """تنسيق نتائج الاستراتيجيات"""
75
- if not strategy_scores:
76
- return "No strategy data available."
77
-
78
  summary = [f"Recommended Strategy: {recommended_strategy}"]
79
  sorted_scores = sorted(strategy_scores.items(), key=lambda item: item[1], reverse=True)
80
  for strategy, score in sorted_scores:
81
  score_display = f"{score:.3f}" if isinstance(score, (int, float)) else str(score)
82
  summary.append(f" • {strategy}: {score_display}")
83
-
84
- return "\n".join(summary)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, re, json
2
  from datetime import datetime
3
 
4
  def safe_float_conversion(value, default=0.0):
5
  try:
6
+ if value is None: return default
7
+ if isinstance(value, (int, float)): return float(value)
 
 
8
  if isinstance(value, str):
9
+ cleaned = ''.join(c for c in value if c.isdigit() or c in '.-')
10
  return float(cleaned) if cleaned else default
11
  return default
12
+ except (ValueError, TypeError): return default
 
13
 
14
  def _apply_patience_logic(decision, hold_minutes, trade_data, processed_data):
15
  action = decision.get('action')
 
16
  if action == "CLOSE_TRADE" and hold_minutes < 20:
17
  current_price = processed_data.get('current_price', 0)
18
  entry_price = trade_data.get('entry_price', 0)
19
+ try: profit_loss_percent = ((current_price - entry_price) / entry_price) * 100
20
+ except (TypeError, ZeroDivisionError): profit_loss_percent = 0
 
 
 
 
21
  if profit_loss_percent < 2:
22
+ decision.update({
23
+ 'action': "HOLD",
24
+ 'reasoning': f"Patience Filter: Blocked premature sell. Held for {hold_minutes:.1f}m. Giving trade more time."
25
+ })
 
26
  return decision
27
 
28
  def parse_json_from_response(response_text: str):
 
29
  try:
30
  json_match = re.search(r'```json\n(.*?)\n```', response_text, re.DOTALL)
31
+ if json_match: return json_match.group(1).strip()
 
 
32
  json_match = re.search(r'\{.*\}', response_text, re.DOTALL)
33
+ if json_match: return json_match.group()
 
 
 
 
34
  return None
35
+ except Exception: return None
36
 
37
  def validate_required_fields(data_dict: dict, required_fields: list) -> bool:
 
38
  return all(field in data_dict for field in required_fields)
39
 
40
  def format_technical_indicators(advanced_indicators):
41
+ if not advanced_indicators: return "No data for advanced indicators."
 
 
 
42
  summary = []
43
  for timeframe, indicators in advanced_indicators.items():
44
  if indicators:
 
46
  if 'rsi' in indicators: parts.append(f"RSI: {indicators['rsi']:.2f}")
47
  if 'macd_hist' in indicators: parts.append(f"MACD Hist: {indicators['macd_hist']:.4f}")
48
  if 'volume_ratio' in indicators: parts.append(f"Volume: {indicators['volume_ratio']:.2f}x")
49
+ if parts: summary.append(f"{timeframe}: {', '.join(parts)}")
 
 
50
  return "\n".join(summary) if summary else "Insufficient indicator data."
51
 
52
  def format_strategy_scores(strategy_scores, recommended_strategy):
53
+ if not strategy_scores: return "No strategy data available."
 
 
 
54
  summary = [f"Recommended Strategy: {recommended_strategy}"]
55
  sorted_scores = sorted(strategy_scores.items(), key=lambda item: item[1], reverse=True)
56
  for strategy, score in sorted_scores:
57
  score_display = f"{score:.3f}" if isinstance(score, (int, float)) else str(score)
58
  summary.append(f" • {strategy}: {score_display}")
59
+ return "\n".join(summary)
60
+
61
+ def local_analyze_opportunity(candidate_data):
62
+ score = candidate_data.get('enhanced_final_score', candidate_data.get('final_score', 0))
63
+ quality_warnings = candidate_data.get('quality_warnings', [])
64
+ rsi_critical = any('🚨 RSI CRITICAL' in warning for warning in quality_warnings)
65
+ rsi_warning = any('⚠️ RSI WARNING' in warning for warning in quality_warnings)
66
+ if rsi_critical:
67
+ return {
68
+ "action": "HOLD", "reasoning": "Local analysis: CRITICAL RSI levels - extreme overbought condition.",
69
+ "trade_type": "NONE", "stop_loss": None, "take_profit": None, "expected_target_minutes": 15,
70
+ "confidence_level": 0.1, "model_source": "local_safety_filter", "strategy": "GENERIC"
71
+ }
72
+ advanced_indicators = candidate_data.get('advanced_indicators', {})
73
+ if not advanced_indicators:
74
+ return {
75
+ "action": "HOLD", "reasoning": "Local analysis: Insufficient advanced indicator data.",
76
+ "trade_type": "NONE", "stop_loss": None, "take_profit": None, "expected_target_minutes": 15,
77
+ "confidence_level": 0.3, "model_source": "local", "strategy": "GENERIC"
78
+ }
79
+ action, reasoning, trade_type = "HOLD", "Local analysis: No strong buy signal based on enhanced rules.", "NONE"
80
+ stop_loss, take_profit, expected_minutes, confidence = None, None, 15, 0.3
81
+ five_minute_indicators = advanced_indicators.get('5m', {})
82
+ one_hour_indicators = advanced_indicators.get('1h', {})
83
+ buy_conditions = total_conditions = 0
84
+ if isinstance(score, (int, float)) and score > 0.70: buy_conditions += 1
85
+ total_conditions += 1
86
+ rsi_five_minute = five_minute_indicators.get('rsi', 50)
87
+ if 30 <= rsi_five_minute <= 65: buy_conditions += 1
88
+ total_conditions += 1
89
+ if five_minute_indicators.get('macd_hist', 0) > 0: buy_conditions += 1
90
+ total_conditions += 1
91
+ if (five_minute_indicators.get('ema_9', 0) > five_minute_indicators.get('ema_21', 0) and
92
+ one_hour_indicators.get('ema_9', 0) > one_hour_indicators.get('ema_21', 0)): buy_conditions += 1
93
+ total_conditions += 1
94
+ if five_minute_indicators.get('volume_ratio', 0) > 1.5: buy_conditions += 1
95
+ total_conditions += 1
96
+ confidence = buy_conditions / total_conditions if total_conditions > 0 else 0.3
97
+ if rsi_warning:
98
+ confidence *= 0.7
99
+ reasoning += " RSI warning applied."
100
+ if confidence >= 0.6:
101
+ action = "BUY"
102
+ current_price = candidate_data['current_price']
103
+ trade_type = "LONG"
104
+ stop_loss = current_price * 0.93 if rsi_warning else current_price * 0.95
105
+ take_profit = five_minute_indicators.get('bb_upper', current_price * 1.05) * 1.02
106
+ expected_minutes = 10 if confidence >= 0.8 else 18 if confidence >= 0.6 else 25
107
+ reasoning = f"Local enhanced analysis: Strong buy signal with {buy_conditions}/{total_conditions} conditions met. Confidence: {confidence:.2f}"
108
+ if rsi_warning: reasoning += " (RSI warning - trading with caution)"
109
+ return {
110
+ "action": action, "reasoning": reasoning, "trade_type": trade_type, "stop_loss": stop_loss,
111
+ "take_profit": take_profit, "expected_target_minutes": expected_minutes, "confidence_level": confidence,
112
+ "model_source": "local", "strategy": "GENERIC"
113
+ }
114
+
115
+ def local_re_analyze_trade(trade_data, processed_data):
116
+ current_price = processed_data['current_price']
117
+ stop_loss = trade_data['stop_loss']
118
+ take_profit = trade_data['take_profit']
119
+ action = "HOLD"
120
+ reasoning = "Local re-analysis: No significant change to trigger an update or close."
121
+ if stop_loss and current_price <= stop_loss:
122
+ action, reasoning = "CLOSE_TRADE", "Local re-analysis: Stop loss has been hit."
123
+ elif take_profit and current_price >= take_profit:
124
+ action, reasoning = "CLOSE_TRADE", "Local re-analysis: Take profit has been hit."
125
+ strategy = trade_data.get('strategy', 'GENERIC')
126
+ if strategy == 'unknown': strategy = trade_data.get('decision_data', {}).get('strategy', 'GENERIC')
127
+ return {
128
+ "action": action, "reasoning": reasoning, "new_stop_loss": None, "new_take_profit": None,
129
+ "new_expected_minutes": None, "model_source": "local", "strategy": strategy
130
+ }