# pyqdt

Python Quote Data Toolkit - 本地行情数据接口

## 简介

pyqdt 是一个轻量级的本地行情数据处理库，提供：

- **行情数据读取** - 从本地 CSV 文件读取 K 线、静态行情数据
- **复权处理** - 支持前复权、后复权计算
- **技术分析** - 内置常用技术指标计算
- **证券信息查询** - 证券基本信息、板块成分、交易日历等
- **代码转换** - 证券代码格式转换工具

## 安装

```bash
pip install pyqdt
```

## 快速开始

### 初始化

```python
from pyqdt import QuoteData, QuoteArchive

# 初始化行情数据（单例模式）
quote = QuoteData(data_path='/path/to/quote/data')

# 初始化静态行情数据
archive = QuoteArchive(data_path='/path/to/quote/data')
```

### 获取行情日期

```python
# 获取最新行情日
quote_date = quote.get_quote_date()

# 获取交易日列表
tdays = quote.get_trade_days(start_date='2024-01-01', end_date='2024-03-31')
tdays = quote.get_trade_days(end_date='2024-03-31', count=20)
```

### 获取 K 线数据

```python
# 获取日 K 线
df = quote.get_price('000001.XSHE', start_date='2024-01-01', end_date='2024-03-31')

# 获取多只股票
df = quote.get_price(['000001.XSHE', '600000.XSHG'], start_date='2024-01-01', end_date='2024-03-31')

# 指定字段
df = quote.get_price('000001.XSHE', fields=['open', 'close', 'high', 'low', 'volume']
                     , start_date='2024-01-01', end_date='2024-03-31')

# 使用 count 参数
df = quote.get_price('000001.XSHE', end_date='2024-03-31', count=100)

# 不同周期
df = quote.get_price('000001.XSHE', period='week', start_date='2024-01-01', end_date='2024-03-31')    # 周K
df = quote.get_price('000001.XSHE', period='month', start_date='2024-01-01', end_date='2024-03-31')   # 月K
df = quote.get_price('000001.XSHE', period='season', start_date='2023-01-01', end_date='2024-03-31')  # 季K
df = quote.get_price('000001.XSHE', period='year', start_date='2020-01-01', end_date='2024-03-31')     # 年K

# 分钟 K 线
df = quote.get_price('000001.XSHE', period='1m', start_date='2024-03-01', end_date='2024-03-31')   # 1分钟
df = quote.get_price('000001.XSHE', period='5m', start_date='2024-03-01', end_date='2024-03-31')   # 5分钟
df = quote.get_price('000001.XSHE', period='15m', start_date='2024-03-01', end_date='2024-03-31')  # 15分钟
df = quote.get_price('000001.XSHE', period='30m', start_date='2024-03-01', end_date='2024-03-31')  # 30分钟
df = quote.get_price('000001.XSHE', period='60m', start_date='2024-03-01', end_date='2024-03-31')  # 60分钟
```

### 复权处理

```python
# 前复权（默认）
df = quote.get_price('000001.XSHE', fq='pre', start_date='2024-01-01', end_date='2024-03-31')

# 后复权
df = quote.get_price('000001.XSHE', fq='post', start_date='2024-01-01', end_date='2024-03-31')

# 不复权
df = quote.get_price('000001.XSHE', fq=None, start_date='2024-01-01', end_date='2024-03-31')

# 成交量复权
df = quote.get_price('000001.XSHE', fq='pre', fq_vol=True, start_date='2024-01-01', end_date='2024-03-31')

# 指定复权参考日
df = quote.get_price('000001.XSHE', fq='2024-01-15', start_date='2024-01-01', end_date='2024-03-31')

# 手动执行复权
df_raw = quote.get_price('000001.XSHE', fq=None, start_date='2024-01-01', end_date='2024-03-31')
df_fq = quote.execute_rehabilitation(df_raw, fq='pre')
```

### 获取静态行情数据

```python
# 获取全市场日行情快照
df = quote.get_quote_static(date='2024-03-15')

# 指定字段
df = quote.get_quote_static(date='2024-03-15', fields=['open', 'close', 'high', 'low', 'volume'])

# 指定交易所
df = quote.get_quote_static(date='2024-03-15', exch=['SH'])

# 从 QuoteArchive 获取（支持分钟数据）
df = archive.get_quote_rawdata(date='2024-03-15', period='daily', types=['stock', 'etf'])
df = archive.get_quote_rawdata(date='2024-03-15', period='minute', types=['stock'])
```

### 获取证券信息

```python
# 获取证券基本信息
info = quote.get_security_info('000001.XSHE')

# 获取多只证券
info = quote.get_security_info(['000001.XSHE', '600000.XSHG'])

# 指定类型
info = quote.get_security_info(types=['stock', 'etf', 'index'])

# 指定字段
info = quote.get_security_info('000001.XSHE', fields=['display_name', 'start_date', 'type'])
```

### 获取除权除息数据

```python
# 获取除权除息信息
xrxd = quote.get_security_xrxd('000001.XSHE', start_date='2023-01-01', end_date='2024-03-31')

# 多只证券
xrxd = quote.get_security_xrxd(['000001.XSHE', '600000.XSHG']
                               , start_date='2023-01-01', end_date='2024-03-31')
```

### 获取板块信息

```python
# 获取所有行业
industries = quote.get_industries()

# 获取所有概念
concepts = quote.get_concepts()

# 获取板块成分股
stocks = quote.get_index_stocks('000300.XSHG')      # 沪深300成分股
stocks = quote.get_industry_stocks('sw801010')      # 行业成分股
stocks = quote.get_concept_stocks('gn001')          # 概念成分股

# 获取指数权重
weights = quote.get_index_weights('000300.XSHG')
```

### 技术分析

```python
# 获取技术指标
df = quote.get_technical_analysis('000001.XSHE'
                                  , indications=[('MA', 5), ('MA', 10), ('MA', 20)]
                                  , start_date='2024-01-01', end_date='2024-03-31')

# 常用指标示例
df = quote.get_technical_analysis('000001.XSHE'
                                  , indications=[
                                      ('MA', 5),           # 5日均线
                                      ('EMA', 12),         # 12日指数移动平均
                                      ('MACD', 12, 26, 9), # MACD
                                      ('KDJ', 9, 3, 3),    # KDJ
                                      ('RSI', 14),         # RSI
                                      ('BOLL', 20, 2),     # 布林带
                                  ]
                                  , start_date='2024-01-01', end_date='2024-03-31')

# 保留行情字段
df = quote.get_technical_analysis('000001.XSHE'
                                  , indications=[('MA', 5), ('MA', 10)]
                                  , start_date='2024-01-01', end_date='2024-03-31'
                                  , keep_quote=True)

# 手动执行技术分析
df = quote.get_price('000001.XSHE', start_date='2024-01-01', end_date='2024-03-31')
df = quote.execute_technical_analysis(df, indications=[('MA', 5), ('MA', 10)])
```

### 代码转换

```python
from pyqdt import JQWraps

# 转换证券代码格式
# JoinQuant 格式 '000001.XSHE' <-> 通达信格式 '000001.SZ'

# 单个代码转换
code = JQWraps.convert_code('000001.XSHE', reverse=True)  # 返回 '000001.SZ'

# 列表转换
codes = JQWraps.convert_code(['000001.XSHE', '600000.XSHG'], reverse=True)

# DataFrame 列转换
df = JQWraps.convert_code(df, reverse=True)
```

### 调试选项

```python
# 开启调试模式
quote.set_option('debug', True)

# 设置技术指标预加载数量
quote.set_option('refer_num', 200)

# 启用多进程（复权计算）
quote.set_option('multi_process', True)
quote.set_option('multi_process', 4)  # 指定进程数
```

## 技术分析指标

pyqdt 内置以下技术分析指标：

| 模块 | 指标 | 说明 |
|------|------|------|
| `moving_average` | MA, EMA, SMA | 移动平均线 |
| `moving_average` | MACD | 指数平滑异同移动平均线 |
| `over_bought_sold` | KDJ | 随机指标 |
| `over_bought_sold` | RSI | 相对强弱指标 |
| `over_bought_sold` | BOLL | 布林带 |
| `trend_lines` | - | 趋势线分析 |
| `path_lines` | - | 路径线分析 |
| `turnover` | - | 换手率分析 |
| `energy` | - | 能量指标 |

## 数据格式

### 数据目录结构

```
/data/path/
├── ckvalid.txt                    # 数据校验文件
├── quote-tdays.csv                # 交易日历
├── quote-ctb.csv                  # 证券信息
├── quote-xrxd.csv                 # 除权除息数据
├── quote-block-map.csv            # 板块映射
├── quote-block-data.csv           # 板块成分
├── day/                           # 日K线数据
│   ├── SH/
│   │   ├── SH_DAY_000001.csv
│   │   └── ...
│   └── SZ/
│       ├── SZ_DAY_000001.csv
│       └── ...
├── mn1/                           # 1分钟K线数据
│   ├── SH/
│   └── SZ/
├── static/                        # 静态行情数据
│   ├── SH/
│   │   ├── 2024/
│   │   │   ├── SH_STATIC_20240115.csv
│   │   │   └── ...
│   │   └── ...
│   └── SZ/
└── ...
```

### CSV 文件格式

#### 日 K 线数据

| 字段 | 类型 | 说明 |
|------|------|------|
| datetime | datetime | 行情日期 |
| open | float | 开盘价 |
| close | float | 收盘价 |
| high | float | 最高价 |
| low | float | 最低价 |
| volume | int | 成交量 |
| money | float | 成交额 |

#### 静态行情数据

| 字段 | 类型 | 说明 |
|------|------|------|
| time | datetime | 行情时间 |
| code | string | 证券代码 |
| open | float | 开盘价 |
| close | float | 收盘价 |
| high | float | 最高价 |
| low | float | 最低价 |
| volume | int | 成交量 |
| money | float | 成交额 |
| high_limit | float | 涨停价 |
| low_limit | float | 跌停价 |
| pre_close | float | 昨收价 |
| paused | int | 停牌标记 |

---

## API 参考

### QuoteData 类

本地行情数据类，单例模式。

#### `__init__(data_path=None)`

初始化行情数据实例。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| data_path | str | None | 数据目录路径 |

---

#### `init(data_path)`

初始化数据目录。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| data_path | str | - | 数据目录路径 |

**返回值**: 无

**异常**: 若目录不存在则抛出 `Exception`

---

#### `get_data_path()`

获取当前数据目录路径。

**返回值**: `str` - 数据目录路径

---

#### `get_quote_date()`

获取最新行情日期。

**返回值**: `datetime.date` - 最新行情日期

---

#### `get_trade_days(start_date=None, end_date=None, count=None)`

获取交易日列表。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| start_date | str / struct_time / datetime.date / datetime.datetime | None | 开始日期，与 count 二选一 |
| end_date | str / struct_time / datetime.date / datetime.datetime | datetime.date.today() | 结束日期 |
| count | int | None | 结果集行数，与 start_date 二选一 |

**返回值**: `list[datetime.date]` - 交易日列表

---

#### `get_price(security, period=None, frequency=None, fre_step=None, fq='pre', fq_vol=False, fields=None, start_date=None, end_date=None, count=None, skip_paused=False)`

获取 K 线数据。本方法为 `get_quote_kdata` 的别名。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| security | str / list | - | 一支股票代码或股票代码列表，如 `'000001.XSHE'` 或 `['000001.XSHE', '600000.XSHG']` |
| period | str | 'day' | 周期，支持 `day`, `daily`, `1d`, `week`, `1w`, `mon`, `month`, `1M`, `season`, `year`, `mnX`, `Xm` |
| frequency | str | None | 周期别名，同 period |
| fre_step | str | None | 周期别名，同 period |
| fq | str / None | 'pre' | 复权方式：`'pre'` 前复权，`'post'` 后复权，`None` 不复权，或指定复权参考日如 `'2024-01-15'` |
| fq_vol | bool | False | 是否复权成交量 |
| fields | list | ['open', 'close', 'high', 'low', 'volume', 'money'] | 获取的字段列表 |
| start_date | str / struct_time / datetime.date / datetime.datetime | None | 开始日期，与 count 二选一 |
| end_date | str / struct_time / datetime.date / datetime.datetime | 最新行情日 | 结束日期 |
| count | int | None | 结果集行数，与 start_date 二选一 |
| skip_paused | bool | False | 是否跳过停牌 |

**返回值**: `pd.DataFrame` - K线数据

| 字段 | 类型 | 说明 |
|------|------|------|
| datetime | datetime | 行情时间 |
| code | str | 证券代码 |
| open | float | 开盘价 |
| close | float | 收盘价 |
| high | float | 最高价 |
| low | float | 最低价 |
| volume | int | 成交量 |
| money | float | 成交额 |

---

#### `get_quote_kdata(security, period='day', fq='pre', fq_vol=False, fields=None, start_date=None, end_date=None, count=None, skip_paused=False)`

获取 K 线数据。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| security | str / list | - | 一支股票代码或股票代码列表 |
| period | str | 'day' | 周期，支持 `day`, `daily`, `1d`, `week`, `1w`, `mon`, `month`, `1M`, `season`, `year`, `mnX`, `Xm`（mnX 或 Xm 代表 X 分钟 K 线，如 mn5、5m、mn15、15m 等） |
| fq | str / None | 'pre' | 复权方式：`'pre'` 前复权，`'post'` 后复权，`None` 不复权，或指定复权参考日 |
| fq_vol | bool | False | 是否复权成交量 |
| fields | list | ['open', 'close', 'high', 'low', 'volume', 'money'] | 获取的字段列表 |
| start_date | str / struct_time / datetime.date / datetime.datetime | None | 开始日期，与 count 二选一 |
| end_date | str / struct_time / datetime.date / datetime.datetime | 最新行情日 | 结束日期 |
| count | int | None | 结果集行数，与 start_date 二选一 |
| skip_paused | bool | False | 是否跳过停牌 |

**返回值**: `pd.DataFrame` - K线数据

---

#### `get_quote_static(date=None, fields=None, exch=None)`

获取静态行情数据（全市场快照）。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| date | str / struct_time / datetime.date / datetime.datetime | 最新行情日 | 行情日期 |
| fields | list | None | 获取的字段列表，可选值：`'open'`, `'close'`, `'high'`, `'low'`, `'volume'`, `'money'`, `'high_limit'`, `'low_limit'`, `'pre_close'`, `'paused'` |
| exch | list | ['SH', 'SZ'] | 交易所列表 |

**返回值**: `pd.DataFrame` - 静态行情数据

| 字段 | 类型 | 说明 |
|------|------|------|
| datetime | datetime | 行情时间 |
| code | str | 证券代码 |
| open | float | 开盘价 |
| close | float | 收盘价 |
| high | float | 最高价 |
| low | float | 最低价 |
| volume | int | 成交量 |
| money | float | 成交额 |
| high_limit | float | 涨停价 |
| low_limit | float | 跌停价 |
| pre_close | float | 昨收价 |
| paused | int | 停牌标记 |

---

#### `get_security_info(security=None, fields=None, types=None)`

获取证券信息数据。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| security | str / list | None | 一支股票代码或股票代码列表，None 表示获取所有 |
| fields | list | None | 获取的字段列表 |
| types | list | ['stock'] | 证券类型列表，可选值：`'stock'`, `'fund'`, `'index'`, `'futures'`, `'options'`, `'etf'`, `'lof'` 等 |

**返回值**: `pd.DataFrame` - 证券信息

| 字段 | 类型 | 说明 |
|------|------|------|
| code (索引) | str | 证券代码 |
| display_name | str | 中文名称 |
| name | str | 缩写简称 |
| start_date | datetime.date | 上市日期 |
| end_date | datetime.date | 退市日期，未退市为 2200-01-01 |
| type | str | 证券类型 |

---

#### `get_security_xrxd(security, start_date=None, end_date=None, count=None)`

获取证券除权除息数据。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| security | str / list | - | 一支股票代码或股票代码列表 |
| start_date | str / struct_time / datetime.date / datetime.datetime | None | 开始日期，与 count 二选一 |
| end_date | str / struct_time / datetime.date / datetime.datetime | datetime.date.today() | 结束日期 |
| count | int | None | 结果集行数，与 start_date 二选一 |

**返回值**: `pd.DataFrame` - 除权除息数据

| 字段 | 类型 | 说明 |
|------|------|------|
| date | datetime.date | 实施日期 |
| code | str | 证券代码 |
| dividend_ratio | float | 送股比例（每 10 股送 X 股） |
| transfer_ratio | float | 转增比例（每 10 股转增 X 股） |
| bonus_ratio | float | 派息比例（每 10 股派 X 元） |

---

#### `get_industries()`

获取所有行业列表。

**返回值**: `pd.DataFrame` - 行业列表

| 字段 | 类型 | 说明 |
|------|------|------|
| 行业代码 (索引) | str | 行业代码 |
| name | str | 行业名称 |
| start_date | datetime.date | 启用日期 |
| type | str | 类型 |

---

#### `get_concepts()`

获取所有概念列表。

**返回值**: `pd.DataFrame` - 概念列表

| 字段 | 类型 | 说明 |
|------|------|------|
| 概念代码 (索引) | str | 概念代码 |
| name | str | 概念名称 |
| start_date | datetime.date | 启用日期 |
| type | str | 类型 |

---

#### `get_index_stocks(index_code)`

获取指数成分股。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| index_code | str | - | 指数代码，如 `'000300.XSHG'` |

**返回值**: `list[str]` - 证券代码列表

---

#### `get_industry_stocks(industry_code)`

获取行业成分股。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| industry_code | str | - | 行业代码 |

**返回值**: `list[str]` - 证券代码列表

---

#### `get_concept_stocks(concept_code)`

获取概念成分股。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| concept_code | str | - | 概念代码 |

**返回值**: `list[str]` - 证券代码列表

---

#### `get_index_weights(index_code)`

获取指数成分股权重。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| index_code | str | - | 指数代码 |

**返回值**: `pd.DataFrame` - 指数权重

| 字段 | 类型 | 说明 |
|------|------|------|
| code (索引) | str | 证券代码 |
| date | datetime.date | 更新日期 |
| weight | float | 权重值 |
| display_name | str | 证券名称 |

---

#### `get_technical_analysis(security, indications, period='day', fq='pre', fq_vol=False, fields=None, start_date=None, end_date=None, count=None, skip_paused=False, keep_quote=False)`

获取技术指标数据。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| security | str / list | - | 一支股票代码或股票代码列表 |
| indications | list | - | 技术指标及参数，如 `[('MA', 5), ('KDJ', 9, 3, 3)]` 或 `['MA', 'KDJ']` |
| period | str | 'day' | 周期 |
| fq | str / None | 'pre' | 复权方式 |
| fq_vol | bool | False | 是否复权成交量 |
| fields | list | None | 获取的字段列表 |
| start_date | str / struct_time / datetime.date / datetime.datetime | None | 开始日期，与 count 二选一 |
| end_date | str / struct_time / datetime.date / datetime.datetime | 最新行情日 | 结束日期 |
| count | int | None | 结果集行数，与 start_date 二选一 |
| skip_paused | bool | False | 是否跳过停牌 |
| keep_quote | bool / str / list | False | 是否保留行情字段 |

**返回值**: `pd.DataFrame` - 技术指标数据

---

#### `execute_rehabilitation(data, fq='pre', fq_vol=False, start_date=None, end_date=None, columns=None, inplace=False, skip_sort=False)`

执行复权操作。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| data | pd.DataFrame | - | 输入行情数据，必须包含 `datetime` 和 `code` 字段 |
| fq | str | 'pre' | 复权方式：`'pre'` 前复权，`'post'` 后复权，或指定复权参考日 |
| fq_vol | bool | False | 是否复权成交量 |
| start_date | str / struct_time / datetime.date / datetime.datetime | data.datetime 最小值 | 复权开始日 |
| end_date | str / struct_time / datetime.date / datetime.datetime | data.datetime 最大值 | 复权结束日 |
| columns | list | None | 需要复权的字段列表 |
| inplace | bool | False | 是否覆盖输入数据 |
| skip_sort | bool | False | 跳过排序，若传入数据已按 code, datetime 排序可设为 True |

**返回值**: `pd.DataFrame` - 复权后的数据

---

#### `execute_technical_analysis(data, indications, prefix=None, lowercase=True, inplace=False, skip_sort=False)`

执行技术指标运算。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| data | pd.DataFrame | - | 输入行情数据 |
| indications | list | - | 技术指标及参数，如 `[('MA', 5), ('KDJ', 9, 3, 3)]` |
| prefix | str | None | 指标名称前缀 |
| lowercase | bool | True | 指标名称是否小写 |
| inplace | bool | False | 是否覆盖输入数据 |
| skip_sort | bool | False | 跳过排序 |

**返回值**: `pd.DataFrame` - 包含技术指标的数据

---

#### `get_option(name)`

获取可选项值。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| name | str | - | 可选项名称 |

**返回值**: 可选项值

---

#### `set_option(name, value)`

设置可选项值。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| name | str | - | 可选项名称 |
| value | any | - | 可选项值 |

**可选项**:

| 名称 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| debug | bool | False | 是否开启调试模式 |
| refer_num | int | 200 | 技术指标预加载数量 |
| multi_process | bool / int | False | 是否启用多进程，可指定进程数 |

---

### QuoteArchive 类

静态行情数据归档类。

#### `get_quote_rawdata(date=None, fields=None, period='daily', types=None)`

获取静态行情数据。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| date | str / struct_time / datetime.date / datetime.datetime | 最新行情日 | 行情日期 |
| fields | list | None | 获取的字段列表 |
| period | str | 'daily' | 周期，可选值：`'daily'`, `'minute'` |
| types | list | ['stock'] | 证券类型列表 |

**返回值**: `pd.DataFrame` - 静态行情数据

---

### JQWraps 类

证券代码转换工具类。

#### `convert_code(data, reverse=False)`

转换证券代码格式。

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| data | str / list / pd.Index / pd.Series / pd.DataFrame | - | 需要转换的数据 |
| reverse | bool | False | 是否反向转换（JoinQuant 格式 → 通达信格式） |

**返回值**: 转换后的数据

**转换规则**:
- `reverse=False`: 通达信格式 → JoinQuant 格式（`'000001.SZ'` → `'000001.XSHE'`）
- `reverse=True`: JoinQuant 格式 → 通达信格式（`'000001.XSHE'` → `'000001.SZ'`）

---

## 依赖

- Python >= 3.9
- pandas >= 0.25
- numpy

## 许可证

LGPL-3.0

## 作者

John Lui <johnlui@live.cn>

## 主页

https://github.com/johnluicn/pyqdt