Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
435039a
fix: 修复 SQLite 写入时 pd.Timestamp 绑定错误
jaden1q84 Apr 4, 2026
4ac78d3
feat: 日线数据引入前复权逻辑
jaden1q84 Apr 4, 2026
3978818
fix: 修复科创板股票未纳入全量同步的问题
jaden1q84 Apr 4, 2026
6ecbbd0
fix: 消除科创板读取时 pytdx 打印的 Unknown security type 噪音
jaden1q84 Apr 4, 2026
3a75fc9
feat: 复权类型改为可选参数,默认前复权,修复全量日线复权缺陷
jaden1q84 Apr 4, 2026
993dcfd
增加gitignore
jaden1q84 Apr 4, 2026
59a6da3
更新CLAUDE.md
jaden1q84 Apr 4, 2026
16112d8
feat: 简化重构为日线专用包(simple-daily)
jaden1q84 Apr 4, 2026
e7c42b3
更新gitignore
jaden1q84 Apr 4, 2026
6d41b32
feat: 合并 simple-daily — 简化重构为日线专用包
jaden1q84 Apr 4, 2026
60f788c
refactor: --code 参数改为纯6位代码,自动识别市场
jaden1q84 Apr 5, 2026
859e5df
refactor: 对齐 daily_data 表字段与外部 kline 表结构
jaden1q84 Apr 5, 2026
93d6095
feat: 支持北交所(bj)日线数据同步
jaden1q84 Apr 5, 2026
b8e05b7
feat: 新增联网下载 TDX 日线数据导入数据库功能
jaden1q84 Apr 7, 2026
a236be2
feat: stock_code 添加市场后缀(.SZ/.SH/.BJ)
jaden1q84 Apr 7, 2026
f5122d0
feat: stock_info 表结构改造,使用 akshare 获取股票中文名
jaden1q84 Apr 7, 2026
9ca5ac4
feat: 新增 kline_statistics 表记录每次同步统计信息
jaden1q84 Apr 7, 2026
e5f4118
fix: 深圳 A 股筛选规则新增 301 开头(创业板注册制)
jaden1q84 Apr 8, 2026
772ffc7
feat: sync 命令自动同步股票列表名称
jaden1q84 Apr 8, 2026
1dd6a77
feat: 新增 SMB 网络访问模式,支持跨机器读取远程 TDX 数据
jaden1q84 Apr 11, 2026
37337ca
feat: SMB 模式改为批量并发下载,大幅提升同步性能
jaden1q84 Apr 12, 2026
2b26f50
feat: 计算并写入日线换手率(turnover_rate)
jaden1q84 Apr 12, 2026
2d4dd8b
fix: 修复换手率计算及相关问题
jaden1q84 Apr 12, 2026
7bad70e
feat: 调整 volume/amount 入库单位(手→股,元→万元)
jaden1q84 Apr 12, 2026
a021e8f
fix: read_daily_data_batch 补充 volume/amount 单位转换
jaden1q84 Apr 12, 2026
15981c4
feat: 用 TDX .tnf 文件替换 akshare 获取股票名称
jaden1q84 Apr 12, 2026
086fb6a
docs: 更新 README,补充测试版本、盘后数据下载步骤及完整表结构说明
jaden1q84 Apr 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,18 @@ LOG_LEVEL=INFO

# 处理选项
USE_TQDM=True # 是否显示进度条

# SMB 网络访问配置(可选,用于访问远程 PC 上的 TDX 安装目录)
# 启用后 TDX_PATH 可不填
SMB_ENABLED=false
SMB_HOST=192.168.1.100
SMB_SHARE=tdx_share
SMB_USER=myuser
SMB_PASSWORD=mypassword
# TDX 在共享目录内的相对路径,若共享根目录即为 TDX 安装目录则留空
SMB_TDX_PATH=TDX
SMB_PORT=445
# 并发下载线程数(批量 SMB 模式)
SMB_WORKERS=16
# 每批同步的股票数量
SMB_BATCH_SIZE=200
20 changes: 5 additions & 15 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: Python package

on:
Expand All @@ -11,30 +8,23 @@ on:

jobs:
build:

runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11"]
python-version: ["3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
pip install pytest
pip install -r requirements.txt
- name: Test with pytest
run: |
pytest
pytest tests/ -v
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,5 @@ poetry.lock
output/

*/__pycache__/
tdx_data.db*
.claude/
79 changes: 53 additions & 26 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,29 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## 项目概述

tdx2db:从本地通达信(TDX)行情软件读取 A 股数据,增量同步到数据库。是量化分析工作站的数据入口
tdx2db:从本地通达信(TDX)行情软件读取 A 股日线数据,增量同步到数据库。支持作为 Python 包被其他项目调用

## 常用命令

```bash
# 安装依赖
pip install -r requirements.txt
# 或安装为可编辑包(支持 import)
pip install -e .

# 一键增量同步(日线 + 5/15/30/60 分钟线)— 日常使用这一个命令即可
# 一键增量同步日线数据 — 日常使用这一个命令
python main.py sync

# 单独同步
python main.py daily --db-only --auto-start --incremental
python main.py minutes --db-only --auto-start --incremental
python main.py daily --incremental
python main.py daily --code 000001 --start 20240101

# 同步股票列表
python main.py stock-list --db-only
```
python main.py stock-list

无测试套件。验证方式是运行 `sync` 命令后检查数据库数据。
# 运行测试
python -m pytest tests/ -v
```

## 架构

Expand All @@ -32,39 +35,63 @@ python main.py stock-list --db-only
```
CLI (cli.py) → Reader (reader.py) → Processor (processor.py) → Storage (storage.py)
↓ ↓ ↓ ↓
argparse pytdx 读取本地 校验 + 重采样 + 均线 SQLAlchemy 批量写库
命令分发 + .day/.lc5 文件 (OHLCV 校验, resample, 支持增量 ON CONFLICT
同步编排 MA5~MA250) 表名白名单保护
argparse pytdx 读取本地 校验 + 复权处理 SQLAlchemy 批量写库
命令分发 + .day 文件 (OHLCV 校验, 前/后复权) 支持增量 ON CONFLICT
同步编排 表名白名单保护
```

- **cli.py**: 除命令分发外,`sync_all_daily_data` / `sync_all_min_data` / `sync_single_stock_min_data` 编排逐股票流式同步
- **config.py**: 全局单例 `config`,从 `.env` 加载配置(TDX_PATH、DB_*)
- **cli.py**: 命令分发 + `sync_all_daily()` 逐股票流式同步
- **config.py**: 全局单例 `config`,从 `.env` 加载配置
- **logger.py**: 全局单例 `logger`
- **`__init__.py`**: 暴露 `TdxDailySync` 公共 API

### 关键数据流
## 关键数据流

日线和分钟线均为**逐股票流式处理**,不全量加载到内存:
逐股票流式处理,不全量加载到内存:

1. **日线**: 逐股票读取 `vipdoc/{sz,sh}/lday/*.day` → `process_daily_data()` 校验 OHLCV + 计算均线 → 增量写入 `daily_data` 表
2. **分钟线**: 逐股票读取 `.lc5`(5 分钟)→ `resample_ohlcv()` 重采样为 15/30/60 分钟 → `process_min_data()` 校验 + 均线 → 分别写入 `minute{5,15,30,60}_data` 表
3. **增量同步**: `save_incremental()` 使用批量 executemany + `ON CONFLICT DO NOTHING`(PostgreSQL)/ `INSERT IGNORE`(MySQL)跳过重复。分钟线按股票精确查询最新日期(`get_latest_datetime_by_code`),日线逐股票增量。
1. 读取 `vipdoc/{sz,sh,bj}/lday/*.day` → `process_daily_data()` 校验 OHLCV + 复权
2. 增量策略:`get_all_latest_dates()` 一次查询所有股票最新日期;若有除权事件则 `delete_stock_data()` + 全量重写
3. `save_incremental()` 使用 `ON CONFLICT DO NOTHING`(PG)/ `INSERT OR IGNORE`(SQLite)/ `INSERT IGNORE`(MySQL)

### 数据库表
## 数据库表

| 表名 | 唯一约束 | 用途 |
|------|----------|------|
| `daily_data` | (code, date) | 日线数据 |
| `minute{5,15,30,60}_data` | (code, datetime) | 分钟线数据 |
| `daily_data` | (code, date) | 日线数据,date 为 YYYYMMDD 整数 |
| `stock_info` | code | 股票列表 |
| `block_stock_relation` | — | 板块关系(未完整实现) |

唯一约束需通过 `scripts/add_constraints.sql` 手动添加
唯一约束由 SQLAlchemy `UniqueConstraint` 在建表时自动创建,无需手动执行 SQL 脚本

### 股票代码格式
## 股票代码格式

代码带市场前缀:`sz000001`、`sh600000`。深圳 market=0,上海 market=1。
A 股筛选规则:深圳 `000/001/002/300` 开头,上海 `60/688` 开头。
- CLI `--code` 参数:纯 6 位数字,如 `000001`、`600000`、`920001`,市场自动识别
- 内部流转层:带市场前缀,如 `sz000001`、`sh600000`、`bj920001`(reader 内部使用)
- 数据库层:纯 6 位数字,如 `000001`(reader 写入时截取)
- 深圳 market=0,上海 market=1,北京 market=2
- A 股筛选:深圳 `000/001/002/300` 开头,上海 `60/688` 开头,北交所 `8xxxxx` 或 `92xxxx` 开头
- 市场自动识别规则:6 开头 → 上海(sh),8 或 92 开头 → 北京(bj),其他 → 深圳(sz)

## 配置

通过 `.env` 文件配置,必填:`TDX_PATH`、`DB_TYPE`、`DB_HOST`、`DB_NAME`、`DB_USER`、`DB_PASSWORD`。
通过 `.env` 文件配置:

| 变量 | 必填 | 说明 |
|------|------|------|
| `TDX_PATH` | 是 | 通达信安装目录 |
| `DB_TYPE` | 否 | `sqlite`(默认)/ `mysql` / `postgresql` |
| `DB_NAME` | 否 | 数据库名,SQLite 时为文件名(生成 `<name>.db`) |
| `DB_HOST` | MySQL/PG 必填 | 数据库主机 |
| `DB_USER` | MySQL/PG 必填 | 数据库用户名 |
| `DB_PASSWORD` | MySQL/PG 必填 | 数据库密码 |
| `DB_PORT` | 否 | 默认 `5432` |
| `DB_BATCH_SIZE` | 否 | 批量写入大小,默认 `10000` |
| `USE_TQDM` | 否 | 是否显示进度条,默认 `True` |

## sync 命令增量策略

`python main.py sync` 内部行为:

- 一次 SQL 查询获取所有股票最新日期(`SELECT code, MAX(date) FROM daily_data GROUP BY code`)
- 对每只股票:检查 gbbq 中是否有除权事件(category=1)发生在 last_date 之后
- 有除权 → 删除该股旧数据,全量重写(保证复权价格正确)
- 无除权 → 只写入 last_date 之后的新数据
Loading