akshare-one 0.3.7__py3-none-any.whl → 0.3.9__py3-none-any.whl

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.
Files changed (41) hide show
  1. akshare_one/__init__.py +214 -214
  2. akshare_one/eastmoney/client.py +80 -80
  3. akshare_one/eastmoney/utils.py +102 -102
  4. akshare_one/indicators.py +395 -395
  5. akshare_one/modules/cache.py +30 -27
  6. akshare_one/modules/financial/base.py +27 -27
  7. akshare_one/modules/financial/eastmoney_direct.py +183 -183
  8. akshare_one/modules/financial/factory.py +46 -46
  9. akshare_one/modules/financial/sina.py +292 -292
  10. akshare_one/modules/historical/base.py +47 -47
  11. akshare_one/modules/historical/eastmoney.py +236 -236
  12. akshare_one/modules/historical/eastmoney_direct.py +79 -78
  13. akshare_one/modules/historical/factory.py +48 -48
  14. akshare_one/modules/historical/sina.py +250 -250
  15. akshare_one/modules/indicators/base.py +158 -158
  16. akshare_one/modules/indicators/factory.py +33 -33
  17. akshare_one/modules/indicators/simple.py +9 -8
  18. akshare_one/modules/indicators/talib.py +263 -263
  19. akshare_one/modules/info/base.py +25 -25
  20. akshare_one/modules/info/eastmoney.py +51 -51
  21. akshare_one/modules/info/factory.py +44 -44
  22. akshare_one/modules/insider/base.py +28 -28
  23. akshare_one/modules/insider/factory.py +44 -44
  24. akshare_one/modules/insider/xueqiu.py +110 -110
  25. akshare_one/modules/news/base.py +22 -22
  26. akshare_one/modules/news/eastmoney.py +43 -43
  27. akshare_one/modules/news/factory.py +44 -44
  28. akshare_one/modules/realtime/base.py +27 -27
  29. akshare_one/modules/realtime/eastmoney.py +53 -53
  30. akshare_one/modules/realtime/eastmoney_direct.py +36 -36
  31. akshare_one/modules/realtime/factory.py +71 -48
  32. akshare_one/modules/realtime/xueqiu.py +57 -57
  33. akshare_one/modules/utils.py +10 -10
  34. akshare_one/py.typed +0 -0
  35. {akshare_one-0.3.7.dist-info → akshare_one-0.3.9.dist-info}/METADATA +72 -74
  36. akshare_one-0.3.9.dist-info/RECORD +38 -0
  37. akshare_one-0.3.9.dist-info/WHEEL +4 -0
  38. akshare_one-0.3.7.dist-info/RECORD +0 -39
  39. akshare_one-0.3.7.dist-info/WHEEL +0 -5
  40. akshare_one-0.3.7.dist-info/licenses/LICENSE +0 -21
  41. akshare_one-0.3.7.dist-info/top_level.txt +0 -1
@@ -1,27 +1,30 @@
1
- from cachetools import TTLCache, cached
2
- import os
3
-
4
- # 缓存配置
5
- CACHE_CONFIG = {
6
- "hist_data_cache": TTLCache(maxsize=1000, ttl=3600), # 历史数据缓存1小时
7
- "realtime_cache": TTLCache(maxsize=500, ttl=60), # 实时数据缓存1分钟
8
- "news_cache": TTLCache(maxsize=500, ttl=3600), # 新闻数据缓存1小时
9
- "financial_cache": TTLCache(maxsize=500, ttl=86400), # 财务数据缓存24小时
10
- "info_cache": TTLCache(maxsize=500, ttl=86400), # 信息数据缓存24小时
11
- }
12
-
13
-
14
- def cache(cache_key, key=None):
15
- cache_enabled = os.getenv("AKSHARE_ONE_CACHE_ENABLED", "true").lower() in (
16
- "1",
17
- "true",
18
- "yes",
19
- "on",
20
- )
21
-
22
- def decorator(func):
23
- if cache_enabled:
24
- return cached(CACHE_CONFIG[cache_key], key=key)(func)
25
- return func
26
-
27
- return decorator
1
+ from cachetools import TTLCache, cached
2
+ import os
3
+ from typing import Any, Callable, TypeVar, Optional
4
+
5
+ F = TypeVar('F', bound=Callable[..., Any])
6
+
7
+ # 缓存配置
8
+ CACHE_CONFIG: dict[str, TTLCache[Any, Any]] = {
9
+ "hist_data_cache": TTLCache(maxsize=1000, ttl=3600), # 历史数据缓存1小时
10
+ "realtime_cache": TTLCache(maxsize=500, ttl=60), # 实时数据缓存1分钟
11
+ "news_cache": TTLCache(maxsize=500, ttl=3600), # 新闻数据缓存1小时
12
+ "financial_cache": TTLCache(maxsize=500, ttl=86400), # 财务数据缓存24小时
13
+ "info_cache": TTLCache(maxsize=500, ttl=86400), # 信息数据缓存24小时
14
+ }
15
+
16
+
17
+ def cache(cache_key: str, key: Optional[Callable[..., Any]] = None) -> Callable[[F], F]:
18
+ cache_enabled = os.getenv("AKSHARE_ONE_CACHE_ENABLED", "true").lower() in (
19
+ "1",
20
+ "true",
21
+ "yes",
22
+ "on",
23
+ )
24
+
25
+ def decorator(func: F) -> F:
26
+ if cache_enabled:
27
+ return cached(CACHE_CONFIG[cache_key], key=key)(func) # type: ignore
28
+ return func
29
+
30
+ return decorator
@@ -1,27 +1,27 @@
1
- from abc import ABC, abstractmethod
2
- import pandas as pd
3
-
4
-
5
- class FinancialDataProvider(ABC):
6
- def __init__(self, symbol: str) -> None:
7
- self.symbol = symbol
8
-
9
- @abstractmethod
10
- def get_balance_sheet(self) -> pd.DataFrame:
11
- """Fetches balance sheet data"""
12
- pass
13
-
14
- @abstractmethod
15
- def get_income_statement(self) -> pd.DataFrame:
16
- """Fetches income statement data"""
17
- pass
18
-
19
- @abstractmethod
20
- def get_cash_flow(self) -> pd.DataFrame:
21
- """Fetches cash flow data"""
22
- pass
23
-
24
- @abstractmethod
25
- def get_financial_metrics(self) -> pd.DataFrame:
26
- """Fetch financial metrics"""
27
- pass
1
+ from abc import ABC, abstractmethod
2
+ import pandas as pd
3
+
4
+
5
+ class FinancialDataProvider(ABC):
6
+ def __init__(self, symbol: str) -> None:
7
+ self.symbol = symbol
8
+
9
+ @abstractmethod
10
+ def get_balance_sheet(self) -> pd.DataFrame:
11
+ """Fetches balance sheet data"""
12
+ pass
13
+
14
+ @abstractmethod
15
+ def get_income_statement(self) -> pd.DataFrame:
16
+ """Fetches income statement data"""
17
+ pass
18
+
19
+ @abstractmethod
20
+ def get_cash_flow(self) -> pd.DataFrame:
21
+ """Fetches cash flow data"""
22
+ pass
23
+
24
+ @abstractmethod
25
+ def get_financial_metrics(self) -> pd.DataFrame:
26
+ """Fetch financial metrics"""
27
+ pass
@@ -1,183 +1,183 @@
1
- import pandas as pd
2
- import requests
3
-
4
- from akshare_one.modules.cache import cache
5
- from .base import FinancialDataProvider
6
-
7
-
8
- class EastMoneyDirectFinancialReport(FinancialDataProvider):
9
- _balance_sheet_rename_map = {
10
- "REPORT_DATE": "report_date",
11
- "TOTAL_ASSETS": "total_assets",
12
- "FIXED_ASSET": "fixed_assets_net",
13
- "MONETARYFUNDS": "cash_and_equivalents",
14
- "ACCOUNTS_RECE": "accounts_receivable",
15
- "INVENTORY": "inventory",
16
- "TOTAL_LIABILITIES": "total_liabilities",
17
- "ACCOUNTS_PAYABLE": "trade_and_non_trade_payables",
18
- "ADVANCE_RECEIVABLES": "deferred_revenue",
19
- "TOTAL_EQUITY": "shareholders_equity",
20
- }
21
-
22
- _income_statement_rename_map = {
23
- "REPORT_DATE": "report_date",
24
- "TOTAL_OPERATE_INCOME": "revenue",
25
- "TOTAL_OPERATE_COST": "total_operating_costs",
26
- "OPERATE_PROFIT": "operating_profit",
27
- "PARENT_NETPROFIT": "net_income_common_stock",
28
- }
29
-
30
- _cash_flow_rename_map = {
31
- "REPORT_DATE": "report_date",
32
- "NETCASH_OPERATE": "net_cash_flow_from_operations",
33
- "NETCASH_INVEST": "net_cash_flow_from_investing",
34
- "NETCASH_FINANCE": "net_cash_flow_from_financing",
35
- "CCE_ADD": "change_in_cash_and_equivalents",
36
- }
37
-
38
- def __init__(self, symbol):
39
- super().__init__(symbol)
40
-
41
- def get_income_statement(self):
42
- pass
43
-
44
- def get_balance_sheet(self):
45
- pass
46
-
47
- def get_cash_flow(self):
48
- pass
49
-
50
- @cache(
51
- "financial_cache",
52
- key=lambda self, symbol=None: f"eastmoney_financial_metrics_{self.symbol}",
53
- )
54
- def get_financial_metrics(self) -> pd.DataFrame:
55
- """获取三大财务报表关键指标"""
56
- balance_sheet = self._fetch_balance_sheet()
57
- income_statement = self._fetch_income_statement()
58
- cash_flow = self._fetch_cash_flow()
59
-
60
- if balance_sheet.empty and income_statement.empty and cash_flow.empty:
61
- return pd.DataFrame()
62
-
63
- merged = pd.merge(
64
- balance_sheet, income_statement, on="report_date", how="outer"
65
- )
66
- merged = pd.merge(merged, cash_flow, on="report_date", how="outer")
67
-
68
- # Convert report_date to datetime and format as YYYY-MM-DD
69
- merged["report_date"] = pd.to_datetime(merged["report_date"]).dt.strftime(
70
- "%Y-%m-%d"
71
- )
72
-
73
- # Sort by report_date in descending order (most recent first)
74
- merged = merged.sort_values("report_date", ascending=False).reset_index(
75
- drop=True
76
- )
77
-
78
- return merged
79
-
80
- def _fetch_balance_sheet(self) -> pd.DataFrame:
81
- """
82
- Get stock balance sheet data from East Money API
83
- """
84
- try:
85
- # API endpoint and parameters
86
- api_url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
87
- params = {
88
- "reportName": "RPT_DMSK_FN_BALANCE",
89
- "filter": f'(SECURITY_CODE="{self.symbol}")',
90
- "pageNumber": "1",
91
- "pageSize": "1000",
92
- "sortColumns": "REPORT_DATE",
93
- "sortTypes": "-1",
94
- "columns": ",".join(self._balance_sheet_rename_map.keys()),
95
- }
96
-
97
- # Fetch data from API
98
- response = requests.get(api_url, params=params)
99
- response.raise_for_status()
100
- data = response.json()
101
-
102
- # Extract the actual data
103
- if data.get("result") and data["result"].get("data"):
104
- df = pd.DataFrame(data["result"]["data"])
105
- df.rename(columns=self._balance_sheet_rename_map, inplace=True)
106
- return df
107
- else:
108
- print("No balance sheet data found in API response")
109
- return pd.DataFrame()
110
-
111
- except Exception as e:
112
- print(f"Error occurred: {str(e)}")
113
- return pd.DataFrame()
114
-
115
- def _fetch_income_statement(self) -> pd.DataFrame:
116
- """
117
- Get stock income statement data from East Money API
118
- """
119
- try:
120
- # API endpoint and parameters
121
- api_url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
122
- params = {
123
- "reportName": "RPT_DMSK_FN_INCOME",
124
- "filter": f'(SECURITY_CODE="{self.symbol}")',
125
- "pageNumber": "1",
126
- "pageSize": "1000",
127
- "sortColumns": "REPORT_DATE",
128
- "sortTypes": "-1",
129
- "columns": ",".join(self._income_statement_rename_map.keys()),
130
- }
131
-
132
- # Fetch data from API
133
- response = requests.get(api_url, params=params)
134
- response.raise_for_status()
135
- data = response.json()
136
-
137
- # Extract the actual data
138
- if data.get("result") and data["result"].get("data"):
139
- df = pd.DataFrame(data["result"]["data"])
140
- df.rename(columns=self._income_statement_rename_map, inplace=True)
141
- return df
142
- else:
143
- print("No income statement data found in API response")
144
- return pd.DataFrame()
145
-
146
- except Exception as e:
147
- print(f"Error occurred: {str(e)}")
148
- return pd.DataFrame()
149
-
150
- def _fetch_cash_flow(self) -> pd.DataFrame:
151
- """
152
- Get stock cash flow statement data from East Money API
153
- """
154
- try:
155
- # API endpoint and parameters
156
- api_url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
157
- params = {
158
- "reportName": "RPT_DMSK_FN_CASHFLOW",
159
- "filter": f'(SECURITY_CODE="{self.symbol}")',
160
- "pageNumber": "1",
161
- "pageSize": "1000",
162
- "sortColumns": "REPORT_DATE",
163
- "sortTypes": "-1",
164
- "columns": ",".join(self._cash_flow_rename_map.keys()),
165
- }
166
-
167
- # Fetch data from API
168
- response = requests.get(api_url, params=params)
169
- response.raise_for_status()
170
- data = response.json()
171
-
172
- # Extract the actual data
173
- if data.get("result") and data["result"].get("data"):
174
- df = pd.DataFrame(data["result"]["data"])
175
- df.rename(columns=self._cash_flow_rename_map, inplace=True)
176
- return df
177
- else:
178
- print("No cash flow statement data found in API response")
179
- return pd.DataFrame()
180
-
181
- except Exception as e:
182
- print(f"Error occurred: {str(e)}")
183
- return pd.DataFrame()
1
+ import pandas as pd
2
+ import requests
3
+
4
+ from akshare_one.modules.cache import cache
5
+ from .base import FinancialDataProvider
6
+
7
+
8
+ class EastMoneyDirectFinancialReport(FinancialDataProvider):
9
+ _balance_sheet_rename_map = {
10
+ "REPORT_DATE": "report_date",
11
+ "TOTAL_ASSETS": "total_assets",
12
+ "FIXED_ASSET": "fixed_assets_net",
13
+ "MONETARYFUNDS": "cash_and_equivalents",
14
+ "ACCOUNTS_RECE": "accounts_receivable",
15
+ "INVENTORY": "inventory",
16
+ "TOTAL_LIABILITIES": "total_liabilities",
17
+ "ACCOUNTS_PAYABLE": "trade_and_non_trade_payables",
18
+ "ADVANCE_RECEIVABLES": "deferred_revenue",
19
+ "TOTAL_EQUITY": "shareholders_equity",
20
+ }
21
+
22
+ _income_statement_rename_map = {
23
+ "REPORT_DATE": "report_date",
24
+ "TOTAL_OPERATE_INCOME": "revenue",
25
+ "TOTAL_OPERATE_COST": "total_operating_costs",
26
+ "OPERATE_PROFIT": "operating_profit",
27
+ "PARENT_NETPROFIT": "net_income_common_stock",
28
+ }
29
+
30
+ _cash_flow_rename_map = {
31
+ "REPORT_DATE": "report_date",
32
+ "NETCASH_OPERATE": "net_cash_flow_from_operations",
33
+ "NETCASH_INVEST": "net_cash_flow_from_investing",
34
+ "NETCASH_FINANCE": "net_cash_flow_from_financing",
35
+ "CCE_ADD": "change_in_cash_and_equivalents",
36
+ }
37
+
38
+ def __init__(self, symbol: str) -> None:
39
+ super().__init__(symbol)
40
+
41
+ def get_income_statement(self) -> pd.DataFrame:
42
+ return pd.DataFrame()
43
+
44
+ def get_balance_sheet(self) -> pd.DataFrame:
45
+ return pd.DataFrame()
46
+
47
+ def get_cash_flow(self) -> pd.DataFrame:
48
+ return pd.DataFrame()
49
+
50
+ @cache(
51
+ "financial_cache",
52
+ key=lambda self, symbol=None: f"eastmoney_financial_metrics_{self.symbol}",
53
+ )
54
+ def get_financial_metrics(self) -> pd.DataFrame:
55
+ """获取三大财务报表关键指标"""
56
+ balance_sheet = self._fetch_balance_sheet()
57
+ income_statement = self._fetch_income_statement()
58
+ cash_flow = self._fetch_cash_flow()
59
+
60
+ if balance_sheet.empty and income_statement.empty and cash_flow.empty:
61
+ return pd.DataFrame()
62
+
63
+ merged = pd.merge(
64
+ balance_sheet, income_statement, on="report_date", how="outer"
65
+ )
66
+ merged = pd.merge(merged, cash_flow, on="report_date", how="outer")
67
+
68
+ # Convert report_date to datetime and format as YYYY-MM-DD
69
+ merged["report_date"] = pd.to_datetime(merged["report_date"]).dt.strftime(
70
+ "%Y-%m-%d"
71
+ )
72
+
73
+ # Sort by report_date in descending order (most recent first)
74
+ merged = merged.sort_values("report_date", ascending=False).reset_index(
75
+ drop=True
76
+ )
77
+
78
+ return merged
79
+
80
+ def _fetch_balance_sheet(self) -> pd.DataFrame:
81
+ """
82
+ Get stock balance sheet data from East Money API
83
+ """
84
+ try:
85
+ # API endpoint and parameters
86
+ api_url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
87
+ params = {
88
+ "reportName": "RPT_DMSK_FN_BALANCE",
89
+ "filter": f'(SECURITY_CODE="{self.symbol}")',
90
+ "pageNumber": "1",
91
+ "pageSize": "1000",
92
+ "sortColumns": "REPORT_DATE",
93
+ "sortTypes": "-1",
94
+ "columns": ",".join(self._balance_sheet_rename_map.keys()),
95
+ }
96
+
97
+ # Fetch data from API
98
+ response = requests.get(api_url, params=params)
99
+ response.raise_for_status()
100
+ data = response.json()
101
+
102
+ # Extract the actual data
103
+ if data.get("result") and data["result"].get("data"):
104
+ df = pd.DataFrame(data["result"]["data"])
105
+ df.rename(columns=self._balance_sheet_rename_map, inplace=True)
106
+ return df
107
+ else:
108
+ print("No balance sheet data found in API response")
109
+ return pd.DataFrame()
110
+
111
+ except Exception as e:
112
+ print(f"Error occurred: {str(e)}")
113
+ return pd.DataFrame()
114
+
115
+ def _fetch_income_statement(self) -> pd.DataFrame:
116
+ """
117
+ Get stock income statement data from East Money API
118
+ """
119
+ try:
120
+ # API endpoint and parameters
121
+ api_url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
122
+ params = {
123
+ "reportName": "RPT_DMSK_FN_INCOME",
124
+ "filter": f'(SECURITY_CODE="{self.symbol}")',
125
+ "pageNumber": "1",
126
+ "pageSize": "1000",
127
+ "sortColumns": "REPORT_DATE",
128
+ "sortTypes": "-1",
129
+ "columns": ",".join(self._income_statement_rename_map.keys()),
130
+ }
131
+
132
+ # Fetch data from API
133
+ response = requests.get(api_url, params=params)
134
+ response.raise_for_status()
135
+ data = response.json()
136
+
137
+ # Extract the actual data
138
+ if data.get("result") and data["result"].get("data"):
139
+ df = pd.DataFrame(data["result"]["data"])
140
+ df.rename(columns=self._income_statement_rename_map, inplace=True)
141
+ return df
142
+ else:
143
+ print("No income statement data found in API response")
144
+ return pd.DataFrame()
145
+
146
+ except Exception as e:
147
+ print(f"Error occurred: {str(e)}")
148
+ return pd.DataFrame()
149
+
150
+ def _fetch_cash_flow(self) -> pd.DataFrame:
151
+ """
152
+ Get stock cash flow statement data from East Money API
153
+ """
154
+ try:
155
+ # API endpoint and parameters
156
+ api_url = "https://datacenter-web.eastmoney.com/api/data/v1/get"
157
+ params = {
158
+ "reportName": "RPT_DMSK_FN_CASHFLOW",
159
+ "filter": f'(SECURITY_CODE="{self.symbol}")',
160
+ "pageNumber": "1",
161
+ "pageSize": "1000",
162
+ "sortColumns": "REPORT_DATE",
163
+ "sortTypes": "-1",
164
+ "columns": ",".join(self._cash_flow_rename_map.keys()),
165
+ }
166
+
167
+ # Fetch data from API
168
+ response = requests.get(api_url, params=params)
169
+ response.raise_for_status()
170
+ data = response.json()
171
+
172
+ # Extract the actual data
173
+ if data.get("result") and data["result"].get("data"):
174
+ df = pd.DataFrame(data["result"]["data"])
175
+ df.rename(columns=self._cash_flow_rename_map, inplace=True)
176
+ return df
177
+ else:
178
+ print("No cash flow statement data found in API response")
179
+ return pd.DataFrame()
180
+
181
+ except Exception as e:
182
+ print(f"Error occurred: {str(e)}")
183
+ return pd.DataFrame()
@@ -1,46 +1,46 @@
1
- from .eastmoney_direct import EastMoneyDirectFinancialReport
2
- from .sina import SinaFinancialReport
3
- from .base import FinancialDataProvider
4
-
5
-
6
- class FinancialDataFactory:
7
- """
8
- Factory class for creating financial data providers
9
- """
10
-
11
- _providers = {
12
- "sina": SinaFinancialReport,
13
- "eastmoney_direct": EastMoneyDirectFinancialReport,
14
- }
15
-
16
- @classmethod
17
- def get_provider(cls, provider_name: str, **kwargs) -> FinancialDataProvider:
18
- """
19
- Get a financial data provider by name
20
-
21
- Args:
22
- provider_name: Name of the provider (e.g., 'sina')
23
- **kwargs: Additional arguments to pass to the provider's constructor
24
-
25
- Returns:
26
- FinancialDataProvider: An instance of the requested provider
27
-
28
- Raises:
29
- ValueError: If the requested provider is not found
30
- """
31
- provider_class = cls._providers.get(provider_name.lower())
32
- if not provider_class:
33
- raise ValueError(f"Unknown financial data provider: {provider_name}")
34
-
35
- return provider_class(**kwargs)
36
-
37
- @classmethod
38
- def register_provider(cls, name: str, provider_class: type):
39
- """
40
- Register a new financial data provider
41
-
42
- Args:
43
- name: Name to associate with this provider
44
- provider_class: The provider class to register
45
- """
46
- cls._providers[name.lower()] = provider_class
1
+ from .eastmoney_direct import EastMoneyDirectFinancialReport
2
+ from .sina import SinaFinancialReport
3
+ from .base import FinancialDataProvider
4
+
5
+
6
+ class FinancialDataFactory:
7
+ """
8
+ Factory class for creating financial data providers
9
+ """
10
+
11
+ _providers = {
12
+ "sina": SinaFinancialReport,
13
+ "eastmoney_direct": EastMoneyDirectFinancialReport,
14
+ }
15
+
16
+ @classmethod
17
+ def get_provider(cls, provider_name: str, **kwargs) -> FinancialDataProvider: # type: ignore
18
+ """
19
+ Get a financial data provider by name
20
+
21
+ Args:
22
+ provider_name: Name of the provider (e.g., 'sina')
23
+ **kwargs: Additional arguments to pass to the provider's constructor
24
+
25
+ Returns:
26
+ FinancialDataProvider: An instance of the requested provider
27
+
28
+ Raises:
29
+ ValueError: If the requested provider is not found
30
+ """
31
+ provider_class = cls._providers.get(provider_name.lower())
32
+ if not provider_class:
33
+ raise ValueError(f"Unknown financial data provider: {provider_name}")
34
+
35
+ return provider_class(**kwargs)
36
+
37
+ @classmethod
38
+ def register_provider(cls, name: str, provider_class: type) -> None:
39
+ """
40
+ Register a new financial data provider
41
+
42
+ Args:
43
+ name: Name to associate with this provider
44
+ provider_class: The provider class to register
45
+ """
46
+ cls._providers[name.lower()] = provider_class # type: ignore