asharehub 0.1.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.
- asharehub-0.1.0/LICENSE +21 -0
- asharehub-0.1.0/PKG-INFO +92 -0
- asharehub-0.1.0/README.md +61 -0
- asharehub-0.1.0/asharehub/__init__.py +3 -0
- asharehub-0.1.0/asharehub/client.py +172 -0
- asharehub-0.1.0/asharehub/models.py +126 -0
- asharehub-0.1.0/asharehub.egg-info/PKG-INFO +92 -0
- asharehub-0.1.0/asharehub.egg-info/SOURCES.txt +12 -0
- asharehub-0.1.0/asharehub.egg-info/dependency_links.txt +1 -0
- asharehub-0.1.0/asharehub.egg-info/requires.txt +5 -0
- asharehub-0.1.0/asharehub.egg-info/top_level.txt +1 -0
- asharehub-0.1.0/pyproject.toml +46 -0
- asharehub-0.1.0/setup.cfg +4 -0
- asharehub-0.1.0/tests/test_sdk.py +83 -0
asharehub-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 AShareHub
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
asharehub-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: asharehub
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for AShareHub — Chinese A-Share market data API
|
|
5
|
+
Author-email: AShareHub <support@asharehub.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://asharehub.com
|
|
8
|
+
Project-URL: Documentation, https://asharehub.com/docs
|
|
9
|
+
Project-URL: Repository, https://github.com/ChuYiCui1/AshareHub
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/ChuYiCui1/AshareHub/issues
|
|
11
|
+
Keywords: asharehub,china,a-share,stock,market,data,api,finance
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: httpx>=0.27.0
|
|
27
|
+
Requires-Dist: pydantic>=2.0.0
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# AShareHub Python SDK
|
|
33
|
+
|
|
34
|
+
Official Python SDK for [AShareHub](https://asharehub.com) — Chinese A-Share market data API.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install asharehub
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Quick Start
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from asharehub import AShareHub
|
|
46
|
+
|
|
47
|
+
# Initialize client with your API key
|
|
48
|
+
client = AShareHub(api_key="ash_your_key_here")
|
|
49
|
+
|
|
50
|
+
# Get daily market data
|
|
51
|
+
df = client.market_daily(ts_code="000001.SZ", start_date="2024-01-01", limit=10)
|
|
52
|
+
print(df)
|
|
53
|
+
|
|
54
|
+
# Get northbound capital flows
|
|
55
|
+
flows = client.northbound_flows(start_date="2024-01-01", end_date="2024-01-31")
|
|
56
|
+
print(flows)
|
|
57
|
+
|
|
58
|
+
# Get financial indicators
|
|
59
|
+
financials = client.financial_indicators(ts_code="000001.SZ", limit=4)
|
|
60
|
+
print(financials)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Available Methods
|
|
64
|
+
|
|
65
|
+
| Method | Endpoint | Description |
|
|
66
|
+
|--------|----------|-------------|
|
|
67
|
+
| `market_daily()` | `/v1/market/daily` | Daily OHLCV prices |
|
|
68
|
+
| `fundamentals()` | `/v1/market/fundamentals` | PE, PB, turnover, market cap |
|
|
69
|
+
| `northbound_flows()` | `/v1/flows/northbound` | Stock Connect capital flows |
|
|
70
|
+
| `chip_distribution()` | `/v1/chips/distribution` | Cost distribution & winner rates |
|
|
71
|
+
| `fx_daily()` | `/v1/fx/daily` | FX rates (default USD/CNH) |
|
|
72
|
+
| `index_daily()` | `/v1/indices/daily` | Index OHLCV data |
|
|
73
|
+
| `financial_indicators()` | `/v1/financials/indicators` | Quarterly financial metrics |
|
|
74
|
+
|
|
75
|
+
## Authentication
|
|
76
|
+
|
|
77
|
+
Get your free API key at [asharehub.com/console/register](https://asharehub.com/console/register).
|
|
78
|
+
|
|
79
|
+
## Documentation
|
|
80
|
+
|
|
81
|
+
- API Documentation: https://asharehub.com/docs
|
|
82
|
+
- Website: https://asharehub.com
|
|
83
|
+
|
|
84
|
+
## Requirements
|
|
85
|
+
|
|
86
|
+
- Python 3.10+
|
|
87
|
+
- httpx >= 0.27.0
|
|
88
|
+
- pydantic >= 2.0.0
|
|
89
|
+
|
|
90
|
+
## License
|
|
91
|
+
|
|
92
|
+
MIT
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# AShareHub Python SDK
|
|
2
|
+
|
|
3
|
+
Official Python SDK for [AShareHub](https://asharehub.com) — Chinese A-Share market data API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install asharehub
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from asharehub import AShareHub
|
|
15
|
+
|
|
16
|
+
# Initialize client with your API key
|
|
17
|
+
client = AShareHub(api_key="ash_your_key_here")
|
|
18
|
+
|
|
19
|
+
# Get daily market data
|
|
20
|
+
df = client.market_daily(ts_code="000001.SZ", start_date="2024-01-01", limit=10)
|
|
21
|
+
print(df)
|
|
22
|
+
|
|
23
|
+
# Get northbound capital flows
|
|
24
|
+
flows = client.northbound_flows(start_date="2024-01-01", end_date="2024-01-31")
|
|
25
|
+
print(flows)
|
|
26
|
+
|
|
27
|
+
# Get financial indicators
|
|
28
|
+
financials = client.financial_indicators(ts_code="000001.SZ", limit=4)
|
|
29
|
+
print(financials)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Available Methods
|
|
33
|
+
|
|
34
|
+
| Method | Endpoint | Description |
|
|
35
|
+
|--------|----------|-------------|
|
|
36
|
+
| `market_daily()` | `/v1/market/daily` | Daily OHLCV prices |
|
|
37
|
+
| `fundamentals()` | `/v1/market/fundamentals` | PE, PB, turnover, market cap |
|
|
38
|
+
| `northbound_flows()` | `/v1/flows/northbound` | Stock Connect capital flows |
|
|
39
|
+
| `chip_distribution()` | `/v1/chips/distribution` | Cost distribution & winner rates |
|
|
40
|
+
| `fx_daily()` | `/v1/fx/daily` | FX rates (default USD/CNH) |
|
|
41
|
+
| `index_daily()` | `/v1/indices/daily` | Index OHLCV data |
|
|
42
|
+
| `financial_indicators()` | `/v1/financials/indicators` | Quarterly financial metrics |
|
|
43
|
+
|
|
44
|
+
## Authentication
|
|
45
|
+
|
|
46
|
+
Get your free API key at [asharehub.com/console/register](https://asharehub.com/console/register).
|
|
47
|
+
|
|
48
|
+
## Documentation
|
|
49
|
+
|
|
50
|
+
- API Documentation: https://asharehub.com/docs
|
|
51
|
+
- Website: https://asharehub.com
|
|
52
|
+
|
|
53
|
+
## Requirements
|
|
54
|
+
|
|
55
|
+
- Python 3.10+
|
|
56
|
+
- httpx >= 0.27.0
|
|
57
|
+
- pydantic >= 2.0.0
|
|
58
|
+
|
|
59
|
+
## License
|
|
60
|
+
|
|
61
|
+
MIT
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"""AShareHub Python SDK — typed client for Chinese A-Share market data."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
from asharehub.models import (
|
|
8
|
+
DailyBar,
|
|
9
|
+
Fundamentals,
|
|
10
|
+
NorthboundFlow,
|
|
11
|
+
ChipDistribution,
|
|
12
|
+
FxDaily,
|
|
13
|
+
IndexDaily,
|
|
14
|
+
FinaIndicator,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
DEFAULT_BASE_URL = "https://asharehub.com"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class AShareHub:
|
|
21
|
+
"""Client for the AShareHub API.
|
|
22
|
+
|
|
23
|
+
Usage::
|
|
24
|
+
|
|
25
|
+
from asharehub import AShareHub
|
|
26
|
+
|
|
27
|
+
client = AShareHub(api_key="ash_...")
|
|
28
|
+
bars = client.daily("000001.SZ", start_date="2024-01-01")
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
api_key: str,
|
|
34
|
+
base_url: str = DEFAULT_BASE_URL,
|
|
35
|
+
timeout: float = 30.0,
|
|
36
|
+
):
|
|
37
|
+
self._client = httpx.Client(
|
|
38
|
+
base_url=base_url,
|
|
39
|
+
headers={"X-API-Key": api_key},
|
|
40
|
+
timeout=timeout,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def close(self):
|
|
44
|
+
self._client.close()
|
|
45
|
+
|
|
46
|
+
def __enter__(self):
|
|
47
|
+
return self
|
|
48
|
+
|
|
49
|
+
def __exit__(self, *args):
|
|
50
|
+
self.close()
|
|
51
|
+
|
|
52
|
+
def _get(self, path: str, params: dict) -> list[dict]:
|
|
53
|
+
params = {k: v for k, v in params.items() if v is not None}
|
|
54
|
+
r = self._client.get(path, params=params)
|
|
55
|
+
r.raise_for_status()
|
|
56
|
+
return r.json()
|
|
57
|
+
|
|
58
|
+
# ── Market ────────────────────────────────────────────────────────────
|
|
59
|
+
|
|
60
|
+
def market_daily(
|
|
61
|
+
self,
|
|
62
|
+
ts_code: Optional[str] = None,
|
|
63
|
+
start_date: Optional[str] = None,
|
|
64
|
+
end_date: Optional[str] = None,
|
|
65
|
+
limit: int = 100,
|
|
66
|
+
offset: int = 0,
|
|
67
|
+
) -> list[DailyBar]:
|
|
68
|
+
"""Get daily OHLC price data."""
|
|
69
|
+
data = self._get("/v1/market/daily", {
|
|
70
|
+
"ts_code": ts_code, "start_date": start_date,
|
|
71
|
+
"end_date": end_date, "limit": limit, "offset": offset,
|
|
72
|
+
})
|
|
73
|
+
return [DailyBar(**row) for row in data]
|
|
74
|
+
|
|
75
|
+
def fundamentals(
|
|
76
|
+
self,
|
|
77
|
+
ts_code: Optional[str] = None,
|
|
78
|
+
start_date: Optional[str] = None,
|
|
79
|
+
end_date: Optional[str] = None,
|
|
80
|
+
limit: int = 100,
|
|
81
|
+
offset: int = 0,
|
|
82
|
+
) -> list[Fundamentals]:
|
|
83
|
+
"""Get daily valuation metrics (PE, PB, turnover rate, market cap)."""
|
|
84
|
+
data = self._get("/v1/market/fundamentals", {
|
|
85
|
+
"ts_code": ts_code, "start_date": start_date,
|
|
86
|
+
"end_date": end_date, "limit": limit, "offset": offset,
|
|
87
|
+
})
|
|
88
|
+
return [Fundamentals(**row) for row in data]
|
|
89
|
+
|
|
90
|
+
# ── Flows ─────────────────────────────────────────────────────────────
|
|
91
|
+
|
|
92
|
+
def northbound_flows(
|
|
93
|
+
self,
|
|
94
|
+
start_date: Optional[str] = None,
|
|
95
|
+
end_date: Optional[str] = None,
|
|
96
|
+
limit: int = 100,
|
|
97
|
+
offset: int = 0,
|
|
98
|
+
) -> list[NorthboundFlow]:
|
|
99
|
+
"""Get northbound capital flows (Stock Connect)."""
|
|
100
|
+
data = self._get("/v1/flows/northbound", {
|
|
101
|
+
"start_date": start_date, "end_date": end_date,
|
|
102
|
+
"limit": limit, "offset": offset,
|
|
103
|
+
})
|
|
104
|
+
return [NorthboundFlow(**row) for row in data]
|
|
105
|
+
|
|
106
|
+
# ── Chips ─────────────────────────────────────────────────────────────
|
|
107
|
+
|
|
108
|
+
def chip_distribution(
|
|
109
|
+
self,
|
|
110
|
+
ts_code: Optional[str] = None,
|
|
111
|
+
start_date: Optional[str] = None,
|
|
112
|
+
end_date: Optional[str] = None,
|
|
113
|
+
limit: int = 100,
|
|
114
|
+
offset: int = 0,
|
|
115
|
+
) -> list[ChipDistribution]:
|
|
116
|
+
"""Get chip distribution (cost basis) data."""
|
|
117
|
+
data = self._get("/v1/chips/distribution", {
|
|
118
|
+
"ts_code": ts_code, "start_date": start_date,
|
|
119
|
+
"end_date": end_date, "limit": limit, "offset": offset,
|
|
120
|
+
})
|
|
121
|
+
return [ChipDistribution(**row) for row in data]
|
|
122
|
+
|
|
123
|
+
# ── FX ────────────────────────────────────────────────────────────────
|
|
124
|
+
|
|
125
|
+
def fx_daily(
|
|
126
|
+
self,
|
|
127
|
+
ts_code: Optional[str] = "USDCNH.FXCM",
|
|
128
|
+
start_date: Optional[str] = None,
|
|
129
|
+
end_date: Optional[str] = None,
|
|
130
|
+
limit: int = 100,
|
|
131
|
+
offset: int = 0,
|
|
132
|
+
) -> list[FxDaily]:
|
|
133
|
+
"""Get daily FX rates (default: USD/CNH)."""
|
|
134
|
+
data = self._get("/v1/fx/daily", {
|
|
135
|
+
"ts_code": ts_code, "start_date": start_date,
|
|
136
|
+
"end_date": end_date, "limit": limit, "offset": offset,
|
|
137
|
+
})
|
|
138
|
+
return [FxDaily(**row) for row in data]
|
|
139
|
+
|
|
140
|
+
# ── Indices ───────────────────────────────────────────────────────────
|
|
141
|
+
|
|
142
|
+
def index_daily(
|
|
143
|
+
self,
|
|
144
|
+
ts_code: Optional[str] = "000001.SH",
|
|
145
|
+
start_date: Optional[str] = None,
|
|
146
|
+
end_date: Optional[str] = None,
|
|
147
|
+
limit: int = 100,
|
|
148
|
+
offset: int = 0,
|
|
149
|
+
) -> list[IndexDaily]:
|
|
150
|
+
"""Get daily index data (default: SSE Composite)."""
|
|
151
|
+
data = self._get("/v1/indices/daily", {
|
|
152
|
+
"ts_code": ts_code, "start_date": start_date,
|
|
153
|
+
"end_date": end_date, "limit": limit, "offset": offset,
|
|
154
|
+
})
|
|
155
|
+
return [IndexDaily(**row) for row in data]
|
|
156
|
+
|
|
157
|
+
# ── Financials ────────────────────────────────────────────────────────
|
|
158
|
+
|
|
159
|
+
def financial_indicators(
|
|
160
|
+
self,
|
|
161
|
+
ts_code: Optional[str] = None,
|
|
162
|
+
start_date: Optional[str] = None,
|
|
163
|
+
end_date: Optional[str] = None,
|
|
164
|
+
limit: int = 20,
|
|
165
|
+
offset: int = 0,
|
|
166
|
+
) -> list[FinaIndicator]:
|
|
167
|
+
"""Get financial indicators by reporting period."""
|
|
168
|
+
data = self._get("/v1/financials/indicators", {
|
|
169
|
+
"ts_code": ts_code, "start_date": start_date,
|
|
170
|
+
"end_date": end_date, "limit": limit, "offset": offset,
|
|
171
|
+
})
|
|
172
|
+
return [FinaIndicator(**row) for row in data]
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""Pydantic models matching the AShareHub API response schemas."""
|
|
2
|
+
|
|
3
|
+
from datetime import date
|
|
4
|
+
from decimal import Decimal
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class DailyBar(BaseModel):
|
|
11
|
+
ts_code: str
|
|
12
|
+
trade_date: date
|
|
13
|
+
open: Optional[Decimal] = None
|
|
14
|
+
high: Optional[Decimal] = None
|
|
15
|
+
low: Optional[Decimal] = None
|
|
16
|
+
close: Optional[Decimal] = None
|
|
17
|
+
pre_close: Optional[Decimal] = None
|
|
18
|
+
change: Optional[Decimal] = None
|
|
19
|
+
pct_chg: Optional[Decimal] = None
|
|
20
|
+
vol: Optional[Decimal] = None
|
|
21
|
+
amount: Optional[Decimal] = None
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Fundamentals(BaseModel):
|
|
25
|
+
ts_code: str
|
|
26
|
+
trade_date: date
|
|
27
|
+
close: Optional[Decimal] = None
|
|
28
|
+
turnover_rate: Optional[Decimal] = None
|
|
29
|
+
turnover_rate_f: Optional[Decimal] = None
|
|
30
|
+
volume_ratio: Optional[Decimal] = None
|
|
31
|
+
pe: Optional[Decimal] = None
|
|
32
|
+
pe_ttm: Optional[Decimal] = None
|
|
33
|
+
pb: Optional[Decimal] = None
|
|
34
|
+
ps: Optional[Decimal] = None
|
|
35
|
+
ps_ttm: Optional[Decimal] = None
|
|
36
|
+
dv_ratio: Optional[Decimal] = None
|
|
37
|
+
dv_ttm: Optional[Decimal] = None
|
|
38
|
+
total_share: Optional[Decimal] = None
|
|
39
|
+
float_share: Optional[Decimal] = None
|
|
40
|
+
free_share: Optional[Decimal] = None
|
|
41
|
+
total_mv: Optional[Decimal] = None
|
|
42
|
+
circ_mv: Optional[Decimal] = None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class NorthboundFlow(BaseModel):
|
|
46
|
+
trade_date: date
|
|
47
|
+
ggt_ss: Optional[Decimal] = None
|
|
48
|
+
ggt_sz: Optional[Decimal] = None
|
|
49
|
+
hgt_ss: Optional[Decimal] = None
|
|
50
|
+
hgt_sz: Optional[Decimal] = None
|
|
51
|
+
north_money: Optional[Decimal] = None
|
|
52
|
+
south_money: Optional[Decimal] = None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ChipDistribution(BaseModel):
|
|
56
|
+
ts_code: str
|
|
57
|
+
trade_date: date
|
|
58
|
+
his_low: Optional[Decimal] = None
|
|
59
|
+
his_high: Optional[Decimal] = None
|
|
60
|
+
cost_5pct: Optional[Decimal] = None
|
|
61
|
+
cost_15pct: Optional[Decimal] = None
|
|
62
|
+
cost_50pct: Optional[Decimal] = None
|
|
63
|
+
cost_85pct: Optional[Decimal] = None
|
|
64
|
+
cost_95pct: Optional[Decimal] = None
|
|
65
|
+
weight_avg: Optional[Decimal] = None
|
|
66
|
+
winner_rate: Optional[Decimal] = None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class FxDaily(BaseModel):
|
|
70
|
+
ts_code: str
|
|
71
|
+
trade_date: date
|
|
72
|
+
bid_open: Optional[Decimal] = None
|
|
73
|
+
bid_close: Optional[Decimal] = None
|
|
74
|
+
bid_high: Optional[Decimal] = None
|
|
75
|
+
bid_low: Optional[Decimal] = None
|
|
76
|
+
ask_open: Optional[Decimal] = None
|
|
77
|
+
ask_close: Optional[Decimal] = None
|
|
78
|
+
ask_high: Optional[Decimal] = None
|
|
79
|
+
ask_low: Optional[Decimal] = None
|
|
80
|
+
tick_qty: Optional[int] = None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class IndexDaily(BaseModel):
|
|
84
|
+
ts_code: str
|
|
85
|
+
trade_date: date
|
|
86
|
+
close: Optional[Decimal] = None
|
|
87
|
+
open: Optional[Decimal] = None
|
|
88
|
+
high: Optional[Decimal] = None
|
|
89
|
+
low: Optional[Decimal] = None
|
|
90
|
+
pre_close: Optional[Decimal] = None
|
|
91
|
+
change: Optional[Decimal] = None
|
|
92
|
+
pct_chg: Optional[Decimal] = None
|
|
93
|
+
vol: Optional[Decimal] = None
|
|
94
|
+
amount: Optional[Decimal] = None
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class FinaIndicator(BaseModel):
|
|
98
|
+
ts_code: str
|
|
99
|
+
ann_date: Optional[date] = None
|
|
100
|
+
end_date: date
|
|
101
|
+
eps: Optional[Decimal] = None
|
|
102
|
+
dt_eps: Optional[Decimal] = None
|
|
103
|
+
total_revenue_ps: Optional[Decimal] = None
|
|
104
|
+
revenue_ps: Optional[Decimal] = None
|
|
105
|
+
bps: Optional[Decimal] = None
|
|
106
|
+
ocfps: Optional[Decimal] = None
|
|
107
|
+
roe: Optional[Decimal] = None
|
|
108
|
+
roe_waa: Optional[Decimal] = None
|
|
109
|
+
roe_dt: Optional[Decimal] = None
|
|
110
|
+
roa: Optional[Decimal] = None
|
|
111
|
+
gross_margin: Optional[Decimal] = None
|
|
112
|
+
netprofit_margin: Optional[Decimal] = None
|
|
113
|
+
grossprofit_margin: Optional[Decimal] = None
|
|
114
|
+
debt_to_assets: Optional[Decimal] = None
|
|
115
|
+
current_ratio: Optional[Decimal] = None
|
|
116
|
+
quick_ratio: Optional[Decimal] = None
|
|
117
|
+
cash_ratio: Optional[Decimal] = None
|
|
118
|
+
assets_turn: Optional[Decimal] = None
|
|
119
|
+
inv_turn: Optional[Decimal] = None
|
|
120
|
+
ar_turn: Optional[Decimal] = None
|
|
121
|
+
roic: Optional[Decimal] = None
|
|
122
|
+
basic_eps_yoy: Optional[Decimal] = None
|
|
123
|
+
dt_eps_yoy: Optional[Decimal] = None
|
|
124
|
+
netprofit_yoy: Optional[Decimal] = None
|
|
125
|
+
dt_netprofit_yoy: Optional[Decimal] = None
|
|
126
|
+
rd_exp: Optional[Decimal] = None
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: asharehub
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for AShareHub — Chinese A-Share market data API
|
|
5
|
+
Author-email: AShareHub <support@asharehub.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://asharehub.com
|
|
8
|
+
Project-URL: Documentation, https://asharehub.com/docs
|
|
9
|
+
Project-URL: Repository, https://github.com/ChuYiCui1/AshareHub
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/ChuYiCui1/AshareHub/issues
|
|
11
|
+
Keywords: asharehub,china,a-share,stock,market,data,api,finance
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: httpx>=0.27.0
|
|
27
|
+
Requires-Dist: pydantic>=2.0.0
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# AShareHub Python SDK
|
|
33
|
+
|
|
34
|
+
Official Python SDK for [AShareHub](https://asharehub.com) — Chinese A-Share market data API.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install asharehub
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Quick Start
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from asharehub import AShareHub
|
|
46
|
+
|
|
47
|
+
# Initialize client with your API key
|
|
48
|
+
client = AShareHub(api_key="ash_your_key_here")
|
|
49
|
+
|
|
50
|
+
# Get daily market data
|
|
51
|
+
df = client.market_daily(ts_code="000001.SZ", start_date="2024-01-01", limit=10)
|
|
52
|
+
print(df)
|
|
53
|
+
|
|
54
|
+
# Get northbound capital flows
|
|
55
|
+
flows = client.northbound_flows(start_date="2024-01-01", end_date="2024-01-31")
|
|
56
|
+
print(flows)
|
|
57
|
+
|
|
58
|
+
# Get financial indicators
|
|
59
|
+
financials = client.financial_indicators(ts_code="000001.SZ", limit=4)
|
|
60
|
+
print(financials)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Available Methods
|
|
64
|
+
|
|
65
|
+
| Method | Endpoint | Description |
|
|
66
|
+
|--------|----------|-------------|
|
|
67
|
+
| `market_daily()` | `/v1/market/daily` | Daily OHLCV prices |
|
|
68
|
+
| `fundamentals()` | `/v1/market/fundamentals` | PE, PB, turnover, market cap |
|
|
69
|
+
| `northbound_flows()` | `/v1/flows/northbound` | Stock Connect capital flows |
|
|
70
|
+
| `chip_distribution()` | `/v1/chips/distribution` | Cost distribution & winner rates |
|
|
71
|
+
| `fx_daily()` | `/v1/fx/daily` | FX rates (default USD/CNH) |
|
|
72
|
+
| `index_daily()` | `/v1/indices/daily` | Index OHLCV data |
|
|
73
|
+
| `financial_indicators()` | `/v1/financials/indicators` | Quarterly financial metrics |
|
|
74
|
+
|
|
75
|
+
## Authentication
|
|
76
|
+
|
|
77
|
+
Get your free API key at [asharehub.com/console/register](https://asharehub.com/console/register).
|
|
78
|
+
|
|
79
|
+
## Documentation
|
|
80
|
+
|
|
81
|
+
- API Documentation: https://asharehub.com/docs
|
|
82
|
+
- Website: https://asharehub.com
|
|
83
|
+
|
|
84
|
+
## Requirements
|
|
85
|
+
|
|
86
|
+
- Python 3.10+
|
|
87
|
+
- httpx >= 0.27.0
|
|
88
|
+
- pydantic >= 2.0.0
|
|
89
|
+
|
|
90
|
+
## License
|
|
91
|
+
|
|
92
|
+
MIT
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
asharehub/__init__.py
|
|
5
|
+
asharehub/client.py
|
|
6
|
+
asharehub/models.py
|
|
7
|
+
asharehub.egg-info/PKG-INFO
|
|
8
|
+
asharehub.egg-info/SOURCES.txt
|
|
9
|
+
asharehub.egg-info/dependency_links.txt
|
|
10
|
+
asharehub.egg-info/requires.txt
|
|
11
|
+
asharehub.egg-info/top_level.txt
|
|
12
|
+
tests/test_sdk.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
asharehub
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "asharehub"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python SDK for AShareHub — Chinese A-Share market data API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "AShareHub", email = "support@asharehub.com"}
|
|
14
|
+
]
|
|
15
|
+
keywords = ["asharehub", "china", "a-share", "stock", "market", "data", "api", "finance"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Intended Audience :: Financial and Insurance Industry",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Topic :: Office/Business :: Financial",
|
|
27
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"httpx>=0.27.0",
|
|
31
|
+
"pydantic>=2.0.0",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://asharehub.com"
|
|
36
|
+
Documentation = "https://asharehub.com/docs"
|
|
37
|
+
Repository = "https://github.com/ChuYiCui1/AshareHub"
|
|
38
|
+
"Bug Tracker" = "https://github.com/ChuYiCui1/AshareHub/issues"
|
|
39
|
+
|
|
40
|
+
[project.optional-dependencies]
|
|
41
|
+
dev = [
|
|
42
|
+
"pytest>=8.0.0",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[tool.pytest.ini_options]
|
|
46
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""SDK integration tests — runs against a live API server.
|
|
2
|
+
|
|
3
|
+
Start the API first:
|
|
4
|
+
cd api && uvicorn app.main:app --port 8000
|
|
5
|
+
|
|
6
|
+
Then run:
|
|
7
|
+
cd sdk && pytest -v
|
|
8
|
+
"""
|
|
9
|
+
import os
|
|
10
|
+
import pytest
|
|
11
|
+
from asharehub import AShareHub
|
|
12
|
+
from asharehub.models import (
|
|
13
|
+
DailyBar, Fundamentals, NorthboundFlow,
|
|
14
|
+
ChipDistribution, FxDaily, IndexDaily, FinaIndicator,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
API_KEY = os.getenv("ASHAREHUB_API_KEY", "")
|
|
18
|
+
BASE_URL = os.getenv("ASHAREHUB_BASE_URL", "http://localhost:8000")
|
|
19
|
+
|
|
20
|
+
requires_server = pytest.mark.skipif(
|
|
21
|
+
not API_KEY, reason="ASHAREHUB_API_KEY not set"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.fixture(scope="module")
|
|
26
|
+
def client():
|
|
27
|
+
c = AShareHub(api_key=API_KEY, base_url=BASE_URL)
|
|
28
|
+
yield c
|
|
29
|
+
c.close()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@requires_server
|
|
33
|
+
def test_daily(client):
|
|
34
|
+
bars = client.daily(ts_code="000001.SZ", limit=3)
|
|
35
|
+
assert len(bars) > 0
|
|
36
|
+
assert isinstance(bars[0], DailyBar)
|
|
37
|
+
assert bars[0].ts_code == "000001.SZ"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@requires_server
|
|
41
|
+
def test_fundamentals(client):
|
|
42
|
+
rows = client.fundamentals(ts_code="000001.SZ", limit=3)
|
|
43
|
+
assert len(rows) > 0
|
|
44
|
+
assert isinstance(rows[0], Fundamentals)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@requires_server
|
|
48
|
+
def test_northbound(client):
|
|
49
|
+
rows = client.northbound(limit=3)
|
|
50
|
+
assert len(rows) > 0
|
|
51
|
+
assert isinstance(rows[0], NorthboundFlow)
|
|
52
|
+
assert rows[0].north_money is not None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@requires_server
|
|
56
|
+
def test_chips(client):
|
|
57
|
+
rows = client.chips(ts_code="000001.SZ", limit=3)
|
|
58
|
+
assert len(rows) > 0
|
|
59
|
+
assert isinstance(rows[0], ChipDistribution)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@requires_server
|
|
63
|
+
def test_fx(client):
|
|
64
|
+
rows = client.fx(limit=3)
|
|
65
|
+
assert len(rows) > 0
|
|
66
|
+
assert isinstance(rows[0], FxDaily)
|
|
67
|
+
assert rows[0].ts_code == "USDCNH.FXCM"
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@requires_server
|
|
71
|
+
def test_indices(client):
|
|
72
|
+
rows = client.indices(limit=3)
|
|
73
|
+
assert len(rows) > 0
|
|
74
|
+
assert isinstance(rows[0], IndexDaily)
|
|
75
|
+
assert rows[0].ts_code == "000001.SH"
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@requires_server
|
|
79
|
+
def test_financials(client):
|
|
80
|
+
rows = client.financials(ts_code="000001.SZ", limit=3)
|
|
81
|
+
assert len(rows) > 0
|
|
82
|
+
assert isinstance(rows[0], FinaIndicator)
|
|
83
|
+
assert rows[0].roe is not None
|