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
@@ -1,479 +0,0 @@
1
- """
2
- K线数据查询测试脚本
3
-
4
- 测试查询 Binance 现货和期货合约的K线数据
5
-
6
- 使用方法:
7
- # 方式1: 作为模块运行(推荐)
8
- cd /Users/user/Desktop/repo/cyqnt_trd
9
- python -m cyqnt_trd.test_script.test_kline_data
10
-
11
- # 方式2: 直接运行脚本
12
- cd /Users/user/Desktop/repo/cyqnt_trd
13
- python cyqnt_trd/test_script/test_kline_data.py
14
- """
15
-
16
- import os
17
- import sys
18
- import logging
19
- from datetime import datetime, timedelta
20
- from typing import Optional, Union
21
-
22
- # 添加项目根目录到路径
23
- current_dir = os.path.dirname(os.path.abspath(__file__))
24
- project_root = os.path.dirname(os.path.dirname(current_dir))
25
- if project_root not in sys.path:
26
- sys.path.insert(0, project_root)
27
-
28
- # 导入 Binance SDK
29
- try:
30
- from binance_sdk_spot.spot import Spot, ConfigurationRestAPI, SPOT_REST_API_PROD_URL
31
- from binance_sdk_spot.rest_api.models import KlinesIntervalEnum
32
- from binance_sdk_derivatives_trading_usds_futures.derivatives_trading_usds_futures import (
33
- DerivativesTradingUsdsFutures,
34
- ConfigurationRestAPI as FuturesConfigurationRestAPI,
35
- DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL,
36
- )
37
- from binance_sdk_derivatives_trading_usds_futures.rest_api.models import (
38
- KlineCandlestickDataIntervalEnum,
39
- )
40
- except ImportError as e:
41
- print(f"导入错误: {e}")
42
- print("\n提示:请确保已安装 binance-connector-python")
43
- sys.exit(1)
44
-
45
- # Configure logging
46
- logging.basicConfig(
47
- level=logging.INFO,
48
- format='%(asctime)s - %(levelname)s - %(message)s'
49
- )
50
-
51
-
52
- def _convert_to_timestamp_ms(time_input: Union[datetime, str, int, None]) -> Optional[int]:
53
- """
54
- 将各种时间格式转换为毫秒时间戳
55
-
56
- Args:
57
- time_input: 时间输入,可以是:
58
- - datetime 对象
59
- - 字符串格式的时间,例如 '2023-01-01 00:00:00' 或 '2023-01-01'
60
- - 整数时间戳(秒或毫秒,自动判断)
61
- - None
62
-
63
- Returns:
64
- 毫秒时间戳,如果输入为 None 则返回 None
65
- """
66
- if time_input is None:
67
- return None
68
-
69
- if isinstance(time_input, datetime):
70
- return int(time_input.timestamp() * 1000)
71
-
72
- if isinstance(time_input, str):
73
- try:
74
- for fmt in ['%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M', '%Y-%m-%d', '%Y/%m/%d %H:%M:%S', '%Y/%m/%d']:
75
- try:
76
- dt = datetime.strptime(time_input, fmt)
77
- return int(dt.timestamp() * 1000)
78
- except ValueError:
79
- continue
80
- raise ValueError(f"无法解析时间字符串: {time_input}")
81
- except Exception as e:
82
- logging.error(f"时间字符串解析失败: {e}")
83
- raise
84
-
85
- if isinstance(time_input, int):
86
- if time_input > 1e10:
87
- return time_input
88
- else:
89
- return time_input * 1000
90
-
91
- raise TypeError(f"不支持的时间类型: {type(time_input)}")
92
-
93
-
94
- def query_spot_klines(
95
- symbol: str,
96
- interval: str = "1h",
97
- limit: int = 100,
98
- start_time: Optional[Union[datetime, str, int]] = None,
99
- end_time: Optional[Union[datetime, str, int]] = None,
100
- ) -> Optional[list]:
101
- """
102
- 查询现货K线数据
103
-
104
- Args:
105
- symbol: 交易对符号,例如 'BTCUSDT', 'ETHUSDT'
106
- interval: 时间间隔,例如 '1d', '1h', '1m'
107
- 可选值: 1s, 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M
108
- limit: 返回的数据条数,默认100,最大1000
109
- start_time: 开始时间,可以是 datetime、字符串或时间戳
110
- end_time: 结束时间,可以是 datetime、字符串或时间戳
111
-
112
- Returns:
113
- 返回查询到的K线数据列表,如果出错返回 None
114
- """
115
- try:
116
- # 创建现货客户端配置
117
- spot_config = ConfigurationRestAPI(
118
- api_key=os.getenv("API_KEY", ""),
119
- api_secret=os.getenv("API_SECRET", ""),
120
- base_path=os.getenv("BASE_PATH", SPOT_REST_API_PROD_URL),
121
- )
122
-
123
- # 初始化现货客户端
124
- spot_client = Spot(config_rest_api=spot_config)
125
-
126
- # 将字符串间隔转换为枚举值
127
- interval_map = {
128
- "1s": KlinesIntervalEnum.INTERVAL_1s,
129
- "1m": KlinesIntervalEnum.INTERVAL_1m,
130
- "3m": KlinesIntervalEnum.INTERVAL_3m,
131
- "5m": KlinesIntervalEnum.INTERVAL_5m,
132
- "15m": KlinesIntervalEnum.INTERVAL_15m,
133
- "30m": KlinesIntervalEnum.INTERVAL_30m,
134
- "1h": KlinesIntervalEnum.INTERVAL_1h,
135
- "2h": KlinesIntervalEnum.INTERVAL_2h,
136
- "4h": KlinesIntervalEnum.INTERVAL_4h,
137
- "6h": KlinesIntervalEnum.INTERVAL_6h,
138
- "8h": KlinesIntervalEnum.INTERVAL_8h,
139
- "12h": KlinesIntervalEnum.INTERVAL_12h,
140
- "1d": KlinesIntervalEnum.INTERVAL_1d,
141
- "3d": KlinesIntervalEnum.INTERVAL_3d,
142
- "1w": KlinesIntervalEnum.INTERVAL_1w,
143
- "1M": KlinesIntervalEnum.INTERVAL_1M,
144
- }
145
-
146
- if interval not in interval_map:
147
- logging.error(f"不支持的间隔: {interval}")
148
- return None
149
-
150
- interval_enum = interval_map[interval]
151
-
152
- # 转换时间参数为毫秒时间戳
153
- start_time_ms = _convert_to_timestamp_ms(start_time) if start_time is not None else None
154
- end_time_ms = _convert_to_timestamp_ms(end_time) if end_time is not None else None
155
-
156
- # 构建查询日志信息
157
- time_info = []
158
- if start_time_ms:
159
- start_str = datetime.fromtimestamp(start_time_ms / 1000).strftime('%Y-%m-%d %H:%M:%S')
160
- time_info.append(f"开始时间: {start_str}")
161
- if end_time_ms:
162
- end_str = datetime.fromtimestamp(end_time_ms / 1000).strftime('%Y-%m-%d %H:%M:%S')
163
- time_info.append(f"结束时间: {end_str}")
164
- time_info_str = ", ".join(time_info) if time_info else "最近数据"
165
-
166
- logging.info(f"正在查询现货 {symbol} 的K线数据,间隔: {interval}, 数量: {limit}, {time_info_str}")
167
-
168
- # 查询K线数据
169
- response = spot_client.rest_api.klines(
170
- symbol=symbol,
171
- interval=interval_enum,
172
- start_time=start_time_ms,
173
- end_time=end_time_ms,
174
- limit=limit
175
- )
176
-
177
- # 获取数据
178
- klines_data = response.data()
179
-
180
- if not klines_data:
181
- logging.warning("未获取到数据")
182
- return None
183
-
184
- logging.info(f"成功获取 {len(klines_data)} 条数据")
185
- return klines_data
186
-
187
- except Exception as e:
188
- logging.error(f"查询现货K线数据时出错: {e}")
189
- import traceback
190
- logging.error(traceback.format_exc())
191
- return None
192
-
193
-
194
- def query_futures_klines(
195
- symbol: str,
196
- interval: str = "1h",
197
- limit: int = 100,
198
- start_time: Optional[Union[datetime, str, int]] = None,
199
- end_time: Optional[Union[datetime, str, int]] = None,
200
- ) -> Optional[list]:
201
- """
202
- 查询期货合约K线数据
203
-
204
- Args:
205
- symbol: 交易对符号,例如 'BTCUSDT', 'ETHUSDT'
206
- interval: 时间间隔,例如 '1d', '1h', '1m'
207
- 可选值: 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M
208
- limit: 返回的数据条数,默认100,最大1000
209
- start_time: 开始时间,可以是 datetime、字符串或时间戳
210
- end_time: 结束时间,可以是 datetime、字符串或时间戳
211
-
212
- Returns:
213
- 返回查询到的K线数据列表,如果出错返回 None
214
- """
215
- try:
216
- # 创建合约客户端配置
217
- futures_config = FuturesConfigurationRestAPI(
218
- api_key=os.getenv("API_KEY", ""),
219
- api_secret=os.getenv("API_SECRET", ""),
220
- base_path=os.getenv(
221
- "BASE_PATH", DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL
222
- ),
223
- )
224
-
225
- # 初始化合约客户端
226
- futures_client = DerivativesTradingUsdsFutures(config_rest_api=futures_config)
227
-
228
- # 将字符串间隔转换为枚举值
229
- interval_map = {
230
- "1m": KlineCandlestickDataIntervalEnum.INTERVAL_1m,
231
- "3m": KlineCandlestickDataIntervalEnum.INTERVAL_3m,
232
- "5m": KlineCandlestickDataIntervalEnum.INTERVAL_5m,
233
- "15m": KlineCandlestickDataIntervalEnum.INTERVAL_15m,
234
- "30m": KlineCandlestickDataIntervalEnum.INTERVAL_30m,
235
- "1h": KlineCandlestickDataIntervalEnum.INTERVAL_1h,
236
- "2h": KlineCandlestickDataIntervalEnum.INTERVAL_2h,
237
- "4h": KlineCandlestickDataIntervalEnum.INTERVAL_4h,
238
- "6h": KlineCandlestickDataIntervalEnum.INTERVAL_6h,
239
- "8h": KlineCandlestickDataIntervalEnum.INTERVAL_8h,
240
- "12h": KlineCandlestickDataIntervalEnum.INTERVAL_12h,
241
- "1d": KlineCandlestickDataIntervalEnum.INTERVAL_1d,
242
- "3d": KlineCandlestickDataIntervalEnum.INTERVAL_3d,
243
- "1w": KlineCandlestickDataIntervalEnum.INTERVAL_1w,
244
- "1M": KlineCandlestickDataIntervalEnum.INTERVAL_1M,
245
- }
246
-
247
- if interval not in interval_map:
248
- logging.error(f"不支持的间隔: {interval}")
249
- return None
250
-
251
- interval_enum = interval_map[interval]
252
-
253
- # 转换时间参数为毫秒时间戳
254
- start_time_ms = _convert_to_timestamp_ms(start_time) if start_time is not None else None
255
- end_time_ms = _convert_to_timestamp_ms(end_time) if end_time is not None else None
256
-
257
- # 构建查询日志信息
258
- time_info = []
259
- if start_time_ms:
260
- start_str = datetime.fromtimestamp(start_time_ms / 1000).strftime('%Y-%m-%d %H:%M:%S')
261
- time_info.append(f"开始时间: {start_str}")
262
- if end_time_ms:
263
- end_str = datetime.fromtimestamp(end_time_ms / 1000).strftime('%Y-%m-%d %H:%M:%S')
264
- time_info.append(f"结束时间: {end_str}")
265
- time_info_str = ", ".join(time_info) if time_info else "最近数据"
266
-
267
- logging.info(f"正在查询期货 {symbol} 的K线数据,间隔: {interval}, 数量: {limit}, {time_info_str}")
268
-
269
- # 查询K线数据
270
- response = futures_client.rest_api.kline_candlestick_data(
271
- symbol=symbol,
272
- interval=interval_enum,
273
- start_time=start_time_ms,
274
- end_time=end_time_ms,
275
- limit=limit
276
- )
277
-
278
- # 获取数据
279
- klines_data = response.data()
280
-
281
- if not klines_data:
282
- logging.warning("未获取到数据")
283
- return None
284
-
285
- logging.info(f"成功获取 {len(klines_data)} 条数据")
286
- return klines_data
287
-
288
- except Exception as e:
289
- logging.error(f"查询期货K线数据时出错: {e}")
290
- import traceback
291
- logging.error(traceback.format_exc())
292
- return None
293
-
294
-
295
- def print_klines_summary(klines_data: list, symbol: str, market_type: str = "现货"):
296
- """
297
- 打印K线数据摘要
298
-
299
- Args:
300
- klines_data: K线数据列表
301
- symbol: 交易对符号
302
- market_type: 市场类型(现货/期货)
303
- """
304
- if not klines_data:
305
- print("无数据可显示")
306
- return
307
-
308
- print(f"\n{'='*80}")
309
- print(f"{market_type} {symbol} K线数据摘要")
310
- print(f"{'='*80}")
311
- print(f"总数据条数: {len(klines_data)}")
312
-
313
- # 解析第一条和最后一条数据
314
- first_kline = klines_data[0]
315
- last_kline = klines_data[-1]
316
-
317
- # K线数据格式: [开盘时间, 开盘价, 最高价, 最低价, 收盘价, 成交量, 收盘时间, 成交额, 成交笔数, ...]
318
- first_open_time = int(first_kline[0]) if isinstance(first_kline[0], str) else first_kline[0]
319
- first_close_time = int(first_kline[6]) if isinstance(first_kline[6], str) else first_kline[6]
320
- last_open_time = int(last_kline[0]) if isinstance(last_kline[0], str) else last_kline[0]
321
- last_close_time = int(last_kline[6]) if isinstance(last_kline[6], str) else last_kline[6]
322
-
323
- print(f"时间范围: {datetime.fromtimestamp(first_open_time / 1000).strftime('%Y-%m-%d %H:%M:%S')} "
324
- f"至 {datetime.fromtimestamp(last_close_time / 1000).strftime('%Y-%m-%d %H:%M:%S')}")
325
-
326
- # 显示前3条和后3条数据
327
- print(f"\n前3条数据:")
328
- print(f"{'时间':<20} {'开盘':>12} {'最高':>12} {'最低':>12} {'收盘':>12} {'成交量':>15}")
329
- print(f"{'-'*80}")
330
- for kline in klines_data[:3]:
331
- open_time = int(kline[0]) if isinstance(kline[0], str) else kline[0]
332
- time_str = datetime.fromtimestamp(open_time / 1000).strftime('%Y-%m-%d %H:%M:%S')
333
- open_price = float(kline[1])
334
- high_price = float(kline[2])
335
- low_price = float(kline[3])
336
- close_price = float(kline[4])
337
- volume = float(kline[5])
338
- print(f"{time_str:<20} {open_price:>12.2f} {high_price:>12.2f} {low_price:>12.2f} "
339
- f"{close_price:>12.2f} {volume:>15.2f}")
340
-
341
- if len(klines_data) > 6:
342
- print(f"\n... (省略 {len(klines_data) - 6} 条数据) ...\n")
343
- print(f"后3条数据:")
344
- print(f"{'时间':<20} {'开盘':>12} {'最高':>12} {'最低':>12} {'收盘':>12} {'成交量':>15}")
345
- print(f"{'-'*80}")
346
- for kline in klines_data[-3:]:
347
- open_time = int(kline[0]) if isinstance(kline[0], str) else kline[0]
348
- time_str = datetime.fromtimestamp(open_time / 1000).strftime('%Y-%m-%d %H:%M:%S')
349
- open_price = float(kline[1])
350
- high_price = float(kline[2])
351
- low_price = float(kline[3])
352
- close_price = float(kline[4])
353
- volume = float(kline[5])
354
- print(f"{time_str:<20} {open_price:>12.2f} {high_price:>12.2f} {low_price:>12.2f} "
355
- f"{close_price:>12.2f} {volume:>15.2f}")
356
- elif len(klines_data) > 3:
357
- print(f"\n后3条数据:")
358
- print(f"{'时间':<20} {'开盘':>12} {'最高':>12} {'最低':>12} {'收盘':>12} {'成交量':>15}")
359
- print(f"{'-'*80}")
360
- for kline in klines_data[3:]:
361
- open_time = int(kline[0]) if isinstance(kline[0], str) else kline[0]
362
- time_str = datetime.fromtimestamp(open_time / 1000).strftime('%Y-%m-%d %H:%M:%S')
363
- open_price = float(kline[1])
364
- high_price = float(kline[2])
365
- low_price = float(kline[3])
366
- close_price = float(kline[4])
367
- volume = float(kline[5])
368
- print(f"{time_str:<20} {open_price:>12.2f} {high_price:>12.2f} {low_price:>12.2f} "
369
- f"{close_price:>12.2f} {volume:>15.2f}")
370
-
371
- print(f"{'='*80}\n")
372
-
373
-
374
- def test_spot_klines():
375
- """测试查询现货K线数据"""
376
- print("\n" + "="*80)
377
- print("测试1: 查询现货K线数据")
378
- print("="*80)
379
-
380
- # 示例1: 查询最近的数据
381
- print("\n示例1: 查询 BTCUSDT 最近100条1小时K线数据")
382
- klines = query_spot_klines(
383
- symbol="BTCUSDT",
384
- interval="1h",
385
- limit=100
386
- )
387
- if klines:
388
- print_klines_summary(klines, "BTCUSDT", "现货")
389
-
390
- # 示例2: 查询指定时间范围的数据
391
- print("\n示例2: 查询 ETHUSDT 最近7天的日线数据")
392
- end_time = datetime.now()
393
- start_time = end_time - timedelta(days=7)
394
- klines = query_spot_klines(
395
- symbol="ETHUSDT",
396
- interval="1d",
397
- limit=10,
398
- start_time=start_time,
399
- end_time=end_time
400
- )
401
- if klines:
402
- print_klines_summary(klines, "ETHUSDT", "现货")
403
-
404
- # 示例3: 使用字符串格式的时间
405
- print("\n示例3: 查询 SOLUSDT 指定时间范围的4小时K线数据")
406
- klines = query_spot_klines(
407
- symbol="SOLUSDT",
408
- interval="4h",
409
- limit=50,
410
- start_time="2024-01-01 00:00:00",
411
- end_time="2024-01-10 23:59:59"
412
- )
413
- if klines:
414
- print_klines_summary(klines, "SOLUSDT", "现货")
415
-
416
-
417
- def test_futures_klines():
418
- """测试查询期货K线数据"""
419
- print("\n" + "="*80)
420
- print("测试2: 查询期货合约K线数据")
421
- print("="*80)
422
-
423
- # 示例1: 查询最近的数据
424
- print("\n示例1: 查询 BTCUSDT 期货最近100条1小时K线数据")
425
- klines = query_futures_klines(
426
- symbol="BTCUSDT",
427
- interval="1h",
428
- limit=100
429
- )
430
- if klines:
431
- print_klines_summary(klines, "BTCUSDT", "期货")
432
-
433
- # 示例2: 查询指定时间范围的数据
434
- print("\n示例2: 查询 ETHUSDT 期货最近7天的日线数据")
435
- end_time = datetime.now()
436
- start_time = end_time - timedelta(days=7)
437
- klines = query_futures_klines(
438
- symbol="ETHUSDT",
439
- interval="1d",
440
- limit=10,
441
- start_time=start_time,
442
- end_time=end_time
443
- )
444
- if klines:
445
- print_klines_summary(klines, "ETHUSDT", "期货")
446
-
447
- # 示例3: 使用字符串格式的时间
448
- print("\n示例3: 查询 SOLUSDT 期货指定时间范围的4小时K线数据")
449
- klines = query_futures_klines(
450
- symbol="SOLUSDT",
451
- interval="4h",
452
- limit=50,
453
- start_time="2024-01-01 00:00:00",
454
- end_time="2024-01-10 23:59:59"
455
- )
456
- if klines:
457
- print_klines_summary(klines, "SOLUSDT", "期货")
458
-
459
-
460
- def main():
461
- """主函数"""
462
- print("\n" + "="*80)
463
- print("Binance K线数据查询测试")
464
- print("="*80)
465
-
466
- # 测试现货K线数据查询
467
- test_spot_klines()
468
-
469
- # 测试期货K线数据查询
470
- test_futures_klines()
471
-
472
- print("\n" + "="*80)
473
- print("测试完成")
474
- print("="*80)
475
-
476
-
477
- if __name__ == "__main__":
478
- main()
479
-