cyqnt-trd 0.1.2__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.
- cyqnt_trd/__init__.py +26 -0
- cyqnt_trd/backtesting/README.md +264 -0
- cyqnt_trd/backtesting/__init__.py +12 -0
- cyqnt_trd/backtesting/factor_test.py +332 -0
- cyqnt_trd/backtesting/framework.py +311 -0
- cyqnt_trd/backtesting/strategy_backtest.py +545 -0
- cyqnt_trd/diagnose_api.py +28 -0
- cyqnt_trd/get_data/__init__.py +15 -0
- cyqnt_trd/get_data/get_futures_data.py +472 -0
- cyqnt_trd/get_data/get_trending_data.py +771 -0
- cyqnt_trd/online_trading/__init__.py +13 -0
- cyqnt_trd/online_trading/realtime_price_tracker.py +1001 -0
- cyqnt_trd/test.py +119 -0
- cyqnt_trd/test_script/README.md +411 -0
- cyqnt_trd/test_script/get_network_info.py +192 -0
- cyqnt_trd/test_script/get_symbols_by_volume.py +227 -0
- cyqnt_trd/test_script/realtime_price_tracker.py +839 -0
- cyqnt_trd/test_script/test_alpha.py +261 -0
- cyqnt_trd/test_script/test_kline_data.py +479 -0
- cyqnt_trd/test_script/test_order.py +1360 -0
- cyqnt_trd/trading_signal/README.md +276 -0
- cyqnt_trd/trading_signal/__init__.py +17 -0
- cyqnt_trd/trading_signal/example_test_alpha.py +430 -0
- cyqnt_trd/trading_signal/example_usage.py +431 -0
- cyqnt_trd/trading_signal/factor/__init__.py +18 -0
- cyqnt_trd/trading_signal/factor/ma_factor.py +75 -0
- cyqnt_trd/trading_signal/factor/rsi_factor.py +56 -0
- cyqnt_trd/trading_signal/selected_alpha/__init__.py +158 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha1.py +87 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha10.py +90 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha100.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha101.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha11.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha12.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha13.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha14.py +87 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha15.py +87 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha16.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha17.py +88 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha18.py +88 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha19.py +87 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha2.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha20.py +88 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha21.py +89 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha22.py +87 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha23.py +88 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha24.py +88 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha25.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha26.py +87 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha27.py +88 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha28.py +88 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha29.py +87 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha3.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha30.py +87 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha31.py +90 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha32.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha33.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha34.py +87 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha35.py +88 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha36.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha37.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha38.py +87 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha39.py +87 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha4.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha40.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha41.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha42.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha43.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha44.py +87 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha45.py +88 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha46.py +89 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha47.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha48.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha49.py +88 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha5.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha50.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha51.py +88 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha52.py +87 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha53.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha54.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha55.py +88 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha56.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha57.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha58.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha59.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha6.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha60.py +89 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha61.py +88 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha62.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha63.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha64.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha65.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha66.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha67.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha68.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha69.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha7.py +88 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha70.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha71.py +92 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha72.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha73.py +91 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha74.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha75.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha76.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha77.py +92 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha78.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha79.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha8.py +87 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha80.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha81.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha82.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha83.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha84.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha85.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha86.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha87.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha88.py +92 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha89.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha9.py +90 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha90.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha91.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha92.py +92 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha93.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha94.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha95.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha96.py +92 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha97.py +74 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha98.py +87 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha99.py +86 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha_utils.py +342 -0
- cyqnt_trd/trading_signal/selected_alpha/create_all_alphas.py +279 -0
- cyqnt_trd/trading_signal/selected_alpha/generate_alphas.py +133 -0
- cyqnt_trd/trading_signal/selected_alpha/test_alpha.py +261 -0
- cyqnt_trd/trading_signal/signal/__init__.py +20 -0
- cyqnt_trd/trading_signal/signal/factor_based_signal.py +387 -0
- cyqnt_trd/trading_signal/signal/ma_signal.py +163 -0
- cyqnt_trd/utils/__init__.py +3 -0
- cyqnt_trd/utils/set_user.py +33 -0
- cyqnt_trd-0.1.2.dist-info/METADATA +148 -0
- cyqnt_trd-0.1.2.dist-info/RECORD +147 -0
- cyqnt_trd-0.1.2.dist-info/WHEEL +5 -0
- cyqnt_trd-0.1.2.dist-info/licenses/LICENSE +21 -0
- cyqnt_trd-0.1.2.dist-info/top_level.txt +2 -0
- test/real_time_trade.py +746 -0
- test/test_example_usage.py +381 -0
- test/test_get_data.py +310 -0
- test/test_realtime_price_tracker.py +546 -0
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
"""
|
|
2
|
+
测试所有101个Alpha因子
|
|
3
|
+
|
|
4
|
+
测试 selected_alpha 模块中的所有 Alpha 因子,验证它们是否能正常工作。
|
|
5
|
+
|
|
6
|
+
使用方法:
|
|
7
|
+
# 方式1: 作为模块运行(推荐)
|
|
8
|
+
cd /Users/user/Desktop/repo/crypto_trading
|
|
9
|
+
python -m cyqnt_trd.trading_signal.example_test_alpha
|
|
10
|
+
|
|
11
|
+
# 方式2: 直接运行脚本
|
|
12
|
+
cd /Users/user/Desktop/repo/crypto_trading
|
|
13
|
+
python cyqnt_trd/trading_signal/example_test_alpha.py
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import sys
|
|
17
|
+
import os
|
|
18
|
+
import pandas as pd
|
|
19
|
+
import numpy as np
|
|
20
|
+
from typing import Dict, List, Tuple
|
|
21
|
+
import traceback
|
|
22
|
+
from datetime import datetime
|
|
23
|
+
|
|
24
|
+
# 添加项目根目录到路径,以便导入模块
|
|
25
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
26
|
+
project_root = os.path.dirname(os.path.dirname(current_dir))
|
|
27
|
+
if project_root not in sys.path:
|
|
28
|
+
sys.path.insert(0, project_root)
|
|
29
|
+
|
|
30
|
+
# 导入所有alpha因子
|
|
31
|
+
try:
|
|
32
|
+
from cyqnt_trd.trading_signal.selected_alpha import ALPHA_FACTORS
|
|
33
|
+
from cyqnt_trd.backtesting import BacktestFramework
|
|
34
|
+
except ImportError as e:
|
|
35
|
+
print(f"导入错误: {e}")
|
|
36
|
+
print(f"\n当前工作目录: {os.getcwd()}")
|
|
37
|
+
print(f"当前文件路径: {os.path.abspath(__file__)}")
|
|
38
|
+
print(f"项目根目录: {project_root}")
|
|
39
|
+
print("\n提示:请使用以下方式运行:")
|
|
40
|
+
print(" cd /Users/user/Desktop/repo/crypto_trading")
|
|
41
|
+
print(" python -m cyqnt_trd.trading_signal.example_test_alpha")
|
|
42
|
+
sys.exit(1)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def create_test_data(n_samples: int = 100) -> pd.DataFrame:
|
|
46
|
+
"""
|
|
47
|
+
创建测试数据
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
n_samples: 样本数量
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
测试用的DataFrame
|
|
54
|
+
"""
|
|
55
|
+
np.random.seed(42)
|
|
56
|
+
|
|
57
|
+
# 生成模拟价格数据
|
|
58
|
+
base_price = 100.0
|
|
59
|
+
prices = [base_price]
|
|
60
|
+
for i in range(n_samples - 1):
|
|
61
|
+
change = np.random.normal(0, 0.02) # 2%的标准差
|
|
62
|
+
prices.append(prices[-1] * (1 + change))
|
|
63
|
+
|
|
64
|
+
# 创建DataFrame
|
|
65
|
+
data = pd.DataFrame({
|
|
66
|
+
'open_price': [p * (1 + np.random.normal(0, 0.01)) for p in prices],
|
|
67
|
+
'high_price': [p * (1 + abs(np.random.normal(0, 0.015))) for p in prices],
|
|
68
|
+
'low_price': [p * (1 - abs(np.random.normal(0, 0.015))) for p in prices],
|
|
69
|
+
'close_price': prices,
|
|
70
|
+
'volume': np.random.uniform(1000, 10000, n_samples),
|
|
71
|
+
'quote_volume': [p * v for p, v in zip(prices, np.random.uniform(1000, 10000, n_samples))],
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
# 确保high >= close >= low, high >= open >= low
|
|
75
|
+
for i in range(len(data)):
|
|
76
|
+
high = max(data.iloc[i]['open_price'], data.iloc[i]['close_price'])
|
|
77
|
+
low = min(data.iloc[i]['open_price'], data.iloc[i]['close_price'])
|
|
78
|
+
data.iloc[i, data.columns.get_loc('high_price')] = max(high, data.iloc[i]['high_price'])
|
|
79
|
+
data.iloc[i, data.columns.get_loc('low_price')] = min(low, data.iloc[i]['low_price'])
|
|
80
|
+
|
|
81
|
+
return data
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_single_alpha(alpha_num: int, alpha_func, test_data: pd.DataFrame) -> Tuple[bool, str, float]:
|
|
85
|
+
"""
|
|
86
|
+
测试单个alpha因子
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
alpha_num: alpha编号
|
|
90
|
+
alpha_func: alpha因子函数
|
|
91
|
+
test_data: 测试数据
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
(是否成功, 错误信息或成功信息, 因子值)
|
|
95
|
+
"""
|
|
96
|
+
try:
|
|
97
|
+
# 测试不同长度的数据切片
|
|
98
|
+
test_sizes = [10, 20, 50, len(test_data)]
|
|
99
|
+
|
|
100
|
+
for size in test_sizes:
|
|
101
|
+
if size > len(test_data):
|
|
102
|
+
continue
|
|
103
|
+
|
|
104
|
+
data_slice = test_data.iloc[:size]
|
|
105
|
+
result = alpha_func(data_slice)
|
|
106
|
+
|
|
107
|
+
# 检查结果类型
|
|
108
|
+
if not isinstance(result, (int, float, np.number)):
|
|
109
|
+
return False, f"返回类型错误: {type(result)}, 期望 float", 0.0
|
|
110
|
+
|
|
111
|
+
# 检查是否为NaN或无穷大
|
|
112
|
+
if pd.isna(result) or np.isinf(result):
|
|
113
|
+
return False, f"返回值为NaN或无穷大: {result}", 0.0
|
|
114
|
+
|
|
115
|
+
# 如果所有测试都通过,返回成功
|
|
116
|
+
final_result = alpha_func(test_data)
|
|
117
|
+
return True, "测试通过", float(final_result)
|
|
118
|
+
|
|
119
|
+
except Exception as e:
|
|
120
|
+
error_msg = f"错误: {str(e)}"
|
|
121
|
+
return False, error_msg, 0.0
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def test_all_alphas_with_test_data():
|
|
125
|
+
"""
|
|
126
|
+
使用模拟测试数据测试所有alpha因子
|
|
127
|
+
"""
|
|
128
|
+
print("=" * 80)
|
|
129
|
+
print("测试所有101个Alpha因子(使用模拟数据)")
|
|
130
|
+
print("=" * 80)
|
|
131
|
+
print(f"测试时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|
132
|
+
print()
|
|
133
|
+
|
|
134
|
+
# 创建测试数据
|
|
135
|
+
print("创建测试数据...")
|
|
136
|
+
test_data = create_test_data(n_samples=200)
|
|
137
|
+
print(f" 测试数据样本数: {len(test_data)}")
|
|
138
|
+
print(f" 数据列: {list(test_data.columns)}")
|
|
139
|
+
print()
|
|
140
|
+
|
|
141
|
+
# 测试结果统计
|
|
142
|
+
results: Dict[int, Tuple[bool, str, float]] = {}
|
|
143
|
+
success_count = 0
|
|
144
|
+
fail_count = 0
|
|
145
|
+
|
|
146
|
+
# 测试每个alpha因子
|
|
147
|
+
print("开始测试alpha因子...")
|
|
148
|
+
print("-" * 80)
|
|
149
|
+
|
|
150
|
+
for alpha_num in sorted(ALPHA_FACTORS.keys()):
|
|
151
|
+
alpha_func = ALPHA_FACTORS[alpha_num]
|
|
152
|
+
success, message, value = test_single_alpha(alpha_num, alpha_func, test_data)
|
|
153
|
+
results[alpha_num] = (success, message, value)
|
|
154
|
+
|
|
155
|
+
if success:
|
|
156
|
+
success_count += 1
|
|
157
|
+
status = "✓"
|
|
158
|
+
else:
|
|
159
|
+
fail_count += 1
|
|
160
|
+
status = "✗"
|
|
161
|
+
|
|
162
|
+
# 打印结果
|
|
163
|
+
print(f"{status} Alpha#{alpha_num:3d}: {message[:50]}")
|
|
164
|
+
if not success:
|
|
165
|
+
print(f" 详情: {message}")
|
|
166
|
+
|
|
167
|
+
print("-" * 80)
|
|
168
|
+
print()
|
|
169
|
+
|
|
170
|
+
# 打印统计结果
|
|
171
|
+
print("=" * 80)
|
|
172
|
+
print("测试结果统计")
|
|
173
|
+
print("=" * 80)
|
|
174
|
+
print(f"总alpha数量: {len(ALPHA_FACTORS)}")
|
|
175
|
+
print(f"测试成功: {success_count}")
|
|
176
|
+
print(f"测试失败: {fail_count}")
|
|
177
|
+
print(f"成功率: {success_count / len(ALPHA_FACTORS) * 100:.2f}%")
|
|
178
|
+
print()
|
|
179
|
+
|
|
180
|
+
# 打印失败的alpha列表
|
|
181
|
+
if fail_count > 0:
|
|
182
|
+
print("失败的Alpha因子:")
|
|
183
|
+
for alpha_num, (success, message, _) in results.items():
|
|
184
|
+
if not success:
|
|
185
|
+
print(f" Alpha#{alpha_num}: {message}")
|
|
186
|
+
print()
|
|
187
|
+
|
|
188
|
+
return results
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def test_all_alphas_with_real_data(data_path: str = None):
|
|
192
|
+
"""
|
|
193
|
+
使用真实数据测试所有alpha因子
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
data_path: 数据文件路径,如果为None则使用默认路径
|
|
197
|
+
"""
|
|
198
|
+
print("=" * 80)
|
|
199
|
+
print("测试所有101个Alpha因子(使用真实数据)")
|
|
200
|
+
print("=" * 80)
|
|
201
|
+
print(f"测试时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|
202
|
+
print()
|
|
203
|
+
|
|
204
|
+
# 确定数据文件路径
|
|
205
|
+
if data_path is None:
|
|
206
|
+
data_path = "/Users/user/Desktop/repo/data_all/tmp/data/BTCUSDT_current/BTCUSDT_3m_32160_20251002_000000_20251208_000000_20251211_111242.json"
|
|
207
|
+
|
|
208
|
+
# 检查文件是否存在
|
|
209
|
+
if not os.path.exists(data_path):
|
|
210
|
+
print(f"错误:数据文件不存在: {data_path}")
|
|
211
|
+
print("请提供正确的数据文件路径")
|
|
212
|
+
return None
|
|
213
|
+
|
|
214
|
+
print(f"加载数据文件: {data_path}")
|
|
215
|
+
|
|
216
|
+
try:
|
|
217
|
+
# 加载数据
|
|
218
|
+
framework = BacktestFramework(data_path=data_path)
|
|
219
|
+
data = framework.data
|
|
220
|
+
|
|
221
|
+
print(f" 数据样本数: {len(data)}")
|
|
222
|
+
print(f" 数据列: {list(data.columns)}")
|
|
223
|
+
print()
|
|
224
|
+
|
|
225
|
+
# 确保数据包含必要的列
|
|
226
|
+
required_columns = ['open_price', 'high_price', 'low_price', 'close_price', 'volume']
|
|
227
|
+
missing_columns = [col for col in required_columns if col not in data.columns]
|
|
228
|
+
|
|
229
|
+
if missing_columns:
|
|
230
|
+
print(f"错误:数据缺少必要的列: {missing_columns}")
|
|
231
|
+
return None
|
|
232
|
+
|
|
233
|
+
# 如果没有quote_volume,使用volume * close_price估算
|
|
234
|
+
if 'quote_volume' not in data.columns:
|
|
235
|
+
data['quote_volume'] = data['volume'] * data['close_price']
|
|
236
|
+
print(" 注意:使用 volume * close_price 估算 quote_volume")
|
|
237
|
+
print()
|
|
238
|
+
|
|
239
|
+
except Exception as e:
|
|
240
|
+
print(f"错误:加载数据失败: {e}")
|
|
241
|
+
traceback.print_exc()
|
|
242
|
+
return None
|
|
243
|
+
|
|
244
|
+
# 测试结果统计
|
|
245
|
+
results: Dict[int, Tuple[bool, str, float]] = {}
|
|
246
|
+
success_count = 0
|
|
247
|
+
fail_count = 0
|
|
248
|
+
|
|
249
|
+
# 测试每个alpha因子
|
|
250
|
+
print("开始测试alpha因子...")
|
|
251
|
+
print("-" * 80)
|
|
252
|
+
|
|
253
|
+
# 使用数据的前1000行进行测试(如果数据足够长)
|
|
254
|
+
test_size = min(1000, len(data))
|
|
255
|
+
test_data = data.iloc[:test_size]
|
|
256
|
+
|
|
257
|
+
for alpha_num in sorted(ALPHA_FACTORS.keys()):
|
|
258
|
+
alpha_func = ALPHA_FACTORS[alpha_num]
|
|
259
|
+
|
|
260
|
+
try:
|
|
261
|
+
# 测试不同长度的数据切片
|
|
262
|
+
test_sizes = [50, 100, 200, test_size]
|
|
263
|
+
all_success = True
|
|
264
|
+
error_msg = ""
|
|
265
|
+
|
|
266
|
+
for size in test_sizes:
|
|
267
|
+
if size > len(test_data):
|
|
268
|
+
continue
|
|
269
|
+
|
|
270
|
+
try:
|
|
271
|
+
data_slice = test_data.iloc[:size]
|
|
272
|
+
result = alpha_func(data_slice)
|
|
273
|
+
|
|
274
|
+
# 检查结果类型
|
|
275
|
+
if not isinstance(result, (int, float, np.number)):
|
|
276
|
+
all_success = False
|
|
277
|
+
error_msg = f"返回类型错误: {type(result)}"
|
|
278
|
+
break
|
|
279
|
+
|
|
280
|
+
# 检查是否为NaN或无穷大
|
|
281
|
+
if pd.isna(result) or np.isinf(result):
|
|
282
|
+
# 对于某些alpha,NaN可能是正常的(数据不足),不算错误
|
|
283
|
+
pass
|
|
284
|
+
|
|
285
|
+
except Exception as e:
|
|
286
|
+
all_success = False
|
|
287
|
+
error_msg = f"计算错误 (size={size}): {str(e)}"
|
|
288
|
+
break
|
|
289
|
+
|
|
290
|
+
if all_success:
|
|
291
|
+
# 最终测试
|
|
292
|
+
final_result = alpha_func(test_data)
|
|
293
|
+
if pd.isna(final_result) or np.isinf(final_result):
|
|
294
|
+
results[alpha_num] = (True, "测试通过(返回NaN/Inf,可能是数据不足)", float(final_result) if not pd.isna(final_result) else 0.0)
|
|
295
|
+
else:
|
|
296
|
+
results[alpha_num] = (True, "测试通过", float(final_result))
|
|
297
|
+
success_count += 1
|
|
298
|
+
status = "✓"
|
|
299
|
+
else:
|
|
300
|
+
results[alpha_num] = (False, error_msg, 0.0)
|
|
301
|
+
fail_count += 1
|
|
302
|
+
status = "✗"
|
|
303
|
+
|
|
304
|
+
except Exception as e:
|
|
305
|
+
error_msg = f"异常: {str(e)}"
|
|
306
|
+
results[alpha_num] = (False, error_msg, 0.0)
|
|
307
|
+
fail_count += 1
|
|
308
|
+
status = "✗"
|
|
309
|
+
|
|
310
|
+
# 打印结果(每10个alpha打印一次详细进度)
|
|
311
|
+
if alpha_num % 10 == 0 or not results[alpha_num][0]:
|
|
312
|
+
print(f"{status} Alpha#{alpha_num:3d}: {results[alpha_num][1][:60]}")
|
|
313
|
+
|
|
314
|
+
print("-" * 80)
|
|
315
|
+
print()
|
|
316
|
+
|
|
317
|
+
# 打印统计结果
|
|
318
|
+
print("=" * 80)
|
|
319
|
+
print("测试结果统计")
|
|
320
|
+
print("=" * 80)
|
|
321
|
+
print(f"总alpha数量: {len(ALPHA_FACTORS)}")
|
|
322
|
+
print(f"测试成功: {success_count}")
|
|
323
|
+
print(f"测试失败: {fail_count}")
|
|
324
|
+
print(f"成功率: {success_count / len(ALPHA_FACTORS) * 100:.2f}%")
|
|
325
|
+
print()
|
|
326
|
+
|
|
327
|
+
# 打印失败的alpha列表
|
|
328
|
+
if fail_count > 0:
|
|
329
|
+
print("失败的Alpha因子:")
|
|
330
|
+
for alpha_num, (success, message, _) in results.items():
|
|
331
|
+
if not success:
|
|
332
|
+
print(f" Alpha#{alpha_num}: {message}")
|
|
333
|
+
print()
|
|
334
|
+
|
|
335
|
+
return results
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def test_alpha_with_backtest_framework(alpha_num: int, data_path: str = None):
|
|
339
|
+
"""
|
|
340
|
+
使用BacktestFramework测试单个alpha因子
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
alpha_num: alpha编号
|
|
344
|
+
data_path: 数据文件路径
|
|
345
|
+
"""
|
|
346
|
+
if data_path is None:
|
|
347
|
+
data_path = "/Users/user/Desktop/repo/data_all/tmp/data/BTCUSDT_current/BTCUSDT_3m_32160_20251002_000000_20251208_000000_20251211_111242.json"
|
|
348
|
+
|
|
349
|
+
if not os.path.exists(data_path):
|
|
350
|
+
print(f"错误:数据文件不存在: {data_path}")
|
|
351
|
+
return
|
|
352
|
+
|
|
353
|
+
print(f"测试 Alpha#{alpha_num} 因子(使用BacktestFramework)")
|
|
354
|
+
print("-" * 80)
|
|
355
|
+
|
|
356
|
+
try:
|
|
357
|
+
framework = BacktestFramework(data_path=data_path)
|
|
358
|
+
alpha_func = ALPHA_FACTORS[alpha_num]
|
|
359
|
+
|
|
360
|
+
# 创建包装函数
|
|
361
|
+
def alpha_wrapper(data_slice):
|
|
362
|
+
return alpha_func(data_slice)
|
|
363
|
+
|
|
364
|
+
# 测试因子
|
|
365
|
+
factor_results = framework.test_factor(
|
|
366
|
+
factor_func=alpha_wrapper,
|
|
367
|
+
forward_periods=7,
|
|
368
|
+
min_periods=50,
|
|
369
|
+
factor_name=f"Alpha#{alpha_num}因子"
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
# 打印简要结果
|
|
373
|
+
print(f" 总样本数: {factor_results['total_samples']}")
|
|
374
|
+
print(f" 看多信号数: {factor_results['long_signals']}")
|
|
375
|
+
print(f" 看空信号数: {factor_results['short_signals']}")
|
|
376
|
+
print(f" 看多胜率: {factor_results['long_win_rate']:.2%}")
|
|
377
|
+
print(f" 看空胜率: {factor_results['short_win_rate']:.2%}")
|
|
378
|
+
print(f" 总体胜率: {factor_results['overall_win_rate']:.2%}")
|
|
379
|
+
print(" 测试成功!")
|
|
380
|
+
|
|
381
|
+
except Exception as e:
|
|
382
|
+
print(f" 测试失败: {e}")
|
|
383
|
+
traceback.print_exc()
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def main():
|
|
387
|
+
"""
|
|
388
|
+
主函数:运行所有测试
|
|
389
|
+
"""
|
|
390
|
+
print("\n" + "=" * 80)
|
|
391
|
+
print("Alpha因子测试脚本")
|
|
392
|
+
print("=" * 80)
|
|
393
|
+
print()
|
|
394
|
+
|
|
395
|
+
# 测试1: 使用模拟数据测试所有alpha
|
|
396
|
+
print("【测试1】使用模拟数据测试所有alpha因子")
|
|
397
|
+
print()
|
|
398
|
+
test_all_alphas_with_test_data()
|
|
399
|
+
print("\n")
|
|
400
|
+
|
|
401
|
+
# 测试2: 使用真实数据测试所有alpha
|
|
402
|
+
print("【测试2】使用真实数据测试所有alpha因子")
|
|
403
|
+
print()
|
|
404
|
+
data_path = "/Users/user/Desktop/repo/data_all/tmp/data/BTCUSDT_current/BTCUSDT_3m_32160_20251002_000000_20251208_000000_20251211_111242.json"
|
|
405
|
+
|
|
406
|
+
if os.path.exists(data_path):
|
|
407
|
+
test_all_alphas_with_real_data(data_path)
|
|
408
|
+
else:
|
|
409
|
+
print(f"警告:真实数据文件不存在: {data_path}")
|
|
410
|
+
print("跳过真实数据测试")
|
|
411
|
+
print("\n")
|
|
412
|
+
|
|
413
|
+
# 测试3: 使用BacktestFramework测试几个示例alpha(可选)
|
|
414
|
+
print("【测试3】使用BacktestFramework测试示例alpha因子(Alpha#1, Alpha#101)")
|
|
415
|
+
print()
|
|
416
|
+
if os.path.exists(data_path):
|
|
417
|
+
test_alpha_with_backtest_framework(1, data_path)
|
|
418
|
+
print()
|
|
419
|
+
test_alpha_with_backtest_framework(101, data_path)
|
|
420
|
+
else:
|
|
421
|
+
print("跳过BacktestFramework测试(数据文件不存在)")
|
|
422
|
+
|
|
423
|
+
print("\n" + "=" * 80)
|
|
424
|
+
print("所有测试完成!")
|
|
425
|
+
print("=" * 80)
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
if __name__ == "__main__":
|
|
429
|
+
main()
|
|
430
|
+
|