Spaces:
Runtime error
Runtime error
Update helpers.py
Browse files- helpers.py +251 -1
helpers.py
CHANGED
|
@@ -60,6 +60,37 @@ def format_strategy_scores(strategy_scores, recommended_strategy):
|
|
| 60 |
summary.append(f" • {strategy}: {score_display}")
|
| 61 |
return "\n".join(summary)
|
| 62 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
def local_analyze_opportunity(candidate_data):
|
| 64 |
score = candidate_data.get('enhanced_final_score', candidate_data.get('final_score', 0))
|
| 65 |
quality_warnings = candidate_data.get('quality_warnings', [])
|
|
@@ -190,4 +221,223 @@ def generate_trade_id():
|
|
| 190 |
def should_update_weights(performance_history_count):
|
| 191 |
if performance_history_count <= 10:
|
| 192 |
return True
|
| 193 |
-
return performance_history_count % 3 == 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
summary.append(f" • {strategy}: {score_display}")
|
| 61 |
return "\n".join(summary)
|
| 62 |
|
| 63 |
+
def format_whale_analysis_for_llm(whale_analysis):
|
| 64 |
+
"""تنسيق تحليل الحيتان للنموذج الضخم بشكل مفيد وواضح"""
|
| 65 |
+
if not whale_analysis or not whale_analysis.get('data_available', False):
|
| 66 |
+
return "📊 تحليل الحيتان: لا توجد بيانات عن تحركات الحيتان الحديثة"
|
| 67 |
+
|
| 68 |
+
summary = whale_analysis.get('llm_friendly_summary', {})
|
| 69 |
+
|
| 70 |
+
if not summary:
|
| 71 |
+
return "📊 تحليل الحيتان: بيانات الحيتان غير متوفرة"
|
| 72 |
+
|
| 73 |
+
formatted = f"📊 تحليل الحيتان:\n"
|
| 74 |
+
formatted += f" • النشاط: {summary.get('whale_activity_summary', 'لا توجد معلومات')}\n"
|
| 75 |
+
formatted += f" • التوصية: {summary.get('recommended_action', 'HOLD')}\n"
|
| 76 |
+
formatted += f" • مستوى الثقة: {summary.get('confidence', 0.5):.1%}\n"
|
| 77 |
+
|
| 78 |
+
metrics = summary.get('key_metrics', {})
|
| 79 |
+
if metrics:
|
| 80 |
+
flow_direction = metrics.get('net_flow_direction', 'غير معروف')
|
| 81 |
+
impact_level = metrics.get('whale_movement_impact', 'غير معروف')
|
| 82 |
+
exchange_involvement = metrics.get('exchange_involvement', 'غير معروف')
|
| 83 |
+
|
| 84 |
+
formatted += f" • اتجاه التدفق: {flow_direction}\n"
|
| 85 |
+
formatted += f" • مستوى التأثير: {impact_level}\n"
|
| 86 |
+
formatted += f" • مشاركة المنصات: {exchange_involvement}"
|
| 87 |
+
|
| 88 |
+
# إضافة تحذير إذا كان هناك نشاط حرج
|
| 89 |
+
if whale_analysis.get('trading_signal', {}).get('critical_alert', False):
|
| 90 |
+
formatted += "\n ⚠️ تحذير: نشاط حيتان حرج يتطلب الحذر"
|
| 91 |
+
|
| 92 |
+
return formatted
|
| 93 |
+
|
| 94 |
def local_analyze_opportunity(candidate_data):
|
| 95 |
score = candidate_data.get('enhanced_final_score', candidate_data.get('final_score', 0))
|
| 96 |
quality_warnings = candidate_data.get('quality_warnings', [])
|
|
|
|
| 221 |
def should_update_weights(performance_history_count):
|
| 222 |
if performance_history_count <= 10:
|
| 223 |
return True
|
| 224 |
+
return performance_history_count % 3 == 0
|
| 225 |
+
|
| 226 |
+
def format_enhanced_analysis_for_llm(candidate_data, whale_analysis=None, market_context=None):
|
| 227 |
+
"""تنسيق تحليل متقدم شامل للنموذج الضخم"""
|
| 228 |
+
formatted = "📈 التحليل الشامل للعملة:\n"
|
| 229 |
+
|
| 230 |
+
# المعلومات الأساسية
|
| 231 |
+
formatted += f"💰 العملة: {candidate_data.get('symbol', 'N/A')}\n"
|
| 232 |
+
formatted += f"💰 السعر الحالي: ${safe_float_conversion(candidate_data.get('current_price', 0)):.4f}\n"
|
| 233 |
+
formatted += f"🎯 النتيجة المحسنة: {safe_float_conversion(candidate_data.get('enhanced_final_score', 0)):.3f}\n"
|
| 234 |
+
|
| 235 |
+
# المؤشرات الفنية
|
| 236 |
+
advanced_indicators = candidate_data.get('advanced_indicators', {})
|
| 237 |
+
if advanced_indicators:
|
| 238 |
+
formatted += "\n🔧 المؤشرات الفنية:\n"
|
| 239 |
+
for timeframe, indicators in advanced_indicators.items():
|
| 240 |
+
if indicators:
|
| 241 |
+
tech_parts = []
|
| 242 |
+
if 'rsi' in indicators: tech_parts.append(f"RSI: {indicators['rsi']:.1f}")
|
| 243 |
+
if 'macd_hist' in indicators: tech_parts.append(f"MACD: {indicators['macd_hist']:.4f}")
|
| 244 |
+
if 'volume_ratio' in indicators: tech_parts.append(f"Volume: {indicators['volume_ratio']:.1f}x")
|
| 245 |
+
if 'ema_9' in indicators and 'ema_21' in indicators:
|
| 246 |
+
ema_signal = "↑" if indicators['ema_9'] > indicators['ema_21'] else "↓"
|
| 247 |
+
tech_parts.append(f"EMA: {ema_signal}")
|
| 248 |
+
if tech_parts:
|
| 249 |
+
formatted += f" • {timeframe}: {', '.join(tech_parts)}\n"
|
| 250 |
+
|
| 251 |
+
# استراتيجيات التداول
|
| 252 |
+
strategy_scores = candidate_data.get('strategy_scores', {})
|
| 253 |
+
if strategy_scores:
|
| 254 |
+
formatted += "\n🎯 استراتيجيات التداول:\n"
|
| 255 |
+
sorted_strategies = sorted(strategy_scores.items(), key=lambda x: x[1], reverse=True)[:3]
|
| 256 |
+
for strategy, score in sorted_strategies:
|
| 257 |
+
formatted += f" • {strategy}: {score:.3f}\n"
|
| 258 |
+
|
| 259 |
+
# بيانات الحيتان (إذا كانت متوفرة)
|
| 260 |
+
if whale_analysis:
|
| 261 |
+
formatted += f"\n{format_whale_analysis_for_llm(whale_analysis)}\n"
|
| 262 |
+
|
| 263 |
+
# سياق السوق (إذا كان متوفراً)
|
| 264 |
+
if market_context:
|
| 265 |
+
formatted += "\n🌍 سياق السوق العام:\n"
|
| 266 |
+
btc_sentiment = market_context.get('btc_sentiment', 'NEUTRAL')
|
| 267 |
+
fear_greed = market_context.get('fear_and_greed_index', 50)
|
| 268 |
+
formatted += f" • اتجاه البيتكوين: {btc_sentiment}\n"
|
| 269 |
+
formatted += f" • مؤشر الخوف والجشع: {fear_greed}\n"
|
| 270 |
+
|
| 271 |
+
# أسباب الترشيح
|
| 272 |
+
reasons = candidate_data.get('reasons_for_candidacy', [])
|
| 273 |
+
if reasons and len(reasons) > 0:
|
| 274 |
+
formatted += "\n📋 أسباب الترشيح:\n"
|
| 275 |
+
for i, reason in enumerate(reasons[:5], 1):
|
| 276 |
+
formatted += f" {i}. {reason}\n"
|
| 277 |
+
|
| 278 |
+
return formatted
|
| 279 |
+
|
| 280 |
+
def create_whale_aware_trading_decision(base_decision, whale_analysis):
|
| 281 |
+
"""إنشاء قرار تداول مدرك لبيانات الحيتان"""
|
| 282 |
+
if not whale_analysis or not whale_analysis.get('data_available', False):
|
| 283 |
+
return base_decision
|
| 284 |
+
|
| 285 |
+
whale_signal = whale_analysis.get('trading_signal', {})
|
| 286 |
+
whale_action = whale_signal.get('action', 'HOLD')
|
| 287 |
+
whale_confidence = whale_signal.get('confidence', 0.5)
|
| 288 |
+
|
| 289 |
+
base_action = base_decision.get('action', 'HOLD')
|
| 290 |
+
base_confidence = base_decision.get('confidence_level', 0.5)
|
| 291 |
+
|
| 292 |
+
# إذا كانت إشارة الحيتان حرجة، نعطيها أولوية عالية
|
| 293 |
+
if whale_signal.get('critical_alert', False):
|
| 294 |
+
if whale_action in ['STRONG_SELL', 'SELL'] and base_action == 'BUY':
|
| 295 |
+
return {
|
| 296 |
+
**base_decision,
|
| 297 |
+
'action': 'HOLD',
|
| 298 |
+
'confidence_level': base_confidence * 0.6,
|
| 299 |
+
'reasoning': f"{base_decision.get('reasoning', '')} | تم التصحيح بسبب نشاط الحيتان الحرج: {whale_signal.get('reason', '')}"
|
| 300 |
+
}
|
| 301 |
+
elif whale_action in ['STRONG_BUY', 'BUY'] and base_action == 'HOLD':
|
| 302 |
+
return {
|
| 303 |
+
**base_decision,
|
| 304 |
+
'action': 'BUY',
|
| 305 |
+
'confidence_level': (base_confidence + whale_confidence) / 2,
|
| 306 |
+
'reasoning': f"{base_decision.get('reasoning', '')} | تم التعزيز بسبب نشاط الحيتان الإيجابي: {whale_signal.get('reason', '')}"
|
| 307 |
+
}
|
| 308 |
+
|
| 309 |
+
# دمج الثقة مع إعطاء وزن 60% لبيانات الحيتان
|
| 310 |
+
combined_confidence = (base_confidence * 0.4) + (whale_confidence * 0.6)
|
| 311 |
+
|
| 312 |
+
# إذا كانت إشارة الحيتان قوية ومعاكسة، نغير القرار
|
| 313 |
+
if whale_confidence > 0.8:
|
| 314 |
+
if (whale_action in ['STRONG_SELL', 'SELL'] and base_action == 'BUY') or \
|
| 315 |
+
(whale_action in ['STRONG_BUY', 'BUY'] and base_action == 'SELL'):
|
| 316 |
+
return {
|
| 317 |
+
**base_decision,
|
| 318 |
+
'action': 'HOLD',
|
| 319 |
+
'confidence_level': combined_confidence * 0.8,
|
| 320 |
+
'reasoning': f"{base_decision.get('reasoning', '')} | تعارض مع تحركات الحيتان: {whale_signal.get('reason', '')}"
|
| 321 |
+
}
|
| 322 |
+
|
| 323 |
+
# إذا كانت الإشارات متوافقة، نعزز الثقة
|
| 324 |
+
if (whale_action in ['STRONG_BUY', 'BUY'] and base_action == 'BUY') or \
|
| 325 |
+
(whale_action in ['STRONG_SELL', 'SELL'] and base_action == 'SELL'):
|
| 326 |
+
enhanced_confidence = min(combined_confidence * 1.2, 0.95)
|
| 327 |
+
return {
|
| 328 |
+
**base_decision,
|
| 329 |
+
'confidence_level': enhanced_confidence,
|
| 330 |
+
'reasoning': f"{base_decision.get('reasoning', '')} | متوافق مع تحركات الحيتان"
|
| 331 |
+
}
|
| 332 |
+
|
| 333 |
+
# في الحالات الأخرى، نعيد القرار الأساسي مع الثقة المجمعة
|
| 334 |
+
return {
|
| 335 |
+
**base_decision,
|
| 336 |
+
'confidence_level': combined_confidence,
|
| 337 |
+
'reasoning': f"{base_decision.get('reasoning', '')} | أخذ بعين الاعتبار نشاط الحيتان"
|
| 338 |
+
}
|
| 339 |
+
|
| 340 |
+
def validate_whale_analysis_data(whale_data):
|
| 341 |
+
"""التحقق من صحة بيانات تحليل الحيتان"""
|
| 342 |
+
if not whale_data:
|
| 343 |
+
return False, "بيانات الحيتان فارغة"
|
| 344 |
+
|
| 345 |
+
required_fields = ['symbol', 'data_available', 'trading_signal']
|
| 346 |
+
for field in required_fields:
|
| 347 |
+
if field not in whale_data:
|
| 348 |
+
return False, f"حقل {field} مفقود في بيانات الحيتان"
|
| 349 |
+
|
| 350 |
+
if not whale_data['data_available']:
|
| 351 |
+
return True, "لا توجد بيانات حيتان متاحة"
|
| 352 |
+
|
| 353 |
+
signal_fields = ['action', 'confidence', 'reason']
|
| 354 |
+
trading_signal = whale_data.get('trading_signal', {})
|
| 355 |
+
for field in signal_fields:
|
| 356 |
+
if field not in trading_signal:
|
| 357 |
+
return False, f"حقل {field} مفقود في إشارة التداول"
|
| 358 |
+
|
| 359 |
+
valid_actions = ['STRONG_BUY', 'BUY', 'HOLD', 'SELL', 'STRONG_SELL']
|
| 360 |
+
if trading_signal.get('action') not in valid_actions:
|
| 361 |
+
return False, f"إجراء تداول غير صالح: {trading_signal.get('action')}"
|
| 362 |
+
|
| 363 |
+
confidence = trading_signal.get('confidence', 0)
|
| 364 |
+
if not (0 <= confidence <= 1):
|
| 365 |
+
return False, f"مستوى الثقة خارج النطاق: {confidence}"
|
| 366 |
+
|
| 367 |
+
return True, "بيانات الحيتان صالحة"
|
| 368 |
+
|
| 369 |
+
def calculate_whale_impact_score(whale_analysis):
|
| 370 |
+
"""حساب درجة تأثير الحيتان من 0 إلى 100"""
|
| 371 |
+
if not whale_analysis or not whale_analysis.get('data_available', False):
|
| 372 |
+
return 0
|
| 373 |
+
|
| 374 |
+
trading_signal = whale_analysis.get('trading_signal', {})
|
| 375 |
+
action = trading_signal.get('action', 'HOLD')
|
| 376 |
+
confidence = trading_signal.get('confidence', 0.5)
|
| 377 |
+
|
| 378 |
+
# تعيين أوزان للإجراءات المختلفة
|
| 379 |
+
action_weights = {
|
| 380 |
+
'STRONG_BUY': 100,
|
| 381 |
+
'BUY': 75,
|
| 382 |
+
'HOLD': 50,
|
| 383 |
+
'SELL': 25,
|
| 384 |
+
'STRONG_SELL': 0
|
| 385 |
+
}
|
| 386 |
+
|
| 387 |
+
base_score = action_weights.get(action, 50)
|
| 388 |
+
|
| 389 |
+
# تعديل الدرجة بناء على مستوى الثقة
|
| 390 |
+
if confidence > 0.8:
|
| 391 |
+
adjusted_score = base_score * 1.2
|
| 392 |
+
elif confidence > 0.6:
|
| 393 |
+
adjusted_score = base_score * 1.0
|
| 394 |
+
else:
|
| 395 |
+
adjusted_score = base_score * 0.8
|
| 396 |
+
|
| 397 |
+
# إذا كان هناك تحذير حرج، نعطي وزن إضافي
|
| 398 |
+
if trading_signal.get('critical_alert', False):
|
| 399 |
+
if action in ['STRONG_SELL', 'SELL']:
|
| 400 |
+
adjusted_score = max(0, adjusted_score - 20)
|
| 401 |
+
elif action in ['STRONG_BUY', 'BUY']:
|
| 402 |
+
adjusted_score = min(100, adjusted_score + 20)
|
| 403 |
+
|
| 404 |
+
return min(100, max(0, adjusted_score))
|
| 405 |
+
|
| 406 |
+
def format_whale_impact_for_display(whale_analysis):
|
| 407 |
+
"""تنسيق تأثير الحيتان للعرض في الواجهة"""
|
| 408 |
+
impact_score = calculate_whale_impact_score(whale_analysis)
|
| 409 |
+
|
| 410 |
+
if impact_score >= 80:
|
| 411 |
+
return "🟢 تأثير إيجابي قوي"
|
| 412 |
+
elif impact_score >= 60:
|
| 413 |
+
return "🟡 تأثير إيجابي متوسط"
|
| 414 |
+
elif impact_score >= 40:
|
| 415 |
+
return "⚪ تأثير محايد"
|
| 416 |
+
elif impact_score >= 20:
|
| 417 |
+
return "🟠 تأثير سلبي متوسط"
|
| 418 |
+
else:
|
| 419 |
+
return "🔴 تأثير سلبي قوي"
|
| 420 |
+
|
| 421 |
+
def should_override_trade_decision(base_decision, whale_analysis):
|
| 422 |
+
"""تحديد إذا كان يجب تغيير قرار التداول بناء على تحركات الحيتان"""
|
| 423 |
+
if not whale_analysis or not whale_analysis.get('data_available', False):
|
| 424 |
+
return False
|
| 425 |
+
|
| 426 |
+
whale_signal = whale_analysis.get('trading_signal', {})
|
| 427 |
+
whale_action = whale_signal.get('action', 'HOLD')
|
| 428 |
+
whale_confidence = whale_signal.get('confidence', 0.5)
|
| 429 |
+
|
| 430 |
+
base_action = base_decision.get('action', 'HOLD')
|
| 431 |
+
|
| 432 |
+
# شروط التغيير الإلزامي
|
| 433 |
+
mandatory_override_conditions = [
|
| 434 |
+
whale_signal.get('critical_alert', False) and whale_confidence > 0.8,
|
| 435 |
+
whale_confidence > 0.9 and whale_action in ['STRONG_SELL', 'STRONG_BUY'],
|
| 436 |
+
base_action == 'BUY' and whale_action == 'STRONG_SELL' and whale_confidence > 0.7,
|
| 437 |
+
base_action == 'SELL' and whale_action == 'STRONG_BUY' and whale_confidence > 0.7
|
| 438 |
+
]
|
| 439 |
+
|
| 440 |
+
return any(mandatory_override_conditions)
|
| 441 |
+
|
| 442 |
+
# إضافة متغير الوقت إذا لم يكن موجوداً
|
| 443 |
+
import time
|