Riy777 commited on
Commit
b4f96f7
·
verified ·
1 Parent(s): 6982ef4

Update LLM.py

Browse files
Files changed (1) hide show
  1. LLM.py +202 -103
LLM.py CHANGED
@@ -1,44 +1,56 @@
1
- # LLM.py (V13.5 - Fixed Variable Name Error)
2
- import os, traceback, json, re, time
 
 
 
 
3
  from datetime import datetime
4
  from typing import Dict, Any, Optional
5
  from openai import AsyncOpenAI, RateLimitError, APIError
6
 
7
  # ==============================================================================
8
- # 🔌 إعدادات الاتصال
9
  # ==============================================================================
10
  LLM_API_URL = os.getenv("LLM_API_URL", "https://integrate.api.nvidia.com/v1")
11
  LLM_API_KEY = os.getenv("LLM_API_KEY")
12
  LLM_MODEL = os.getenv("LLM_MODEL", "nvidia/llama-3.1-nemotron-ultra-253b-v1")
13
 
 
14
  LLM_TEMPERATURE = 0.2
15
  LLM_TOP_P = 0.7
16
- LLM_MAX_TOKENS = 16384
17
  LLM_FREQUENCY_PENALTY = 0.8
18
  LLM_PRESENCE_PENALTY = 0.5
19
- CLIENT_TIMEOUT = 300.0
20
 
21
  class LLMService:
22
  def __init__(self):
23
  if not LLM_API_KEY:
24
- raise ValueError("❌ [LLM] LLM_API_KEY is missing!")
25
 
26
  self.client = AsyncOpenAI(
27
  base_url=LLM_API_URL,
28
  api_key=LLM_API_KEY,
29
  timeout=CLIENT_TIMEOUT
30
  )
 
31
  self.r2_service = None
32
  self.learning_hub = None
33
- print(f"🧠 [LLM V13.5] Brain Online: {LLM_MODEL}")
 
34
 
35
  async def _call_llm(self, prompt: str) -> Optional[str]:
36
- system_prompt = "detailed thinking on"
 
 
 
 
 
37
  try:
38
  response = await self.client.chat.completions.create(
39
  model=LLM_MODEL,
40
  messages=[
41
- {"role": "system", "content": system_prompt},
42
  {"role": "user", "content": prompt}
43
  ],
44
  temperature=LLM_TEMPERATURE,
@@ -47,184 +59,271 @@ class LLMService:
47
  frequency_penalty=LLM_FREQUENCY_PENALTY,
48
  presence_penalty=LLM_PRESENCE_PENALTY,
49
  stream=False,
50
- response_format={"type": "json_object"}
51
  )
52
- return response.choices[0].message.content
 
 
 
 
 
 
53
  except Exception as e:
54
- print(f"❌ [LLM Call Error] {e}")
55
  return None
56
 
57
  def _parse_json_secure(self, text: str) -> Optional[Dict]:
 
 
 
 
58
  try:
59
- match = re.search(r'\{.*\}', text, re.DOTALL)
60
- if match: return json.loads(match.group(0))
61
- except: pass
62
- return None
 
 
 
 
 
 
 
 
 
63
 
64
  # ==================================================================
65
- # 🧠 الوظائف الرئيسية
66
  # ==================================================================
67
  async def get_trading_decision(self, candidate_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
68
- symbol = candidate_data.get('symbol', 'UNKNOWN')
 
 
 
69
  try:
70
- learning_context = "Playbook: No specific prior learning."
 
71
  if self.learning_hub:
72
  learning_context = await self.learning_hub.get_active_context_for_llm("general", f"{symbol} entry analysis")
73
 
 
74
  prompt = self._create_heavyweight_entry_prompt(candidate_data, learning_context)
 
 
75
  response_text = await self._call_llm(prompt)
 
 
 
76
  decision = self._parse_json_secure(response_text)
77
 
78
- if self.r2_service and response_text:
 
79
  await self.r2_service.save_llm_prompt_async(symbol, "entry_decision_full", prompt, response_text)
80
 
81
  return decision
 
82
  except Exception as e:
83
- print(f"❌ [LLM Entry Error] {symbol}: {e}")
84
  traceback.print_exc()
85
  return None
86
 
 
 
 
87
  async def re_analyze_trade_async(self, trade_data: Dict[str, Any], current_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
88
- symbol = trade_data.get('symbol', 'UNKNOWN')
 
 
 
89
  try:
90
- strategy = trade_data.get('entry_reason', 'GENERIC')
91
- learning_context = "Playbook: Maintain original strategy unless validated invalidation occurs."
 
92
  if self.learning_hub:
93
- learning_context = await self.learning_hub.get_active_context_for_llm("strategy", f"{symbol} re-eval {strategy}")
94
 
 
95
  prompt = self._create_heavyweight_reanalysis_prompt(trade_data, current_data, learning_context)
 
 
96
  response_text = await self._call_llm(prompt)
 
 
 
97
  decision = self._parse_json_secure(response_text)
98
 
99
- if self.r2_service and response_text:
 
100
  await self.r2_service.save_llm_prompt_async(symbol, "re_analysis_full", prompt, response_text)
101
 
102
  return decision
 
103
  except Exception as e:
104
- print(f"❌ [LLM Re-Eval Error] {symbol}: {e}")
105
  return None
106
 
107
  # ==================================================================
108
- # 📝 هندسة البرومبتات (مصححة)
109
  # ==================================================================
110
  def _create_heavyweight_entry_prompt(self, data: Dict[str, Any], learning_context: str) -> str:
111
- symbol = data.get('symbol')
112
- current_price = data.get('current_price')
 
 
 
 
 
 
 
113
 
114
- titan_score = data.get('titan_details', {}).get('score', 0)
115
- titan_trend = "STRONG_UP" if titan_score > 0.7 else "UP" if titan_score > 0.5 else "WEAK"
116
- pat_details = data.get('pattern_details', {})
117
- pat_name = pat_details.get('pattern_detected', 'None')
118
- pat_conf = pat_details.get('pattern_confidence', 0)
119
- mc_score = data.get('components', {}).get('mc_score', 0)
120
 
121
- # تصحيح الاسم هنا واستخدامه بالأسفل
122
- l1_total = data.get('enhanced_final_score', 0)
123
- l2_total = data.get('layer2_score', 0)
 
 
124
 
 
 
125
  whale = data.get('whale_data', {})
126
  whale_1h = whale.get('exchange_flows', {})
127
  whale_24h = whale.get('accumulation_analysis_24h', {})
128
- whale_section = f"""
129
- - 1H Net Flow to Exchanges: ${whale_1h.get('net_flow_usd', 0):,.2f}
130
- - 1H Deposits: {whale_1h.get('deposit_count', 0)} | Withdrawals: {whale_1h.get('withdrawal_count', 0)}
131
- - 24H Accumulation Flow: ${whale_24h.get('net_flow_usd', 0):,.2f}
132
- - 24H Whale Transaction Count: {whale_24h.get('whale_transfers_count', 0)}
133
- - Relative Flow Impact (24H): {whale_24h.get('relative_net_flow_percent', 0):.4f}%
 
134
  """
135
- news_text = data.get('news_text', 'No specific news available.')
136
- ohlcv = data.get('ohlcv_sample', {})
137
- price_section = ""
138
- for tf, candle in ohlcv.items():
139
- if candle:
140
- price_section += f" - {tf.upper()}: Open={candle[1]}, High={candle[2]}, Low={candle[3]}, Close={candle[4]}, Vol={candle[5]}\n"
141
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  return f"""
143
- YOU ARE THE OMNISCIENT BRAIN. A skeptical, master-level crypto trading AI.
144
- Your goal is to validate the findings of your sub-systems and make the FINAL GO/NO-GO decision for {symbol}.
145
- Current Price: {current_price}
146
-
147
- ========== 🧠 PART 1: SUB-SYSTEM REPORTS (PRELIMINARY ANALYSIS) ==========
148
- Your subordinate systems have flagged this asset with the following scores:
149
- * Layer 1 Technical Score: {l1_total:.4f} / 1.0 <-- ✅ تم التصحيح هنا
150
- - Titan ML Trend Model: {titan_score:.4f} ({titan_trend})
151
- - Chart Pattern Recognition: {pat_name} (Confidence: {pat_conf:.2f})
152
- - Monte Carlo Probability (1H): {mc_score:.4f}
153
- * Layer 2 Enhanced Score: {l2_total:.4f} / 1.0 (After initial whale/news weighting)
154
 
155
  ========== 🔍 PART 2: RAW EVIDENCE FOR VERIFICATION (THE TRUTH) ==========
156
- Do not trust the scores above blindly. Verify them against this raw data:
157
 
158
- [A] RAW PRICE ACTION SNAPSHOT (OHLCV Last Closed Candles):
159
- {price_section}
160
- -> TASK: Does this price action confirm the 'Titan Trend' reported above?
161
 
162
- [B] RAW WHALE ON-CHAIN ACTIVITY:
163
- {whale_section}
164
- -> TASK: Is there hidden distribution (selling) despite the technical uptrend?
165
 
166
  [C] RAW NEWSWIRE FEED (Latest Headlines & Summaries):
167
- \"\"\"{news_text}\"\"\"
168
- -> TASK: Are there any immediate red flags, FUD, or regulatory risks in this text?
 
 
169
 
170
  ========== 📖 PART 3: INSTITUTIONAL MEMORY (LEARNING PLAYBOOK) ==========
 
171
  {learning_context}
172
 
173
  ========== 🛑 FINAL DECISION TASK ==========
174
- Perform a deep, step-by-step internal analysis (triggered by your system mode).
175
  Compare PART 1 (Opinions) vs PART 2 (Facts).
176
- If FACTS contradict OPINIONS, you MUST reject the trade.
177
 
178
- REQUIRED OUTPUT (Strict JSON format ONLY):
179
  {{
180
  "action": "WATCH" or "IGNORE",
181
- "confidence_level": 0.00 to 1.00,
182
- "reasoning": "A rigorous, professional justification citing specific raw evidence.",
183
  "strategy_directive": "MOMENTUM_BREAKOUT" or "DIP_ACCUMULATION" or "SCALP_REVERSAL",
184
- "key_risk_factor": "Identify the single biggest risk based on raw evidence."
185
  }}
186
  """
187
 
188
  def _create_heavyweight_reanalysis_prompt(self, trade: Dict, current: Dict, learning_context: str) -> str:
189
- symbol = trade.get('symbol')
190
- entry_price = trade.get('entry_price')
191
- current_price = current.get('current_price')
192
- pnl_pct = ((current_price - entry_price) / entry_price) * 100
193
- duration_min = (datetime.now(timezone.utc) - datetime.fromisoformat(trade.get('entry_time').replace('Z', '+00:00'))).total_seconds() / 60
194
- titan_now = current.get('titan_score', 0)
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  whale_now = current.get('whale_data', {})
196
- whale_1h_net = whale_now.get('exchange_flows', {}).get('net_flow_usd', 0)
197
- news_now = current.get('news_text', 'No new significant news.')
 
 
198
 
199
  return f"""
200
  ROLE: Omniscient Brain (Trade Guardian Mode).
201
- EVENT: Mandatory periodic re-evaluation of OPEN POSITION.
202
  ASSET: {symbol}
203
- TIME IN TRADE: {duration_min:.1f} minutes
204
 
205
- ========== 📉 POSITION STATUS ==========
206
  * Entry Price: {entry_price}
207
- * Current Price: {current_price}
208
- * Unrealized PnL: {pnl_pct:+.2f}%
209
- * Original Entry Reason: "{trade.get('entry_reason')}"
 
 
 
 
 
 
 
 
210
 
211
- ========== 🆕 CHANGED MARKET CONDITIONS (RAW DATA) ==========
212
- 1. ML Trend Update (Titan): Currently {titan_now:.4f}
213
- 2. Fresh Whale Activity (Last 1H): Net Flow ${whale_1h_net:,.0f}
214
- 3. Latest News Update:
215
- \"\"\"{news_now[:1000]}\"\"\"
216
 
217
- ========== 📖 PLAYBOOK GUIDELINES ==========
 
 
 
218
  {learning_context}
219
 
220
- ========== 🛡️ GUARDIAN DECISION ==========
221
- Analyze if the original investment thesis is still valid based on the NEW raw data.
222
- Output Strict JSON ONLY:
 
 
223
  {{
224
  "action": "HOLD" or "EMERGENCY_EXIT" or "UPDATE_TARGETS",
225
- "suggested_new_tp": null or float value,
226
- "suggested_new_sl": null or float value,
227
- "reasoning": "Professional assessment of current risk vs original thesis."
228
  }}
229
  """
230
  print("✅ LLM Service V13.4 (Heavyweight Omniscient Brain) Loaded - NO SHORTCUTS")
 
1
+ # LLM.py (V13.6 - Final Production Version - FULL PROMPTS)
2
+ import os
3
+ import traceback
4
+ import json
5
+ import re
6
+ import time
7
  from datetime import datetime
8
  from typing import Dict, Any, Optional
9
  from openai import AsyncOpenAI, RateLimitError, APIError
10
 
11
  # ==============================================================================
12
+ # 🔌 إعدادات الاتصال بالنموذج (Model Connection Settings)
13
  # ==============================================================================
14
  LLM_API_URL = os.getenv("LLM_API_URL", "https://integrate.api.nvidia.com/v1")
15
  LLM_API_KEY = os.getenv("LLM_API_KEY")
16
  LLM_MODEL = os.getenv("LLM_MODEL", "nvidia/llama-3.1-nemotron-ultra-253b-v1")
17
 
18
+ # بارامترات التوليد (مضبوطة لصرامة التحليل)
19
  LLM_TEMPERATURE = 0.2
20
  LLM_TOP_P = 0.7
21
+ LLM_MAX_TOKENS = 16384 # السماح بأقصى طول استجابة ممكن
22
  LLM_FREQUENCY_PENALTY = 0.8
23
  LLM_PRESENCE_PENALTY = 0.5
24
+ CLIENT_TIMEOUT = 300.0 # 5 دقائق مهلة للردود المعقدة
25
 
26
  class LLMService:
27
  def __init__(self):
28
  if not LLM_API_KEY:
29
+ raise ValueError("❌ [LLM FATAL] LLM_API_KEY environment variable is missing!")
30
 
31
  self.client = AsyncOpenAI(
32
  base_url=LLM_API_URL,
33
  api_key=LLM_API_KEY,
34
  timeout=CLIENT_TIMEOUT
35
  )
36
+ # سيتم حقن هذه التبعيات لاحقاً من app.py
37
  self.r2_service = None
38
  self.learning_hub = None
39
+
40
+ print(f"🧠 [LLM V13.6] Omniscient Brain Online. Model: {LLM_MODEL}")
41
 
42
  async def _call_llm(self, prompt: str) -> Optional[str]:
43
+ """
44
+ تنفيذ استدعاء API للنموذج مع تفعيل وضع التفكير العميق (Nemotron Specific).
45
+ """
46
+ # ⚠️ عبارة تفعيل وضع التفكير الخاصة بنموذج Nemotron
47
+ system_prompt_trigger = "detailed thinking on"
48
+
49
  try:
50
  response = await self.client.chat.completions.create(
51
  model=LLM_MODEL,
52
  messages=[
53
+ {"role": "system", "content": system_prompt_trigger},
54
  {"role": "user", "content": prompt}
55
  ],
56
  temperature=LLM_TEMPERATURE,
 
59
  frequency_penalty=LLM_FREQUENCY_PENALTY,
60
  presence_penalty=LLM_PRESENCE_PENALTY,
61
  stream=False,
62
+ response_format={"type": "json_object"} # إجبار النموذج على الرد بصيغة JSON
63
  )
64
+
65
+ if response.choices and response.choices[0].message.content:
66
+ return response.choices[0].message.content
67
+ else:
68
+ print("⚠️ [LLM Warning] Received empty response from model.")
69
+ return None
70
+
71
  except Exception as e:
72
+ print(f"❌ [LLM Call Error] API request failed: {e}")
73
  return None
74
 
75
  def _parse_json_secure(self, text: str) -> Optional[Dict]:
76
+ """
77
+ محلل JSON قوي يحاول استخراج أول كائن JSON صالح من النص،
78
+ حتى لو كان الرد يحتوي على نصوص إضافية قبل أو بعد الـ JSON.
79
+ """
80
  try:
81
+ # البحث عن نمط {...} عبر الأسطر المتعددة
82
+ json_match = re.search(r'\{.*\}', text, re.DOTALL)
83
+ if json_match:
84
+ return json.loads(json_match.group(0))
85
+ else:
86
+ print("⚠️ [LLM Parser] No JSON object found in response text.")
87
+ return None
88
+ except json.JSONDecodeError as e:
89
+ print(f"⚠️ [LLM Parser] JSON decode failed: {e}")
90
+ return None
91
+ except Exception as e:
92
+ print(f"❌ [LLM Parser] Unexpected error: {e}")
93
+ return None
94
 
95
  # ==================================================================
96
+ # 🧠 الوظيفة الرئيسية 1: قرار الدخول الاستراتيجي (Layer 3)
97
  # ==================================================================
98
  async def get_trading_decision(self, candidate_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
99
+ """
100
+ تحليل بيانات المرشح الكاملة واتخاذ قرار نهائي بالمراقبة أو الرفض.
101
+ """
102
+ symbol = candidate_data.get('symbol', 'UNKNOWN_ASSET')
103
  try:
104
+ # 1. جلب سياق التعلم المؤسسي (Institutional Memory)
105
+ learning_context = "Playbook: No specific prior learning records found for this context."
106
  if self.learning_hub:
107
  learning_context = await self.learning_hub.get_active_context_for_llm("general", f"{symbol} entry analysis")
108
 
109
+ # 2. بناء البرومبت الشامل (Heavyweight Prompt)
110
  prompt = self._create_heavyweight_entry_prompt(candidate_data, learning_context)
111
+
112
+ # 3. استشارة النموذج
113
  response_text = await self._call_llm(prompt)
114
+ if not response_text: return None
115
+
116
+ # 4. تحليل الرد
117
  decision = self._parse_json_secure(response_text)
118
 
119
+ # 5. أرشفة عملية اتخاذ القرار (للشفافية والتدقيق المستقبلي)
120
+ if self.r2_service and decision:
121
  await self.r2_service.save_llm_prompt_async(symbol, "entry_decision_full", prompt, response_text)
122
 
123
  return decision
124
+
125
  except Exception as e:
126
+ print(f"❌ [LLM Entry Error] Critical failure for {symbol}: {e}")
127
  traceback.print_exc()
128
  return None
129
 
130
+ # ==================================================================
131
+ # 🔄 الوظيفة الرئيسية 2: إعادة التحليل الدوري (Strategic Re-eval)
132
+ # ==================================================================
133
  async def re_analyze_trade_async(self, trade_data: Dict[str, Any], current_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
134
+ """
135
+ مراجعة صفقة مفتوحة بناءً على تغيرات السوق وإصدار أوامر تحديث أو خروج.
136
+ """
137
+ symbol = trade_data.get('symbol', 'UNKNOWN_ASSET')
138
  try:
139
+ # 1. جلب سياق التعلم الخاص بالاستراتيجية
140
+ strategy_name = trade_data.get('entry_reason', 'GENERIC_STRATEGY')
141
+ learning_context = "Playbook: Stick to original trading plan unless validated invalidation criteria are met."
142
  if self.learning_hub:
143
+ learning_context = await self.learning_hub.get_active_context_for_llm("strategy", f"{symbol} re-eval {strategy_name}")
144
 
145
+ # 2. بناء برومبت إعادة التحليل
146
  prompt = self._create_heavyweight_reanalysis_prompt(trade_data, current_data, learning_context)
147
+
148
+ # 3. استشارة النموذج
149
  response_text = await self._call_llm(prompt)
150
+ if not response_text: return None
151
+
152
+ # 4. تحليل الرد
153
  decision = self._parse_json_secure(response_text)
154
 
155
+ # 5. الأرشفة
156
+ if self.r2_service and decision:
157
  await self.r2_service.save_llm_prompt_async(symbol, "re_analysis_full", prompt, response_text)
158
 
159
  return decision
160
+
161
  except Exception as e:
162
+ print(f"❌ [LLM Re-Eval Error] Critical failure for {symbol}: {e}")
163
  return None
164
 
165
  # ==================================================================
166
+ # 📝 قسم هندسة البرومبتات الكاملة (Full Prompt Engineering)
167
  # ==================================================================
168
  def _create_heavyweight_entry_prompt(self, data: Dict[str, Any], learning_context: str) -> str:
169
+ """
170
+ إنشاء برومبت ضخم يحتوي على كل التفاصيل المتاحة بدون أي اختصار.
171
+ """
172
+ symbol = data.get('symbol', 'UNKNOWN')
173
+ current_price = data.get('current_price', 0.0)
174
+
175
+ # --- بيانات الطبقات السابقة (Preliminary Scores) ---
176
+ l1_total_score = data.get('enhanced_final_score', 0.0)
177
+ l2_total_score = data.get('layer2_score', 0.0)
178
 
179
+ titan_raw_score = data.get('titan_details', {}).get('score', 0.0)
180
+ titan_trend_label = "STRONG_UPTREND" if titan_raw_score > 0.7 else "UPTREND" if titan_raw_score > 0.5 else "NEUTRAL/WEAK"
 
 
 
 
181
 
182
+ pat_data = data.get('pattern_details', {})
183
+ pattern_name = pat_data.get('pattern_detected', 'None detected')
184
+ pattern_confidence = pat_data.get('pattern_confidence', 0.0)
185
+
186
+ mc_prob = data.get('components', {}).get('mc_score', 0.0)
187
 
188
+ # --- الأدلة الخام (Raw Evidence Data) ---
189
+ # 1. بيانات الحيتان
190
  whale = data.get('whale_data', {})
191
  whale_1h = whale.get('exchange_flows', {})
192
  whale_24h = whale.get('accumulation_analysis_24h', {})
193
+
194
+ whale_evidence_block = f"""
195
+ - [1H Window] Net Flow to Exchanges: ${whale_1h.get('net_flow_usd', 0):,.2f}
196
+ - [1H Window] Deposit Tx Count: {whale_1h.get('deposit_count', 0)} | Withdrawal Tx Count: {whale_1h.get('withdrawal_count', 0)}
197
+ - [24H Window] Net Accumulation Flow: ${whale_24h.get('net_flow_usd', 0):,.2f}
198
+ - [24H Window] Total Large Transactions: {whale_24h.get('whale_transfers_count', 0)}
199
+ - [24H Window] Relative Flow Impact: {whale_24h.get('relative_net_flow_percent', 0):.4f}% of daily volume
200
  """
 
 
 
 
 
 
201
 
202
+ # 2. نص الأخبار الكامل
203
+ raw_news_text = data.get('news_text', 'No specific news articles found for this asset in the last 12 hours.')
204
+
205
+ # 3. لقطة حركة السعر (OHLCV Snapshot)
206
+ ohlcv_data = data.get('ohlcv_sample', {})
207
+ price_snapshot_block = ""
208
+ for tf, candle in ohlcv_data.items():
209
+ if candle and len(candle) >= 6:
210
+ # Format: [Timestamp, Open, High, Low, Close, Volume]
211
+ price_snapshot_block += f" - {tf.upper()} Frame: Open={candle[1]}, High={candle[2]}, Low={candle[3]}, Close={candle[4]}, Vol={candle[5]}\n"
212
+
213
+ # --- تجميع البرومبت النهائي ---
214
  return f"""
215
+ YOU ARE THE OMNISCIENT BRAIN. A skeptical, master-level crypto trading AI with absolute veto power.
216
+ Your goal is to validate the preliminary findings of your sub-systems and make the FINAL GO/NO-GO decision for asset: {symbol}.
217
+ Current Market Price: {current_price}
218
+
219
+ ========== 🧠 PART 1: SUB-SYSTEM REPORTS (PRELIMINARY OPINIONS) ==========
220
+ Your subordinate analytical layers have flagged this asset with the following scores:
221
+ * Layer 1 Technical Score: {l1_total_score:.4f} / 1.0
222
+ - Titan ML Trend Model: {titan_raw_score:.4f} ({titan_trend_label})
223
+ - Chart Pattern Recognition: {pattern_name} (Confidence: {pattern_confidence:.2f})
224
+ - Monte Carlo Win Probability (1H): {mc_prob:.4f}
225
+ * Layer 2 Enhanced Score: {l2_total_score:.4f} / 1.0 (Adjusted for initial whale/news sentiment)
226
 
227
  ========== 🔍 PART 2: RAW EVIDENCE FOR VERIFICATION (THE TRUTH) ==========
228
+ Do NOT trust the scores above blindly. Verify them against this raw data yourself:
229
 
230
+ [A] RAW PRICE ACTION SNAPSHOT (Latest Closed Candles OHLCV):
231
+ {price_snapshot_block}
232
+ -> VERIFICATION TASK: Does this raw price action actually confirm the 'Titan Trend' reported above? Look for contradictions.
233
 
234
+ [B] RAW WHALE ON-CHAIN ACTIVITY (Flows & Accumulation):
235
+ {whale_evidence_block}
236
+ -> VERIFICATION TASK: Is there hidden distribution (selling) occurring despite the technical uptrend? High inflows to exchanges are a red flag.
237
 
238
  [C] RAW NEWSWIRE FEED (Latest Headlines & Summaries):
239
+ \"\"\"
240
+ {raw_news_text}
241
+ \"\"\"
242
+ -> VERIFICATION TASK: Read the text above. Are there any immediate red flags, FUD (Fear, Uncertainty, Doubt), or regulatory risks that the sentiment score might have missed?
243
 
244
  ========== 📖 PART 3: INSTITUTIONAL MEMORY (LEARNING PLAYBOOK) ==========
245
+ The following rules have been learned from previous trading outcomes:
246
  {learning_context}
247
 
248
  ========== 🛑 FINAL DECISION TASK ==========
249
+ Perform a deep, step-by-step internal analysis (triggered by your 'detailed thinking' mode).
250
  Compare PART 1 (Opinions) vs PART 2 (Facts).
251
+ If FACTS strongly contradict OPINIONS, you MUST reject the trade regardless of the high scores.
252
 
253
+ REQUIRED OUTPUT (Strict JSON format ONLY, no other text):
254
  {{
255
  "action": "WATCH" or "IGNORE",
256
+ "confidence_level": 0.00 to 1.00 (Two decimal places),
257
+ "reasoning": "A rigorous, professional justification citing specific raw evidence points that swayed your decision.",
258
  "strategy_directive": "MOMENTUM_BREAKOUT" or "DIP_ACCUMULATION" or "SCALP_REVERSAL",
259
+ "key_risk_factor": "Identify the single biggest risk factor based on the raw evidence provided."
260
  }}
261
  """
262
 
263
  def _create_heavyweight_reanalysis_prompt(self, trade: Dict, current: Dict, learning_context: str) -> str:
264
+ """
265
+ إنشاء برومبت مفصل لإعادة تقييم صفقة مفتوحة، مقارنة ظروف الدخول بالوضع الحالي.
266
+ """
267
+ symbol = trade.get('symbol', 'UNKNOWN')
268
+ entry_price = trade.get('entry_price', 0.0)
269
+ current_price = current.get('current_price', 0.0)
270
+
271
+ # حساب مدة الصفقة بالدقائق
272
+ try:
273
+ entry_time = datetime.fromisoformat(trade.get('entry_time').replace('Z', '+00:00'))
274
+ duration_minutes = (datetime.now(entry_time.tzinfo) - entry_time).total_seconds() / 60
275
+ except:
276
+ duration_minutes = 0.0
277
+
278
+ pnl_percentage = ((current_price - entry_price) / entry_price) * 100
279
+
280
+ # البيانات الحالية المقارنة
281
+ titan_score_now = current.get('titan_score', 0.0)
282
+
283
  whale_now = current.get('whale_data', {})
284
+ whale_1h_net = whale_now.get('exchange_flows', {}).get('net_flow_usd', 0.0)
285
+ whale_24h_net = whale_now.get('accumulation_analysis_24h', {}).get('net_flow_usd', 0.0)
286
+
287
+ news_text_now = current.get('news_text', 'No new significant news.')
288
 
289
  return f"""
290
  ROLE: Omniscient Brain (Trade Guardian Mode).
291
+ EVENT: Mandatory periodic strategic re-evaluation of an OPEN POSITION.
292
  ASSET: {symbol}
293
+ TIME IN TRADE: {duration_minutes:.1f} minutes
294
 
295
+ ========== 📉 CURRENT POSITION STATUS ==========
296
  * Entry Price: {entry_price}
297
+ * Current Market Price: {current_price}
298
+ * Unrealized PnL: {pnl_percentage:+.2f}%
299
+ * Original Entry Reason: "{trade.get('entry_reason', 'N/A')}"
300
+ * Current Targets -> TP: {trade.get('tp_price', 'N/A')} | SL: {trade.get('sl_price', 'N/A')}
301
+
302
+ ========== 🆕 CHANGED MARKET CONDITIONS (RAW DATA UPDATE) ==========
303
+ 1. ML Trend Model Update (Titan): Currently at {titan_score_now:.4f}
304
+ (Is the trend weakening compared to entry?)
305
+
306
+ 2. Fresh Whale Activity (Last 1H Window): Net Flow ${whale_1h_net:,.0f}
307
+ (Positive value = potential selling pressure flowing to exchanges. Negative = accumulation.)
308
 
309
+ 3. 24H Cumulative Whale Flow: Net ${whale_24h_net:,.0f}
 
 
 
 
310
 
311
+ 4. Latest News Update Raw Text:
312
+ \"\"\"{news_text_now[:1500]}\"\"\"
313
+
314
+ ========== 📖 PLAYBOOK & STRATEGY GUIDELINES ==========
315
  {learning_context}
316
 
317
+ ========== 🛡️ GUARDIAN DECISION TASK ==========
318
+ Analyze if the original investment thesis is still valid based on the NEW raw data above.
319
+ Do NOT recommend closing just because of small fluctuations. Look for FUNDAMENTAL thesisINVALIDATION.
320
+
321
+ REQUIRED OUTPUT (Strict JSON format ONLY):
322
  {{
323
  "action": "HOLD" or "EMERGENCY_EXIT" or "UPDATE_TARGETS",
324
+ "new_tp": null or a specific new float value (if action is UPDATE_TARGETS),
325
+ "new_sl": null or a specific new float value (if action is UPDATE_TARGETS),
326
+ "reasoning": "Concise professional assessment of current risk vs original thesis based on new data."
327
  }}
328
  """
329
  print("✅ LLM Service V13.4 (Heavyweight Omniscient Brain) Loaded - NO SHORTCUTS")