Riy777 commited on
Commit
fa87138
·
verified ·
1 Parent(s): 0156a9b

Create reflector.py

Browse files
Files changed (1) hide show
  1. learning_hub/reflector.py +151 -0
learning_hub/reflector.py ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # learning_hub/reflector.py
2
+ import json
3
+ import traceback
4
+ from typing import Dict, Any, TYPE_CHECKING
5
+ from .schemas import TraceLog, ReflectorOutput
6
+ from .memory_store import MemoryStore
7
+
8
+ # (استخدام TYPE_CHECKING لتجنب الاستيراد الدائري الفعلي)
9
+ if TYPE_CHECKING:
10
+ from LLM import LLMService
11
+
12
+ class Reflector:
13
+ def __init__(self, llm_service: 'LLMService', memory_store: MemoryStore):
14
+ self.llm_service = llm_service
15
+ self.memory_store = memory_store
16
+ print("✅ Learning Hub Module: Reflector (Fast-Learner) loaded")
17
+
18
+ async def analyze_trade_outcome(self, trade_object: Dict[str, Any], close_reason: str):
19
+ """
20
+ Analyzes the trade outcome using LLM to generate a learning 'Delta' (rule).
21
+ (Implements Point 2 & 4 of the 16-point plan)
22
+ """
23
+ try:
24
+ # 1. Create the TraceLog
25
+ # (Note: We will later modify TradeManager to store
26
+ # 'market_context_at_decision' and 'indicators_at_decision'
27
+ # inside 'decision_data' when opening the trade)
28
+
29
+ decision_data = trade_object.get('decision_data', {})
30
+
31
+ trace_log = TraceLog(
32
+ decision_context=decision_data,
33
+ market_context_at_decision=decision_data.get('market_context_at_decision', {}),
34
+ indicators_at_decision=decision_data.get('indicators_at_decision', {}),
35
+ closed_trade_object=trade_object,
36
+ actual_outcome_reason=close_reason
37
+ )
38
+
39
+ # 2. Create the Reflector Prompt (Now in English)
40
+ prompt = self._create_reflector_prompt(trace_log)
41
+
42
+ # 3. Call the LLM
43
+ response_text = await self.llm_service._call_llm(prompt)
44
+
45
+ if not response_text:
46
+ raise ValueError("Reflector LLM call returned no response.")
47
+
48
+ # 4. Parse the response
49
+ # (We use the enhanced parser from LLM.py which handles JSON)
50
+ reflector_json = self.llm_service._parse_llm_response_enhanced(
51
+ response_text,
52
+ fallback_strategy="reflection",
53
+ symbol=trade_object.get('symbol', 'N/A')
54
+ )
55
+
56
+ if not reflector_json:
57
+ raise ValueError(f"Failed to parse Reflector LLM response: {response_text}")
58
+
59
+ # (Validate against the strict schema from schemas.py)
60
+ reflector_output = ReflectorOutput(**reflector_json)
61
+
62
+ # 5. Determine the 'Domain' for the Delta
63
+ strategy = trade_object.get('strategy', 'general')
64
+ domain = self._determine_domain(strategy, reflector_output.error_mode)
65
+
66
+ # 6. Save the suggested 'Delta' to the Memory Store
67
+ # (MemoryStore will use PolicyEngine to decide on auto-approval)
68
+ await self.memory_store.save_new_delta(
69
+ reflector_output=reflector_output,
70
+ trade_object=trade_object,
71
+ domain=domain
72
+ )
73
+
74
+ print(f"✅ [Reflector] Successfully analyzed {trade_object.get('symbol')}. New Delta created.")
75
+
76
+ except Exception as e:
77
+ print(f"❌ [Reflector] Failed to analyze trade outcome for {trade_object.get('symbol')}: {e}")
78
+ traceback.print_exc()
79
+
80
+ def _determine_domain(self, strategy: str, error_mode: str) -> str:
81
+ """Determines the domain the suggested Delta belongs to."""
82
+ error_mode = error_mode.lower()
83
+ if "pattern" in error_mode or "triangle" in error_mode or "flag" in error_mode:
84
+ return "pattern"
85
+ if "indicator" in error_mode or "rsi" in error_mode or "macd" in error_mode:
86
+ return "indicator"
87
+ if "monte_carlo" in error_mode or "garch" in error_mode or "simulation" in error_mode:
88
+ return "monte_carlo"
89
+ if "strategy" in error_mode or "exit" in error_mode or "entry" in error_mode:
90
+ return "strategy"
91
+
92
+ # Default to the strategy's domain
93
+ if strategy in ["trend_following", "mean_reversion", "breakout_momentum"]:
94
+ return "strategy"
95
+
96
+ return "general"
97
+
98
+ def _create_reflector_prompt(self, trace_log: TraceLog) -> str:
99
+ """
100
+ Creates the (English-only) prompt for the LLM to act as a Reflector.
101
+ (Implements Point 4 - Reflector prompt)
102
+ """
103
+
104
+ trade = trace_log.closed_trade_object
105
+ pnl_percent = trade.get('pnl_percent', 0)
106
+
107
+ # Determine initial success
108
+ is_success = pnl_percent > 0.1 # (Consider any small profit a success)
109
+
110
+ prompt = f"""
111
+ SYSTEM: You are an expert trading analyst Reflector. Your task is to analyze a completed trade "Trace" and determine the cause of success or failure. You must suggest a concise "Rule" (Delta) (max 25 words) to improve future performance.
112
+
113
+ --- TRACE LOG START ---
114
+
115
+ 1. **Original Decision Context (What we decided):**
116
+ * Strategy Used: {trade.get('strategy', 'N/A')}
117
+ * Exit Profile: {trade.get('decision_data', {}).get('exit_profile', 'N/A')}
118
+ * Reasoning (at entry): {trade.get('decision_data', {}).get('reasoning', 'N/A')[:200]}...
119
+ * Entry Price: {trade.get('entry_price')}
120
+ * Initial Stop Loss: {trade.get('stop_loss')}
121
+ * Initial Take Profit: {trade.get('take_profit')}
122
+
123
+ 2. **Environment Context (When we decided):**
124
+ * Market Context: {json.dumps(trace_log.market_context_at_decision)}
125
+ * Key Indicators: {json.dumps(trace_log.indicators_at_decision)}
126
+
127
+ 3. **Actual Outcome (What happened):**
128
+ * Close Price: {trade.get('close_price')}
129
+ * Final PnL: {pnl_percent:+.2f}%
130
+ * Close Reason: {trace_log.actual_outcome_reason}
131
+ * Trade Duration: {trade.get('hold_duration_minutes', 'N/A')} minutes
132
+
133
+ --- TRACE LOG END ---
134
+
135
+ TASK: Analyze the Trace above.
136
+ 1. Compare the "Actual Outcome" with the "Original Decision Context".
137
+ 2. Was the original decision correct given what happened?
138
+ 3. Was the "Close Reason" optimal? (e.g., Did it close too early? Too late?)
139
+ 4. Identify the primary "Error Mode" (e.g., 'ignored_volatility', 'premature_exit_by_ATR') or "Success Factor" (e.g., 'correct_pattern_identification').
140
+ 5. Suggest ONE concise "Rule" (Delta) (max 25 words) to improve performance.
141
+
142
+ OUTPUT FORMAT (JSON Only - Adhere strictly to this schema):
143
+ {{
144
+ "success": {str(is_success).lower()},
145
+ "score": 0.0,
146
+ "error_mode": "Short description of the error mode or success factor (e.g., 'ignored_high_market_volatility').",
147
+ "suggested_rule": "The concise 25-word rule for future use (e.g., 'If market volatility is HIGH, increase ATR multiplier for stop loss.').",
148
+ "confidence": 0.0
149
+ }}
150
+ """
151
+ return prompt