alpha-dc-client 0.1.23__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.
@@ -0,0 +1,90 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .coverage
43
+ .coverage.*
44
+ .cache
45
+ nosetests.xml
46
+ coverage.xml
47
+ *.cover
48
+ *.py,cover
49
+ .hypothesis/
50
+ .pytest_cache/
51
+
52
+ # Jupyter Notebook
53
+ .ipynb_checkpoints
54
+
55
+ # IPython
56
+ profile_default/
57
+ ipython_config.py
58
+
59
+ # pyenv
60
+ .python-version
61
+
62
+ # PEP 582; __pypackages__
63
+ __pypackages__/
64
+
65
+ # Environments
66
+ .env
67
+ .venv
68
+ env/
69
+ venv/
70
+ ENV/
71
+ env.bak/
72
+ venv.bak/
73
+
74
+ # mypy
75
+ .mypy_cache/
76
+ .dmypy.json
77
+ dmypy.json
78
+
79
+ # uv lock file
80
+ uv.lock
81
+
82
+ # Log files
83
+ logs/
84
+ *.log
85
+
86
+ # Data directories (runtime generated data)
87
+ data/
88
+
89
+ # Project specific files
90
+ services/worker_service/data_fetchers/StockClassifyUse_stock.xls
@@ -0,0 +1,6 @@
1
+ Metadata-Version: 2.4
2
+ Name: alpha-dc-client
3
+ Version: 0.1.23
4
+ Author-email: Hang GuangLiang <hanguangliang@alphaaidig.com>
5
+ Requires-Dist: dc-common==0.1.23
6
+ Requires-Dist: httpx
@@ -0,0 +1,438 @@
1
+ # DataCenter Client 使用指南
2
+
3
+ ## 1. 🚀 安装
4
+
5
+ ```bash
6
+ pip install datacenter_client
7
+ ```
8
+
9
+ ## 2. 🔑 认证设置
10
+
11
+ ### 获取API Token
12
+ 1. 联系管理员申请API Token
13
+ 2. 或者访问数据管理后台获取访问权限
14
+
15
+ ### 初始化客户端
16
+ ```python
17
+ import datacenter_client as dc
18
+
19
+ # 基础初始化
20
+ client = dc.init(
21
+ token='your_api_token_here'
22
+ )
23
+
24
+ # 使用环境变量
25
+ import os
26
+ client = dc.init(token=os.getenv('DATACENTER_API_TOKEN'))
27
+ ```
28
+
29
+ ## 3. 🔍 查找需要的接口
30
+
31
+ ### 方法一:查看完整API列表
32
+ ```python
33
+ import requests
34
+
35
+ # 获取所有API
36
+ response = requests.get('http://data.alphaaidig.com/api/v1/docs/json')
37
+ if response.status_code == 200:
38
+ docs = response.json()
39
+ print(f"总共有 {docs['total_count']} 个API")
40
+ for api in docs['apis']:
41
+ print(f"- {api['name']}: {api['description']}")
42
+ ```
43
+
44
+ ### 方法二:搜索特定功能
45
+ ```python
46
+ # 搜索融资融券相关接口
47
+ response = requests.get('http://data.alphaaidig.com/api/v1/docs/search?q=margin')
48
+ if response.status_code == 200:
49
+ results = response.json()
50
+ for api in results['results']:
51
+ print(f"- {api['name']}: {api['description']}")
52
+ ```
53
+
54
+ ### 方法三:按类别查看
55
+ ```python
56
+ # 获取API分类
57
+ response = requests.get('http://data.alphaaidig.com/api/v1/docs/categories')
58
+ if response.status_code == 200:
59
+ categories = response.json()
60
+ print(f"API分类: {categories['categories']}")
61
+ ```
62
+
63
+ ## 4. 📋 访问接口
64
+
65
+ ### 基本调用方式
66
+ ```python
67
+ # 方式一:通过动态方法调用
68
+ result = client.hsgt_fund_page_list(page=1, page_size=20)
69
+
70
+ # 方式二:通过通用query方法
71
+ result = client.query('hsgt_fund_page_list', page=1, page_size=20)
72
+
73
+ # 方式三:指定返回字段
74
+ result = client.hsgt_fund_page_list(
75
+ page=1,
76
+ page_size=10,
77
+ fields='trade_date,stock_code,stock_name,hold_market_cap'
78
+ )
79
+ ```
80
+
81
+ ### 常用接口示例
82
+ ```python
83
+ # 沪深港通数据
84
+ df = client.hsgt_fund_page_list(page=1, page_size=20)
85
+ df = client.hsgt_north_fundxx()
86
+ df = client.hsgt_south_fundxx()
87
+
88
+ # A股数据
89
+ df = client.a_stock_page_list(page=1, page_size=20)
90
+ df = client.a_stock_list(limit=50)
91
+
92
+ # 港股数据
93
+ df = client.hk_stock_page_list(page=1, page_size=20)
94
+ df = client.hk_stock_list(limit=50)
95
+
96
+ # 行业数据
97
+ df = client.hs_industry_page_list(page=1, page_size=20)
98
+ df = client.hs_industry_company_page_list(page=1, page_size=20)
99
+ df = client.sw_industry_page_list(page=1, page_size=20)
100
+ df = client.sw_industry_company_page_list(page=1, page_size=20, level_type='level1')
101
+
102
+ # 融资融券数据
103
+ df = client.margin_account_page_list(page=1, page_size=20)
104
+ df = client.margin_account_list(limit=50)
105
+ df = client.margin_analysis_page_list(page=1, page_size=20)
106
+ df = client.margin_analysis_list(limit=50)
107
+ df = client.margin_detail_page_list_by_date(page=1, page_size=20)
108
+ df = client.margin_detail_page_list_by_stock(page=1, page_size=20)
109
+ df = client.margin_detail_list_by_stock(stock_code='000001.SZ', limit=50)
110
+ ```
111
+
112
+ ## 5. ❌ 错误处理
113
+
114
+ ```python
115
+ import datacenter_client as dc
116
+ from datacenter_client.exceptions import (
117
+ DatacenterAPIError,
118
+ APIError,
119
+ AuthenticationError,
120
+ NotFoundError,
121
+ InvalidRequestError
122
+ )
123
+
124
+ def safe_api_call():
125
+ try:
126
+ client = dc.init(token='your_api_token')
127
+ df = client.hsgt_fund_page_list(page=1, page_size=10)
128
+ return df
129
+
130
+ except AuthenticationError:
131
+ print("❌ 认证失败:请检查API token是否正确")
132
+ return None
133
+
134
+ except NotFoundError:
135
+ print("❌ API不存在:请检查API名称是否正确")
136
+ return None
137
+
138
+ except InvalidRequestError as e:
139
+ print(f"❌ 请求参数错误:{e}")
140
+ return None
141
+
142
+ except DatacenterAPIError as e:
143
+ print(f"❌ API错误:{e.message}")
144
+ return None
145
+
146
+ except Exception as e:
147
+ print(f"❌ 未知错误:{e}")
148
+ return None
149
+
150
+ # 使用
151
+ result = safe_api_call()
152
+ if result is not None:
153
+ print(f"✅ 成功获取 {len(result)} 条数据")
154
+ ```
155
+
156
+ ## 6. 📊 分页数据解析
157
+
158
+ ### 识别分页数据
159
+ ```python
160
+ import datacenter_client as dc
161
+
162
+ client = dc.init(token='your_api_token')
163
+
164
+ # 调用分页接口
165
+ result = client.hsgt_fund_page_list(page=1, page_size=20)
166
+
167
+ # 检查是否为分页数据
168
+ if hasattr(result, 'has_pagination') and result.has_pagination:
169
+ print("✅ 这是分页数据")
170
+ print(f"当前页: {result.current_page}")
171
+ print(f"每页大小: {result.page_size}")
172
+ print(f"总记录数: {result.total_count}")
173
+ print(f"总页数: {result.total_pages}")
174
+ else:
175
+ print("✅ 这是普通数据")
176
+ print(f"数据行数: {len(result)}")
177
+ ```
178
+
179
+ ### 遍历所有分页数据
180
+ ```python
181
+ def get_all_paginated_data(client, api_method, **kwargs):
182
+ """获取所有分页数据的通用函数"""
183
+ all_data = []
184
+ page = 1
185
+ page_size = 100 # 每页大小
186
+
187
+ while True:
188
+ try:
189
+ # 调用分页接口
190
+ result = api_method(page=page, page_size=page_size, **kwargs)
191
+
192
+ if hasattr(result, 'has_pagination') and result.has_pagination:
193
+ # 分页数据处理
194
+ all_data.extend(result.to_dict('records'))
195
+ print(f"✅ 第 {page} 页,累计 {len(all_data)} 条数据")
196
+
197
+ # 检查是否还有下一页
198
+ if page >= result.total_pages:
199
+ break
200
+ page += 1
201
+ else:
202
+ # 非分页数据
203
+ all_data.extend(result.to_dict('records'))
204
+ break
205
+
206
+ except Exception as e:
207
+ print(f"❌ 获取第 {page} 页数据失败:{e}")
208
+ break
209
+
210
+ return all_data
211
+
212
+ # 使用示例
213
+ client = dc.init(token='your_api_token')
214
+ all_hsgt_data = get_all_paginated_data(
215
+ client,
216
+ client.hsgt_fund_page_list
217
+ )
218
+ print(f"总共获取 {len(all_hsgt_data)} 条数据")
219
+ ```
220
+
221
+ ## 7. 📄 非分页数据解析
222
+
223
+ ### 处理普通数据
224
+ ```python
225
+ import pandas as pd
226
+ import datacenter_client as dc
227
+
228
+ client = dc.init(token='your_api_token')
229
+
230
+ # 调用非分页接口
231
+ result = client.hsgt_north_fundxx()
232
+
233
+ # 检查数据类型
234
+ if isinstance(result, pd.DataFrame):
235
+ print(f"✅ 获取到DataFrame,共 {len(result)} 行")
236
+ print(f"列名: {list(result.columns)}")
237
+ print("前5行数据:")
238
+ print(result.head())
239
+ else:
240
+ print("✅ 获取到其他格式数据")
241
+ print(f"数据类型: {type(result)}")
242
+ print(f"数据内容: {result}")
243
+ ```
244
+
245
+ ### 指定返回字段
246
+ ```python
247
+ # 只获取需要的字段
248
+ result = client.hsgt_fund_page_list(
249
+ page=1,
250
+ page_size=10,
251
+ fields='trade_date,stock_code,stock_name,hold_market_cap'
252
+ )
253
+
254
+ print("返回的字段:", result.columns.tolist())
255
+ print("数据示例:")
256
+ print(result.head())
257
+ ```
258
+
259
+ ## 8. 🛠️ 高级用法
260
+
261
+ ### 配置化客户端
262
+ ```python
263
+ import os
264
+ from pathlib import Path
265
+ import json
266
+
267
+ class DataCenterConfig:
268
+ def __init__(self):
269
+ self.api_token = os.getenv('DATACENTER_API_TOKEN')
270
+ self.base_url = os.getenv('DATACENTER_BASE_URL', 'https://data.alphaaidig.com')
271
+ self.timeout = int(os.getenv('DATACENTER_TIMEOUT', '30'))
272
+
273
+ # 从配置文件读取
274
+ config_file = Path.home() / '.datacenter' / 'config.json'
275
+ if config_file.exists():
276
+ with open(config_file, 'r') as f:
277
+ config = json.load(f)
278
+ self.api_token = config.get('api_token', self.api_token)
279
+ self.base_url = config.get('base_url', self.base_url)
280
+ self.timeout = config.get('timeout', self.timeout)
281
+
282
+ def get_client(self):
283
+ if not self.api_token:
284
+ raise ValueError("❌ API Token未设置,请设置DATACENTER_API_TOKEN环境变量或配置文件")
285
+
286
+ return dc.init(
287
+ token=self.api_token,
288
+ base_url=self.base_url,
289
+ timeout=self.timeout
290
+ )
291
+
292
+ # 使用
293
+ config = DataCenterConfig()
294
+ client = config.get_client()
295
+ ```
296
+
297
+ ### 批量查询
298
+ ```python
299
+ import pandas as pd
300
+ from typing import List
301
+ import time
302
+
303
+ def batch_query_stocks(stock_codes: List[str]) -> pd.DataFrame:
304
+ """批量查询多只股票数据"""
305
+ client = dc.init(token='your_api_token')
306
+ all_data = []
307
+
308
+ for i, stock_code in enumerate(stock_codes):
309
+ try:
310
+ print(f"📊 查询股票 {stock_code} ({i+1}/{len(stock_codes)})")
311
+
312
+ # 这里可以根据需要调用不同的接口
313
+ result = client.a_stock_list(limit=1) # 示例调用
314
+
315
+ # 添加股票代码到结果中(如果接口没有返回)
316
+ if hasattr(result, 'to_dict'):
317
+ data_dict = result.to_dict()
318
+ if isinstance(data_dict, list):
319
+ all_data.extend(data_dict)
320
+ else:
321
+ all_data.append(data_dict)
322
+
323
+ # 添加延迟避免频率限制
324
+ time.sleep(0.1)
325
+
326
+ except Exception as e:
327
+ print(f"❌ 查询股票 {stock_code} 失败:{e}")
328
+ continue
329
+
330
+ if all_data:
331
+ return pd.DataFrame(all_data)
332
+ else:
333
+ return pd.DataFrame()
334
+
335
+ # 使用示例
336
+ stock_codes = ['000001', '000002', '600000', '600036']
337
+ df = batch_query_stocks(stock_codes)
338
+ print(f"总共获取 {len(df)} 条股票数据")
339
+ ```
340
+
341
+ ### 动态接口调用
342
+ ```python
343
+ def dynamic_api_call(client, api_name: str, **params):
344
+ """动态调用任意API接口"""
345
+ try:
346
+ # 方法一:通过动态属性调用
347
+ api_method = getattr(client, api_name)
348
+ result = api_method(**params)
349
+
350
+ # 方法二:通过query方法调用
351
+ # result = client.query(api_name, **params)
352
+
353
+ return result
354
+
355
+ except AttributeError:
356
+ print(f"❌ 接口 {api_name} 不存在")
357
+ return None
358
+ except Exception as e:
359
+ print(f"❌ 调用接口 {api_name} 失败:{e}")
360
+ return None
361
+
362
+ # 使用示例
363
+ client = dc.init(token='your_api_token')
364
+ result = dynamic_api_call(client, 'hsgt_fund_page_list', page=1, page_size=10)
365
+ if result is not None:
366
+ print(f"成功获取 {len(result)} 条数据")
367
+ ```
368
+
369
+ ## 9. ❓ 常见问题
370
+
371
+ ### Q1: 如何获取API Token?
372
+ **A**: 请联系系统管理员或访问数据管理后台申请API访问权限。
373
+
374
+ ### Q2: 支持哪些股票代码格式?
375
+ **A**:
376
+ - A股:基础格式6位数字或带后缀格式,如 "000001", "600000","000001.SZ", "600000.SH"
377
+ - 港股:基础格式5位数字,如 "00700", "00941", "00700.HK"
378
+ - 指数:通常包含后缀,如 "000300.SH", "000905.SZ"
379
+
380
+ ### Q3: 如何知道某个接口是否存在?
381
+ **A**:
382
+ ```python
383
+ # 搜索接口
384
+ import requests
385
+ response = requests.get('http://data.alphaaidig.com/api/v1/docs/search?q=接口名')
386
+ if response.status_code == 200:
387
+ results = response.json()
388
+ print(f"找到 {results['total_count']} 个相关接口")
389
+ ```
390
+
391
+ ### Q4: 如何处理大量数据?
392
+ **A**:
393
+ 1. 每次请求适量数据
394
+ 2. 正确处理分页信息,避免遗漏数据
395
+ 3. 添加适当的延迟避免频率限制
396
+ 4. 使用批量处理提高效率
397
+
398
+ ### Q5: API调用失败怎么办?
399
+ **A**:
400
+ 1. 检查网络连接和base_url是否正确
401
+ 2. 验证API token是否有效
402
+ 3. 确认接口名称和参数是否正确
403
+ 4. 查看错误信息进行针对性处理
404
+ 5. 使用错误处理机制捕获异常
405
+
406
+ ### Q6: 返回的数据格式是什么?
407
+ **A**:
408
+ - **分页数据**: PageDataFrame,包含分页信息和数据
409
+ - **普通数据**: pandas DataFrame
410
+ - **单条记录**: pandas DataFrame(单行)
411
+ - **其他**: 根据具体接口可能返回不同格式
412
+
413
+ ### Q7: 如何获取完整的接口文档?
414
+ **A**:
415
+ ```python
416
+ import requests
417
+
418
+ # 获取完整文档
419
+ response = requests.get('http://data.alphaaidig.com/api/v1/docs/json')
420
+ if response.status_code == 200:
421
+ docs = response.json()
422
+ print(f"总共有 {docs['total_count']} 个接口")
423
+ for api in docs['apis']:
424
+ print(f"- {api['name']}: {api['description']}")
425
+ ```
426
+
427
+ ### Q8: IDE无法识别动态方法怎么办?
428
+ **A**: 现代IDE(如PyCharm、VSCode)会通过运行时学习动态方法,使用几次后就能识别。也可以:
429
+ 1. 使用 `client.query('方法名')` 的方式调用
430
+ 2. 添加类型提示注释
431
+ 3. 确保导入正确的异常类
432
+
433
+ ## 📞 技术支持
434
+
435
+ 如果遇到问题,可以:
436
+ 1. 查看API错误信息进行调试
437
+ 2. 访问 http://data.alphaaidig.com/api/v1/docs 查看完整API文档
438
+ 3. 联系技术支持团队
@@ -0,0 +1,20 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "alpha-dc-client"
7
+ version = "0.1.23"
8
+ authors = [
9
+ {name = "Hang GuangLiang", email = "hanguangliang@alphaaidig.com"},
10
+ ]
11
+ dependencies = [
12
+ "httpx",
13
+ "dc_common==0.1.23"
14
+ ]
15
+
16
+ [tool.hatch.build.targets.wheel]
17
+ packages = ["src/dc_client"]
18
+
19
+ [tool.uv.sources]
20
+ dc_common = { workspace = true }
@@ -0,0 +1,20 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "dc_client"
7
+ version = "0.1.23"
8
+ authors = [
9
+ {name = "Hang GuangLiang", email = "hanguangliang@alphaaidig.com"},
10
+ ]
11
+ dependencies = [
12
+ "httpx",
13
+ "dc_common==0.1.23"
14
+ ]
15
+
16
+ [tool.hatch.build.targets.wheel]
17
+ packages = ["src/dc_client"]
18
+
19
+ [tool.uv.sources]
20
+ dc_common = { workspace = true }
@@ -0,0 +1,13 @@
1
+ from .exceptions import APIError, AuthenticationError, NotFoundError, InvalidRequestError
2
+ from .client import DataApi, init, PageDataFrame, DatacenterAPIError
3
+
4
+ __all__ = [
5
+ "DataApi",
6
+ "init",
7
+ "PageDataFrame",
8
+ "DatacenterAPIError",
9
+ "APIError",
10
+ "AuthenticationError",
11
+ "NotFoundError",
12
+ "InvalidRequestError",
13
+ ]
@@ -0,0 +1,69 @@
1
+ import httpx
2
+ from typing import Optional, Dict, Any
3
+
4
+ from .exceptions import APIError, AuthenticationError, NotFoundError, InvalidRequestError
5
+
6
+ class BaseClient:
7
+ """
8
+ A base client for making requests to the Datacenter API.
9
+ """
10
+ def __init__(self, base_url: str, token: Optional[str] = None, timeout: int = 30):
11
+ """
12
+ Initializes the API client.
13
+
14
+ Args:
15
+ base_url: The base URL for the API, e.g., "http://localhost:10000".
16
+ token: An optional token for authentication.
17
+ timeout: The request timeout in seconds.
18
+ """
19
+ self._base_url = base_url.rstrip('/')
20
+ self._token = token
21
+ self._timeout = timeout
22
+
23
+ headers = {"Content-Type": "application/json"}
24
+ if self._token:
25
+ headers["X-API-Key"] = self._token
26
+
27
+ self._http_client = httpx.Client(base_url=self._base_url, headers=headers, timeout=self._timeout)
28
+
29
+ def _request(self, method: str, endpoint: str, params: Optional[Dict[str, Any]] = None, json: Optional[Dict[str, Any]] = None) -> Any:
30
+ """
31
+ Makes an HTTP request and handles potential errors.
32
+ """
33
+ try:
34
+ response = self._http_client.request(method, endpoint, params=params, json=json)
35
+ response.raise_for_status()
36
+
37
+ response_data = response.json()
38
+ if response_data.get("status") == "success":
39
+ return response_data
40
+
41
+ raise APIError(f"API returned non-success status: {response_data.get('status', 'N/A')}", status_code=response.status_code)
42
+
43
+ except httpx.HTTPStatusError as e:
44
+ status_code = e.response.status_code
45
+ try:
46
+ detail = e.response.json().get("detail", e.response.text)
47
+ except Exception:
48
+ detail = e.response.text
49
+
50
+ if status_code == 404:
51
+ raise NotFoundError(detail) from e
52
+ elif status_code in [401, 403]:
53
+ raise AuthenticationError(detail) from e
54
+ elif status_code == 400:
55
+ raise InvalidRequestError(detail) from e
56
+ else:
57
+ raise APIError(f"HTTP Error: {detail}", status_code=status_code) from e
58
+ except httpx.RequestError as e:
59
+ raise APIError(f"Request failed: {e}") from e
60
+
61
+ def close(self):
62
+ """Closes the underlying HTTP client."""
63
+ self._http_client.close()
64
+
65
+ def __enter__(self):
66
+ return self
67
+
68
+ def __exit__(self, exc_type, exc_val, exc_tb):
69
+ self.close()