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,133 @@
|
|
|
1
|
+
"""
|
|
2
|
+
生成所有101个Alpha因子文件的脚本
|
|
3
|
+
|
|
4
|
+
这个脚本读取alpha_cal_reference.py并生成适配crypto数据格式的alpha因子文件。
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import re
|
|
8
|
+
import os
|
|
9
|
+
|
|
10
|
+
# Alpha因子定义(从reference文件中提取)
|
|
11
|
+
ALPHA_DEFINITIONS = {
|
|
12
|
+
1: ("rank(Ts_ArgMax(SignedPower(((returns < 0) ? stddev(returns, 20) : close), 2.), 5)) -0.5",
|
|
13
|
+
"rank(Ts_ArgMax(SignedPower(((returns<0)?stddev(returns,20):close),2.),5))-0.5)"),
|
|
14
|
+
2: ("-1 * correlation(rank(delta(log(volume), 2)), rank(((close - open) / open)), 6)",
|
|
15
|
+
"-1 * correlation(rank(delta(log(volume), 2)), rank(((close - open) / open)), 6)"),
|
|
16
|
+
3: ("-1 * correlation(rank(open), rank(volume), 10)",
|
|
17
|
+
"-1 * correlation(rank(open), rank(volume), 10)"),
|
|
18
|
+
4: ("-1 * Ts_Rank(rank(low), 9)",
|
|
19
|
+
"-1 * ts_rank(rank(low), 9)"),
|
|
20
|
+
5: ("(rank((open - (sum(vwap, 10) / 10))) * (-1 * abs(rank((close - vwap)))))",
|
|
21
|
+
"(rank((open - (ts_sum(vwap, 10) / 10))) * (-1 * abs(rank((close - vwap)))))"),
|
|
22
|
+
6: ("-1 * correlation(open, volume, 10)",
|
|
23
|
+
"-1 * correlation(open, volume, 10)"),
|
|
24
|
+
7: ("((adv20 < volume) ? ((-1 * ts_rank(abs(delta(close, 7)), 60)) * sign(delta(close, 7))) : (-1* 1))",
|
|
25
|
+
"((adv20 < volume) ? ((-1 * ts_rank(abs(delta(close, 7)), 60)) * sign(delta(close, 7))) : (-1* 1))"),
|
|
26
|
+
8: ("-1 * rank(((sum(open, 5) * sum(returns, 5)) - delay((sum(open, 5) * sum(returns, 5)),10))))",
|
|
27
|
+
"-1 * rank(((ts_sum(open, 5) * ts_sum(returns, 5)) - delay((ts_sum(open, 5) * ts_sum(returns, 5)),10))))"),
|
|
28
|
+
9: ("((0 < ts_min(delta(close, 1), 5)) ? delta(close, 1) : ((ts_max(delta(close, 1), 5) < 0) ?delta(close, 1) : (-1 * delta(close, 1))))",
|
|
29
|
+
"((0 < ts_min(delta(close, 1), 5)) ? delta(close, 1) : ((ts_max(delta(close, 1), 5) < 0) ?delta(close, 1) : (-1 * delta(close, 1))))"),
|
|
30
|
+
10: ("rank(((0 < ts_min(delta(close, 1), 4)) ? delta(close, 1) : ((ts_max(delta(close, 1), 4) < 0)? delta(close, 1) : (-1 * delta(close, 1)))))",
|
|
31
|
+
"rank(((0 < ts_min(delta(close, 1), 4)) ? delta(close, 1) : ((ts_max(delta(close, 1), 4) < 0)? delta(close, 1) : (-1 * delta(close, 1)))))"),
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
def generate_alpha_file(alpha_num, formula, description=""):
|
|
35
|
+
"""生成单个alpha文件"""
|
|
36
|
+
|
|
37
|
+
template = f'''"""
|
|
38
|
+
Alpha#{alpha_num} 因子
|
|
39
|
+
|
|
40
|
+
公式: {formula}
|
|
41
|
+
|
|
42
|
+
说明:
|
|
43
|
+
{description}
|
|
44
|
+
|
|
45
|
+
标签:待补充
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
import pandas as pd
|
|
49
|
+
import numpy as np
|
|
50
|
+
from typing import Optional
|
|
51
|
+
from .alpha_utils import (
|
|
52
|
+
ts_sum, sma, stddev, correlation, covariance,
|
|
53
|
+
ts_rank, product, ts_min, ts_max, delta, delay,
|
|
54
|
+
rank, scale, ts_argmax, ts_argmin, decay_linear,
|
|
55
|
+
sign, abs, log, signed_power
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def alpha{alpha_num}_factor(
|
|
60
|
+
data_slice: pd.DataFrame,
|
|
61
|
+
**kwargs
|
|
62
|
+
) -> float:
|
|
63
|
+
"""
|
|
64
|
+
Alpha#{alpha_num} 因子计算
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
data_slice: 数据切片,必须包含以下列:
|
|
68
|
+
- open_price: 开盘价
|
|
69
|
+
- high_price: 最高价
|
|
70
|
+
- low_price: 最低价
|
|
71
|
+
- close_price: 收盘价
|
|
72
|
+
- volume: 成交量
|
|
73
|
+
- quote_volume: 成交额(用于计算vwap)
|
|
74
|
+
**kwargs: 其他可选参数
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
因子值(最后一个时间点的值)
|
|
78
|
+
"""
|
|
79
|
+
try:
|
|
80
|
+
if len(data_slice) < 2:
|
|
81
|
+
return 0.0
|
|
82
|
+
|
|
83
|
+
# 提取数据列
|
|
84
|
+
open_price = data_slice['open_price']
|
|
85
|
+
high_price = data_slice['high_price']
|
|
86
|
+
low_price = data_slice['low_price']
|
|
87
|
+
close_price = data_slice['close_price']
|
|
88
|
+
volume = data_slice['volume']
|
|
89
|
+
quote_volume = data_slice.get('quote_volume', volume * close_price) # 如果没有quote_volume,使用volume*close_price估算
|
|
90
|
+
|
|
91
|
+
# 计算收益率
|
|
92
|
+
returns = close_price.pct_change().fillna(0)
|
|
93
|
+
|
|
94
|
+
# 计算VWAP (Volume Weighted Average Price)
|
|
95
|
+
# vwap = quote_volume / volume,如果volume为0则使用close_price
|
|
96
|
+
vwap = (quote_volume / (volume + 1e-10)).fillna(close_price)
|
|
97
|
+
|
|
98
|
+
# 计算adv20 (20日平均成交量)
|
|
99
|
+
adv20 = sma(volume, 20)
|
|
100
|
+
|
|
101
|
+
# 实现Alpha因子逻辑
|
|
102
|
+
# TODO: 根据具体公式实现
|
|
103
|
+
|
|
104
|
+
# 临时返回0,需要根据具体公式实现
|
|
105
|
+
return 0.0
|
|
106
|
+
|
|
107
|
+
except Exception as e:
|
|
108
|
+
# 如果计算出错,返回0
|
|
109
|
+
return 0.0
|
|
110
|
+
'''
|
|
111
|
+
|
|
112
|
+
return template
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
if __name__ == "__main__":
|
|
116
|
+
# 生成所有alpha文件
|
|
117
|
+
base_dir = os.path.dirname(os.path.abspath(__file__))
|
|
118
|
+
|
|
119
|
+
for alpha_num in range(1, 102):
|
|
120
|
+
if alpha_num in ALPHA_DEFINITIONS:
|
|
121
|
+
formula, _ = ALPHA_DEFINITIONS[alpha_num]
|
|
122
|
+
else:
|
|
123
|
+
formula = f"Alpha#{alpha_num} formula"
|
|
124
|
+
|
|
125
|
+
content = generate_alpha_file(alpha_num, formula)
|
|
126
|
+
|
|
127
|
+
file_path = os.path.join(base_dir, f"alpha{alpha_num}.py")
|
|
128
|
+
with open(file_path, 'w', encoding='utf-8') as f:
|
|
129
|
+
f.write(content)
|
|
130
|
+
|
|
131
|
+
print(f"Generated alpha{alpha_num}.py")
|
|
132
|
+
|
|
133
|
+
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Alpha因子测试脚本
|
|
3
|
+
|
|
4
|
+
测试 selected_alpha 模块中的 Alpha 因子
|
|
5
|
+
|
|
6
|
+
这个文件是 test_script/test_alpha.py 的快捷方式,可以直接在 selected_alpha 目录下运行测试。
|
|
7
|
+
|
|
8
|
+
使用方法:
|
|
9
|
+
# 方式1: 作为模块运行(推荐)
|
|
10
|
+
cd /Users/user/Desktop/repo/cyqnt_trd
|
|
11
|
+
python -m cyqnt_trd.trading_signal.selected_alpha.test_alpha
|
|
12
|
+
|
|
13
|
+
# 方式2: 直接运行脚本
|
|
14
|
+
cd /Users/user/Desktop/repo/cyqnt_trd
|
|
15
|
+
python cyqnt_trd/trading_signal/selected_alpha/test_alpha.py
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import sys
|
|
19
|
+
import os
|
|
20
|
+
|
|
21
|
+
# 添加项目根目录到路径,以便导入模块
|
|
22
|
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
23
|
+
# 获取项目根目录(cyqnt_trd 的父目录)
|
|
24
|
+
# test_alpha.py 位于: cyqnt_trd/cyqnt_trd/trading_signal/selected_alpha/test_alpha.py
|
|
25
|
+
# 需要向上4级到达: cyqnt_trd/
|
|
26
|
+
project_root = os.path.dirname(os.path.dirname(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.backtesting import BacktestFramework
|
|
33
|
+
from cyqnt_trd.trading_signal.selected_alpha import alpha1_factor
|
|
34
|
+
from cyqnt_trd.trading_signal.signal import factor_based_signal
|
|
35
|
+
except ImportError as e:
|
|
36
|
+
print(f"导入错误: {e}")
|
|
37
|
+
print(f"\n当前工作目录: {os.getcwd()}")
|
|
38
|
+
print(f"当前文件路径: {os.path.abspath(__file__)}")
|
|
39
|
+
print(f"项目根目录: {project_root}")
|
|
40
|
+
print(f"Python路径: {sys.path[:3]}")
|
|
41
|
+
print("\n提示:请使用以下方式运行:")
|
|
42
|
+
print(" cd /Users/user/Desktop/repo/cyqnt_trd")
|
|
43
|
+
print(" python -m cyqnt_trd.trading_signal.selected_alpha.test_alpha")
|
|
44
|
+
print("\n或者直接运行脚本:")
|
|
45
|
+
print(" cd /Users/user/Desktop/repo/cyqnt_trd")
|
|
46
|
+
print(" python cyqnt_trd/trading_signal/selected_alpha/test_alpha.py")
|
|
47
|
+
sys.exit(1)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_alpha1_factor():
|
|
51
|
+
"""
|
|
52
|
+
测试 Alpha#1 因子
|
|
53
|
+
|
|
54
|
+
测试因子在预测未来价格方向上的胜率
|
|
55
|
+
"""
|
|
56
|
+
print("=" * 60)
|
|
57
|
+
print("测试 Alpha#1 因子")
|
|
58
|
+
print("=" * 60)
|
|
59
|
+
print("\n因子说明:")
|
|
60
|
+
print(" - 公式: rank(Ts_ArgMax(SignedPower(((returns<0)?stddev(returns,20):close),2.),5))-0.5)")
|
|
61
|
+
print(" - 策略逻辑:对过去5天按照收盘价最高或下行波动率最高进行排名")
|
|
62
|
+
print(" - 下行波动率最高的一天离计算时间越近,越可以投资")
|
|
63
|
+
print(" - 收盘价最高离计算时间越近,越可以投资")
|
|
64
|
+
print(" - 标签:mean-reversion+momentum")
|
|
65
|
+
print()
|
|
66
|
+
|
|
67
|
+
# 加载数据
|
|
68
|
+
# 可以使用不同的数据文件进行测试
|
|
69
|
+
data_path = '/Users/user/Desktop/repo/cyqnt_trd/tmp/data/BTCUSDT_futures/BTCUSDT_3m_158879_20250101_000000_20251127_235959_20251128_145101.json'
|
|
70
|
+
|
|
71
|
+
# 如果数据文件不存在,尝试其他路径
|
|
72
|
+
if not os.path.exists(data_path):
|
|
73
|
+
# 尝试查找其他可用的数据文件
|
|
74
|
+
data_dir = '/Users/user/Desktop/repo/cyqnt_trd/tmp/data'
|
|
75
|
+
if os.path.exists(data_dir):
|
|
76
|
+
# 查找第一个可用的JSON文件
|
|
77
|
+
for root, dirs, files in os.walk(data_dir):
|
|
78
|
+
for file in files:
|
|
79
|
+
if file.endswith('.json'):
|
|
80
|
+
data_path = os.path.join(root, file)
|
|
81
|
+
print(f"使用数据文件: {data_path}")
|
|
82
|
+
break
|
|
83
|
+
if data_path and os.path.exists(data_path):
|
|
84
|
+
break
|
|
85
|
+
|
|
86
|
+
if not os.path.exists(data_path):
|
|
87
|
+
print(f"错误:找不到数据文件: {data_path}")
|
|
88
|
+
print("请确保数据文件存在,或修改 data_path 变量指向正确的数据文件")
|
|
89
|
+
return
|
|
90
|
+
|
|
91
|
+
framework = BacktestFramework(data_path=data_path)
|
|
92
|
+
|
|
93
|
+
# 创建因子包装函数
|
|
94
|
+
def alpha1_wrapper(data_slice):
|
|
95
|
+
"""
|
|
96
|
+
Alpha#1 因子包装函数
|
|
97
|
+
|
|
98
|
+
使用默认参数:lookback_days=5, stddev_period=20, power=2.0
|
|
99
|
+
"""
|
|
100
|
+
return alpha1_factor(
|
|
101
|
+
data_slice,
|
|
102
|
+
lookback_days=5,
|
|
103
|
+
stddev_period=20,
|
|
104
|
+
power=2.0
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# 测试因子
|
|
108
|
+
print("开始测试 Alpha#1 因子...")
|
|
109
|
+
print(f" 回看天数: 5")
|
|
110
|
+
print(f" 标准差周期: 20")
|
|
111
|
+
print(f" 幂次: 2.0")
|
|
112
|
+
print(f" 向前看周期: 7")
|
|
113
|
+
print()
|
|
114
|
+
|
|
115
|
+
factor_results = framework.test_factor(
|
|
116
|
+
factor_func=alpha1_wrapper,
|
|
117
|
+
forward_periods=7, # 未来7个周期
|
|
118
|
+
min_periods=30, # 至少需要30个周期(5+20+一些缓冲)
|
|
119
|
+
factor_name="Alpha#1因子"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# 打印结果并保存
|
|
123
|
+
save_dir = '/Users/user/Desktop/repo/cyqnt_trd/result'
|
|
124
|
+
framework.print_factor_results(
|
|
125
|
+
factor_results,
|
|
126
|
+
save_dir=save_dir
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def test_alpha1_with_different_params():
|
|
131
|
+
"""
|
|
132
|
+
测试 Alpha#1 因子的不同参数组合
|
|
133
|
+
"""
|
|
134
|
+
print("\n" + "=" * 60)
|
|
135
|
+
print("测试 Alpha#1 因子的不同参数组合")
|
|
136
|
+
print("=" * 60)
|
|
137
|
+
|
|
138
|
+
# 加载数据
|
|
139
|
+
data_path = '/Users/user/Desktop/repo/cyqnt_trd/tmp/data/BTCUSDT_futures/BTCUSDT_1d_1095_20251127_113603.json'
|
|
140
|
+
|
|
141
|
+
if not os.path.exists(data_path):
|
|
142
|
+
print(f"错误:找不到数据文件: {data_path}")
|
|
143
|
+
return
|
|
144
|
+
|
|
145
|
+
framework = BacktestFramework(data_path=data_path)
|
|
146
|
+
|
|
147
|
+
# 测试不同的参数组合
|
|
148
|
+
param_combinations = [
|
|
149
|
+
{"lookback_days": 3, "stddev_period": 10, "power": 2.0, "name": "Alpha#1 (lookback=3, stddev=10)"},
|
|
150
|
+
{"lookback_days": 5, "stddev_period": 20, "power": 2.0, "name": "Alpha#1 (lookback=5, stddev=20)"},
|
|
151
|
+
{"lookback_days": 7, "stddev_period": 30, "power": 2.0, "name": "Alpha#1 (lookback=7, stddev=30)"},
|
|
152
|
+
]
|
|
153
|
+
|
|
154
|
+
for params in param_combinations:
|
|
155
|
+
print(f"\n测试参数组合: {params['name']}")
|
|
156
|
+
print(f" lookback_days={params['lookback_days']}, stddev_period={params['stddev_period']}, power={params['power']}")
|
|
157
|
+
|
|
158
|
+
def alpha1_wrapper(data_slice):
|
|
159
|
+
return alpha1_factor(
|
|
160
|
+
data_slice,
|
|
161
|
+
lookback_days=params['lookback_days'],
|
|
162
|
+
stddev_period=params['stddev_period'],
|
|
163
|
+
power=params['power']
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
min_periods = params['lookback_days'] + params['stddev_period'] + 5
|
|
167
|
+
|
|
168
|
+
factor_results = framework.test_factor(
|
|
169
|
+
factor_func=alpha1_wrapper,
|
|
170
|
+
forward_periods=7,
|
|
171
|
+
min_periods=min_periods,
|
|
172
|
+
factor_name=params['name']
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
# 只打印简要结果
|
|
176
|
+
print(f" 总样本数: {factor_results['total_samples']}")
|
|
177
|
+
print(f" 看多信号数: {factor_results['long_signals']}")
|
|
178
|
+
print(f" 看空信号数: {factor_results['short_signals']}")
|
|
179
|
+
print(f" 看多胜率: {factor_results['long_win_rate']:.2%}")
|
|
180
|
+
print(f" 看空胜率: {factor_results['short_win_rate']:.2%}")
|
|
181
|
+
print(f" 总体胜率: {factor_results['overall_win_rate']:.2%}")
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def test_alpha1_in_signal():
|
|
185
|
+
"""
|
|
186
|
+
测试在信号策略中使用 Alpha#1 因子
|
|
187
|
+
"""
|
|
188
|
+
print("\n" + "=" * 60)
|
|
189
|
+
print("测试在信号策略中使用 Alpha#1 因子")
|
|
190
|
+
print("=" * 60)
|
|
191
|
+
|
|
192
|
+
# 加载数据
|
|
193
|
+
data_path = '/Users/user/Desktop/repo/cyqnt_trd/tmp/data/BTCUSDT_futures/BTCUSDT_1d_1095_20251127_113603.json'
|
|
194
|
+
|
|
195
|
+
if not os.path.exists(data_path):
|
|
196
|
+
print(f"错误:找不到数据文件: {data_path}")
|
|
197
|
+
return
|
|
198
|
+
|
|
199
|
+
framework = BacktestFramework(data_path=data_path)
|
|
200
|
+
|
|
201
|
+
# 创建使用 Alpha#1 因子的信号策略
|
|
202
|
+
def alpha1_signal_wrapper(data_slice, position, entry_price, entry_index, take_profit, stop_loss, check_periods):
|
|
203
|
+
"""
|
|
204
|
+
使用 Alpha#1 因子的信号策略
|
|
205
|
+
"""
|
|
206
|
+
# 使用 Alpha#1 因子
|
|
207
|
+
factor_func = lambda d: alpha1_factor(d, lookback_days=5, stddev_period=20, power=2.0)
|
|
208
|
+
return factor_based_signal(
|
|
209
|
+
data_slice, position, entry_price, entry_index,
|
|
210
|
+
take_profit, stop_loss, check_periods,
|
|
211
|
+
factor_func=factor_func
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
# 回测策略
|
|
215
|
+
print("开始回测基于 Alpha#1 因子的策略...")
|
|
216
|
+
backtest_results = framework.backtest_strategy(
|
|
217
|
+
signal_func=alpha1_signal_wrapper,
|
|
218
|
+
min_periods=30, # 至少需要30个周期
|
|
219
|
+
position_size=0.2, # 每次使用20%的资金
|
|
220
|
+
initial_capital=10000.0,
|
|
221
|
+
commission_rate=0.00001, # 0.001%手续费
|
|
222
|
+
take_profit=0.1, # 止盈10%
|
|
223
|
+
stop_loss=0.5, # 止损50%
|
|
224
|
+
check_periods=1, # 只能为1,因为实际使用时无法看到未来数据
|
|
225
|
+
strategy_name="基于Alpha#1因子的策略"
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
# 打印结果
|
|
229
|
+
framework.print_backtest_results(backtest_results)
|
|
230
|
+
|
|
231
|
+
# 绘制结果并保存
|
|
232
|
+
save_dir = '/Users/user/Desktop/repo/cyqnt_trd/result'
|
|
233
|
+
framework.plot_backtest_results(
|
|
234
|
+
backtest_results,
|
|
235
|
+
save_dir=save_dir
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def main():
|
|
240
|
+
"""
|
|
241
|
+
主函数:运行所有测试
|
|
242
|
+
"""
|
|
243
|
+
# 测试 Alpha#1 因子
|
|
244
|
+
# test_alpha1_factor()
|
|
245
|
+
|
|
246
|
+
# 测试不同参数组合(可选,取消注释以运行)
|
|
247
|
+
# test_alpha1_with_different_params()
|
|
248
|
+
|
|
249
|
+
# 测试在信号策略中使用 Alpha#1 因子(可选,取消注释以运行)
|
|
250
|
+
test_alpha1_in_signal()
|
|
251
|
+
|
|
252
|
+
print("\n" + "=" * 60)
|
|
253
|
+
print("测试完成!")
|
|
254
|
+
print("=" * 60)
|
|
255
|
+
print("\n提示:")
|
|
256
|
+
print(" - 取消注释 main() 函数中的其他测试函数来运行更多测试")
|
|
257
|
+
print(" - 推荐使用模块方式运行: python3 -m cyqnt_trd.trading_signal.selected_alpha.test_alpha")
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
if __name__ == "__main__":
|
|
261
|
+
main()
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""
|
|
2
|
+
交易信号策略模块
|
|
3
|
+
|
|
4
|
+
定义各种交易信号策略,可以组合使用factor中的因子
|
|
5
|
+
信号函数签名: signal_func(data, index, position, entry_price, entry_index, take_profit, stop_loss, check_periods) -> str
|
|
6
|
+
- 返回: 'buy'(买入), 'sell'(卖出), 'hold'(持有)
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# 导入所有信号策略
|
|
10
|
+
from .ma_signal import ma_signal, ma_cross_signal
|
|
11
|
+
from .factor_based_signal import factor_based_signal, multi_factor_signal, normalized_factor_signal
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
'ma_signal',
|
|
15
|
+
'ma_cross_signal',
|
|
16
|
+
'factor_based_signal',
|
|
17
|
+
'multi_factor_signal',
|
|
18
|
+
'normalized_factor_signal',
|
|
19
|
+
]
|
|
20
|
+
|