96 lines
3.0 KiB
Python
96 lines
3.0 KiB
Python
"""下载 PVC 5分钟 K 线数据到桌面。
|
||
|
||
使用 tqsdk 拉取 PVC主连(KQ.m@DCE.v) 的 5 分钟 K 线,
|
||
保存为项目兼容的 Parquet 格式(time/open/high/low/close/tick_volume)。
|
||
"""
|
||
import json
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
# 读取 tqsdk 凭证(优先 web_settings.json,未配置则用默认账号)
|
||
settings_path = Path(__file__).parent / "web_settings.json"
|
||
try:
|
||
settings = json.loads(settings_path.read_text(encoding="utf-8"))
|
||
user = str(settings.get("tqsdk_user", "")).strip()
|
||
pwd = str(settings.get("tqsdk_password", "")).strip()
|
||
except Exception:
|
||
user, pwd = "", ""
|
||
|
||
# 内置默认账号
|
||
if not user or not pwd:
|
||
user, pwd = "七斗居士", "ghhkphs8"
|
||
|
||
print(f"tqsdk 账号: {user}")
|
||
print("正在连接天勤量化...")
|
||
|
||
from tqsdk import TqApi, TqAuth, TqSim
|
||
import pandas as pd
|
||
|
||
# PVC主连 → tqsdk 主连代码
|
||
TQSDK_SYMBOL = "KQ.m@DCE.v"
|
||
DURATION = 300 # 5分钟 = 300秒
|
||
DATA_LENGTH = 8000 # 尽量多拉
|
||
|
||
api = None
|
||
try:
|
||
api = TqApi(TqSim(), auth=TqAuth(user, pwd), disable_print=True)
|
||
print("连接成功,正在拉取 PVC 5分钟 K 线...")
|
||
|
||
# adj_type="F" 前复权,消除换月跳价
|
||
df = api.get_kline_serial(
|
||
TQSDK_SYMBOL, DURATION, data_length=DATA_LENGTH, adj_type="F"
|
||
)
|
||
print(f"拉取到 {len(df)} 根 K 线")
|
||
finally:
|
||
if api is not None:
|
||
try:
|
||
api.close()
|
||
except Exception:
|
||
pass
|
||
|
||
if df is None or df.empty:
|
||
print("ERROR: 未拉取到数据")
|
||
sys.exit(1)
|
||
|
||
# 过滤无效行(volume=0 的非交易时段,或 datetime=0)
|
||
df = df[df["datetime"] != 0].copy()
|
||
df = df[df["volume"] > 0].copy()
|
||
print(f"过滤后有效 K 线: {len(df)} 根")
|
||
|
||
# 转换为项目兼容格式
|
||
# tqsdk datetime 是纳秒级 Unix 时间戳 → 转秒
|
||
result = pd.DataFrame()
|
||
result["time"] = (df["datetime"].astype("int64") // 1_000_000_000).astype("int64")
|
||
result["open"] = df["open"].astype("float64")
|
||
result["high"] = df["high"].astype("float64")
|
||
result["low"] = df["low"].astype("float64")
|
||
result["close"] = df["close"].astype("float64")
|
||
result["tick_volume"] = df["volume"].astype("int64")
|
||
|
||
# 按时间升序排列
|
||
result = result.sort_values("time").reset_index(drop=True)
|
||
|
||
# 去除可能重复的时间戳
|
||
result = result.drop_duplicates(subset=["time"], keep="last").reset_index(drop=True)
|
||
|
||
# 输出目录
|
||
out_dir = Path(r"C:\Users\14795\Desktop\国内期货K线数据")
|
||
out_dir.mkdir(parents=True, exist_ok=True)
|
||
out_file = out_dir / "PVC_5min.parquet"
|
||
|
||
# 保存为 Parquet
|
||
result.to_parquet(out_file, index=False)
|
||
print(f"\n已保存: {out_file}")
|
||
print(f"总行数: {len(result)}")
|
||
|
||
# 显示数据概览
|
||
print(f"\n=== 数据概览 ===")
|
||
print(f"时间范围: {pd.to_datetime(result['time'].iloc[0], unit='s')} ~ {pd.to_datetime(result['time'].iloc[-1], unit='s')}")
|
||
print(f"开盘价范围: {result['open'].min():.2f} ~ {result['open'].max():.2f}")
|
||
print(f"收盘价范围: {result['close'].min():.2f} ~ {result['close'].max():.2f}")
|
||
print(f"\n前 5 行:")
|
||
print(result.head().to_string())
|
||
print(f"\n后 5 行:")
|
||
print(result.tail().to_string())
|
||
print("\n下载完成!")
|