cyqnt-trd 0.1.2__py3-none-any.whl → 0.1.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. cyqnt_trd/CHANGELOG_0.1.7.md +111 -0
  2. cyqnt_trd/__init__.py +1 -1
  3. cyqnt_trd/backtesting/factor_test.py +3 -2
  4. cyqnt_trd/get_data/__init__.py +16 -1
  5. cyqnt_trd/get_data/get_futures_data.py +3 -3
  6. cyqnt_trd/get_data/get_kline_with_factor.py +808 -0
  7. cyqnt_trd/get_data/get_web3_trending_data.py +389 -0
  8. cyqnt_trd/online_trading/__init__.py +1 -0
  9. cyqnt_trd/online_trading/realtime_price_tracker.py +142 -2
  10. cyqnt_trd/trading_signal/example_usage.py +123 -7
  11. cyqnt_trd/trading_signal/factor/__init__.py +23 -0
  12. cyqnt_trd/trading_signal/factor/adx_factor.py +116 -0
  13. cyqnt_trd/trading_signal/factor/ao_factor.py +66 -0
  14. cyqnt_trd/trading_signal/factor/bbp_factor.py +68 -0
  15. cyqnt_trd/trading_signal/factor/cci_factor.py +65 -0
  16. cyqnt_trd/trading_signal/factor/ema_factor.py +102 -0
  17. cyqnt_trd/trading_signal/factor/macd_factor.py +97 -0
  18. cyqnt_trd/trading_signal/factor/momentum_factor.py +44 -0
  19. cyqnt_trd/trading_signal/factor/stochastic_factor.py +76 -0
  20. cyqnt_trd/trading_signal/factor/stochastic_tsi_factor.py +129 -0
  21. cyqnt_trd/trading_signal/factor/uo_factor.py +92 -0
  22. cyqnt_trd/trading_signal/factor/williams_r_factor.py +60 -0
  23. cyqnt_trd/trading_signal/factor_details.json +107 -0
  24. cyqnt_trd/trading_signal/selected_alpha/alpha1.py +4 -2
  25. cyqnt_trd/trading_signal/selected_alpha/alpha15.py +4 -2
  26. cyqnt_trd/trading_signal/selected_alpha/generate_alphas.py +1 -0
  27. {cyqnt_trd-0.1.2.dist-info → cyqnt_trd-0.1.7.dist-info}/METADATA +16 -12
  28. {cyqnt_trd-0.1.2.dist-info → cyqnt_trd-0.1.7.dist-info}/RECORD +34 -23
  29. {cyqnt_trd-0.1.2.dist-info → cyqnt_trd-0.1.7.dist-info}/WHEEL +1 -1
  30. test/real_time_trade.py +467 -10
  31. test/test_now_factor.py +1082 -0
  32. test/track_k_line_continue.py +372 -0
  33. cyqnt_trd/test_script/get_symbols_by_volume.py +0 -227
  34. cyqnt_trd/test_script/test_alpha.py +0 -261
  35. cyqnt_trd/test_script/test_kline_data.py +0 -479
  36. test/test_example_usage.py +0 -381
  37. test/test_get_data.py +0 -310
  38. test/test_realtime_price_tracker.py +0 -546
  39. {cyqnt_trd-0.1.2.dist-info → cyqnt_trd-0.1.7.dist-info}/licenses/LICENSE +0 -0
  40. {cyqnt_trd-0.1.2.dist-info → cyqnt_trd-0.1.7.dist-info}/top_level.txt +0 -0
test/real_time_trade.py CHANGED
@@ -18,11 +18,16 @@ import os
18
18
  import sys
19
19
  import asyncio
20
20
  import logging
21
+ import warnings
21
22
  from pathlib import Path
22
23
  from datetime import datetime
23
- from typing import Optional, Dict, Any
24
+ from typing import Optional, Dict, Any, Callable
25
+ from concurrent.futures import ThreadPoolExecutor
24
26
  from cyqnt_trd.utils import set_user
25
27
 
28
+ # 抑制 pandas FutureWarning 关于 fillna 的警告
29
+ warnings.filterwarnings('ignore', category=FutureWarning, message='.*Downcasting object dtype arrays on .fillna.*')
30
+
26
31
  # 添加项目根目录到路径
27
32
  project_root = Path(__file__).parent.parent
28
33
  if str(project_root) not in sys.path:
@@ -42,10 +47,17 @@ try:
42
47
  cancel_futures_order
43
48
  )
44
49
  from cyqnt_trd.trading_signal.signal.ma_signal import ma_signal, ma_cross_signal
45
- from cyqnt_trd.trading_signal.signal.factor_based_signal import factor_based_signal
50
+ from cyqnt_trd.trading_signal.signal.factor_based_signal import factor_based_signal, normalized_factor_signal
46
51
  from cyqnt_trd.trading_signal.factor.ma_factor import ma_factor
47
52
  from cyqnt_trd.trading_signal.factor.rsi_factor import rsi_factor
48
- from cyqnt_trd.trading_signal.selected_alpha.alpha1 import alpha1_factor
53
+ from cyqnt_trd.trading_signal.selected_alpha import (
54
+ alpha1_factor, alpha3_factor, alpha7_factor, alpha9_factor,
55
+ alpha11_factor, alpha15_factor, alpha17_factor, alpha21_factor,
56
+ alpha23_factor, alpha25_factor, alpha29_factor, alpha33_factor,
57
+ alpha34_factor
58
+ )
59
+ from cyqnt_trd.backtesting.factor_test import FactorTester
60
+ import numpy as np
49
61
  except ImportError as e:
50
62
  print(f"导入错误: {e}")
51
63
  print("\n提示:请确保已安装 cyqnt_trd package: pip install -e /path/to/crypto_trading")
@@ -147,6 +159,360 @@ class RealTimeTradingBot:
147
159
  logger.warning("⚠️ 实盘模式:将执行真实订单!")
148
160
  logger.warning("="*80)
149
161
 
162
+ def _calculate_normalized_alpha_factor(
163
+ self,
164
+ data_slice,
165
+ factor_func: Callable,
166
+ factor_name: str,
167
+ min_required: int = 30,
168
+ lookback_periods: int = 30,
169
+ **factor_kwargs
170
+ ) -> Optional[Dict[str, Any]]:
171
+ """
172
+ 计算归一化Alpha因子的通用函数
173
+
174
+ Args:
175
+ data_slice: 数据切片
176
+ factor_func: 因子计算函数
177
+ factor_name: 因子名称(用于日志)
178
+ min_required: 因子计算所需的最小周期数
179
+ lookback_periods: 归一化回看周期数
180
+ **factor_kwargs: 传递给因子函数的额外参数
181
+
182
+ Returns:
183
+ 包含因子值和看多/看空结果的字典,如果计算失败则返回None
184
+ """
185
+ try:
186
+ if len(data_slice) < min_required + 2:
187
+ return None
188
+
189
+ available_periods = len(data_slice) - min_required - 1
190
+ if available_periods < 2:
191
+ return None
192
+
193
+ actual_lookback = min(lookback_periods, max(2, available_periods))
194
+
195
+ # 计算因子值:当前周期和之前actual_lookback个周期(使用多线程并行计算)
196
+ def compute_factor_value(i):
197
+ """计算单个时间点的因子值"""
198
+ end_idx = len(data_slice) - i
199
+ start_idx = max(0, end_idx - min_required - 1)
200
+ if end_idx <= start_idx:
201
+ return 0.0
202
+
203
+ period_slice = data_slice.iloc[start_idx:end_idx]
204
+ try:
205
+ # 调用因子函数,传入额外参数
206
+ factor_value = factor_func(period_slice, **factor_kwargs)
207
+ if factor_value is not None:
208
+ return factor_value
209
+ else:
210
+ return 0.0
211
+ except Exception:
212
+ return 0.0
213
+
214
+ # 使用多线程并行计算因子值
215
+ indices = list(range(actual_lookback + 1))
216
+ factor_values = []
217
+ with ThreadPoolExecutor() as executor:
218
+ # 返回顺序保证和原for循环一致
219
+ factor_values = list(executor.map(compute_factor_value, indices))
220
+
221
+ if len(factor_values) < 2:
222
+ return None
223
+
224
+ # 归一化
225
+ factor_array = np.array(factor_values)
226
+ factor_min = factor_array.min()
227
+ factor_max = factor_array.max()
228
+
229
+ if factor_max == factor_min:
230
+ normalized_factors = np.zeros_like(factor_array)
231
+ else:
232
+ # Min-Max归一化到[-1, 1]区间
233
+ normalized_factors = 2 * (factor_array - factor_min) / (factor_max - factor_min) - 1
234
+
235
+ current_normalized = float(normalized_factors[0])
236
+ prev_normalized = float(normalized_factors[1]) if len(normalized_factors) > 1 else 0.0
237
+
238
+ # 判断信号:从负转正看多,从正转负看空
239
+ if prev_normalized <= 0 and current_normalized > 0:
240
+ signal = '看多'
241
+ elif prev_normalized >= 0 and current_normalized < 0:
242
+ signal = '看空'
243
+ else:
244
+ signal = '中性'
245
+
246
+ return {
247
+ 'value': current_normalized,
248
+ 'signal': signal,
249
+ 'raw_value': float(factor_values[0]) if len(factor_values) > 0 else 0.0,
250
+ 'prev_normalized': prev_normalized
251
+ }
252
+ except Exception as e:
253
+ logger.debug(f"计算归一化{factor_name}因子时出错: {e}")
254
+ return None
255
+
256
+ def _calculate_factor_win_rate(
257
+ self,
258
+ data_df,
259
+ factor_func: Callable,
260
+ forward_periods: int = 24,
261
+ min_periods: int = 30,
262
+ factor_name: str = "factor"
263
+ ) -> Optional[Dict[str, float]]:
264
+ """
265
+ 计算因子基于历史数据的胜率(使用FactorTester.test_factor)
266
+
267
+ Args:
268
+ data_df: 历史数据DataFrame
269
+ factor_func: 因子计算函数,接受数据切片作为参数,返回因子值
270
+ forward_periods: 向前看的周期数(默认24,即未来24个周期)
271
+ min_periods: 最小需要的周期数
272
+ factor_name: 因子名称
273
+
274
+ Returns:
275
+ 包含胜率信息的字典,如果计算失败则返回None
276
+ """
277
+ try:
278
+ if len(data_df) < min_periods + forward_periods + 1:
279
+ return None
280
+
281
+ # 创建FactorTester实例
282
+ factor_tester = FactorTester(data_df)
283
+
284
+ # 调用test_factor计算胜率
285
+ test_results = factor_tester.test_factor(
286
+ factor_func=factor_func,
287
+ forward_periods=forward_periods,
288
+ min_periods=min_periods,
289
+ factor_name=factor_name
290
+ )
291
+
292
+ # 提取需要的胜率信息
293
+ result = {
294
+ 'long_win_rate': test_results.get('long_win_rate', 0.0),
295
+ 'short_win_rate': test_results.get('short_win_rate', 0.0),
296
+ 'overall_win_rate': test_results.get('overall_win_rate', 0.0),
297
+ 'long_avg_return': test_results.get('long_avg_return', 0.0),
298
+ 'short_avg_return': test_results.get('short_avg_return', 0.0),
299
+ 'long_signals': test_results.get('long_signals', 0),
300
+ 'short_signals': test_results.get('short_signals', 0),
301
+ 'total_samples': test_results.get('total_samples', 0)
302
+ }
303
+
304
+ return result
305
+
306
+ except Exception as e:
307
+ logger.debug(f"计算因子胜率时出错: {e}")
308
+ return None
309
+
310
+ def _calculate_factor_values(self, data_df) -> Dict[str, Any]:
311
+ """
312
+ 计算各种因子的因子值和看多/看空结果(使用多线程并行计算)
313
+
314
+ Args:
315
+ data_df: 历史数据DataFrame
316
+
317
+ Returns:
318
+ 包含因子值和看多/看空结果的字典
319
+ """
320
+ result = {}
321
+
322
+ if len(data_df) < 10:
323
+ return result
324
+
325
+ # 使用足够的数据切片(对于alpha因子,需要更多数据)
326
+ # 至少需要65个周期(30+30+5缓冲)用于归一化alpha因子计算
327
+ min_slice_size = 65
328
+ if len(data_df) >= min_slice_size:
329
+ data_slice = data_df.iloc[-min_slice_size:].copy()
330
+ elif len(data_df) >= 30:
331
+ data_slice = data_df.iloc[-30:].copy()
332
+ else:
333
+ data_slice = data_df.copy()
334
+
335
+ try:
336
+ # 定义所有需要计算的因子任务
337
+ def calculate_ma_factor():
338
+ """计算MA因子"""
339
+ if len(data_slice) < 6:
340
+ return None
341
+ try:
342
+ ma_factor_value = ma_factor(data_slice, period=5)
343
+ ma_win_rate = self._calculate_factor_win_rate(
344
+ data_df=data_df,
345
+ factor_func=lambda d: ma_factor(d, period=5),
346
+ forward_periods=2,
347
+ min_periods=6,
348
+ factor_name="MA5因子"
349
+ )
350
+ return ('ma_factor_5', {
351
+ 'value': ma_factor_value,
352
+ 'signal': '看多' if ma_factor_value > 0 else '看空' if ma_factor_value < 0 else '中性',
353
+ 'raw_value': ma_factor_value,
354
+ 'win_rate': ma_win_rate
355
+ })
356
+ except Exception as e:
357
+ logger.debug(f"计算MA因子时出错: {e}")
358
+ return None
359
+
360
+ def calculate_normalized_alpha1():
361
+ """计算归一化Alpha#1因子"""
362
+ normalized_result = self._calculate_normalized_alpha_factor(
363
+ data_slice=data_slice,
364
+ factor_func=alpha1_factor,
365
+ factor_name="Alpha#1",
366
+ min_required=30,
367
+ lookback_periods=30,
368
+ lookback_days=5,
369
+ stddev_period=20,
370
+ power=2.0
371
+ )
372
+ if normalized_result:
373
+ def normalized_alpha1_wrapper(d):
374
+ norm_res = self._calculate_normalized_alpha_factor(
375
+ data_slice=d,
376
+ factor_func=alpha1_factor,
377
+ factor_name="Alpha#1",
378
+ min_required=30,
379
+ lookback_periods=30,
380
+ lookback_days=5,
381
+ stddev_period=20,
382
+ power=2.0
383
+ )
384
+ if norm_res:
385
+ return norm_res['value']
386
+ return 0.0
387
+
388
+ alpha1_win_rate = self._calculate_factor_win_rate(
389
+ data_df=data_df,
390
+ factor_func=normalized_alpha1_wrapper,
391
+ forward_periods=2,
392
+ min_periods=65,
393
+ factor_name="归一化Alpha#1因子"
394
+ )
395
+ normalized_result['win_rate'] = alpha1_win_rate
396
+ return ('normalized_alpha1', normalized_result)
397
+ return None
398
+
399
+ def calculate_normalized_alpha15():
400
+ """计算归一化Alpha#15因子"""
401
+ normalized_result = self._calculate_normalized_alpha_factor(
402
+ data_slice=data_slice,
403
+ factor_func=alpha15_factor,
404
+ factor_name="Alpha#15",
405
+ min_required=30,
406
+ lookback_periods=30
407
+ )
408
+ if normalized_result:
409
+ def normalized_alpha15_wrapper(d):
410
+ norm_res = self._calculate_normalized_alpha_factor(
411
+ data_slice=d,
412
+ factor_func=alpha15_factor,
413
+ factor_name="Alpha#15",
414
+ min_required=30,
415
+ lookback_periods=30
416
+ )
417
+ if norm_res:
418
+ return norm_res['value']
419
+ return 0.0
420
+
421
+ alpha15_win_rate = self._calculate_factor_win_rate(
422
+ data_df=data_df,
423
+ factor_func=normalized_alpha15_wrapper,
424
+ forward_periods=2,
425
+ min_periods=65,
426
+ factor_name="归一化Alpha#15因子"
427
+ )
428
+ normalized_result['win_rate'] = alpha15_win_rate
429
+ return ('normalized_alpha15', normalized_result)
430
+ return None
431
+
432
+ def calculate_normalized_alpha(factor_key, factor_func, min_req, alpha_num):
433
+ """计算归一化Alpha因子的通用函数"""
434
+ try:
435
+ normalized_result = self._calculate_normalized_alpha_factor(
436
+ data_slice=data_slice,
437
+ factor_func=factor_func,
438
+ factor_name=f"Alpha#{alpha_num}",
439
+ min_required=min_req,
440
+ lookback_periods=30
441
+ )
442
+ if normalized_result:
443
+ def normalized_wrapper(d, func=factor_func, req=min_req, num=alpha_num):
444
+ norm_res = self._calculate_normalized_alpha_factor(
445
+ data_slice=d,
446
+ factor_func=func,
447
+ factor_name=f"Alpha#{num}",
448
+ min_required=req,
449
+ lookback_periods=30
450
+ )
451
+ if norm_res:
452
+ return norm_res['value']
453
+ return 0.0
454
+
455
+ win_rate = self._calculate_factor_win_rate(
456
+ data_df=data_df,
457
+ factor_func=normalized_wrapper,
458
+ forward_periods=2,
459
+ min_periods=65,
460
+ factor_name=f"归一化Alpha#{alpha_num}因子"
461
+ )
462
+ normalized_result['win_rate'] = win_rate
463
+ return (f'normalized_{factor_key}', normalized_result)
464
+ except Exception as e:
465
+ logger.debug(f"计算{factor_key}因子时出错: {e}")
466
+ return None
467
+
468
+ # 准备所有因子计算任务
469
+ tasks = []
470
+
471
+ # MA因子
472
+ if len(data_slice) >= 6:
473
+ tasks.append(calculate_ma_factor)
474
+
475
+ # 归一化Alpha#1和Alpha#15
476
+ tasks.append(calculate_normalized_alpha1)
477
+ tasks.append(calculate_normalized_alpha15)
478
+
479
+ # 其他归一化Alpha因子
480
+ alpha_factors_to_add = [
481
+ ('alpha3', alpha3_factor, 30, '3'),
482
+ ('alpha7', alpha7_factor, 30, '7'),
483
+ ('alpha9', alpha9_factor, 30, '9'),
484
+ ('alpha11', alpha11_factor, 30, '11'),
485
+ ('alpha17', alpha17_factor, 30, '17'),
486
+ ('alpha21', alpha21_factor, 30, '21'),
487
+ ('alpha23', alpha23_factor, 30, '23'),
488
+ ('alpha25', alpha25_factor, 30, '25'),
489
+ ('alpha29', alpha29_factor, 30, '29'),
490
+ ('alpha33', alpha33_factor, 30, '33'),
491
+ ('alpha34', alpha34_factor, 30, '34'),
492
+ ]
493
+
494
+ for factor_key, factor_func, min_req, alpha_num in alpha_factors_to_add:
495
+ # 使用默认参数捕获循环变量,避免闭包问题
496
+ tasks.append(lambda k=factor_key, f=factor_func, r=min_req, n=alpha_num:
497
+ calculate_normalized_alpha(k, f, r, n))
498
+
499
+ # 使用多线程并行计算所有因子
500
+ with ThreadPoolExecutor() as executor:
501
+ futures = [executor.submit(task) for task in tasks]
502
+ for future in futures:
503
+ try:
504
+ task_result = future.result()
505
+ if task_result is not None:
506
+ key, value = task_result
507
+ result[key] = value
508
+ except Exception as e:
509
+ logger.debug(f"计算因子任务时出错: {e}")
510
+
511
+ except Exception as e:
512
+ logger.debug(f"计算因子值时出错: {e}")
513
+
514
+ return result
515
+
150
516
  def _calculate_signal(self, data_df) -> Optional[str]:
151
517
  """
152
518
  根据策略计算交易信号
@@ -518,8 +884,8 @@ class RealTimeTradingBot:
518
884
  # 计算交易信号
519
885
  signal = self._calculate_signal(data_df)
520
886
 
521
- # 显示状态
522
- self._display_status(current_time, current_price, signal)
887
+ # 显示状态(包含因子值)
888
+ self._display_status(current_time, current_price, signal, data_df)
523
889
 
524
890
  # 检查止盈止损(如果有持仓)
525
891
  if self.position > 0:
@@ -551,7 +917,7 @@ class RealTimeTradingBot:
551
917
  self.last_signal = 'sell'
552
918
  self.last_signal_time = datetime.now()
553
919
 
554
- def _display_status(self, time_str: str, price: float, signal: Optional[str]):
920
+ def _display_status(self, time_str: str, price: float, signal: Optional[str], data_df=None):
555
921
  """
556
922
  显示当前状态
557
923
 
@@ -559,6 +925,7 @@ class RealTimeTradingBot:
559
925
  time_str: 时间字符串
560
926
  price: 当前价格
561
927
  signal: 交易信号
928
+ data_df: 历史数据DataFrame(用于计算因子值)
562
929
  """
563
930
  # 计算统计信息
564
931
  runtime = datetime.now() - self.start_time
@@ -586,6 +953,96 @@ class RealTimeTradingBot:
586
953
  print(f"持仓: {self.position:.6f} | 入场价: {self.entry_price:.2f} | 浮动盈亏: {profit_pct:+.2f}%")
587
954
  else:
588
955
  print(f"持仓: 无")
956
+
957
+ # 计算并显示因子值
958
+ if data_df is not None:
959
+ try:
960
+ factor_results = self._calculate_factor_values(data_df)
961
+ if factor_results:
962
+ print(f"{'='*80}")
963
+ print(f"📈 因子分析:")
964
+
965
+ # MA因子
966
+ if 'ma_factor_5' in factor_results:
967
+ ma_info = factor_results['ma_factor_5']
968
+ signal_emoji = "🟢" if ma_info.get('signal') == '看多' else "🔴" if ma_info.get('signal') == '看空' else "⚪"
969
+ signal_text = ma_info.get('signal', '中性')
970
+ win_rate_info = ""
971
+ if ma_info.get('win_rate'):
972
+ wr = ma_info['win_rate']
973
+ if wr and isinstance(wr, dict):
974
+ if signal_text == '看多' and wr.get('long_win_rate') is not None:
975
+ win_rate_info = f" | 看多胜率={wr['long_win_rate']:.2%} (样本={wr.get('long_signals', 0)})"
976
+ elif signal_text == '看空' and wr.get('short_win_rate') is not None:
977
+ win_rate_info = f" | 看空胜率={wr['short_win_rate']:.2%} (样本={wr.get('short_signals', 0)})"
978
+ if wr.get('overall_win_rate') is not None:
979
+ win_rate_info += f" | 总体胜率={wr['overall_win_rate']:.2%}"
980
+ print(f" MA5因子: 因子值={ma_info.get('raw_value', 0):+.4f} | {signal_emoji} {signal_text}{win_rate_info}")
981
+
982
+ # # 归一化Alpha#1因子
983
+ # if 'normalized_alpha1' in factor_results:
984
+ # alpha1_info = factor_results['normalized_alpha1']
985
+ # signal_emoji = "🟢" if alpha1_info.get('signal') == '看多' else "🔴" if alpha1_info.get('signal') == '看空' else "⚪"
986
+ # signal_text = alpha1_info.get('signal', '中性')
987
+ # win_rate_info = ""
988
+ # if alpha1_info.get('win_rate'):
989
+ # wr = alpha1_info['win_rate']
990
+ # if wr and isinstance(wr, dict):
991
+ # if signal_text == '看多' and wr.get('long_win_rate') is not None:
992
+ # win_rate_info = f" | 看多胜率={wr['long_win_rate']:.2%} (样本={wr.get('long_signals', 0)})"
993
+ # elif signal_text == '看空' and wr.get('short_win_rate') is not None:
994
+ # win_rate_info = f" | 看空胜率={wr['short_win_rate']:.2%} (样本={wr.get('short_signals', 0)})"
995
+ # if wr.get('overall_win_rate') is not None:
996
+ # win_rate_info += f" | 总体胜率={wr['overall_win_rate']:.2%}"
997
+ # print(f" 归一化Alpha#1: 原始值={alpha1_info.get('raw_value', 0):+.6f} | 归一化值={alpha1_info.get('value', 0):+.4f} | {signal_emoji} {signal_text}{win_rate_info}")
998
+
999
+ # # 归一化Alpha#15因子
1000
+ # if 'normalized_alpha15' in factor_results:
1001
+ # alpha15_info = factor_results['normalized_alpha15']
1002
+ # signal_emoji = "🟢" if alpha15_info.get('signal') == '看多' else "🔴" if alpha15_info.get('signal') == '看空' else "⚪"
1003
+ # signal_text = alpha15_info.get('signal', '中性')
1004
+ # win_rate_info = ""
1005
+ # if alpha15_info.get('win_rate'):
1006
+ # wr = alpha15_info['win_rate']
1007
+ # if wr and isinstance(wr, dict):
1008
+ # if signal_text == '看多' and wr.get('long_win_rate') is not None:
1009
+ # win_rate_info = f" | 看多胜率={wr['long_win_rate']:.2%} (样本={wr.get('long_signals', 0)})"
1010
+ # elif signal_text == '看空' and wr.get('short_win_rate') is not None:
1011
+ # win_rate_info = f" | 看空胜率={wr['short_win_rate']:.2%} (样本={wr.get('short_signals', 0)})"
1012
+ # if wr.get('overall_win_rate') is not None:
1013
+ # win_rate_info += f" | 总体胜率={wr['overall_win_rate']:.2%}"
1014
+ # print(f" 归一化Alpha#15: 原始值={alpha15_info.get('raw_value', 0):+.6f} | 归一化值={alpha15_info.get('value', 0):+.4f} | {signal_emoji} {signal_text}{win_rate_info}")
1015
+
1016
+ # 显示其他归一化Alpha因子
1017
+ other_alpha_factors = [
1018
+ 'normalized_alpha1', 'normalized_alpha15', 'normalized_alpha3', 'normalized_alpha7', 'normalized_alpha9',
1019
+ 'normalized_alpha11', 'normalized_alpha17', 'normalized_alpha21',
1020
+ 'normalized_alpha23', 'normalized_alpha25', 'normalized_alpha29',
1021
+ 'normalized_alpha33', 'normalized_alpha34'
1022
+ ]
1023
+
1024
+ for factor_key in other_alpha_factors:
1025
+ if factor_key in factor_results:
1026
+ alpha_info = factor_results[factor_key]
1027
+ alpha_num = factor_key.replace('normalized_alpha', '')
1028
+ signal_emoji = "🟢" if alpha_info.get('signal') == '看多' else "🔴" if alpha_info.get('signal') == '看空' else "⚪"
1029
+ signal_text = alpha_info.get('signal', '中性')
1030
+ win_rate_info = ""
1031
+ if alpha_info.get('win_rate'):
1032
+ wr = alpha_info['win_rate']
1033
+ if wr and isinstance(wr, dict):
1034
+ if signal_text == '看多' and wr.get('long_win_rate') is not None:
1035
+ win_rate_info = f" | 看多胜率={wr['long_win_rate']:.2%} (样本={wr.get('long_signals', 0)})"
1036
+ elif signal_text == '看空' and wr.get('short_win_rate') is not None:
1037
+ win_rate_info = f" | 看空胜率={wr['short_win_rate']:.2%} (样本={wr.get('short_signals', 0)})"
1038
+ if wr.get('overall_win_rate') is not None:
1039
+ win_rate_info += f" | 总体胜率={wr['overall_win_rate']:.2%}"
1040
+ print(f" 归一化Alpha#{alpha_num}: 原始值={alpha_info.get('raw_value', 0):+.6f} | 归一化值={alpha_info.get('value', 0):+.4f} | {signal_emoji} {signal_text}{win_rate_info}")
1041
+ except Exception as e:
1042
+ logger.debug(f"显示因子分析时出错: {e}")
1043
+ import traceback
1044
+ logger.debug(traceback.format_exc())
1045
+
589
1046
  print(f"{'='*80}")
590
1047
  print(f"💰 账户信息:")
591
1048
  print(f" 可用余额: {available_balance:.2f}")
@@ -684,9 +1141,9 @@ async def test_real_time_trading():
684
1141
  # 创建实盘交易机器人
685
1142
  # ⚠️ 警告:设置 dry_run=False 将执行真实交易!
686
1143
  bot = RealTimeTradingBot(
687
- symbol="BNBUSDT",
688
- interval="3m",
689
- lookback_periods=1000,
1144
+ symbol="ETHUSDT",
1145
+ interval="5m",
1146
+ lookback_periods=800,
690
1147
  market_type="futures", # 或 "spot"
691
1148
  position_size_pct=0.01,
692
1149
  take_profit=0.1,
@@ -694,7 +1151,7 @@ async def test_real_time_trading():
694
1151
  strategy="ma5", # 可选: ma5, ma_cross, ma_factor, rsi_factor, alpha1
695
1152
  min_order_quantity=0.00001,
696
1153
  ssl_verify=False,
697
- dry_run=False # ⚠️ 设置为 False 将执行真实交易!
1154
+ dry_run=True # ⚠️ 设置为 False 将执行真实交易!
698
1155
  )
699
1156
 
700
1157
  try: