From ace1099ab0a290717ebbdd6b8718fc9577f8db08 Mon Sep 17 00:00:00 2001 From: Justin Gu <97915@qq.com> Date: Thu, 21 May 2026 13:02:27 +0800 Subject: [PATCH] chore: add CLAUDE.md and .claude config --- .claude/settings.json | 16 ++++++++++ .claude/settings.local.json | 14 +++++++++ .claude/skills/verify/SKILL.md | 16 ++++++++++ CLAUDE.md | 54 ++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+) create mode 100644 .claude/settings.json create mode 100644 .claude/settings.local.json create mode 100644 .claude/skills/verify/SKILL.md create mode 100644 CLAUDE.md diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..8429890 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,16 @@ +{ + "hooks": { + "PostToolUse": [ + { + "matcher": "Write|Edit", + "hooks": [ + { + "type": "command", + "command": "python scripts/ruff_hook.py", + "timeout": 30 + } + ] + } + ] + } +} diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..3651d7b --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,14 @@ +{ + "permissions": { + "allow": [ + "Skill(update-config)", + "Bash(echo '{\"tool_name\":\"Edit\",\"tool_input\":{\"file_path\":\"D:\\\\\\\\python\\\\\\\\xmtdx\\\\\\\\src\\\\\\\\xmtdx\\\\\\\\__init__.py\"}}')", + "Bash(python -c \"import sys,json,subprocess;d=json.load\\(sys.stdin\\);f=d.get\\('tool_input',{}\\).get\\('file_path',''\\);exec\\('' if not f.endswith\\(\\\\\\\\'.py\\\\\\\\'\\) else 'subprocess.run\\([\\\\\\\\'ruff\\\\\\\\',\\\\\\\\'check\\\\\\\\',\\\\\\\\'--fix\\\\\\\\',f],capture_output=True\\);subprocess.run\\([\\\\\\\\'ruff\\\\\\\\',\\\\\\\\'format\\\\\\\\',f],capture_output=True\\)'\\);print\\(f'done: {f}'\\)\")", + "Bash(python *)", + "Bash(ruff check *)", + "Bash(git add *)", + "Bash(git commit *)", + "Bash(git push *)" + ] + } +} diff --git a/.claude/skills/verify/SKILL.md b/.claude/skills/verify/SKILL.md new file mode 100644 index 0000000..c01491b --- /dev/null +++ b/.claude/skills/verify/SKILL.md @@ -0,0 +1,16 @@ +--- +name: verify +description: Run full offline verification suite (pytest unit tests + mypy + ruff) before committing changes. +disable-model-invocation: true +--- + +# Verify + +Run the full offline verification pipeline: + +1. Run `python -m pytest tests/unit/ -v` — all unit tests must pass. +2. Run `mypy src/` — strict type checking must pass with zero errors. +3. Run `ruff check src/ tests/` — no lint errors. +4. Run `ruff format --check src/ tests/` — formatting must be clean. + +If any step fails, fix the issues and re-run. Do not report completion until all four steps pass. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..0b1c1cd --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,54 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Build / Test / Lint + +```bash +# 单元测试(无需网络,使用 tests/fixtures/ 中的 hex 数据) +python -m pytest tests/unit/ -v + +# 集成测试(需要网络,默认跳过) +XMTDX_LIVE=1 python -m pytest tests/integration/ -v + +# 类型检查(strict mypy) +mypy src/ + +# lint + format +ruff check src/ tests/ +ruff format --check src/ tests/ +``` + +## 架构 + +``` +src/xmtdx/ +├── client.py # TdxClient / AsyncTdxClient(高层 API) +├── transport/ +│ ├── sync.py # TdxConnection(socket)+ ping_host / ping_all +│ └── async_.py # AsyncTdxConnection(asyncio) +├── commands/ # 每条命令:build_request() + parse_response(),无 IO +├── codec/ # price / volume / datetime / frame 编解码 +└── models/ # 纯 dataclass,无业务逻辑 +``` + +commands 层不依赖 transport,可独立单测。修改 codec 或 commands 时不需要网络。 + +## 协议编解码注意事项 + +- **价格编码**:变长有符号整数(类 LEB128),bit8=继续,bit7=符号。差分编码(相邻 tick 存 delta)。 +- **成交量编码**:4 字节自定义浮点(`_decode_volume`),字节 3=指数,字节 0-2=精度。**不可用于价格字段**。 +- **握手**:连接后必须顺序发送 3 条 setup 命令,响应丢弃。 +- **帧格式**:16 字节响应头,body 按需 zlib 解压。 +- 新增编解码逻辑时务必在 `tests/fixtures/` 中补充 hex fixture 并编写对应的离线解析测试。 + +## 已知限制 + +- `Market.BJ` 的 `get_security_list()` 不能稳定获取(服务器端问题),不要尝试依赖它。 +- `limit_up` / `limit_down` 在 `SecurityQuote` 中默认为 `None`,涨跌停价应通过 `get_price_limits()` 或 `compute_price_limits()` 计算。 + +## 代码风格 + +- ruff: line-length 100, target py310, rules: E/F/I/UP +- mypy strict mode +- 纯标准库,零运行时依赖。新增代码不要引入第三方库。