Riy777 commited on
Commit
9839a07
·
verified ·
1 Parent(s): 58b62b9

Update backtest_engine.py

Browse files
Files changed (1) hide show
  1. backtest_engine.py +75 -35
backtest_engine.py CHANGED
@@ -1,16 +1,17 @@
1
  # ============================================================
2
- # 🧪 backtest_engine.py (V38.1 - GEM-Architect: Oracle Interrogation)
3
  # ============================================================
4
- # الهدف: معرفة لماذا يرفض Oracle كل الفرص (468 فرصة!).
5
- # التغييرات:
6
- # 1. طباعة سبب الرفض التفصيلي من Oracle.
7
- # 2. طباعة مصفوفة الثقة (Long vs Short).
8
  # ============================================================
9
 
10
  import asyncio
11
  import pandas as pd
12
  import numpy as np
13
  import time
 
14
  import traceback
15
  from datetime import datetime
16
  from typing import Dict, Any, List
@@ -19,6 +20,24 @@ from ml_engine.processor import MLProcessor, SystemLimits
19
  from ml_engine.data_manager import DataManager
20
  from learning_hub.adaptive_hub import StrategyDNA
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  class BacktestSimulator:
23
  def __init__(self, data_manager, processor):
24
  self.dm = data_manager
@@ -30,14 +49,12 @@ class BacktestSimulator:
30
  self.TARGET_COINS = ['BNB/USDT', 'XRP/USDT', 'DOGE/USDT']
31
 
32
  self.funnel_stats = {'scanned': 0, 'passed_l2': 0, 'passed_oracle': 0, 'passed_sniper': 0}
33
-
34
- # عدادات لأسباب الرفض
35
  self.oracle_rejection_reasons = {'bearish': 0, 'low_conf': 0, 'error': 0}
36
 
37
- print("🧪 [Backtest Engine V38.1] Oracle Interrogation Mode.")
38
 
39
  # ==========================================================================
40
- # 1. Data Loading (كما هي)
41
  # ==========================================================================
42
  async def fetch_deep_history_1m(self):
43
  print(f"\n⏳ [Data] Loading {len(self.TARGET_COINS)} coins ({self.DAYS_TO_FETCH} days)...")
@@ -74,7 +91,7 @@ class BacktestSimulator:
74
  print(" ⚠️ No Data")
75
 
76
  # ==========================================================================
77
- # 2. Snapshot Helper
78
  # ==========================================================================
79
  def get_market_snapshot(self, symbol, end_idx):
80
  try:
@@ -89,7 +106,6 @@ class BacktestSimulator:
89
 
90
  cols_order = ['timestamp', 'open', 'high', 'low', 'close', 'volume']
91
  timeframes = {'1m': slice_1m[cols_order].values.tolist()}
92
-
93
  agg = {'timestamp': 'first', 'open': 'first', 'high': 'max', 'low': 'min', 'close': 'last', 'volume': 'sum'}
94
 
95
  for tf, rule in [('5m', '5T'), ('15m', '15T'), ('1h', '1H'), ('4h', '4H')]:
@@ -101,7 +117,7 @@ class BacktestSimulator:
101
  except: return None
102
 
103
  # ==========================================================================
104
- # 3. Process Logic (The Interrogation Room)
105
  # ==========================================================================
106
  async def process_market_layers(self, symbol, snapshot, current_price, weights, l1_threshold):
107
  self.funnel_stats['scanned'] += 1
@@ -131,7 +147,7 @@ class BacktestSimulator:
131
  if l2_score < l1_threshold: return None
132
  self.funnel_stats['passed_l2'] += 1
133
 
134
- # --- ORACLE DEBUG ---
135
  mc_adv_score = 0.0
136
  if self.proc.mc_analyzer:
137
  closes = [c[4] for c in snapshot['1h']]
@@ -140,73 +156,97 @@ class BacktestSimulator:
140
 
141
  oracle_decision = {'action': 'WAIT'}
142
  if self.proc.oracle:
143
- self.proc.oracle.set_threshold(0.50)
144
  oracle_input = {'ohlcv': snapshot, 'current_price': current_price, 'titan_score': titan_score, 'mc_score': mc_light, 'patterns_score': pattern_score}
145
  oracle_decision = await self.proc.oracle.predict(oracle_input)
146
 
147
- # 🔥 استجواب العراف
148
- if oracle_decision['action'] != 'BUY':
 
149
  reason = oracle_decision.get('reason', 'Unknown')
150
- conf = oracle_decision.get('confidence', 0.0)
151
- short_conf = oracle_decision.get('short_confidence', 0.0)
152
-
153
- # تصنيف سبب الرفض
154
  if 'Bearish' in reason or 'SHORT' in str(oracle_decision.get('direction')):
155
  self.oracle_rejection_reasons['bearish'] += 1
156
  elif 'Low Confidence' in reason:
157
  self.oracle_rejection_reasons['low_conf'] += 1
158
  else:
159
  self.oracle_rejection_reasons['error'] += 1
160
-
161
- # طباعة أول 5 حالات رفض للتفاصيل
162
- if self.funnel_stats['passed_oracle'] == 0 and self.funnel_stats['passed_l2'] % 50 == 0:
163
- print(f" ⛔ Oracle Reject {symbol}: {reason} | Long:{conf:.2f} Short:{short_conf:.2f}")
164
 
165
- if oracle_decision['action'] != 'BUY': return None
166
  self.funnel_stats['passed_oracle'] += 1
167
 
168
  # --- Sniper ---
169
  sniper_res = {'signal': 'WAIT'}
170
  if self.proc.sniper:
171
- self.proc.sniper.configure_settings(threshold=0.30, wall_ratio=0.9, w_ml=1.0, w_ob=0.0)
172
  sniper_res = await self.proc.sniper.check_entry_signal_async(snapshot['1m'], None)
173
 
174
  if sniper_res['signal'] == 'BUY':
175
  self.funnel_stats['passed_sniper'] += 1
176
- return {'price': current_price}
 
 
 
 
 
 
177
  return None
178
 
179
  # ==========================================================================
180
- # 4. Simulation Runner
181
  # ==========================================================================
182
  async def run_simulation(self):
183
  self.funnel_stats = {'scanned': 0, 'passed_l2': 0, 'passed_oracle': 0, 'passed_sniper': 0}
184
  self.oracle_rejection_reasons = {'bearish': 0, 'low_conf': 0, 'error': 0}
 
185
  weights = {'titan': 0.3, 'patterns': 0.3, 'sniper': 0.3, 'mc': 0.1}
186
  l1_thresh = 0.25
187
 
188
- print(f" ▶️ Running Oracle Interrogation...")
 
 
 
 
189
 
190
  for sym, df_history in self.history_cache.items():
191
  start_loop = 6000
192
  if len(df_history) < start_loop + 100: continue
193
-
194
- for i in range(start_loop, len(df_history) - 100, 50):
 
195
  snapshot = self.get_market_snapshot(sym, i)
196
  if not snapshot: continue
197
 
198
  current_price = snapshot['1m'][-1][4]
199
- await self.process_market_layers(sym, snapshot, current_price, weights, l1_thresh)
 
 
 
 
 
 
 
 
 
 
200
 
201
  print(f" Done.")
202
- print(f" 📊 Funnel: {self.funnel_stats}")
203
- print(f" 📉 Oracle Rejections: {self.oracle_rejection_reasons}")
 
 
 
 
 
 
 
 
 
204
 
205
  # ============================================================
206
  # 🚀 Run
207
  # ============================================================
208
  async def run_strategic_optimization_task():
209
- print("\n🧪 [STRATEGIC BACKTEST V38.1] Oracle Debug...")
210
  from r2 import R2Service
211
  r2 = R2Service()
212
  dm = DataManager(None, None, r2)
 
1
  # ============================================================
2
+ # 🧪 backtest_engine.py (V38.2 - GEM-Architect: Unlocked Oracle)
3
  # ============================================================
4
+ # الإصلاحات:
5
+ # 1. قبول "WATCH" كإشارة نجاح من Oracle (حل مشكلة الرفض الخاطئ).
6
+ # 2. كتم إشعارات PatternEngine المزعجة.
7
+ # 3. جاهزية تامة لاكتشاف الصفقات.
8
  # ============================================================
9
 
10
  import asyncio
11
  import pandas as pd
12
  import numpy as np
13
  import time
14
+ import logging
15
  import traceback
16
  from datetime import datetime
17
  from typing import Dict, Any, List
 
20
  from ml_engine.data_manager import DataManager
21
  from learning_hub.adaptive_hub import StrategyDNA
22
 
23
+ # 🔇 كتم الإشعارات المزعجة
24
+ logging.getLogger('ml_engine.patterns').setLevel(logging.WARNING)
25
+
26
+ class VirtualPortfolio:
27
+ def __init__(self, initial_capital=1000.0):
28
+ self.capital = initial_capital
29
+ self.active_trades = {}
30
+ self.stats = {"max_win_usd": 0.0, "max_loss_usd": 0.0, "max_drawdown_pct": 0.0, "max_runup_pct": 0.0}
31
+ self.MAX_SLOTS_MAP = {'BULL': 6, 'BEAR': 3, 'RANGE': 4, 'DEAD': 2}
32
+
33
+ def can_open_trade(self, regime):
34
+ max_slots = self.MAX_SLOTS_MAP.get(regime, 3)
35
+ return len(self.active_trades) < max_slots
36
+
37
+ def calculate_size(self, confidence, regime):
38
+ # حجم ثابت للتجربة
39
+ return self.capital * 0.10
40
+
41
  class BacktestSimulator:
42
  def __init__(self, data_manager, processor):
43
  self.dm = data_manager
 
49
  self.TARGET_COINS = ['BNB/USDT', 'XRP/USDT', 'DOGE/USDT']
50
 
51
  self.funnel_stats = {'scanned': 0, 'passed_l2': 0, 'passed_oracle': 0, 'passed_sniper': 0}
 
 
52
  self.oracle_rejection_reasons = {'bearish': 0, 'low_conf': 0, 'error': 0}
53
 
54
+ print("🧪 [Backtest Engine V38.2] Protocol Fixed.")
55
 
56
  # ==========================================================================
57
+ # 1. Data Loading
58
  # ==========================================================================
59
  async def fetch_deep_history_1m(self):
60
  print(f"\n⏳ [Data] Loading {len(self.TARGET_COINS)} coins ({self.DAYS_TO_FETCH} days)...")
 
91
  print(" ⚠️ No Data")
92
 
93
  # ==========================================================================
94
+ # 2. Helpers
95
  # ==========================================================================
96
  def get_market_snapshot(self, symbol, end_idx):
97
  try:
 
106
 
107
  cols_order = ['timestamp', 'open', 'high', 'low', 'close', 'volume']
108
  timeframes = {'1m': slice_1m[cols_order].values.tolist()}
 
109
  agg = {'timestamp': 'first', 'open': 'first', 'high': 'max', 'low': 'min', 'close': 'last', 'volume': 'sum'}
110
 
111
  for tf, rule in [('5m', '5T'), ('15m', '15T'), ('1h', '1H'), ('4h', '4H')]:
 
117
  except: return None
118
 
119
  # ==========================================================================
120
+ # 3. Process Logic (Fixed)
121
  # ==========================================================================
122
  async def process_market_layers(self, symbol, snapshot, current_price, weights, l1_threshold):
123
  self.funnel_stats['scanned'] += 1
 
147
  if l2_score < l1_threshold: return None
148
  self.funnel_stats['passed_l2'] += 1
149
 
150
+ # --- Oracle ---
151
  mc_adv_score = 0.0
152
  if self.proc.mc_analyzer:
153
  closes = [c[4] for c in snapshot['1h']]
 
156
 
157
  oracle_decision = {'action': 'WAIT'}
158
  if self.proc.oracle:
159
+ self.proc.oracle.set_threshold(0.55) # عتبة معقولة
160
  oracle_input = {'ohlcv': snapshot, 'current_price': current_price, 'titan_score': titan_score, 'mc_score': mc_light, 'patterns_score': pattern_score}
161
  oracle_decision = await self.proc.oracle.predict(oracle_input)
162
 
163
+ # 🔥 الإصلاح: قبول WATCH أو BUY
164
+ # إذا كان القرار ليس BUY وليس WATCH، نعتبره رفضاً
165
+ if oracle_decision['action'] not in ['BUY', 'WATCH']:
166
  reason = oracle_decision.get('reason', 'Unknown')
 
 
 
 
167
  if 'Bearish' in reason or 'SHORT' in str(oracle_decision.get('direction')):
168
  self.oracle_rejection_reasons['bearish'] += 1
169
  elif 'Low Confidence' in reason:
170
  self.oracle_rejection_reasons['low_conf'] += 1
171
  else:
172
  self.oracle_rejection_reasons['error'] += 1
173
+ return None
 
 
 
174
 
 
175
  self.funnel_stats['passed_oracle'] += 1
176
 
177
  # --- Sniper ---
178
  sniper_res = {'signal': 'WAIT'}
179
  if self.proc.sniper:
180
+ self.proc.sniper.configure_settings(threshold=0.35, wall_ratio=0.9, w_ml=1.0, w_ob=0.0)
181
  sniper_res = await self.proc.sniper.check_entry_signal_async(snapshot['1m'], None)
182
 
183
  if sniper_res['signal'] == 'BUY':
184
  self.funnel_stats['passed_sniper'] += 1
185
+ return {
186
+ 'entry_price': sniper_res.get('entry_price', current_price),
187
+ 'tp': oracle_decision.get('primary_tp'),
188
+ 'sl': oracle_decision.get('sl_price'),
189
+ 'oracle_conf': oracle_decision.get('confidence'),
190
+ 'l2_score': l3_score
191
+ }
192
  return None
193
 
194
  # ==========================================================================
195
+ # 4. Simulation Runner (Silent)
196
  # ==========================================================================
197
  async def run_simulation(self):
198
  self.funnel_stats = {'scanned': 0, 'passed_l2': 0, 'passed_oracle': 0, 'passed_sniper': 0}
199
  self.oracle_rejection_reasons = {'bearish': 0, 'low_conf': 0, 'error': 0}
200
+
201
  weights = {'titan': 0.3, 'patterns': 0.3, 'sniper': 0.3, 'mc': 0.1}
202
  l1_thresh = 0.25
203
 
204
+ # تصفير المحفظة
205
+ self.portfolio = VirtualPortfolio()
206
+ trades_log = []
207
+
208
+ print(f" ▶️ Running V38.2 (Fixed Logic)...")
209
 
210
  for sym, df_history in self.history_cache.items():
211
  start_loop = 6000
212
  if len(df_history) < start_loop + 100: continue
213
+
214
+ # فحص كل 15 دقيقة
215
+ for i in range(start_loop, len(df_history) - 100, 15):
216
  snapshot = self.get_market_snapshot(sym, i)
217
  if not snapshot: continue
218
 
219
  current_price = snapshot['1m'][-1][4]
220
+ signal = await self.process_market_layers(sym, snapshot, current_price, weights, l1_thresh)
221
+
222
+ if signal:
223
+ # تنفيذ الصفقة افتراضياً
224
+ entry = current_price
225
+ # محاكاة لمدة ساعتين (120 دقيقة)
226
+ future = df_history.iloc[i+120]['close'] if i+120 < len(df_history) else entry
227
+
228
+ pnl = (future - entry) / entry
229
+ trades_log.append(pnl)
230
+ self.portfolio.capital *= (1 + pnl)
231
 
232
  print(f" Done.")
233
+
234
+ wins = len([p for p in trades_log if p > 0])
235
+ total = len(trades_log)
236
+ wr = (wins/total*100) if total > 0 else 0.0
237
+
238
+ print(f" 📊 Final Results:")
239
+ print(f" Trades: {total}")
240
+ print(f" Win Rate: {wr:.1f}%")
241
+ print(f" Final Capital: ${self.portfolio.capital:.2f}")
242
+ print(f" 📉 Funnel: {self.funnel_stats}")
243
+ print(f" 🚫 Rejections: {self.oracle_rejection_reasons}")
244
 
245
  # ============================================================
246
  # 🚀 Run
247
  # ============================================================
248
  async def run_strategic_optimization_task():
249
+ print("\n🧪 [STRATEGIC BACKTEST V38.2] Unlocking Oracle...")
250
  from r2 import R2Service
251
  r2 = R2Service()
252
  dm = DataManager(None, None, r2)