mirror of
https://ghfast.top/https://github.com/aeroxw/easy-tdx.git
synced 2026-09-12 14:34:15 +08:00
- Add MacClient/AsyncMacClient with full MAC protocol support (quotes, kline with adjustment, tick charts, transactions, boards, capital flow, auction, unusual, symbol info, server info) - Add MacExClient/AsyncMacExClient for extended markets (HK, US, futures) - Add UnifiedTdxClient auto-routing between A-share and extended markets - Add `easy-tdx` CLI tool with JSON default output, Agent-friendly - Add field bitmap protocol for custom quote field selection - Fix quote-list missing fields (default to BASIC+VOLUME preset) - Add config.py with centralized host management and auto-discovery - Add 50+ examples covering all APIs (01-20) - Rewrite README with CLI-first, Agent-friendly documentation - Bump version to 1.1.0 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
140 lines
5.4 KiB
Python
140 lines
5.4 KiB
Python
"""演示:板块数据读取(本地 .dat 文件 + 网络自动回退)。
|
||
|
||
系统板块获取优先级:
|
||
1. 本地 .dat 文件(离线读取,速度快)
|
||
2. TDX 服务器在线获取(自动回退,需要网络)
|
||
|
||
自定义板块仅支持本地读取(存储在通达信本地目录中)。
|
||
|
||
TdxBlock dataclass 字段(系统板块):
|
||
name str 板块名称(如"房地产")
|
||
category int 板块分类(0=行业, 1=地域, 2=概念, 3=风格)
|
||
count int 板块包含的股票数量
|
||
codes list 股票代码列表(6位数字字符串,如"600000")
|
||
|
||
CustomerBlock dataclass 字段(自定义板块):
|
||
blockname str 板块名称(用户自定义,如"我的自选")
|
||
block_type str 板块类型标识(对应 .blk 文件名)
|
||
codes list 股票代码列表(6位数字字符串)
|
||
|
||
板块文件位置:
|
||
系统板块: vipdoc/block_zs.dat(行业)、vipdoc/block_gn.dat(概念)、vipdoc/block_fg.dat(风格)
|
||
自定义板块: TDX_HOME/T0002/blocknew/blocknew.cfg + *.blk
|
||
|
||
自定义板块目录结构:
|
||
blocknew/
|
||
├── blocknew.cfg 板块索引(120 字节/条:50B 名称 + 70B 文件名)
|
||
├── TDXBlock0.blk 板块内容文件(每行一个代码,首位为市场标识)
|
||
├── TDXBlock1.blk
|
||
└── ...
|
||
"""
|
||
|
||
from pathlib import Path
|
||
|
||
from easy_tdx import TdxClient
|
||
from easy_tdx.models.finance import TdxBlock
|
||
from easy_tdx.offline import detect_tdx_home, read_block_dat, read_customer_blocks
|
||
|
||
|
||
def _print_blocks(blocks: list[TdxBlock], title: str) -> None:
|
||
print(f"\n{title} ({len(blocks)} 个板块):")
|
||
for block in blocks[:5]:
|
||
codes_preview = ", ".join(block.codes[:5])
|
||
suffix = "..." if len(block.codes) > 5 else ""
|
||
print(f" {block.name} ({block.count}只): {codes_preview}{suffix}")
|
||
if len(blocks) > 5:
|
||
print(f" ... 还有 {len(blocks) - 5} 个板块")
|
||
|
||
|
||
home = detect_tdx_home()
|
||
|
||
# --- 系统板块 ---
|
||
print("=" * 60)
|
||
print("系统板块")
|
||
print("=" * 60)
|
||
|
||
vipdoc = Path(home) / "vipdoc" if home else None
|
||
block_names = ["block_zs.dat", "block_gn.dat", "block_fg.dat"]
|
||
block_labels = {
|
||
"block_zs.dat": "行业板块",
|
||
"block_gn.dat": "概念板块",
|
||
"block_fg.dat": "风格板块",
|
||
}
|
||
|
||
need_fetch = []
|
||
for name in block_names:
|
||
local_path = vipdoc / name if vipdoc else None
|
||
if local_path and local_path.is_file():
|
||
blocks = read_block_dat(local_path)
|
||
_print_blocks(blocks, f"{block_labels[name]} ({name}, 本地)")
|
||
else:
|
||
print(f"\n{block_labels[name]}: 本地文件不存在,将从服务器获取")
|
||
need_fetch.append(name)
|
||
|
||
# 本地没有的板块,通过网络获取
|
||
if need_fetch:
|
||
print(f"\n正在连接服务器获取 {len(need_fetch)} 个板块文件...")
|
||
with TdxClient.from_best_host() as c:
|
||
for name in need_fetch:
|
||
df = c.get_block_info(name)
|
||
print(f"\n{block_labels[name]} ({name}, 网络) ({len(df)} 个板块):")
|
||
for _, row in df.head(5).iterrows():
|
||
codes = row["codes"]
|
||
codes_preview = ", ".join(str(c) for c in codes[:5])
|
||
suffix = "..." if len(codes) > 5 else ""
|
||
print(f" {row['name']} ({row['count']}只): {codes_preview}{suffix}")
|
||
if len(df) > 5:
|
||
print(f" ... 还有 {len(df) - 5} 个板块")
|
||
|
||
# --- 自定义板块 ---
|
||
print(f"\n{'=' * 60}")
|
||
print("自定义板块")
|
||
print("=" * 60)
|
||
|
||
if home:
|
||
blocknew_dir = Path(home) / "T0002" / "blocknew"
|
||
if blocknew_dir.is_dir():
|
||
blocks = read_customer_blocks(blocknew_dir)
|
||
if blocks:
|
||
print(f"\n共 {len(blocks)} 个自定义板块:")
|
||
for block in blocks[:10]:
|
||
codes_preview = ", ".join(block.codes[:5])
|
||
suffix = "..." if len(block.codes) > 5 else ""
|
||
print(f" {block.blockname} ({len(block.codes)}只): {codes_preview}{suffix}")
|
||
else:
|
||
print("未找到自定义板块数据")
|
||
else:
|
||
print(f"自定义板块目录不存在: {blocknew_dir}")
|
||
else:
|
||
print("需要本地通达信安装目录才能读取自定义板块")
|
||
|
||
# 运行结果:
|
||
# ============================================================
|
||
# 系统板块
|
||
# ============================================================
|
||
#
|
||
# 行业板块 (block_zs.dat, 本地) (82 个板块):
|
||
# 房地产 (78只): 000002, 000006, 000011, 000014, 000029...
|
||
# 电力行业 (62只): 000027, 000037, 000426, 000539, 000543...
|
||
# 计算机设备 (43只): 000066, 000977, 002236, 002415, 002416...
|
||
# 电子元件 (112只): 000045, 000050, 000725, 000727, 000823...
|
||
# 通信服务 (46只): 000035, 000063, 000069, 000547, 000555...
|
||
# ... 还有 77 个板块
|
||
#
|
||
# 概念板块 (block_gn.dat, 本地) (412 个板块):
|
||
# IPv6 (38只): 000063, 000938, 000948, 000977, 002089...
|
||
# AI智能体 (56只): 300033, 300052, 300418, 300454, 300496...
|
||
# BCH概念 (18只): 000063, 000938, 002123, 002152, 002177...
|
||
# C2M概念 (22只): 000725, 000823, 002095, 002131, 002154...
|
||
# IPO受益 (35只): 000031, 000063, 000415, 000532, 000540...
|
||
# ... 还有 407 个板块
|
||
#
|
||
# ============================================================
|
||
# 自定义板块
|
||
# ============================================================
|
||
#
|
||
# 共 3 个自定义板块:
|
||
# 自选股 (8只): 600000, 000001, 000002, 600036, 601318...
|
||
# 中字头 (5只): 601857, 601988, 601398, 601288, 601328
|
||
# 龙头股 (12只): 600519, 000858, 600036, 601318, 000333...
|