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.
- cyqnt_trd/CHANGELOG_0.1.7.md +111 -0
- cyqnt_trd/__init__.py +1 -1
- cyqnt_trd/backtesting/factor_test.py +3 -2
- cyqnt_trd/get_data/__init__.py +16 -1
- cyqnt_trd/get_data/get_futures_data.py +3 -3
- cyqnt_trd/get_data/get_kline_with_factor.py +808 -0
- cyqnt_trd/get_data/get_web3_trending_data.py +389 -0
- cyqnt_trd/online_trading/__init__.py +1 -0
- cyqnt_trd/online_trading/realtime_price_tracker.py +142 -2
- cyqnt_trd/trading_signal/example_usage.py +123 -7
- cyqnt_trd/trading_signal/factor/__init__.py +23 -0
- cyqnt_trd/trading_signal/factor/adx_factor.py +116 -0
- cyqnt_trd/trading_signal/factor/ao_factor.py +66 -0
- cyqnt_trd/trading_signal/factor/bbp_factor.py +68 -0
- cyqnt_trd/trading_signal/factor/cci_factor.py +65 -0
- cyqnt_trd/trading_signal/factor/ema_factor.py +102 -0
- cyqnt_trd/trading_signal/factor/macd_factor.py +97 -0
- cyqnt_trd/trading_signal/factor/momentum_factor.py +44 -0
- cyqnt_trd/trading_signal/factor/stochastic_factor.py +76 -0
- cyqnt_trd/trading_signal/factor/stochastic_tsi_factor.py +129 -0
- cyqnt_trd/trading_signal/factor/uo_factor.py +92 -0
- cyqnt_trd/trading_signal/factor/williams_r_factor.py +60 -0
- cyqnt_trd/trading_signal/factor_details.json +107 -0
- cyqnt_trd/trading_signal/selected_alpha/alpha1.py +4 -2
- cyqnt_trd/trading_signal/selected_alpha/alpha15.py +4 -2
- cyqnt_trd/trading_signal/selected_alpha/generate_alphas.py +1 -0
- {cyqnt_trd-0.1.2.dist-info → cyqnt_trd-0.1.7.dist-info}/METADATA +16 -12
- {cyqnt_trd-0.1.2.dist-info → cyqnt_trd-0.1.7.dist-info}/RECORD +34 -23
- {cyqnt_trd-0.1.2.dist-info → cyqnt_trd-0.1.7.dist-info}/WHEEL +1 -1
- test/real_time_trade.py +467 -10
- test/test_now_factor.py +1082 -0
- test/track_k_line_continue.py +372 -0
- cyqnt_trd/test_script/get_symbols_by_volume.py +0 -227
- cyqnt_trd/test_script/test_alpha.py +0 -261
- cyqnt_trd/test_script/test_kline_data.py +0 -479
- test/test_example_usage.py +0 -381
- test/test_get_data.py +0 -310
- test/test_realtime_price_tracker.py +0 -546
- {cyqnt_trd-0.1.2.dist-info → cyqnt_trd-0.1.7.dist-info}/licenses/LICENSE +0 -0
- {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
|
-
|