Trad / helpers.py
Riy777's picture
Update helpers.py
1cab813
raw
history blame
22 kB
import os, re, json, hashlib
from datetime import datetime
import pandas as pd
import numpy as np
def safe_float_conversion(value, default=0.0):
try:
if value is None: return default
if isinstance(value, (int, float)): return float(value)
if isinstance(value, str):
cleaned = ''.join(c for c in value if c.isdigit() or c in '.-')
return float(cleaned) if cleaned else default
return default
except (ValueError, TypeError): return default
def _apply_patience_logic(decision, hold_minutes, trade_data, processed_data):
action = decision.get('action')
if action == "CLOSE_TRADE" and hold_minutes < 20:
current_price = processed_data.get('current_price', 0)
entry_price = trade_data.get('entry_price', 0)
try: profit_loss_percent = ((current_price - entry_price) / entry_price) * 100
except (TypeError, ZeroDivisionError): profit_loss_percent = 0
if profit_loss_percent < 2:
decision.update({
'action': "HOLD",
'reasoning': f"Patience Filter: Blocked premature sell. Held for {hold_minutes:.1f}m. Giving trade more time."
})
return decision
def parse_json_from_response(response_text: str):
try:
json_match = re.search(r'```json\n(.*?)\n```', response_text, re.DOTALL)
if json_match: return json_match.group(1).strip()
json_match = re.search(r'\{.*\}', response_text, re.DOTALL)
if json_match: return json_match.group()
return None
except Exception: return None
def validate_required_fields(data_dict: dict, required_fields: list) -> bool:
return all(field in data_dict for field in required_fields)
def format_technical_indicators(advanced_indicators):
if not advanced_indicators: return "No data for advanced indicators."
summary = []
for timeframe, indicators in advanced_indicators.items():
if indicators:
parts = []
if 'rsi' in indicators: parts.append(f"RSI: {indicators['rsi']:.2f}")
if 'macd_hist' in indicators: parts.append(f"MACD Hist: {indicators['macd_hist']:.4f}")
if 'volume_ratio' in indicators: parts.append(f"Volume: {indicators['volume_ratio']:.2f}x")
if parts: summary.append(f"{timeframe}: {', '.join(parts)}")
return "\n".join(summary) if summary else "Insufficient indicator data."
def format_strategy_scores(strategy_scores, recommended_strategy):
if not strategy_scores: return "No strategy data available."
summary = [f"Recommended Strategy: {recommended_strategy}"]
sorted_scores = sorted(strategy_scores.items(), key=lambda item: item[1], reverse=True)
for strategy, score in sorted_scores:
score_display = f"{score:.3f}" if isinstance(score, (int, float)) else str(score)
summary.append(f" • {strategy}: {score_display}")
return "\n".join(summary)
def format_whale_analysis_for_llm(whale_analysis):
"""تنسيق تحليل الحيتان للنموذج الضخم بشكل مفيد وواضح"""
if not whale_analysis or not whale_analysis.get('data_available', False):
return "📊 تحليل الحيتان: لا توجد بيانات عن تحركات الحيتان الحديثة"
summary = whale_analysis.get('llm_friendly_summary', {})
if not summary:
return "📊 تحليل الحيتان: بيانات الحيتان غير متوفرة"
formatted = f"📊 تحليل الحيتان:\n"
formatted += f" • النشاط: {summary.get('whale_activity_summary', 'لا توجد معلومات')}\n"
formatted += f" • التوصية: {summary.get('recommended_action', 'HOLD')}\n"
formatted += f" • مستوى الثقة: {summary.get('confidence', 0.5):.1%}\n"
metrics = summary.get('key_metrics', {})
if metrics:
flow_direction = metrics.get('net_flow_direction', 'غير معروف')
impact_level = metrics.get('whale_movement_impact', 'غير معروف')
exchange_involvement = metrics.get('exchange_involvement', 'غير معروف')
formatted += f" • اتجاه التدفق: {flow_direction}\n"
formatted += f" • مستوى التأثير: {impact_level}\n"
formatted += f" • مشاركة المنصات: {exchange_involvement}"
# إضافة تحذير إذا كان هناك نشاط حرج
if whale_analysis.get('trading_signal', {}).get('critical_alert', False):
formatted += "\n ⚠️ تحذير: نشاط حيتان حرج يتطلب الحذر"
return formatted
def local_analyze_opportunity(candidate_data):
score = candidate_data.get('enhanced_final_score', candidate_data.get('final_score', 0))
quality_warnings = candidate_data.get('quality_warnings', [])
rsi_critical = any('🚨 RSI CRITICAL' in warning for warning in quality_warnings)
rsi_warning = any('⚠️ RSI WARNING' in warning for warning in quality_warnings)
if rsi_critical:
return {
"action": "HOLD", "reasoning": "Local analysis: CRITICAL RSI levels - extreme overbought condition.",
"trade_type": "NONE", "stop_loss": None, "take_profit": None, "expected_target_minutes": 15,
"confidence_level": 0.1, "model_source": "local_safety_filter", "strategy": "GENERIC"
}
advanced_indicators = candidate_data.get('advanced_indicators', {})
if not advanced_indicators:
return {
"action": "HOLD", "reasoning": "Local analysis: Insufficient advanced indicator data.",
"trade_type": "NONE", "stop_loss": None, "take_profit": None, "expected_target_minutes": 15,
"confidence_level": 0.3, "model_source": "local", "strategy": "GENERIC"
}
action, reasoning, trade_type = "HOLD", "Local analysis: No strong buy signal based on enhanced rules.", "NONE"
stop_loss, take_profit, expected_minutes, confidence = None, None, 15, 0.3
five_minute_indicators = advanced_indicators.get('5m', {})
one_hour_indicators = advanced_indicators.get('1h', {})
buy_conditions = total_conditions = 0
if isinstance(score, (int, float)) and score > 0.70: buy_conditions += 1
total_conditions += 1
rsi_five_minute = five_minute_indicators.get('rsi', 50)
if 30 <= rsi_five_minute <= 65: buy_conditions += 1
total_conditions += 1
if five_minute_indicators.get('macd_hist', 0) > 0: buy_conditions += 1
total_conditions += 1
if (five_minute_indicators.get('ema_9', 0) > five_minute_indicators.get('ema_21', 0) and
one_hour_indicators.get('ema_9', 0) > one_hour_indicators.get('ema_21', 0)): buy_conditions += 1
total_conditions += 1
if five_minute_indicators.get('volume_ratio', 0) > 1.5: buy_conditions += 1
total_conditions += 1
confidence = buy_conditions / total_conditions if total_conditions > 0 else 0.3
if rsi_warning:
confidence *= 0.7
reasoning += " RSI warning applied."
if confidence >= 0.6:
action = "BUY"
current_price = candidate_data['current_price']
trade_type = "LONG"
stop_loss = current_price * 0.93 if rsi_warning else current_price * 0.95
take_profit = five_minute_indicators.get('bb_upper', current_price * 1.05) * 1.02
expected_minutes = 10 if confidence >= 0.8 else 18 if confidence >= 0.6 else 25
reasoning = f"Local enhanced analysis: Strong buy signal with {buy_conditions}/{total_conditions} conditions met. Confidence: {confidence:.2f}"
if rsi_warning: reasoning += " (RSI warning - trading with caution)"
return {
"action": action, "reasoning": reasoning, "trade_type": trade_type, "stop_loss": stop_loss,
"take_profit": take_profit, "expected_target_minutes": expected_minutes, "confidence_level": confidence,
"model_source": "local", "strategy": "GENERIC"
}
def local_re_analyze_trade(trade_data, processed_data):
current_price = processed_data['current_price']
stop_loss = trade_data['stop_loss']
take_profit = trade_data['take_profit']
action = "HOLD"
reasoning = "Local re-analysis: No significant change to trigger an update or close."
if stop_loss and current_price <= stop_loss:
action, reasoning = "CLOSE_TRADE", "Local re-analysis: Stop loss has been hit."
elif take_profit and current_price >= take_profit:
action, reasoning = "CLOSE_TRADE", "Local re-analysis: Take profit has been hit."
strategy = trade_data.get('strategy', 'GENERIC')
if strategy == 'unknown': strategy = trade_data.get('decision_data', {}).get('strategy', 'GENERIC')
return {
"action": action, "reasoning": reasoning, "new_stop_loss": None, "new_take_profit": None,
"new_expected_minutes": None, "model_source": "local", "strategy": strategy
}
def validate_candidate_data_enhanced(candidate):
try:
required_fields = ['symbol', 'current_price', 'final_score', 'enhanced_final_score']
for field in required_fields:
if field not in candidate: candidate[field] = 0.0 if field.endswith('_score') or field == 'current_price' else 'UNKNOWN'
candidate['current_price'] = safe_float_conversion(candidate.get('current_price'), 0.0)
candidate['final_score'] = safe_float_conversion(candidate.get('final_score'), 0.5)
candidate['enhanced_final_score'] = safe_float_conversion(candidate.get('enhanced_final_score'), candidate['final_score'])
if 'reasons_for_candidacy' not in candidate: candidate['reasons_for_candidacy'] = ['unknown_reason']
if 'sentiment_data' not in candidate: candidate['sentiment_data'] = {'btc_sentiment': 'NEUTRAL','fear_and_greed_index': 50,'general_whale_activity': {'sentiment': 'NEUTRAL', 'critical_alert': False}}
if 'advanced_indicators' not in candidate: candidate['advanced_indicators'] = {}
if 'strategy_scores' not in candidate: candidate['strategy_scores'] = {}
if 'target_strategy' not in candidate: candidate['target_strategy'] = 'GENERIC'
return True
except Exception as error:
print(f"Failed to validate candidate data for {candidate.get('symbol')}: {error}")
return False
def normalize_weights(weights_dict):
total = sum(weights_dict.values())
if total > 0:
for strategy in weights_dict:
weights_dict[strategy] /= total
return weights_dict
def calculate_market_volatility(market_context):
try:
btc_price = market_context.get('bitcoin_price_usd', 0)
fear_greed = market_context.get('fear_and_greed_index', 50)
whale_sentiment = market_context.get('general_whale_activity', {}).get('sentiment', 'NEUTRAL')
volatility_score = 0
if btc_price > 0:
if abs(fear_greed - 50) > 20:
volatility_score += 1
if whale_sentiment in ['BULLISH', 'BEARISH']:
volatility_score += 1
elif whale_sentiment == 'SLIGHTLY_BULLISH':
volatility_score += 0.5
if volatility_score >= 1.5:
return "high"
elif volatility_score >= 0.5:
return "medium"
else:
return "low"
except Exception as e:
print(f"Volatility calculation error: {e}")
return "medium"
def generate_trade_id():
return str(int(time.time()))
def should_update_weights(performance_history_count):
if performance_history_count <= 10:
return True
return performance_history_count % 3 == 0
def format_enhanced_analysis_for_llm(candidate_data, whale_analysis=None, market_context=None):
"""تنسيق تحليل متقدم شامل للنموذج الضخم"""
formatted = "📈 التحليل الشامل للعملة:\n"
# المعلومات الأساسية
formatted += f"💰 العملة: {candidate_data.get('symbol', 'N/A')}\n"
formatted += f"💰 السعر الحالي: ${safe_float_conversion(candidate_data.get('current_price', 0)):.4f}\n"
formatted += f"🎯 النتيجة المحسنة: {safe_float_conversion(candidate_data.get('enhanced_final_score', 0)):.3f}\n"
# المؤشرات الفنية
advanced_indicators = candidate_data.get('advanced_indicators', {})
if advanced_indicators:
formatted += "\n🔧 المؤشرات الفنية:\n"
for timeframe, indicators in advanced_indicators.items():
if indicators:
tech_parts = []
if 'rsi' in indicators: tech_parts.append(f"RSI: {indicators['rsi']:.1f}")
if 'macd_hist' in indicators: tech_parts.append(f"MACD: {indicators['macd_hist']:.4f}")
if 'volume_ratio' in indicators: tech_parts.append(f"Volume: {indicators['volume_ratio']:.1f}x")
if 'ema_9' in indicators and 'ema_21' in indicators:
ema_signal = "↑" if indicators['ema_9'] > indicators['ema_21'] else "↓"
tech_parts.append(f"EMA: {ema_signal}")
if tech_parts:
formatted += f" • {timeframe}: {', '.join(tech_parts)}\n"
# استراتيجيات التداول
strategy_scores = candidate_data.get('strategy_scores', {})
if strategy_scores:
formatted += "\n🎯 استراتيجيات التداول:\n"
sorted_strategies = sorted(strategy_scores.items(), key=lambda x: x[1], reverse=True)[:3]
for strategy, score in sorted_strategies:
formatted += f" • {strategy}: {score:.3f}\n"
# بيانات الحيتان (إذا كانت متوفرة)
if whale_analysis:
formatted += f"\n{format_whale_analysis_for_llm(whale_analysis)}\n"
# سياق السوق (إذا كان متوفراً)
if market_context:
formatted += "\n🌍 سياق السوق العام:\n"
btc_sentiment = market_context.get('btc_sentiment', 'NEUTRAL')
fear_greed = market_context.get('fear_and_greed_index', 50)
formatted += f" • اتجاه البيتكوين: {btc_sentiment}\n"
formatted += f" • مؤشر الخوف والجشع: {fear_greed}\n"
# أسباب الترشيح
reasons = candidate_data.get('reasons_for_candidacy', [])
if reasons and len(reasons) > 0:
formatted += "\n📋 أسباب الترشيح:\n"
for i, reason in enumerate(reasons[:5], 1):
formatted += f" {i}. {reason}\n"
return formatted
def create_whale_aware_trading_decision(base_decision, whale_analysis):
"""إنشاء قرار تداول مدرك لبيانات الحيتان"""
if not whale_analysis or not whale_analysis.get('data_available', False):
return base_decision
whale_signal = whale_analysis.get('trading_signal', {})
whale_action = whale_signal.get('action', 'HOLD')
whale_confidence = whale_signal.get('confidence', 0.5)
base_action = base_decision.get('action', 'HOLD')
base_confidence = base_decision.get('confidence_level', 0.5)
# إذا كانت إشارة الحيتان حرجة، نعطيها أولوية عالية
if whale_signal.get('critical_alert', False):
if whale_action in ['STRONG_SELL', 'SELL'] and base_action == 'BUY':
return {
**base_decision,
'action': 'HOLD',
'confidence_level': base_confidence * 0.6,
'reasoning': f"{base_decision.get('reasoning', '')} | تم التصحيح بسبب نشاط الحيتان الحرج: {whale_signal.get('reason', '')}"
}
elif whale_action in ['STRONG_BUY', 'BUY'] and base_action == 'HOLD':
return {
**base_decision,
'action': 'BUY',
'confidence_level': (base_confidence + whale_confidence) / 2,
'reasoning': f"{base_decision.get('reasoning', '')} | تم التعزيز بسبب نشاط الحيتان الإيجابي: {whale_signal.get('reason', '')}"
}
# دمج الثقة مع إعطاء وزن 60% لبيانات الحيتان
combined_confidence = (base_confidence * 0.4) + (whale_confidence * 0.6)
# إذا كانت إشارة الحيتان قوية ومعاكسة، نغير القرار
if whale_confidence > 0.8:
if (whale_action in ['STRONG_SELL', 'SELL'] and base_action == 'BUY') or \
(whale_action in ['STRONG_BUY', 'BUY'] and base_action == 'SELL'):
return {
**base_decision,
'action': 'HOLD',
'confidence_level': combined_confidence * 0.8,
'reasoning': f"{base_decision.get('reasoning', '')} | تعارض مع تحركات الحيتان: {whale_signal.get('reason', '')}"
}
# إذا كانت الإشارات متوافقة، نعزز الثقة
if (whale_action in ['STRONG_BUY', 'BUY'] and base_action == 'BUY') or \
(whale_action in ['STRONG_SELL', 'SELL'] and base_action == 'SELL'):
enhanced_confidence = min(combined_confidence * 1.2, 0.95)
return {
**base_decision,
'confidence_level': enhanced_confidence,
'reasoning': f"{base_decision.get('reasoning', '')} | متوافق مع تحركات الحيتان"
}
# في الحالات الأخرى، نعيد القرار الأساسي مع الثقة المجمعة
return {
**base_decision,
'confidence_level': combined_confidence,
'reasoning': f"{base_decision.get('reasoning', '')} | أخذ بعين الاعتبار نشاط الحيتان"
}
def validate_whale_analysis_data(whale_data):
"""التحقق من صحة بيانات تحليل الحيتان"""
if not whale_data:
return False, "بيانات الحيتان فارغة"
required_fields = ['symbol', 'data_available', 'trading_signal']
for field in required_fields:
if field not in whale_data:
return False, f"حقل {field} مفقود في بيانات الحيتان"
if not whale_data['data_available']:
return True, "لا توجد بيانات حيتان متاحة"
signal_fields = ['action', 'confidence', 'reason']
trading_signal = whale_data.get('trading_signal', {})
for field in signal_fields:
if field not in trading_signal:
return False, f"حقل {field} مفقود في إشارة التداول"
valid_actions = ['STRONG_BUY', 'BUY', 'HOLD', 'SELL', 'STRONG_SELL']
if trading_signal.get('action') not in valid_actions:
return False, f"إجراء تداول غير صالح: {trading_signal.get('action')}"
confidence = trading_signal.get('confidence', 0)
if not (0 <= confidence <= 1):
return False, f"مستوى الثقة خارج النطاق: {confidence}"
return True, "بيانات الحيتان صالحة"
def calculate_whale_impact_score(whale_analysis):
"""حساب درجة تأثير الحيتان من 0 إلى 100"""
if not whale_analysis or not whale_analysis.get('data_available', False):
return 0
trading_signal = whale_analysis.get('trading_signal', {})
action = trading_signal.get('action', 'HOLD')
confidence = trading_signal.get('confidence', 0.5)
# تعيين أوزان للإجراءات المختلفة
action_weights = {
'STRONG_BUY': 100,
'BUY': 75,
'HOLD': 50,
'SELL': 25,
'STRONG_SELL': 0
}
base_score = action_weights.get(action, 50)
# تعديل الدرجة بناء على مستوى الثقة
if confidence > 0.8:
adjusted_score = base_score * 1.2
elif confidence > 0.6:
adjusted_score = base_score * 1.0
else:
adjusted_score = base_score * 0.8
# إذا كان هناك تحذير حرج، نعطي وزن إضافي
if trading_signal.get('critical_alert', False):
if action in ['STRONG_SELL', 'SELL']:
adjusted_score = max(0, adjusted_score - 20)
elif action in ['STRONG_BUY', 'BUY']:
adjusted_score = min(100, adjusted_score + 20)
return min(100, max(0, adjusted_score))
def format_whale_impact_for_display(whale_analysis):
"""تنسيق تأثير الحيتان للعرض في الواجهة"""
impact_score = calculate_whale_impact_score(whale_analysis)
if impact_score >= 80:
return "🟢 تأثير إيجابي قوي"
elif impact_score >= 60:
return "🟡 تأثير إيجابي متوسط"
elif impact_score >= 40:
return "⚪ تأثير محايد"
elif impact_score >= 20:
return "🟠 تأثير سلبي متوسط"
else:
return "🔴 تأثير سلبي قوي"
def should_override_trade_decision(base_decision, whale_analysis):
"""تحديد إذا كان يجب تغيير قرار التداول بناء على تحركات الحيتان"""
if not whale_analysis or not whale_analysis.get('data_available', False):
return False
whale_signal = whale_analysis.get('trading_signal', {})
whale_action = whale_signal.get('action', 'HOLD')
whale_confidence = whale_signal.get('confidence', 0.5)
base_action = base_decision.get('action', 'HOLD')
# شروط التغيير الإلزامي
mandatory_override_conditions = [
whale_signal.get('critical_alert', False) and whale_confidence > 0.8,
whale_confidence > 0.9 and whale_action in ['STRONG_SELL', 'STRONG_BUY'],
base_action == 'BUY' and whale_action == 'STRONG_SELL' and whale_confidence > 0.7,
base_action == 'SELL' and whale_action == 'STRONG_BUY' and whale_confidence > 0.7
]
return any(mandatory_override_conditions)
# إضافة متغير الوقت إذا لم يكن موجوداً
import time