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.
@@ -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.
@@ -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,3 @@
1
+ from asharehub.client import AShareHub
2
+
3
+ __all__ = ["AShareHub"]
@@ -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,5 @@
1
+ httpx>=0.27.0
2
+ pydantic>=2.0.0
3
+
4
+ [dev]
5
+ pytest>=8.0.0
@@ -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,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -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