jcdata 0.2.0__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
jcdata-0.2.2/PKG-INFO ADDED
@@ -0,0 +1,198 @@
1
+ Metadata-Version: 2.4
2
+ Name: jcdata
3
+ Version: 0.2.2
4
+ Summary: Python client for JCDATA market data and factor APIs
5
+ Author: JiceQuant
6
+ License-Expression: LicenseRef-Proprietary
7
+ Project-URL: Homepage, https://jicequant.com/
8
+ Project-URL: Documentation, https://jicequant.com/
9
+ Project-URL: Repository, https://pypi.org/project/jcdata/
10
+ Keywords: finance,quant,market-data,china,a-share
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Financial and Insurance Industry
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Office/Business :: Financial :: Investment
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.8
24
+ Description-Content-Type: text/markdown
25
+ Requires-Dist: httpx>=0.24
26
+ Requires-Dist: pandas>=1.3
27
+ Requires-Dist: pyarrow>=14
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=7; extra == "dev"
30
+
31
+ # jcdata
32
+
33
+ `jcdata` 是 JCDATA 的 Python 客户端,用于获取市场数据、证券基础信息、因子、财务、ETF、期权、利率和宏观数据
34
+
35
+ ## 安装
36
+
37
+ ```bash
38
+ pip install jcdata
39
+ ```
40
+
41
+ ## 认证
42
+
43
+ 使用访问令牌登录。请将令牌保存在环境变量或密钥管理系统中,禁止写入源码、笔记本、日志或版本控制系统。
44
+
45
+ ```python
46
+ import jcdata
47
+
48
+ login_info = jcdata.login("YOUR_TOKEN")
49
+ if not login_info.get("user_name"):
50
+ raise PermissionError("令牌无效、已过期或无访问权限")
51
+
52
+ print(login_info["user_name"])
53
+ print(login_info["cell_quota_remaining"])
54
+ ```
55
+
56
+ 也可使用环境变量:
57
+
58
+ ```bash
59
+ # Linux / macOS
60
+ export JCDATA_TOKEN="YOUR_TOKEN"
61
+ ```
62
+
63
+ ```powershell
64
+ # Windows PowerShell
65
+ $env:JCDATA_TOKEN = "YOUR_TOKEN"
66
+ ```
67
+
68
+ ```python
69
+ jcdata.login()
70
+ ```
71
+
72
+ 令牌查找顺序为:`login(token=...)` 参数、`JCDATA_TOKEN` 环境变量。`login()` 返回用户名、接口使用量和剩余配额;认证未通过时这些字段为 `None`。
73
+
74
+ ## 基本使用
75
+
76
+ ```python
77
+ import jcdata
78
+
79
+ jcdata.login()
80
+
81
+ bars = jcdata.get_market_data(
82
+ "600000.SH",
83
+ "2025-01-02",
84
+ "2025-01-10",
85
+ fields=["date", "open", "high", "low", "close", "volume"],
86
+ )
87
+ frame = bars["600000.SH"]
88
+
89
+ if not frame.empty:
90
+ print(frame.tail())
91
+ ```
92
+
93
+ 多数按证券代码查询的接口返回 `dict[str, pandas.DataFrame]`:字典 key 为请求代码,DataFrame 中不依赖 `symbol` 列分组。没有匹配数据时也会保留对应的空 DataFrame,因此请显式处理 `frame.empty`。
94
+
95
+ 日期参数支持 `YYYY-MM-DD` 或 `YYYYMMDD`,例如 `2025-01-02` 或 `20250102`。
96
+
97
+ ## 常用接口
98
+
99
+ | 分类 | 接口 |
100
+ |---|---|
101
+ | 日 K | `get_market_data`、`iter_market_data`、`iter_market_data_batches` |
102
+ | 基础信息 | `get_instrument`、`get_adj_factor`、`get_settlement`、`get_future_contract` |
103
+ | 股票扩展 | `get_factors`、`get_valuation`、`get_market_value`、`get_finance`、`get_money_flow`、`get_margin`、`get_leader_board` |
104
+ | 期权 | `get_market_data`、`get_option_greeks` |
105
+ | ETF | `get_etf_share`、`get_etf_tracking` |
106
+ | 日历与板块 | `get_trade_dates`、`get_all_sectors`、`get_stock_list_by_sector` |
107
+ | 利率与宏观 | `get_interest_rate`、`get_government_yield`、`get_macro_indicators` |
108
+
109
+ ## 批量行情
110
+
111
+ 直接传入代码列表即可查询多标的行情:
112
+
113
+ ```python
114
+ symbols = ["600000.SH", "000001.SZ", "510300.SH"]
115
+ bars = jcdata.get_market_data(symbols, "2025-01-02", "2025-01-10", fields=["date", "close"])
116
+
117
+ for symbol, frame in bars.items():
118
+ print(symbol, len(frame))
119
+ ```
120
+
121
+ 混合查询不同资产时,各 DataFrame 只返回该资产适用的字段。请按单个 DataFrame 的实际列名处理,不要假设所有资产具有相同字段。
122
+
123
+ ```python
124
+ mixed = jcdata.get_market_data(["600000.SH", "IF2501.CFE"], "2025-01-02", "2025-01-10")
125
+ print(mixed["600000.SH"].columns.tolist())
126
+ print(mixed["IF2501.CFE"].columns.tolist())
127
+ ```
128
+
129
+ ## 复权
130
+
131
+ `get_market_data()` 支持股票、ETF 和可转债复权:
132
+
133
+ ```python
134
+ adjusted = jcdata.get_market_data(
135
+ "600000.SH",
136
+ "2024-01-01",
137
+ "2025-01-31",
138
+ dividend_type="front",
139
+ fields=["date", "close"],
140
+ )
141
+ ```
142
+
143
+ 可用 `dividend_type`:`none`、`front`、`back`、`point`。使用 `point` 时必须同时传 `adjust_date`。指数不参与复权。
144
+
145
+ ## 大数据读取
146
+
147
+ 代码数量较多但希望按代码处理时,使用 `iter_market_data()`:
148
+
149
+ ```python
150
+ for chunk_symbols, frames in jcdata.iter_market_data(
151
+ symbols,
152
+ "2020-01-01",
153
+ "2025-01-01",
154
+ chunk_size=60,
155
+ fields=["date", "close", "volume"],
156
+ ):
157
+ for symbol in chunk_symbols:
158
+ process(frames[symbol])
159
+ ```
160
+
161
+ 超长历史数据使用 `iter_market_data_batches()`,并在循环内及时处理结果:
162
+
163
+ ```python
164
+ for present_symbols, frames in jcdata.iter_market_data_batches(
165
+ symbols,
166
+ "2015-01-01",
167
+ "2025-01-01",
168
+ fields=["date", "close"],
169
+ stream_batch_rows=65_536,
170
+ ):
171
+ for symbol in present_symbols:
172
+ frames[symbol].to_parquet(f"{symbol}.parquet", index=False)
173
+ ```
174
+
175
+ 同一代码可能跨多个批次出现。请不要将全部批次累积到内存中。
176
+
177
+ ## 错误处理
178
+
179
+ ```python
180
+ try:
181
+ jcdata.login()
182
+ bars = jcdata.get_market_data("600000.SH", "2025-01-02", "2025-01-10")
183
+ except jcdata.CellQuotaExceededError as exc:
184
+ print("配额已用尽,剩余:", exc.cell_quota_remaining)
185
+ except jcdata.InvalidParameterError as exc:
186
+ print("参数错误:", exc.param, exc.value)
187
+ except PermissionError as exc:
188
+ print("认证或授权失败:", exc)
189
+ ```
190
+
191
+ `CellQuotaExceededError` 是 `PermissionError` 的子类,因此应优先捕获。参数问题会引发 `InvalidParameterError`,可通过 `.param` 和 `.value` 定位。对于无效代码或正常无数据区间,按代码查询接口一般返回空 DataFrame,而非异常。
192
+
193
+ ## 更多说明
194
+
195
+ - 代码格式通常为 `代码.市场后缀`,例如 `600000.SH`、`000001.SZ`、`IF2501.CFE`。
196
+ - 使用 `get_asset_type_by_symbol()` 可识别常见代码的资产类型。
197
+ - 使用 `fields` 限定实际需要的列,可减少传输量和处理成本。
198
+ - 如遇访问频率或配额限制,请控制并发、缩小查询范围并保存任务进度。
jcdata-0.2.2/README.md ADDED
@@ -0,0 +1,168 @@
1
+ # jcdata
2
+
3
+ `jcdata` 是 JCDATA 的 Python 客户端,用于获取市场数据、证券基础信息、因子、财务、ETF、期权、利率和宏观数据
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ pip install jcdata
9
+ ```
10
+
11
+ ## 认证
12
+
13
+ 使用访问令牌登录。请将令牌保存在环境变量或密钥管理系统中,禁止写入源码、笔记本、日志或版本控制系统。
14
+
15
+ ```python
16
+ import jcdata
17
+
18
+ login_info = jcdata.login("YOUR_TOKEN")
19
+ if not login_info.get("user_name"):
20
+ raise PermissionError("令牌无效、已过期或无访问权限")
21
+
22
+ print(login_info["user_name"])
23
+ print(login_info["cell_quota_remaining"])
24
+ ```
25
+
26
+ 也可使用环境变量:
27
+
28
+ ```bash
29
+ # Linux / macOS
30
+ export JCDATA_TOKEN="YOUR_TOKEN"
31
+ ```
32
+
33
+ ```powershell
34
+ # Windows PowerShell
35
+ $env:JCDATA_TOKEN = "YOUR_TOKEN"
36
+ ```
37
+
38
+ ```python
39
+ jcdata.login()
40
+ ```
41
+
42
+ 令牌查找顺序为:`login(token=...)` 参数、`JCDATA_TOKEN` 环境变量。`login()` 返回用户名、接口使用量和剩余配额;认证未通过时这些字段为 `None`。
43
+
44
+ ## 基本使用
45
+
46
+ ```python
47
+ import jcdata
48
+
49
+ jcdata.login()
50
+
51
+ bars = jcdata.get_market_data(
52
+ "600000.SH",
53
+ "2025-01-02",
54
+ "2025-01-10",
55
+ fields=["date", "open", "high", "low", "close", "volume"],
56
+ )
57
+ frame = bars["600000.SH"]
58
+
59
+ if not frame.empty:
60
+ print(frame.tail())
61
+ ```
62
+
63
+ 多数按证券代码查询的接口返回 `dict[str, pandas.DataFrame]`:字典 key 为请求代码,DataFrame 中不依赖 `symbol` 列分组。没有匹配数据时也会保留对应的空 DataFrame,因此请显式处理 `frame.empty`。
64
+
65
+ 日期参数支持 `YYYY-MM-DD` 或 `YYYYMMDD`,例如 `2025-01-02` 或 `20250102`。
66
+
67
+ ## 常用接口
68
+
69
+ | 分类 | 接口 |
70
+ |---|---|
71
+ | 日 K | `get_market_data`、`iter_market_data`、`iter_market_data_batches` |
72
+ | 基础信息 | `get_instrument`、`get_adj_factor`、`get_settlement`、`get_future_contract` |
73
+ | 股票扩展 | `get_factors`、`get_valuation`、`get_market_value`、`get_finance`、`get_money_flow`、`get_margin`、`get_leader_board` |
74
+ | 期权 | `get_market_data`、`get_option_greeks` |
75
+ | ETF | `get_etf_share`、`get_etf_tracking` |
76
+ | 日历与板块 | `get_trade_dates`、`get_all_sectors`、`get_stock_list_by_sector` |
77
+ | 利率与宏观 | `get_interest_rate`、`get_government_yield`、`get_macro_indicators` |
78
+
79
+ ## 批量行情
80
+
81
+ 直接传入代码列表即可查询多标的行情:
82
+
83
+ ```python
84
+ symbols = ["600000.SH", "000001.SZ", "510300.SH"]
85
+ bars = jcdata.get_market_data(symbols, "2025-01-02", "2025-01-10", fields=["date", "close"])
86
+
87
+ for symbol, frame in bars.items():
88
+ print(symbol, len(frame))
89
+ ```
90
+
91
+ 混合查询不同资产时,各 DataFrame 只返回该资产适用的字段。请按单个 DataFrame 的实际列名处理,不要假设所有资产具有相同字段。
92
+
93
+ ```python
94
+ mixed = jcdata.get_market_data(["600000.SH", "IF2501.CFE"], "2025-01-02", "2025-01-10")
95
+ print(mixed["600000.SH"].columns.tolist())
96
+ print(mixed["IF2501.CFE"].columns.tolist())
97
+ ```
98
+
99
+ ## 复权
100
+
101
+ `get_market_data()` 支持股票、ETF 和可转债复权:
102
+
103
+ ```python
104
+ adjusted = jcdata.get_market_data(
105
+ "600000.SH",
106
+ "2024-01-01",
107
+ "2025-01-31",
108
+ dividend_type="front",
109
+ fields=["date", "close"],
110
+ )
111
+ ```
112
+
113
+ 可用 `dividend_type`:`none`、`front`、`back`、`point`。使用 `point` 时必须同时传 `adjust_date`。指数不参与复权。
114
+
115
+ ## 大数据读取
116
+
117
+ 代码数量较多但希望按代码处理时,使用 `iter_market_data()`:
118
+
119
+ ```python
120
+ for chunk_symbols, frames in jcdata.iter_market_data(
121
+ symbols,
122
+ "2020-01-01",
123
+ "2025-01-01",
124
+ chunk_size=60,
125
+ fields=["date", "close", "volume"],
126
+ ):
127
+ for symbol in chunk_symbols:
128
+ process(frames[symbol])
129
+ ```
130
+
131
+ 超长历史数据使用 `iter_market_data_batches()`,并在循环内及时处理结果:
132
+
133
+ ```python
134
+ for present_symbols, frames in jcdata.iter_market_data_batches(
135
+ symbols,
136
+ "2015-01-01",
137
+ "2025-01-01",
138
+ fields=["date", "close"],
139
+ stream_batch_rows=65_536,
140
+ ):
141
+ for symbol in present_symbols:
142
+ frames[symbol].to_parquet(f"{symbol}.parquet", index=False)
143
+ ```
144
+
145
+ 同一代码可能跨多个批次出现。请不要将全部批次累积到内存中。
146
+
147
+ ## 错误处理
148
+
149
+ ```python
150
+ try:
151
+ jcdata.login()
152
+ bars = jcdata.get_market_data("600000.SH", "2025-01-02", "2025-01-10")
153
+ except jcdata.CellQuotaExceededError as exc:
154
+ print("配额已用尽,剩余:", exc.cell_quota_remaining)
155
+ except jcdata.InvalidParameterError as exc:
156
+ print("参数错误:", exc.param, exc.value)
157
+ except PermissionError as exc:
158
+ print("认证或授权失败:", exc)
159
+ ```
160
+
161
+ `CellQuotaExceededError` 是 `PermissionError` 的子类,因此应优先捕获。参数问题会引发 `InvalidParameterError`,可通过 `.param` 和 `.value` 定位。对于无效代码或正常无数据区间,按代码查询接口一般返回空 DataFrame,而非异常。
162
+
163
+ ## 更多说明
164
+
165
+ - 代码格式通常为 `代码.市场后缀`,例如 `600000.SH`、`000001.SZ`、`IF2501.CFE`。
166
+ - 使用 `get_asset_type_by_symbol()` 可识别常见代码的资产类型。
167
+ - 使用 `fields` 限定实际需要的列,可减少传输量和处理成本。
168
+ - 如遇访问频率或配额限制,请控制并发、缩小查询范围并保存任务进度。
@@ -1,72 +1,78 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- JCDATA 客户端:连接数据服务后取历史行情与因子数据。
4
-
5
- 使用前调用 ``jcdata.login("...")``(或设置环境变量 ``JCDATA_TOKEN``)::
6
-
7
- import jcdata
8
-
9
- jcdata.login("你的访问令牌")
10
- df = jcdata.get_market_data("600000.SH", "2025-01-01", "2025-01-31")["600000.SH"]
11
- """
12
- from __future__ import annotations
13
-
14
- from ._http import current_user, login, whoami
15
- from .errors import CellQuotaExceededError, ErrorCode, InvalidParameterError, RowQuotaExceededError
16
- from .data import (
17
- get_adj_factor,
18
- get_etf_share,
19
- get_etf_tracking,
20
- get_finance,
21
- get_future_contract,
22
- get_instrument,
23
- get_interest_rate,
24
- get_leader_board,
25
- get_margin,
26
- get_market_data,
27
- iter_market_data,
28
- iter_market_data_batches,
29
- get_market_value,
30
- get_money_flow,
31
- get_option_bars,
32
- get_option_info,
33
- get_settlement,
34
- get_all_sectors,
35
- get_stock_list_by_sector,
36
- get_trade_dates,
37
- get_valuation,
38
- )
39
-
40
- __version__ = "0.1.6"
41
-
42
- __all__ = [
43
- "__version__",
44
- "login",
45
- "whoami",
46
- "current_user",
47
- "ErrorCode",
48
- "CellQuotaExceededError",
49
- "InvalidParameterError",
50
- "RowQuotaExceededError",
51
- "get_market_data",
52
- "iter_market_data",
53
- "iter_market_data_batches",
54
- "get_instrument",
55
- "get_adj_factor",
56
- "get_settlement",
57
- "get_future_contract",
58
- "get_valuation",
59
- "get_market_value",
60
- "get_finance",
61
- "get_trade_dates",
62
- "get_all_sectors",
63
- "get_stock_list_by_sector",
64
- "get_option_bars",
65
- "get_option_info",
66
- "get_money_flow",
67
- "get_margin",
68
- "get_leader_board",
69
- "get_etf_share",
70
- "get_etf_tracking",
71
- "get_interest_rate",
72
- ]
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ JCDATA Python 客户端:用于查询市场数据和相关数据集。
4
+
5
+ 使用前调用 ``jcdata.login("...")``(或设置环境变量 ``JCDATA_TOKEN``)::
6
+
7
+ import jcdata
8
+
9
+ jcdata.login("你的访问令牌")
10
+ df = jcdata.get_market_data("600000.SH", "2025-01-01", "2025-01-31")["600000.SH"]
11
+ """
12
+ from __future__ import annotations
13
+
14
+ from ._http import current_user, login, whoami
15
+ from .errors import CellQuotaExceededError, ErrorCode, InvalidParameterError, RowQuotaExceededError
16
+ from .data import (
17
+ get_adj_factor,
18
+ get_asset_type_by_symbol,
19
+ get_etf_share,
20
+ get_etf_tracking,
21
+ get_finance,
22
+ get_factors,
23
+ get_future_contract,
24
+ get_government_yield,
25
+ get_instrument,
26
+ get_interest_rate,
27
+ get_leader_board,
28
+ get_margin,
29
+ get_market_data,
30
+ iter_market_data,
31
+ iter_market_data_batches,
32
+ get_market_value,
33
+ get_macro_indicators,
34
+ get_money_flow,
35
+ get_option_greeks,
36
+ get_settlement,
37
+ get_all_sectors,
38
+ get_stock_list_by_sector,
39
+ get_trade_dates,
40
+ get_valuation,
41
+ )
42
+
43
+ __version__ = "0.2.2"
44
+
45
+ __all__ = [
46
+ "__version__",
47
+ "login",
48
+ "whoami",
49
+ "current_user",
50
+ "ErrorCode",
51
+ "CellQuotaExceededError",
52
+ "InvalidParameterError",
53
+ "RowQuotaExceededError",
54
+ "get_market_data",
55
+ "get_asset_type_by_symbol",
56
+ "iter_market_data",
57
+ "iter_market_data_batches",
58
+ "get_instrument",
59
+ "get_adj_factor",
60
+ "get_settlement",
61
+ "get_future_contract",
62
+ "get_valuation",
63
+ "get_market_value",
64
+ "get_government_yield",
65
+ "get_macro_indicators",
66
+ "get_finance",
67
+ "get_factors",
68
+ "get_trade_dates",
69
+ "get_all_sectors",
70
+ "get_stock_list_by_sector",
71
+ "get_option_greeks",
72
+ "get_money_flow",
73
+ "get_margin",
74
+ "get_leader_board",
75
+ "get_etf_share",
76
+ "get_etf_tracking",
77
+ "get_interest_rate",
78
+ ]
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- """解析 API 返回的 Arrow IPC 行情。"""
2
+ """解析行情数据响应。"""
3
3
  from __future__ import annotations
4
4
 
5
5
  import io
@@ -36,14 +36,14 @@ def _split_by_symbol(df: pd.DataFrame) -> dict[str, pd.DataFrame]:
36
36
 
37
37
 
38
38
  def decode_arrow_by_symbol(data: bytes) -> dict[str, pd.DataFrame]:
39
- """兼容整包 Arrow IPC 响应。"""
39
+ """解析行情数据响应。"""
40
40
  if not data:
41
41
  return {}
42
42
  return _split_by_symbol(normalize_datetimes(ipc.open_stream(io.BytesIO(data)).read_all().to_pandas()))
43
43
 
44
44
 
45
45
  def iter_zstd_arrow_by_symbol(chunks: Iterable[bytes]) -> Iterator[dict[str, pd.DataFrame]]:
46
- """逐段、逐 RecordBatch 解码长度帧 Zstd Arrow 流。"""
46
+ """逐批解析行情数据流。"""
47
47
  buffer = bytearray()
48
48
  expected: int | None = None
49
49
  for chunk in chunks:
@@ -64,9 +64,9 @@ def iter_zstd_arrow_by_symbol(chunks: Iterable[bytes]) -> Iterator[dict[str, pd.
64
64
  if frames:
65
65
  yield frames
66
66
  if expected is not None or buffer:
67
- raise ValueError("不完整的 JCDATA Arrow Zstd 流")
67
+ raise ValueError("行情数据流不完整")
68
68
 
69
69
 
70
70
  def decode_bars_arrow(data: bytes) -> dict[str, pd.DataFrame]:
71
- """兼容旧名。"""
71
+ """解析行情数据。"""
72
72
  return decode_arrow_by_symbol(data)