Riy777 commited on
Commit
22847cc
·
1 Parent(s): 51bab74

Update simulation_engine/sim_runner.py

Browse files
Files changed (1) hide show
  1. simulation_engine/sim_runner.py +100 -110
simulation_engine/sim_runner.py CHANGED
@@ -1,10 +1,9 @@
1
  # simulation_engine/sim_runner.py
2
- # (V1.4 - Streamlined Simulation Loop - FIXED TITAN DATA SCARCITY)
3
 
4
  import asyncio
5
  import os
6
  import pandas as pd
7
- import traceback
8
  from tqdm import tqdm
9
  from datetime import datetime
10
 
@@ -17,162 +16,153 @@ try:
17
  from .mock_kucoin import MockKuCoin
18
  from .virtual_exchange import VirtualExchange
19
  except ImportError:
20
- print("❌ [SimRunner] Missing mock components.")
21
 
22
- # === إعدادات المحاكاة ===
23
  SIM_CONFIG = {
24
  "START_DATE": "2025-09-10",
25
- "END_DATE": "2025-11-09",
26
- "INITIAL_BALANCE": 10.0, # تم التعديل بناء على طلب المستخدم
27
  "TEST_SYMBOLS": [
28
  "BTC/USDT", "ETH/USDT", "SOL/USDT", "BNB/USDT", "XRP/USDT",
29
  "DOGE/USDT", "ADA/USDT", "AVAX/USDT", "LINK/USDT"
30
  ],
31
- "LOCAL_DATA_DIR": "./simulation_data"
32
  }
33
 
34
- # متغير عالمي لتتبع الحالة من app.py
35
- SIM_STATUS = {
36
- "running": False,
37
- "progress": 0.0,
38
- "current_balance": 0.0,
39
- "trades_count": 0
40
- }
41
 
42
- # 🔥 متغير ثابت للإصلاح 🔥
43
- REQUIRED_CANDLES = 200 # الحد الأدنى للشموع المطلوبة لحساب المؤشرات الكبيرة (مثل 200 EMA)
44
- FETCH_LIMIT = 500 # نطلب 500 شمعة لضمان توفر الـ 200
45
 
46
  async def run_realistic_simulation():
47
- global SIM_STATUS
48
  SIM_STATUS["running"] = True
49
- print(f"🚀 بدء المحاكاة التعليمية المبسطة من {SIM_CONFIG['START_DATE']} إلى {SIM_CONFIG['END_DATE']}")
50
 
51
  r2_service = R2Service()
52
-
53
  if not os.path.exists(SIM_CONFIG["LOCAL_DATA_DIR"]):
54
- print(f"❌ مجلد البيانات غير موجود: {SIM_CONFIG['LOCAL_DATA_DIR']}")
55
  SIM_STATUS["running"] = False
56
  return
57
 
58
- print("🛠️ تجهيز البيئة...")
59
  mock_exchange = MockKuCoin(SIM_CONFIG["LOCAL_DATA_DIR"])
60
  await mock_exchange.load_data(SIM_CONFIG["TEST_SYMBOLS"], ['5m', '15m', '1h', '4h', '1d'])
61
  virtual_wallet = VirtualExchange(SIM_CONFIG["INITIAL_BALANCE"])
62
 
63
- print("🧠 تهيئة النظام الهجين مع التعلم النشط...")
64
  data_manager = DataManager(None, None, r2_service=r2_service, mock_exchange=mock_exchange)
65
-
66
  learning_hub = LearningHubManager(r2_service, None, data_manager)
67
  await learning_hub.initialize()
68
-
69
  processor = MLProcessor(None, data_manager, learning_hub)
70
  await processor.initialize()
71
-
72
- print("✅ النظام جاهز. بدء المعركة (وضع السرعة القصوى)...")
73
 
74
  start_ts = int(pd.Timestamp(SIM_CONFIG["START_DATE"]).timestamp() * 1000)
75
  end_ts = int(pd.Timestamp(SIM_CONFIG["END_DATE"]).timestamp() * 1000)
76
- step_ms = 15 * 60 * 1000
77
  timeline = range(start_ts, end_ts, step_ms)
78
  total_steps = len(timeline)
79
-
80
  progress_bar = tqdm(timeline, desc="Simulating", unit="step")
81
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  for i, current_ts in enumerate(progress_bar):
83
  mock_exchange.set_time(current_ts)
84
-
85
  if i % 10 == 0:
86
- SIM_STATUS["progress"] = (i / total_steps) * 100
87
- SIM_STATUS["current_balance"] = virtual_wallet.get_balance()
88
- SIM_STATUS["trades_count"] = len(virtual_wallet.trade_history)
89
 
90
- # --- أ. تحديث المحفظة + تعلم من الصفقات المغلقة ---
91
  current_prices = {}
92
  for sym in SIM_CONFIG["TEST_SYMBOLS"]:
93
- ticker = await mock_exchange.fetch_ticker(sym)
94
- current_prices[sym] = ticker['last']
95
-
96
  closed_trades = virtual_wallet.update_positions(current_prices, current_ts)
97
- for trade in closed_trades:
98
- await learning_hub.analyze_trade_and_learn(trade, trade['close_reason'])
99
-
100
- # --- ب. دورة البحث عن فرص جديدة (مباشرة وبسيطة) ---
101
- # تم تعديل الشرط ليناسب الرصيد الصغير (أكبر من 5 دولارات كحد أدنى)
102
- if virtual_wallet.get_balance() > 5:
103
- for symbol in SIM_CONFIG["TEST_SYMBOLS"]:
104
- try:
105
- ohlcv_packet = {}
106
- REQUIRED_TFS = ['5m', '15m', '1h', '4h', '1d']
107
- valid_packet = True
108
-
109
- for tf in REQUIRED_TFS:
110
- # 🔥 جلب 500 شمعة بدلاً من 100
111
- candles = await mock_exchange.fetch_ohlcv(symbol, tf, limit=FETCH_LIMIT)
112
-
113
- # 🔥 التحقق من الحد الأدنى للشموع المطلوبة
114
- if not candles or len(candles) < REQUIRED_CANDLES:
115
- valid_packet = False
116
- break
117
-
118
- ohlcv_packet[tf] = candles
119
-
120
- if not valid_packet: continue
121
-
122
- raw_data = {
123
- 'symbol': symbol,
124
- 'ohlcv': ohlcv_packet,
125
- 'current_price': current_prices.get(symbol, 0.0)
126
- }
127
-
128
- res = await processor.process_and_score_symbol_enhanced(raw_data)
129
-
130
- entry_threshold = getattr(data_manager, 'HYBRID_ENTRY_THRESHOLD', 0.10)
131
-
132
- if res and res['enhanced_final_score'] >= entry_threshold:
133
- if symbol not in virtual_wallet.positions:
134
- # 🔥 حجم الصفقة 100% من الرصيد المتاح (للاستثمار بالكامل)
135
- pos_size = virtual_wallet.get_balance()
136
-
137
- virtual_wallet.execute_buy(
138
- symbol,
139
- res['current_price'],
140
- pos_size,
141
- current_ts,
142
- res.get('components', {})
143
- )
144
-
145
- except Exception as e:
146
- # تتبع الأخطاء الصامتة فقط
147
- if not valid_packet: continue # نمرر الأخطاء المتعلقة بالبيانات غير الكافية في بداية المحاكاة
148
- # يمكنك إلغاء التعليق هنا إذا أردت رؤية الأخطاء الأخرى:
149
- # print(f"⚠️ Error processing {symbol} at {current_ts}: {e}")
150
- pass
151
-
152
- # الختام
153
- print("\n🏁 نهاية فترة المحاكاة. إغلاق الصفقات المتبقية...")
154
  final_ts = end_ts
155
  mock_exchange.set_time(final_ts)
156
  final_prices = {}
157
  for sym in SIM_CONFIG["TEST_SYMBOLS"]:
158
- t = await mock_exchange.fetch_ticker(sym)
159
- final_prices[sym] = t['last']
160
-
161
  for sym in list(virtual_wallet.positions.keys()):
162
- trade = virtual_wallet.execute_sell(sym, final_prices.get(sym, 0), final_ts, "END_OF_SIM")
163
- if trade: await learning_hub.analyze_trade_and_learn(trade, "END_OF_SIM")
 
164
 
165
- print("💾 جاري حفظ النتائج إلى R2...")
166
  await r2_service.save_simulation_results(virtual_wallet.trade_history, virtual_wallet.metrics)
167
-
168
  await learning_hub.shutdown()
169
-
170
  SIM_STATUS["running"] = False
171
  SIM_STATUS["progress"] = 100.0
172
-
173
- print("\n🎉 === تقرير المحاكاة السريع ===")
174
- print(f"💰 الرصيد النهائي: ${virtual_wallet.get_balance():.2f} (من ${SIM_CONFIG['INITIAL_BALANCE']})")
175
- print(f"📈 إجمالي الربح/الخسارة: ${virtual_wallet.metrics['total_pnl_usd']:.2f}")
176
- print(f"🔢 عدد الصفقات: {len(virtual_wallet.trade_history)} (فوز: {virtual_wallet.metrics['wins']} | خسارة: {virtual_wallet.metrics['losses']})")
177
- print(f"📉 أقصى تراجع (Max Drawdown): {virtual_wallet.metrics['max_drawdown']*100:.2f}%")
178
- print("===============================\n")
 
1
  # simulation_engine/sim_runner.py
2
+ # (V1.6 - Streamlined Simulation Loop with DEBUG prints)
3
 
4
  import asyncio
5
  import os
6
  import pandas as pd
 
7
  from tqdm import tqdm
8
  from datetime import datetime
9
 
 
16
  from .mock_kucoin import MockKuCoin
17
  from .virtual_exchange import VirtualExchange
18
  except ImportError:
19
+ print("❌ [SimRunner] Missing mock components.", flush=True)
20
 
 
21
  SIM_CONFIG = {
22
  "START_DATE": "2025-09-10",
23
+ "END_DATE": "2025-11-09",
24
+ "INITIAL_BALANCE": 10.0,
25
  "TEST_SYMBOLS": [
26
  "BTC/USDT", "ETH/USDT", "SOL/USDT", "BNB/USDT", "XRP/USDT",
27
  "DOGE/USDT", "ADA/USDT", "AVAX/USDT", "LINK/USDT"
28
  ],
29
+ "LOCAL_DATA_DIR": "./simulation_data"
30
  }
31
 
32
+ SIM_STATUS = { "running": False, "progress": 0.0, "current_balance": 0.0, "trades_count": 0 }
 
 
 
 
 
 
33
 
34
+ REQUIRED_CANDLES = 200
35
+ FETCH_LIMIT = 500
 
36
 
37
  async def run_realistic_simulation():
 
38
  SIM_STATUS["running"] = True
39
+ print(f"🚀 Sim from {SIM_CONFIG['START_DATE']} -> {SIM_CONFIG['END_DATE']} | symbols={len(SIM_CONFIG['TEST_SYMBOLS'])}", flush=True)
40
 
41
  r2_service = R2Service()
 
42
  if not os.path.exists(SIM_CONFIG["LOCAL_DATA_DIR"]):
43
+ print(f"❌ Missing data dir: {SIM_CONFIG['LOCAL_DATA_DIR']}", flush=True)
44
  SIM_STATUS["running"] = False
45
  return
46
 
47
+ print("🛠️ Bootstrapping...", flush=True)
48
  mock_exchange = MockKuCoin(SIM_CONFIG["LOCAL_DATA_DIR"])
49
  await mock_exchange.load_data(SIM_CONFIG["TEST_SYMBOLS"], ['5m', '15m', '1h', '4h', '1d'])
50
  virtual_wallet = VirtualExchange(SIM_CONFIG["INITIAL_BALANCE"])
51
 
52
+ print("🧠 Initializing hybrid system...", flush=True)
53
  data_manager = DataManager(None, None, r2_service=r2_service, mock_exchange=mock_exchange)
 
54
  learning_hub = LearningHubManager(r2_service, None, data_manager)
55
  await learning_hub.initialize()
 
56
  processor = MLProcessor(None, data_manager, learning_hub)
57
  await processor.initialize()
58
+ print(f"✅ Ready. Threshold={getattr(data_manager, 'HYBRID_ENTRY_THRESHOLD', 'NA')}", flush=True)
 
59
 
60
  start_ts = int(pd.Timestamp(SIM_CONFIG["START_DATE"]).timestamp() * 1000)
61
  end_ts = int(pd.Timestamp(SIM_CONFIG["END_DATE"]).timestamp() * 1000)
62
+ step_ms = 15 * 60 * 1000
63
  timeline = range(start_ts, end_ts, step_ms)
64
  total_steps = len(timeline)
65
+
66
  progress_bar = tqdm(timeline, desc="Simulating", unit="step")
67
+
68
+ def log(msg: str):
69
+ # يضمن الظهور حتى مع tqdm
70
+ try:
71
+ progress_bar.write(msg)
72
+ except Exception:
73
+ print(msg, flush=True)
74
+
75
+ # طباعة ملخص البيانات المتاحة لكل رمز
76
+ for sym in SIM_CONFIG["TEST_SYMBOLS"]:
77
+ counts = {}
78
+ for tf in ['5m', '15m', '1h', '4h', '1d']:
79
+ data = await mock_exchange.fetch_ohlcv(sym, tf, limit=1_000_000)
80
+ counts[tf] = len(data)
81
+ log(f"[DATA] {sym} -> lens: {counts}")
82
+
83
  for i, current_ts in enumerate(progress_bar):
84
  mock_exchange.set_time(current_ts)
85
+
86
  if i % 10 == 0:
87
+ SIM_STATUS["progress"] = (i / total_steps) * 100
88
+ SIM_STATUS["current_balance"] = virtual_wallet.get_balance()
89
+ SIM_STATUS["trades_count"] = len(virtual_wallet.trade_history)
90
 
91
+ # أ) تحديث المراكز الحالية
92
  current_prices = {}
93
  for sym in SIM_CONFIG["TEST_SYMBOLS"]:
94
+ t = await mock_exchange.fetch_ticker(sym)
95
+ current_prices[sym] = t['last']
 
96
  closed_trades = virtual_wallet.update_positions(current_prices, current_ts)
97
+ for tr in closed_trades:
98
+ log(f"[CLOSE] {tr['symbol']} reason={tr['close_reason']} pnl={tr['pnl_percent']:.2f}%")
99
+ await learning_hub.analyze_trade_and_learn(tr, tr['close_reason'])
100
+
101
+ # ب) البحث عن فرص
102
+ entry_threshold = getattr(data_manager, 'HYBRID_ENTRY_THRESHOLD', 0.75)
103
+ for symbol in SIM_CONFIG["TEST_SYMBOLS"]:
104
+ REQUIRED_TFS = ['5m', '15m', '1h', '4h', '1d']
105
+ ohlcv_packet = {}
106
+ valid_packet = True
107
+ lens = {}
108
+ for tf in REQUIRED_TFS:
109
+ candles = await mock_exchange.fetch_ohlcv(symbol, tf, limit=FETCH_LIMIT)
110
+ n = len(candles) if candles else 0
111
+ lens[tf] = n
112
+ if not candles or n < REQUIRED_CANDLES:
113
+ valid_packet = False
114
+ if not valid_packet:
115
+ if i % 50 == 0: # لا نغرق الطرفية
116
+ log(f"[SKIP][{symbol}] insufficient data {lens} need>={REQUIRED_CANDLES}")
117
+ continue
118
+
119
+ # إذا صالح، خزّنه
120
+ for tf in REQUIRED_TFS:
121
+ ohlcv_packet[tf] = await mock_exchange.fetch_ohlcv(symbol, tf, limit=FETCH_LIMIT)
122
+
123
+ raw_data = {'symbol': symbol, 'ohlcv': ohlcv_packet, 'current_price': current_prices.get(symbol, 0.0)}
124
+ res = await processor.process_and_score_symbol_enhanced(raw_data)
125
+
126
+ if not res:
127
+ log(f"[NORES] {symbol}")
128
+ continue
129
+
130
+ final_s = res['enhanced_final_score']
131
+ comps = res.get('components', {})
132
+ log(f"[SCORE] {symbol} final={final_s:.3f} thr={entry_threshold:.3f} comps={comps}")
133
+
134
+ if final_s >= entry_threshold:
135
+ if symbol not in virtual_wallet.positions and virtual_wallet.get_balance() > 5:
136
+ pos_size = virtual_wallet.get_balance()
137
+ ok = virtual_wallet.execute_buy(symbol, res['current_price'], pos_size, current_ts, comps)
138
+ if ok:
139
+ log(f"[BUY] {symbol} @ {res['current_price']} size=${pos_size:.2f}")
140
+ else:
141
+ log(f"[BUY-FAIL] {symbol} balance={virtual_wallet.get_balance():.2f}")
142
+
143
+ # إنهاء
144
+ print("\n🏁 نهاية فترة المحاكاة. إغلاق الصفقات المتبقية...", flush=True)
 
 
 
 
 
 
 
 
 
145
  final_ts = end_ts
146
  mock_exchange.set_time(final_ts)
147
  final_prices = {}
148
  for sym in SIM_CONFIG["TEST_SYMBOLS"]:
149
+ t = await mock_exchange.fetch_ticker(sym)
150
+ final_prices[sym] = t['last']
 
151
  for sym in list(virtual_wallet.positions.keys()):
152
+ tr = virtual_wallet.execute_sell(sym, final_prices.get(sym, 0), final_ts, "END_OF_SIM")
153
+ if tr:
154
+ await learning_hub.analyze_trade_and_learn(tr, "END_OF_SIM")
155
 
156
+ print("💾 جاري حفظ النتائج إلى R2...", flush=True)
157
  await r2_service.save_simulation_results(virtual_wallet.trade_history, virtual_wallet.metrics)
 
158
  await learning_hub.shutdown()
159
+
160
  SIM_STATUS["running"] = False
161
  SIM_STATUS["progress"] = 100.0
162
+
163
+ print("\n🎉 === تقرير المحاكاة السريع ===", flush=True)
164
+ print(f"💰 الرصيد النهائي: ${virtual_wallet.get_balance():.2f} (من ${SIM_CONFIG['INITIAL_BALANCE']})", flush=True)
165
+ print(f"📈 إجمالي الربح/الخسارة: ${virtual_wallet.metrics['total_pnl_usd']:.2f}", flush=True)
166
+ print(f"🔢 عدد الصفقات: {len(virtual_wallet.trade_history)} (فوز: {virtual_wallet.metrics['wins']} | خسارة: {virtual_wallet.metrics['losses']})", flush=True)
167
+ print(f"📉 أقصى تراجع (Max Drawdown): {virtual_wallet.metrics['max_drawdown']*100:.2f}%", flush=True)
168
+ print("===============================\n", flush=True)