openbb-akshare 0.3.1__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,148 @@
1
+ Metadata-Version: 2.3
2
+ Name: openbb-akshare
3
+ Version: 0.3.1
4
+ Summary: AKShare extension for OpenBB
5
+ License: AGPL-3.0-only
6
+ Author: Roger Ye
7
+ Author-email: shugaoye@yahoo.com
8
+ Requires-Python: >=3.9,<3.13
9
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Dist: akshare (==1.16.98)
16
+ Requires-Dist: openbb-core (>=1.4.7,<2.0.0)
17
+ Description-Content-Type: text/markdown
18
+
19
+ # How to Use AKShare as a Data Source for OpenBB
20
+
21
+ **OpenBB**, as an open-source financial data platform, is dedicated to providing free and transparent financial data interfaces for investors, analysts, and developers. For a detailed introduction to OpenBB and its usage, please refer to [Introduction to OpenBB and How to Use It to Aid Financial Data Analysis of China A-share and Hong Kong Stocks]().
22
+
23
+ Although OpenBB supports multi-source data interfaces, the acquisition of financial data in China (including Hong Kong) mainly relies on Yahoo Finance. As a free basic data source, it can meet basic needs, but its coverage depth for the Chinese and Hong Kong markets is still insufficient. More importantly, mainland Chinese users need to use a VPN to access this service, creating significant usage barriers.
24
+
25
+ To enhance service capabilities in Greater China, OpenBB urgently needs to improve the implementation of localized financial data sources. The mainstream paid solutions include Wind, Eastmoney Choice, and 同花顺 iFind (mainly for institutional clients), while the free solutions focus on the open-source tool AKShare as the core solution. By integrating data interfaces from platforms such as Eastmoney, 同花顺, Tencent, Sina, and 雪球, AKShare has become one of the most comprehensive, up-to-date, and developer-friendly financial data aggregation libraries in the domestic Python ecosystem.
26
+
27
+ The `openbb_akshare` project, as a data source extension for OpenBB, enables seamless integration of AKShare data into the OpenBB platform. Below is a detailed usage guide:
28
+
29
+ ## 💻 Environment Setup and Installation Process
30
+
31
+ As developers, we primarily interact with the platform through the OpenBB Platform CLI. To integrate the AKShare data source, follow these steps to configure the development environment:
32
+
33
+ 1. **Create a Python Virtual Environment**
34
+
35
+ You can use `venv`, `uv`, or `poetry` to create a virtual environment. Here, we use venv (built into Python):
36
+
37
+ ```bash
38
+ # Create a virtual environment
39
+ python3 -m venv .venv
40
+
41
+ # Activate the virtual environment (Linux/Mac)
42
+ source .venv/bin/activate
43
+
44
+ # For Windows
45
+ .venv\Scripts\activate
46
+ ```
47
+
48
+ 2. **Install OpenBB Platform CLI**
49
+
50
+ Install the core OpenBB CLI via pip. Users in mainland China can configure a mirror for faster installation:
51
+
52
+ ```bash
53
+ # (Optional) Set a domestic mirror for pip
54
+ # For Linux/Mac
55
+ export PIP_INDEX_URL=https://mirrors.aliyun.com/pypi/simple
56
+
57
+ # Install OpenBB CLI
58
+ pip install openbb-cli
59
+ ```
60
+
61
+ 3. **Install openbb_akshare**
62
+
63
+ Next, install the `openbb_akshare` extenstion to use the AKShare data source:
64
+
65
+ ```bash
66
+ # Install the AKShare data source extension
67
+ pip install openbb_akshare
68
+
69
+ # Rebuild OpenBB resources to activate the plugin
70
+ python -c "import openbb; openbb.build()"
71
+ ```
72
+
73
+ ## 🚀 Using the AKShare Data Source
74
+
75
+ ### Case 1: Query A-Share Company News (Vanke as an Example)
76
+
77
+ **Jupyter Notebook**:
78
+
79
+ ```Python
80
+ from openbb import obb
81
+ messages = obb.news.company("000002", provider="akshare")
82
+ for result in messages.results:
83
+ print(f"{result.title}")
84
+ ```
85
+
86
+ Output:
87
+
88
+ ```plaintext
89
+ 开源证券发布万科A研报,公司信息更新报告:销售均价有所提升,股东持续借款提供支持
90
+ 万科A出售2086万股库存股,金额1.36亿元
91
+ 万科A:已完成所有A股库存股出售 所得资金4.79亿元
92
+ ...
93
+ ```
94
+
95
+ **Using OpenBB CLI**:
96
+
97
+ ```bash
98
+ openbb
99
+ 2025 Jun 26, 03:11 (🦋) /news/ $ company --symbol 000002 --provider akshare
100
+ ```
101
+
102
+ After entering the command, the results will be displayed in a WebView, as shown below:
103
+
104
+ ![openbb04](images/openbb04.png)
105
+
106
+ ### Case 2: Obtain Historical Stock Prices of Hong Kong Stocks (Hong Kong Telecom as an Example)
107
+
108
+ **Using OpenBB CLI**:
109
+
110
+ ```
111
+ 2025 Jun 26, 03:28 (🦋) /equity/price/ $ historical --symbol 06823 --provider akshare
112
+ ```
113
+
114
+ Results in WebView:![openbb05](images/openbb05.png)
115
+
116
+ **Jupyter Notebook**:
117
+
118
+ ```Python
119
+ from openbb import obb
120
+ prices = obb.equity.price.historical(symbol='06823', start_date="2025-06-01", end_date="2025-06-10", provider="akshare")
121
+ prices.results[0].date, prices.results[0].open, prices.results[0].close, prices.results[0].high, prices.results[0].low, prices.results[0].volume
122
+ ```
123
+
124
+ Output:
125
+
126
+ ```
127
+ (datetime.date(2025, 6, 2), 11.28, 11.3, 11.3, 11.14, 10308375)
128
+ ```
129
+
130
+ ## 🌟 openbb_akshare Project Ecosystem
131
+
132
+ The `openbb_akshare` project is currently in an active development phase, and contributions from the open-source community are welcome:
133
+
134
+ ### Code Repositories
135
+
136
+ - **GitHub**: https://github.com/finanalyzer/openbb_akshare
137
+
138
+ - **GitCode (Domestic Mirror)**: https://gitcode.com/finanalyzer/openbb_akshare
139
+
140
+ ### Ways to Contribute
141
+
142
+ 1. Submit Issues to report data needs or bugs.
143
+
144
+ 2. Contribute PRs to optimize data source interfaces.
145
+
146
+ 3. Improve documentation to help more users.
147
+
148
+ Through the integration of AKShare and OpenBB, users in China can more conveniently access real-time and historical data for markets such as A-Shares and Hong Kong Stocks, providing strong data support for quantitative analysis and investment research.
@@ -0,0 +1,130 @@
1
+ # How to Use AKShare as a Data Source for OpenBB
2
+
3
+ **OpenBB**, as an open-source financial data platform, is dedicated to providing free and transparent financial data interfaces for investors, analysts, and developers. For a detailed introduction to OpenBB and its usage, please refer to [Introduction to OpenBB and How to Use It to Aid Financial Data Analysis of China A-share and Hong Kong Stocks]().
4
+
5
+ Although OpenBB supports multi-source data interfaces, the acquisition of financial data in China (including Hong Kong) mainly relies on Yahoo Finance. As a free basic data source, it can meet basic needs, but its coverage depth for the Chinese and Hong Kong markets is still insufficient. More importantly, mainland Chinese users need to use a VPN to access this service, creating significant usage barriers.
6
+
7
+ To enhance service capabilities in Greater China, OpenBB urgently needs to improve the implementation of localized financial data sources. The mainstream paid solutions include Wind, Eastmoney Choice, and 同花顺 iFind (mainly for institutional clients), while the free solutions focus on the open-source tool AKShare as the core solution. By integrating data interfaces from platforms such as Eastmoney, 同花顺, Tencent, Sina, and 雪球, AKShare has become one of the most comprehensive, up-to-date, and developer-friendly financial data aggregation libraries in the domestic Python ecosystem.
8
+
9
+ The `openbb_akshare` project, as a data source extension for OpenBB, enables seamless integration of AKShare data into the OpenBB platform. Below is a detailed usage guide:
10
+
11
+ ## 💻 Environment Setup and Installation Process
12
+
13
+ As developers, we primarily interact with the platform through the OpenBB Platform CLI. To integrate the AKShare data source, follow these steps to configure the development environment:
14
+
15
+ 1. **Create a Python Virtual Environment**
16
+
17
+ You can use `venv`, `uv`, or `poetry` to create a virtual environment. Here, we use venv (built into Python):
18
+
19
+ ```bash
20
+ # Create a virtual environment
21
+ python3 -m venv .venv
22
+
23
+ # Activate the virtual environment (Linux/Mac)
24
+ source .venv/bin/activate
25
+
26
+ # For Windows
27
+ .venv\Scripts\activate
28
+ ```
29
+
30
+ 2. **Install OpenBB Platform CLI**
31
+
32
+ Install the core OpenBB CLI via pip. Users in mainland China can configure a mirror for faster installation:
33
+
34
+ ```bash
35
+ # (Optional) Set a domestic mirror for pip
36
+ # For Linux/Mac
37
+ export PIP_INDEX_URL=https://mirrors.aliyun.com/pypi/simple
38
+
39
+ # Install OpenBB CLI
40
+ pip install openbb-cli
41
+ ```
42
+
43
+ 3. **Install openbb_akshare**
44
+
45
+ Next, install the `openbb_akshare` extenstion to use the AKShare data source:
46
+
47
+ ```bash
48
+ # Install the AKShare data source extension
49
+ pip install openbb_akshare
50
+
51
+ # Rebuild OpenBB resources to activate the plugin
52
+ python -c "import openbb; openbb.build()"
53
+ ```
54
+
55
+ ## 🚀 Using the AKShare Data Source
56
+
57
+ ### Case 1: Query A-Share Company News (Vanke as an Example)
58
+
59
+ **Jupyter Notebook**:
60
+
61
+ ```Python
62
+ from openbb import obb
63
+ messages = obb.news.company("000002", provider="akshare")
64
+ for result in messages.results:
65
+ print(f"{result.title}")
66
+ ```
67
+
68
+ Output:
69
+
70
+ ```plaintext
71
+ 开源证券发布万科A研报,公司信息更新报告:销售均价有所提升,股东持续借款提供支持
72
+ 万科A出售2086万股库存股,金额1.36亿元
73
+ 万科A:已完成所有A股库存股出售 所得资金4.79亿元
74
+ ...
75
+ ```
76
+
77
+ **Using OpenBB CLI**:
78
+
79
+ ```bash
80
+ openbb
81
+ 2025 Jun 26, 03:11 (🦋) /news/ $ company --symbol 000002 --provider akshare
82
+ ```
83
+
84
+ After entering the command, the results will be displayed in a WebView, as shown below:
85
+
86
+ ![openbb04](images/openbb04.png)
87
+
88
+ ### Case 2: Obtain Historical Stock Prices of Hong Kong Stocks (Hong Kong Telecom as an Example)
89
+
90
+ **Using OpenBB CLI**:
91
+
92
+ ```
93
+ 2025 Jun 26, 03:28 (🦋) /equity/price/ $ historical --symbol 06823 --provider akshare
94
+ ```
95
+
96
+ Results in WebView:![openbb05](images/openbb05.png)
97
+
98
+ **Jupyter Notebook**:
99
+
100
+ ```Python
101
+ from openbb import obb
102
+ prices = obb.equity.price.historical(symbol='06823', start_date="2025-06-01", end_date="2025-06-10", provider="akshare")
103
+ prices.results[0].date, prices.results[0].open, prices.results[0].close, prices.results[0].high, prices.results[0].low, prices.results[0].volume
104
+ ```
105
+
106
+ Output:
107
+
108
+ ```
109
+ (datetime.date(2025, 6, 2), 11.28, 11.3, 11.3, 11.14, 10308375)
110
+ ```
111
+
112
+ ## 🌟 openbb_akshare Project Ecosystem
113
+
114
+ The `openbb_akshare` project is currently in an active development phase, and contributions from the open-source community are welcome:
115
+
116
+ ### Code Repositories
117
+
118
+ - **GitHub**: https://github.com/finanalyzer/openbb_akshare
119
+
120
+ - **GitCode (Domestic Mirror)**: https://gitcode.com/finanalyzer/openbb_akshare
121
+
122
+ ### Ways to Contribute
123
+
124
+ 1. Submit Issues to report data needs or bugs.
125
+
126
+ 2. Contribute PRs to optimize data source interfaces.
127
+
128
+ 3. Improve documentation to help more users.
129
+
130
+ Through the integration of AKShare and OpenBB, users in China can more conveniently access real-time and historical data for markets such as A-Shares and Hong Kong Stocks, providing strong data support for quantitative analysis and investment research.
@@ -0,0 +1,26 @@
1
+ """openbb_akshare OpenBB Platform Provider."""
2
+
3
+ from openbb_core.provider.abstract.provider import Provider
4
+ from openbb_akshare.models.company_news import AKShareCompanyNewsFetcher
5
+ from openbb_akshare.models.equity_quote import AKShareEquityQuoteFetcher
6
+ from openbb_akshare.models.equity_historical import AKShareEquityHistoricalFetcher
7
+ from openbb_akshare.models.historical_dividends import AKShareHistoricalDividendsFetcher
8
+
9
+ # mypy: disable-error-code="list-item"
10
+
11
+ provider = Provider(
12
+ name="akshare",
13
+ description="Data provider for openbb-akshare.",
14
+ # Only add 'credentials' if they are needed.
15
+ # For multiple login details, list them all here.
16
+ # credentials=["api_key"],
17
+ website="https://akshare.akfamily.xyz/",
18
+ # Here, we list out the fetchers showing what our provider can get.
19
+ # The dictionary key is the fetcher's name, used in the `router.py`.
20
+ fetcher_dict={
21
+ "CompanyNews": AKShareCompanyNewsFetcher,
22
+ "EquityQuote": AKShareEquityQuoteFetcher,
23
+ "EquityHistorical": AKShareEquityHistoricalFetcher,
24
+ "HistoricalDividends": AKShareHistoricalDividendsFetcher,
25
+ }
26
+ )
@@ -0,0 +1 @@
1
+ """AKShare models directory."""
@@ -0,0 +1,100 @@
1
+ """AKShare Company News Model."""
2
+
3
+ # pylint: disable=unused-argument
4
+ from typing import Any, Dict, List, Optional
5
+
6
+ from openbb_core.provider.abstract.fetcher import Fetcher
7
+ from openbb_core.provider.standard_models.company_news import (
8
+ CompanyNewsData,
9
+ CompanyNewsQueryParams,
10
+ )
11
+ from pydantic import Field, field_validator
12
+
13
+ class AKshareCompanyNewsQueryParams(CompanyNewsQueryParams):
14
+ """AKShare Company News Query.
15
+
16
+ Source: https://so.eastmoney.com/news/s
17
+ """
18
+
19
+ __json_schema_extra__ = {"symbol": {"multiple_items_allowed": True}}
20
+
21
+ @field_validator("symbol", mode="before", check_fields=False)
22
+ @classmethod
23
+ def _symbol_mandatory(cls, v):
24
+ """Symbol mandatory validator."""
25
+ if not v:
26
+ raise ValueError("Required field missing -> symbol")
27
+ return v
28
+
29
+
30
+ class AKShareCompanyNewsData(CompanyNewsData):
31
+ """AKShare Company News Data."""
32
+
33
+ source: Optional[str] = Field(
34
+ default=None, description="Source of the news article"
35
+ )
36
+
37
+
38
+ class AKShareCompanyNewsFetcher(
39
+ Fetcher[
40
+ AKshareCompanyNewsQueryParams,
41
+ List[AKShareCompanyNewsData],
42
+ ]
43
+ ):
44
+ """Transform the query, extract and transform the data from the AKShare endpoints."""
45
+
46
+ @staticmethod
47
+ def transform_query(params: Dict[str, Any]) -> AKshareCompanyNewsQueryParams:
48
+ """Define example transform_query.
49
+
50
+ Here we can pre-process the query parameters and add any extra parameters that
51
+ will be used inside the extract_data method.
52
+ """
53
+ return AKshareCompanyNewsQueryParams(**params)
54
+
55
+ @staticmethod
56
+ async def aextract_data(
57
+ query: AKshareCompanyNewsQueryParams,
58
+ credentials: Optional[Dict[str, str]],
59
+ **kwargs: Any,
60
+ ) -> List[dict]:
61
+ """Extract data."""
62
+ # pylint: disable=import-outside-toplevel
63
+ import asyncio # noqa
64
+ from openbb_core.provider.utils.errors import EmptyDataError
65
+ from openbb_core.provider.utils.helpers import get_requests_session
66
+ import akshare as ak
67
+
68
+ results: list = []
69
+ symbols = query.symbol.split(",") # type: ignore
70
+ async def get_one(symbol):
71
+ data = ak.stock_news_em(symbol)
72
+ for idx, d in data.iterrows():
73
+ new_content: dict = {}
74
+ new_content["text"] = d["新闻内容"]
75
+ new_content["url"] = d["新闻链接"]
76
+ new_content["source"] = d["文章来源"]
77
+ new_content["title"] = d["新闻标题"]
78
+ new_content["date"] = d["发布时间"]
79
+
80
+ results.append(new_content)
81
+
82
+ tasks = [get_one(symbol) for symbol in symbols]
83
+
84
+ await asyncio.gather(*tasks)
85
+
86
+ if not results:
87
+ raise EmptyDataError("No data was returned for the given symbol(s)")
88
+
89
+ return results
90
+
91
+ @staticmethod
92
+ def transform_data(
93
+ query: AKshareCompanyNewsQueryParams, data: List[dict], **kwargs: Any
94
+ ) -> List[AKShareCompanyNewsData]:
95
+ """Define example transform_data.
96
+
97
+ Right now, we're converting the data to fit our desired format.
98
+ You can apply other transformations to it here.
99
+ """
100
+ return [AKShareCompanyNewsData(**d) for d in data]
@@ -0,0 +1,118 @@
1
+ """AKShare Equity Historical Price Model."""
2
+
3
+ # pylint: disable=unused-argument
4
+
5
+ import asyncio
6
+ from datetime import datetime
7
+ from typing import Any, Dict, List, Literal, Optional
8
+ from warnings import warn
9
+
10
+ from dateutil.relativedelta import relativedelta
11
+ from openbb_core.provider.abstract.fetcher import Fetcher
12
+ from openbb_core.provider.standard_models.equity_historical import (
13
+ EquityHistoricalData,
14
+ EquityHistoricalQueryParams,
15
+ )
16
+ from openbb_core.provider.utils.descriptions import (
17
+ DATA_DESCRIPTIONS,
18
+ QUERY_DESCRIPTIONS,
19
+ )
20
+ from openbb_core.provider.utils.errors import EmptyDataError
21
+ from openbb_core.provider.utils.helpers import (
22
+ amake_request,
23
+ get_querystring,
24
+ )
25
+ from openbb_fmp.utils.helpers import get_interval
26
+ from pydantic import Field
27
+
28
+
29
+ class AKShareEquityHistoricalQueryParams(EquityHistoricalQueryParams):
30
+ """AKShare Equity Historical Price Query.
31
+
32
+ Source: https://financialmodelingprep.com/developer/docs/#Stock-Historical-Price
33
+ """
34
+
35
+ __json_schema_extra__ = {
36
+ "symbol": {"multiple_items_allowed": True},
37
+ "period": {"choices": ["daily", "weekly", "monthly"]},
38
+ }
39
+
40
+ period: Literal["daily", "weekly", "monthly"] = Field(
41
+ default="daily", description=QUERY_DESCRIPTIONS.get("period", "")
42
+ )
43
+
44
+
45
+ class AKShareEquityHistoricalData(EquityHistoricalData):
46
+ """AKShare Equity Historical Price Data."""
47
+
48
+ __alias_dict__ = {
49
+ "date": "日期",
50
+ "open": "开盘",
51
+ "close": "收盘",
52
+ "high": "最高",
53
+ "low": "最低",
54
+ "volume": "成交量",
55
+ "change": "涨跌额",
56
+ "change_percent": "涨跌幅",
57
+ }
58
+
59
+ change: Optional[float] = Field(
60
+ default=None,
61
+ description="Change in the price from the previous close.",
62
+ )
63
+ change_percent: Optional[float] = Field(
64
+ default=None,
65
+ description="Change in the price from the previous close, as a normalized percent.",
66
+ json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
67
+ )
68
+
69
+
70
+ class AKShareEquityHistoricalFetcher(
71
+ Fetcher[
72
+ AKShareEquityHistoricalQueryParams,
73
+ List[AKShareEquityHistoricalData],
74
+ ]
75
+ ):
76
+ """Transform the query, extract and transform the data from the AKShare endpoints."""
77
+
78
+ @staticmethod
79
+ def transform_query(params: Dict[str, Any]) -> AKShareEquityHistoricalQueryParams:
80
+ """Transform the query params."""
81
+ transformed_params = params
82
+
83
+ now = datetime.now().date()
84
+ if params.get("start_date") is None:
85
+ transformed_params["start_date"] = now - relativedelta(years=1)
86
+
87
+ if params.get("end_date") is None:
88
+ transformed_params["end_date"] = now
89
+
90
+ return AKShareEquityHistoricalQueryParams(**transformed_params)
91
+
92
+ @staticmethod
93
+ def extract_data(
94
+ query: AKShareEquityHistoricalQueryParams,
95
+ credentials: Optional[Dict[str, str]],
96
+ **kwargs: Any,
97
+ ) -> List[Dict]:
98
+ """Return the raw data from the AKShare endpoint."""
99
+ from openbb_akshare.utils.helpers import ak_download
100
+
101
+ data = ak_download(symbol=query.symbol, start_date=query.start_date, end_date=query.end_date, period="daily", adjust="")
102
+
103
+ if data.empty:
104
+ raise EmptyDataError()
105
+
106
+ return data
107
+
108
+
109
+ @staticmethod
110
+ def transform_data(
111
+ query: AKShareEquityHistoricalQueryParams, data: List[Dict], **kwargs: Any
112
+ ) -> List[AKShareEquityHistoricalData]:
113
+ """Return the transformed data."""
114
+
115
+ return [
116
+ AKShareEquityHistoricalData.model_validate(d)
117
+ for d in data.to_dict("records")
118
+ ]
@@ -0,0 +1,153 @@
1
+ """AKShare Equity Quote Model."""
2
+
3
+ # pylint: disable=unused-argument
4
+
5
+ from typing import Any, Dict, List, Optional
6
+ from warnings import warn
7
+
8
+ from openbb_core.provider.abstract.fetcher import Fetcher
9
+ from openbb_core.provider.standard_models.equity_quote import (
10
+ EquityQuoteData,
11
+ EquityQuoteQueryParams,
12
+ )
13
+ from pydantic import Field
14
+ import logging
15
+ from openbb_akshare.utils.tools import setup_logger, normalize_symbol, get_symbol_base
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+ class AKShareEquityQuoteQueryParams(EquityQuoteQueryParams):
20
+ """AKShare Equity Quote Query."""
21
+
22
+ __json_schema_extra__ = {"symbol": {"multiple_items_allowed": True}}
23
+
24
+
25
+ class AKShareEquityQuoteData(EquityQuoteData):
26
+ """AKShare Equity Quote Data."""
27
+
28
+ __alias_dict__ = {
29
+ "symbol": "代码",
30
+ "name": "名称",
31
+ "exchange": "交易所",
32
+ "last_price": "现价",
33
+ "open": "今开",
34
+ "close": "均价",
35
+ "high": "最高",
36
+ "low": "最低",
37
+ "prev_close": "昨收",
38
+ "year_high": "52周最高",
39
+ "year_low": "52周最低",
40
+ "volume": "成交量",
41
+ "change": "涨跌",
42
+ "participant_timestamp": "时间",
43
+ "market_cap": "流通值",
44
+ "pe_ratio": "市盈率(动)",
45
+ "pe_ratio_ttm": "市盈率(TTM)",
46
+ "turnover": "成交额",
47
+ "currency": "货币",
48
+ }
49
+
50
+ market_cap: Optional[float] = Field(
51
+ default=None,
52
+ description="Market capitalization.",
53
+ )
54
+ pe_ratio: Optional[float] = Field(
55
+ default=None,
56
+ description="Price-to-earnings ratio.",
57
+ )
58
+ pe_ratio_ttm: Optional[float] = Field(
59
+ default=None,
60
+ description="Price-to-earnings ratio (TTM).",
61
+ )
62
+ turnover: Optional[float] = Field(
63
+ default=None,
64
+ description="Turnover of the stock.",
65
+ )
66
+ currency: Optional[str] = Field(
67
+ default=None,
68
+ description="Currency of the price.",
69
+ )
70
+
71
+
72
+ class AKShareEquityQuoteFetcher(
73
+ Fetcher[AKShareEquityQuoteQueryParams, List[AKShareEquityQuoteData]]
74
+ ):
75
+ """AKShare Equity Quote Fetcher."""
76
+
77
+ @staticmethod
78
+ def transform_query(params: Dict[str, Any]) -> AKShareEquityQuoteQueryParams:
79
+ """Transform the query."""
80
+ return AKShareEquityQuoteQueryParams(**params)
81
+
82
+ @staticmethod
83
+ async def aextract_data(
84
+ query: AKShareEquityQuoteQueryParams,
85
+ credentials: Optional[Dict[str, str]],
86
+ **kwargs: Any,
87
+ ) -> List[Dict]:
88
+ """Extract the raw data from AKShare."""
89
+ # pylint: disable=import-outside-toplevel
90
+ import asyncio # noqa
91
+ from curl_adapter import CurlCffiAdapter
92
+ from openbb_core.provider.utils.helpers import get_requests_session
93
+ import akshare as ak
94
+
95
+ symbols = query.symbol.split(",")
96
+ results = []
97
+ fields = ['代码',
98
+ '名称',
99
+ '交易所',
100
+ '现价',
101
+ '今开',
102
+ '均价',
103
+ '最高',
104
+ '最低',
105
+ '昨收',
106
+ '52周最高',
107
+ '52周最低',
108
+ '成交量',
109
+ '涨跌',
110
+ '时间',
111
+ '流通值',
112
+ '市盈率(动)',
113
+ '市盈率(TTM)',
114
+ '成交额',
115
+ '货币']
116
+ async def get_one(symbol):
117
+ """Get the data for one ticker symbol."""
118
+ result: dict = {}
119
+ ticker: dict = {}
120
+ try:
121
+ symbol_b, symbol_f, market = normalize_symbol(symbol)
122
+ if market == "SH" or market == "SZ":
123
+ symbol = market+symbol_b
124
+ elif market == "BJ":
125
+ symbol = "NQ"+symbol_b
126
+ ticker_df = ak.stock_individual_spot_xq(symbol)
127
+ if ticker_df.empty:
128
+ logger.debug("ticker_df is empty.")
129
+ else:
130
+ ticker = dict(zip(ticker_df['item'], ticker_df['value']))
131
+ except Exception as e:
132
+ warn(f"Error getting data for {symbol}: {e}")
133
+ if ticker:
134
+ for field in fields:
135
+ if field in ticker:
136
+ result[field] = ticker.get(field, None)
137
+ if result:
138
+ results.append(result)
139
+
140
+ tasks = [get_one(symbol) for symbol in symbols]
141
+
142
+ await asyncio.gather(*tasks)
143
+
144
+ return results
145
+
146
+ @staticmethod
147
+ def transform_data(
148
+ query: AKShareEquityQuoteQueryParams,
149
+ data: List[Dict],
150
+ **kwargs: Any,
151
+ ) -> List[AKShareEquityQuoteData]:
152
+ """Transform the data."""
153
+ return [AKShareEquityQuoteData.model_validate(d) for d in data]