ffdata 0.2.0__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.
- ffdata-0.2.0/PKG-INFO +32 -0
- ffdata-0.2.0/README.md +20 -0
- ffdata-0.2.0/pyproject.toml +28 -0
- ffdata-0.2.0/scripts/configure_ffdata.sh +59 -0
- ffdata-0.2.0/setup.cfg +4 -0
- ffdata-0.2.0/src/ffdata/__init__.py +162 -0
- ffdata-0.2.0/src/ffdata/cli.py +46 -0
- ffdata-0.2.0/src/ffdata/client.py +554 -0
- ffdata-0.2.0/src/ffdata/datasets/__init__.py +5 -0
- ffdata-0.2.0/src/ffdata/datasets/manager.py +132 -0
- ffdata-0.2.0/src/ffdata/local/__init__.py +5 -0
- ffdata-0.2.0/src/ffdata/local/store.py +146 -0
- ffdata-0.2.0/src/ffdata/transport/__init__.py +5 -0
- ffdata-0.2.0/src/ffdata/transport/http.py +175 -0
- ffdata-0.2.0/src/ffdata.egg-info/PKG-INFO +32 -0
- ffdata-0.2.0/src/ffdata.egg-info/SOURCES.txt +25 -0
- ffdata-0.2.0/src/ffdata.egg-info/dependency_links.txt +1 -0
- ffdata-0.2.0/src/ffdata.egg-info/entry_points.txt +2 -0
- ffdata-0.2.0/src/ffdata.egg-info/requires.txt +5 -0
- ffdata-0.2.0/src/ffdata.egg-info/top_level.txt +2 -0
- ffdata-0.2.0/src/ffdata_common/__init__.py +6 -0
- ffdata-0.2.0/src/ffdata_common/codecs/__init__.py +5 -0
- ffdata-0.2.0/src/ffdata_common/codecs/arrow.py +26 -0
- ffdata-0.2.0/src/ffdata_common/errors.py +30 -0
- ffdata-0.2.0/src/ffdata_common/protocol.py +18 -0
- ffdata-0.2.0/src/ffdata_common/schemas/__init__.py +5 -0
- ffdata-0.2.0/src/ffdata_common/schemas/manifest.py +52 -0
ffdata-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ffdata
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: ffdata lightweight Python client for governed financial-data APIs
|
|
5
|
+
Requires-Python: <3.13,>=3.12
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: httpx>=0.28.0
|
|
8
|
+
Requires-Dist: pandas>=3.0.5
|
|
9
|
+
Requires-Dist: polars>=1.43.2
|
|
10
|
+
Requires-Dist: pyarrow>=21.0.0
|
|
11
|
+
Requires-Dist: pydantic>=2.11.0
|
|
12
|
+
|
|
13
|
+
# ffdata
|
|
14
|
+
|
|
15
|
+
`ffdata` 是面向量化研究的轻量 Python 客户端。它只通过 HTTP 调用已部署的
|
|
16
|
+
ffdata 数据服务,不包含服务端、JYDB SQL、数据库配置或后台管理实现。
|
|
17
|
+
|
|
18
|
+
完整的客户端职责说明见 [客户端模块说明](../docs/模块说明/客户端.md);安装、构建和升级见
|
|
19
|
+
[客户端打包与交付](../docs/部署与运维/客户端打包与交付.md);每个对外 API 的可运行案例见
|
|
20
|
+
[使用案例](examples/README.md)。
|
|
21
|
+
|
|
22
|
+
## 配置服务地址与 Token
|
|
23
|
+
|
|
24
|
+
安装客户端 wheel 后运行:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
source "$(dirname "$(command -v ffdata)")/configure_ffdata.sh"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
脚本会交互式设置 `FFDATA_BASE_URL` 与 `FFDATA_TOKEN`,Token 输入不回显,并将两者写入
|
|
31
|
+
`~/.bash_profile`(仅当前用户可读)。因此新的 Bash 终端及其他项目都能直接读取配置;若当前使用
|
|
32
|
+
的是 zsh 等其他 shell,可执行 `source ~/.bash_profile` 加载。
|
ffdata-0.2.0/README.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# ffdata
|
|
2
|
+
|
|
3
|
+
`ffdata` 是面向量化研究的轻量 Python 客户端。它只通过 HTTP 调用已部署的
|
|
4
|
+
ffdata 数据服务,不包含服务端、JYDB SQL、数据库配置或后台管理实现。
|
|
5
|
+
|
|
6
|
+
完整的客户端职责说明见 [客户端模块说明](../docs/模块说明/客户端.md);安装、构建和升级见
|
|
7
|
+
[客户端打包与交付](../docs/部署与运维/客户端打包与交付.md);每个对外 API 的可运行案例见
|
|
8
|
+
[使用案例](examples/README.md)。
|
|
9
|
+
|
|
10
|
+
## 配置服务地址与 Token
|
|
11
|
+
|
|
12
|
+
安装客户端 wheel 后运行:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
source "$(dirname "$(command -v ffdata)")/configure_ffdata.sh"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
脚本会交互式设置 `FFDATA_BASE_URL` 与 `FFDATA_TOKEN`,Token 输入不回显,并将两者写入
|
|
19
|
+
`~/.bash_profile`(仅当前用户可读)。因此新的 Bash 终端及其他项目都能直接读取配置;若当前使用
|
|
20
|
+
的是 zsh 等其他 shell,可执行 `source ~/.bash_profile` 加载。
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "ffdata"
|
|
3
|
+
version = "0.2.0"
|
|
4
|
+
description = "ffdata lightweight Python client for governed financial-data APIs"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12,<3.13"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"httpx>=0.28.0",
|
|
9
|
+
"pandas>=3.0.5",
|
|
10
|
+
"polars>=1.43.2",
|
|
11
|
+
"pyarrow>=21.0.0",
|
|
12
|
+
"pydantic>=2.11.0",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[project.scripts]
|
|
16
|
+
ffdata = "ffdata.cli:main"
|
|
17
|
+
|
|
18
|
+
[build-system]
|
|
19
|
+
requires = ["setuptools>=75"]
|
|
20
|
+
build-backend = "setuptools.build_meta"
|
|
21
|
+
|
|
22
|
+
[tool.setuptools]
|
|
23
|
+
package-dir = {"" = "src"}
|
|
24
|
+
script-files = ["scripts/configure_ffdata.sh"]
|
|
25
|
+
|
|
26
|
+
[tool.setuptools.packages.find]
|
|
27
|
+
where = ["src"]
|
|
28
|
+
include = ["ffdata", "ffdata.*", "ffdata_common", "ffdata_common.*"]
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# 配置 ffdata 客户端所需的服务地址与研究员 Token。
|
|
3
|
+
# 请使用 source 执行本脚本,使环境变量立即对当前终端生效:
|
|
4
|
+
# source client/scripts/configure_ffdata.sh
|
|
5
|
+
|
|
6
|
+
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
|
|
7
|
+
printf '%s\n' "请使用 source 执行本脚本:source client/scripts/configure_ffdata.sh" >&2
|
|
8
|
+
exit 1
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
printf '%s' 'ffdata 服务地址 [http://127.0.0.1:8000]: '
|
|
12
|
+
IFS= read -r FFDATA_SETUP_BASE_URL
|
|
13
|
+
FFDATA_SETUP_BASE_URL=${FFDATA_SETUP_BASE_URL:-http://127.0.0.1:8000}
|
|
14
|
+
|
|
15
|
+
case "$FFDATA_SETUP_BASE_URL" in
|
|
16
|
+
http://*|https://*) ;;
|
|
17
|
+
*)
|
|
18
|
+
printf '%s\n' '服务地址必须以 http:// 或 https:// 开头。' >&2
|
|
19
|
+
return 1
|
|
20
|
+
;;
|
|
21
|
+
esac
|
|
22
|
+
|
|
23
|
+
printf '%s' '研究员 Token(输入不回显): '
|
|
24
|
+
IFS= read -r -s FFDATA_SETUP_TOKEN
|
|
25
|
+
printf '\n'
|
|
26
|
+
if [[ -z "$FFDATA_SETUP_TOKEN" ]]; then
|
|
27
|
+
printf '%s\n' 'Token 不能为空。' >&2
|
|
28
|
+
return 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
export FFDATA_BASE_URL="$FFDATA_SETUP_BASE_URL"
|
|
32
|
+
export FFDATA_TOKEN="$FFDATA_SETUP_TOKEN"
|
|
33
|
+
|
|
34
|
+
FFDATA_SETUP_PROFILE="$HOME/.bash_profile"
|
|
35
|
+
FFDATA_SETUP_TEMP_FILE=$(mktemp "$HOME/.bash_profile.ffdata.XXXXXX")
|
|
36
|
+
|
|
37
|
+
if [[ -f "$FFDATA_SETUP_PROFILE" ]]; then
|
|
38
|
+
awk '
|
|
39
|
+
/^# >>> ffdata environment >>>$/ { in_ffdata_block = 1; next }
|
|
40
|
+
/^# <<< ffdata environment <<</ { in_ffdata_block = 0; next }
|
|
41
|
+
!in_ffdata_block { print }
|
|
42
|
+
' "$FFDATA_SETUP_PROFILE" > "$FFDATA_SETUP_TEMP_FILE"
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
{
|
|
46
|
+
printf '\n# >>> ffdata environment >>>\n'
|
|
47
|
+
printf 'export FFDATA_BASE_URL=%q\n' "$FFDATA_BASE_URL"
|
|
48
|
+
printf 'export FFDATA_TOKEN=%q\n' "$FFDATA_TOKEN"
|
|
49
|
+
printf '# <<< ffdata environment <<<\n'
|
|
50
|
+
} >> "$FFDATA_SETUP_TEMP_FILE"
|
|
51
|
+
|
|
52
|
+
mv "$FFDATA_SETUP_TEMP_FILE" "$FFDATA_SETUP_PROFILE"
|
|
53
|
+
chmod 600 "$FFDATA_SETUP_PROFILE"
|
|
54
|
+
|
|
55
|
+
printf '%s\n' '当前终端已设置 FFDATA_BASE_URL 与 FFDATA_TOKEN。'
|
|
56
|
+
printf '%s\n' "已写入 $FFDATA_SETUP_PROFILE(仅当前用户可读)。"
|
|
57
|
+
printf '%s\n' '新的 Bash 终端会自动加载;使用其他 shell 时可执行:source ~/.bash_profile'
|
|
58
|
+
|
|
59
|
+
unset FFDATA_SETUP_BASE_URL FFDATA_SETUP_TOKEN FFDATA_SETUP_PROFILE FFDATA_SETUP_TEMP_FILE
|
ffdata-0.2.0/setup.cfg
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"""ffdata 轻量客户端的公共入口。
|
|
2
|
+
|
|
3
|
+
本模块提供全局客户端配置和与 ``Client`` 同名的便捷查询函数。研究代码只需
|
|
4
|
+
依赖本包,不需要接触数据库连接、聚源表结构或服务端配置。
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from .client import Client
|
|
14
|
+
|
|
15
|
+
_default_client: Client | None = None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def configure(
|
|
19
|
+
*,
|
|
20
|
+
base_url: str | None = None,
|
|
21
|
+
token: str | None = None,
|
|
22
|
+
data_dir: str | Path | None = None,
|
|
23
|
+
) -> Client:
|
|
24
|
+
"""创建并保存模块级默认客户端,返回该客户端实例。"""
|
|
25
|
+
global _default_client
|
|
26
|
+
_default_client = Client(
|
|
27
|
+
base_url=base_url or os.getenv("FFDATA_BASE_URL", "http://127.0.0.1:8000"),
|
|
28
|
+
token=token or os.getenv("FFDATA_TOKEN"),
|
|
29
|
+
data_dir=data_dir,
|
|
30
|
+
)
|
|
31
|
+
return _default_client
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def set_token(token: str) -> None:
|
|
35
|
+
"""仅更新默认客户端使用的 Token。"""
|
|
36
|
+
configure(token=token)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _client() -> Client:
|
|
40
|
+
return _default_client or configure()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def query(api_name: str, **params: Any):
|
|
44
|
+
"""通过默认客户端调用通用数据查询接口。"""
|
|
45
|
+
return _client().query(api_name, **params)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def sql_query(sql: str, **kwargs: Any):
|
|
49
|
+
"""通过默认客户端执行单条受限 SELECT。"""
|
|
50
|
+
return _client().sql_query(sql, **kwargs)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def stock_daily(*args: Any, **kwargs: Any):
|
|
54
|
+
return _client().stock_daily(*args, **kwargs)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def stock_adjusting_factor(*args: Any, **kwargs: Any):
|
|
58
|
+
return _client().stock_adjusting_factor(*args, **kwargs)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def stock_valuation_daily(*args: Any, **kwargs: Any):
|
|
62
|
+
"""通过默认客户端查询 A 股估值分析(日频)。"""
|
|
63
|
+
return _client().stock_valuation_daily(*args, **kwargs)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def index_daily(*args: Any, **kwargs: Any):
|
|
67
|
+
return _client().index_daily(*args, **kwargs)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def index_basic(*args: Any, **kwargs: Any):
|
|
71
|
+
"""通过默认客户端查询指数基本信息(返回含 inner_code 指数聚源内码)。"""
|
|
72
|
+
return _client().index_basic(*args, **kwargs)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def index_weight(*args: Any, **kwargs: Any):
|
|
76
|
+
"""通过默认客户端查询指数成分与权重。"""
|
|
77
|
+
return _client().index_weight(*args, **kwargs)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def etf_basic(*args: Any, **kwargs: Any):
|
|
81
|
+
"""通过默认客户端查询 ETF 基础信息(返回含 ETF 与跟踪目标两个聚源内码)。"""
|
|
82
|
+
return _client().etf_basic(*args, **kwargs)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def etf_daily(*args: Any, **kwargs: Any):
|
|
86
|
+
"""通过默认客户端查询 ETF 日线行情(83 列,含聚源区间表现列)。"""
|
|
87
|
+
return _client().etf_daily(*args, **kwargs)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def etf_adj_daily(*args: Any, **kwargs: Any):
|
|
91
|
+
"""通过默认客户端查询 ETF 后复权行情(13 列,支持精确/比例复权口径)。"""
|
|
92
|
+
return _client().etf_adj_daily(*args, **kwargs)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def cb_basic(*args: Any, **kwargs: Any):
|
|
96
|
+
"""通过默认客户端查询可转债基本信息(125 列,含条款文本与最新评级)。"""
|
|
97
|
+
return _client().cb_basic(*args, **kwargs)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def cb_daily(*args: Any, **kwargs: Any):
|
|
101
|
+
"""通过默认客户端查询可转债行情(22 列,对齐 Tushare cb_daily 前 11 列)。"""
|
|
102
|
+
return _client().cb_daily(*args, **kwargs)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def cb_deriv(*args: Any, **kwargs: Any):
|
|
106
|
+
"""通过默认客户端查询可转债衍生指标(26 列,含 YTM、久期、凸性、双低)。"""
|
|
107
|
+
return _client().cb_deriv(*args, **kwargs)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def cb_issue(*args: Any, **kwargs: Any):
|
|
111
|
+
"""通过默认客户端查询可转债发行信息(90 列,对齐 Tushare cb_issue 并输出聚源全字段)。"""
|
|
112
|
+
return _client().cb_issue(*args, **kwargs)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def fund_basic(*args: Any, **kwargs: Any):
|
|
116
|
+
"""通过默认客户端查询公募基金列表(71 列,含管理人/托管人全称与投资范围)。"""
|
|
117
|
+
return _client().fund_basic(*args, **kwargs)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def macro_indicator_basic(*args: Any, **kwargs: Any):
|
|
121
|
+
return _client().macro_indicator_basic(*args, **kwargs)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def macro_indicator_data(*args: Any, **kwargs: Any):
|
|
125
|
+
return _client().macro_indicator_data(*args, **kwargs)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def trade_cal(*args: Any, **kwargs: Any):
|
|
129
|
+
"""通过默认客户端查询交易日历(8 列,支持沪深/北交所/港股/美股/银行间)。"""
|
|
130
|
+
return _client().trade_cal(*args, **kwargs)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def stock_basic(*args: Any, **kwargs: Any):
|
|
134
|
+
"""通过默认客户端查询股票列表基础信息(18 列,含退市日期与沪深港通标的)。"""
|
|
135
|
+
return _client().stock_basic(*args, **kwargs)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
__all__ = [
|
|
139
|
+
"Client",
|
|
140
|
+
"cb_basic",
|
|
141
|
+
"cb_daily",
|
|
142
|
+
"cb_deriv",
|
|
143
|
+
"cb_issue",
|
|
144
|
+
"configure",
|
|
145
|
+
"etf_adj_daily",
|
|
146
|
+
"etf_basic",
|
|
147
|
+
"etf_daily",
|
|
148
|
+
"fund_basic",
|
|
149
|
+
"index_basic",
|
|
150
|
+
"index_daily",
|
|
151
|
+
"index_weight",
|
|
152
|
+
"macro_indicator_basic",
|
|
153
|
+
"macro_indicator_data",
|
|
154
|
+
"query",
|
|
155
|
+
"sql_query",
|
|
156
|
+
"set_token",
|
|
157
|
+
"stock_adjusting_factor",
|
|
158
|
+
"stock_basic",
|
|
159
|
+
"stock_daily",
|
|
160
|
+
"stock_valuation_daily",
|
|
161
|
+
"trade_cal",
|
|
162
|
+
]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""ffdata 客户端命令行入口,提供数据集查询、同步和校验命令。"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
from .client import Client
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _client() -> Client:
|
|
13
|
+
return Client(
|
|
14
|
+
base_url=os.getenv("FFDATA_BASE_URL", "http://127.0.0.1:8000"),
|
|
15
|
+
token=os.getenv("FFDATA_TOKEN"),
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def main() -> None:
|
|
20
|
+
parser = argparse.ArgumentParser(prog="ffdata")
|
|
21
|
+
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
22
|
+
dataset = subparsers.add_parser("dataset")
|
|
23
|
+
dataset_commands = dataset.add_subparsers(dest="dataset_command", required=True)
|
|
24
|
+
dataset_commands.add_parser("list")
|
|
25
|
+
status = dataset_commands.add_parser("status")
|
|
26
|
+
status.add_argument("name")
|
|
27
|
+
sync = dataset_commands.add_parser("sync")
|
|
28
|
+
sync.add_argument("name")
|
|
29
|
+
verify = dataset_commands.add_parser("verify")
|
|
30
|
+
verify.add_argument("name")
|
|
31
|
+
args = parser.parse_args()
|
|
32
|
+
|
|
33
|
+
with _client() as client:
|
|
34
|
+
if args.dataset_command == "list":
|
|
35
|
+
result = {"datasets": client.datasets.list()}
|
|
36
|
+
elif args.dataset_command == "status":
|
|
37
|
+
result = client.datasets.status(args.name)
|
|
38
|
+
elif args.dataset_command == "sync":
|
|
39
|
+
result = client.datasets.sync(args.name)
|
|
40
|
+
else:
|
|
41
|
+
result = client.datasets.verify(args.name)
|
|
42
|
+
print(json.dumps(result, ensure_ascii=False, indent=2))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
if __name__ == "__main__":
|
|
46
|
+
main()
|