akshare-one 0.1.2__py3-none-any.whl → 0.1.3__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.
- akshare_one/adapters/__init__.py +1 -1
- akshare_one/adapters/cache/cache.py +4 -4
- akshare_one/adapters/eastmoney.py +13 -2
- akshare_one/adapters/sina.py +20 -4
- akshare_one/adapters/xueqiu.py +72 -3
- akshare_one/insider.py +3 -1
- akshare_one/stock.py +9 -3
- {akshare_one-0.1.2.dist-info → akshare_one-0.1.3.dist-info}/METADATA +2 -2
- akshare_one-0.1.3.dist-info/RECORD +15 -0
- {akshare_one-0.1.2.dist-info → akshare_one-0.1.3.dist-info}/WHEEL +1 -1
- akshare_one-0.1.2.dist-info/RECORD +0 -15
- {akshare_one-0.1.2.dist-info → akshare_one-0.1.3.dist-info}/licenses/LICENSE +0 -0
- {akshare_one-0.1.2.dist-info → akshare_one-0.1.3.dist-info}/top_level.txt +0 -0
akshare_one/adapters/__init__.py
CHANGED
@@ -2,8 +2,8 @@ from cachetools import TTLCache
|
|
2
2
|
|
3
3
|
# 缓存配置
|
4
4
|
CACHE_CONFIG = {
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
"hist_data_cache": TTLCache(maxsize=1000, ttl=3600), # 历史数据缓存1小时
|
6
|
+
"realtime_cache": TTLCache(maxsize=500, ttl=60), # 实时数据缓存1分钟
|
7
|
+
"news_cache": TTLCache(maxsize=500, ttl=3600),
|
8
|
+
"financial_cache": TTLCache(maxsize=500, ttl=86400), # 财务数据缓存24小时
|
9
9
|
}
|
@@ -16,7 +16,15 @@ class EastMoneyAdapter:
|
|
16
16
|
interval_multiplier,
|
17
17
|
start_date,
|
18
18
|
end_date,
|
19
|
-
adjust: (
|
19
|
+
adjust: (
|
20
|
+
"eastmoney",
|
21
|
+
symbol,
|
22
|
+
interval,
|
23
|
+
interval_multiplier,
|
24
|
+
start_date,
|
25
|
+
end_date,
|
26
|
+
adjust,
|
27
|
+
),
|
20
28
|
)
|
21
29
|
def get_hist_data(
|
22
30
|
self,
|
@@ -137,7 +145,10 @@ class EastMoneyAdapter:
|
|
137
145
|
# Standardize the data format
|
138
146
|
return self._clean_data(raw_df)
|
139
147
|
|
140
|
-
@cached(
|
148
|
+
@cached(
|
149
|
+
CACHE_CONFIG["realtime_cache"],
|
150
|
+
key=lambda self, symbol=None: f"eastmoney_{symbol if symbol else 'all'}",
|
151
|
+
)
|
141
152
|
def get_realtime_data(self, symbol: Optional[str] = None) -> pd.DataFrame:
|
142
153
|
"""获取沪深京A股实时行情数据"""
|
143
154
|
raw_df = ak.stock_zh_a_spot_em()
|
akshare_one/adapters/sina.py
CHANGED
@@ -12,7 +12,10 @@ class SinaAdapter:
|
|
12
12
|
- Historical market data
|
13
13
|
"""
|
14
14
|
|
15
|
-
@cached(
|
15
|
+
@cached(
|
16
|
+
CACHE_CONFIG["financial_cache"],
|
17
|
+
key=lambda self, symbol: f"sina_balance_{symbol}",
|
18
|
+
)
|
16
19
|
def get_balance_sheet(self, symbol: str) -> pd.DataFrame:
|
17
20
|
"""获取资产负债表数据
|
18
21
|
|
@@ -26,7 +29,10 @@ class SinaAdapter:
|
|
26
29
|
raw_df = ak.stock_financial_report_sina(stock=stock, symbol="资产负债表")
|
27
30
|
return self._clean_balance_data(raw_df)
|
28
31
|
|
29
|
-
@cached(
|
32
|
+
@cached(
|
33
|
+
CACHE_CONFIG["financial_cache"],
|
34
|
+
key=lambda self, symbol: f"sina_income_{symbol}",
|
35
|
+
)
|
30
36
|
def get_income_statement(self, symbol: str) -> pd.DataFrame:
|
31
37
|
"""获取利润表数据
|
32
38
|
|
@@ -40,7 +46,9 @@ class SinaAdapter:
|
|
40
46
|
raw_df = ak.stock_financial_report_sina(stock=stock, symbol="利润表")
|
41
47
|
return self._clean_income_data(raw_df)
|
42
48
|
|
43
|
-
@cached(
|
49
|
+
@cached(
|
50
|
+
CACHE_CONFIG["financial_cache"], key=lambda self, symbol: f"sina_cash_{symbol}"
|
51
|
+
)
|
44
52
|
def get_cash_flow(self, symbol: str) -> pd.DataFrame:
|
45
53
|
"""获取现金流量表数据
|
46
54
|
|
@@ -207,7 +215,15 @@ class SinaAdapter:
|
|
207
215
|
interval_multiplier,
|
208
216
|
start_date,
|
209
217
|
end_date,
|
210
|
-
adjust: (
|
218
|
+
adjust: (
|
219
|
+
"sina",
|
220
|
+
symbol,
|
221
|
+
interval,
|
222
|
+
interval_multiplier,
|
223
|
+
start_date,
|
224
|
+
end_date,
|
225
|
+
adjust,
|
226
|
+
),
|
211
227
|
)
|
212
228
|
def get_hist_data(
|
213
229
|
self,
|
akshare_one/adapters/xueqiu.py
CHANGED
@@ -8,7 +8,65 @@ from .cache.cache import CACHE_CONFIG
|
|
8
8
|
class XueQiuAdapter:
|
9
9
|
"""Adapter for XueQiu insider trading data API"""
|
10
10
|
|
11
|
-
@cached(
|
11
|
+
@cached(
|
12
|
+
cache=CACHE_CONFIG,
|
13
|
+
key=lambda self, symbol=None: f"xueqiu_{symbol}",
|
14
|
+
)
|
15
|
+
def get_realtime_data(self, symbol: str) -> pd.DataFrame:
|
16
|
+
"""获取雪球实时行情数据
|
17
|
+
|
18
|
+
Args:
|
19
|
+
symbol: 股票代码 ("600000")
|
20
|
+
|
21
|
+
Returns:
|
22
|
+
- symbol: 股票代码
|
23
|
+
- price: 最新价
|
24
|
+
- change: 涨跌额
|
25
|
+
- pct_change: 涨跌幅(%)
|
26
|
+
- timestamp: 时间戳
|
27
|
+
- volume: 成交量(手)
|
28
|
+
- amount: 成交额(元)
|
29
|
+
- open: 今开
|
30
|
+
- high: 最高
|
31
|
+
- low: 最低
|
32
|
+
- prev_close: 昨收
|
33
|
+
|
34
|
+
Raises:
|
35
|
+
ValueError: 如果symbol格式不正确或API返回错误
|
36
|
+
"""
|
37
|
+
|
38
|
+
raw_df = ak.stock_individual_spot_xq(symbol=self._convert_symbol(symbol))
|
39
|
+
|
40
|
+
# Transform to match EastMoney format
|
41
|
+
data = {
|
42
|
+
"symbol": symbol,
|
43
|
+
"price": float(raw_df.loc[raw_df["item"] == "现价", "value"].values[0]),
|
44
|
+
"change": float(raw_df.loc[raw_df["item"] == "涨跌", "value"].values[0]),
|
45
|
+
"pct_change": float(
|
46
|
+
raw_df.loc[raw_df["item"] == "涨幅", "value"].values[0]
|
47
|
+
),
|
48
|
+
"timestamp": pd.to_datetime(
|
49
|
+
raw_df.loc[raw_df["item"] == "时间", "value"].values[0]
|
50
|
+
)
|
51
|
+
.tz_localize("Asia/Shanghai")
|
52
|
+
.tz_convert("UTC"),
|
53
|
+
"volume": int(raw_df.loc[raw_df["item"] == "成交量", "value"].values[0])
|
54
|
+
/ 100,
|
55
|
+
"amount": float(raw_df.loc[raw_df["item"] == "成交额", "value"].values[0]),
|
56
|
+
"open": float(raw_df.loc[raw_df["item"] == "今开", "value"].values[0]),
|
57
|
+
"high": float(raw_df.loc[raw_df["item"] == "最高", "value"].values[0]),
|
58
|
+
"low": float(raw_df.loc[raw_df["item"] == "最低", "value"].values[0]),
|
59
|
+
"prev_close": float(
|
60
|
+
raw_df.loc[raw_df["item"] == "昨收", "value"].values[0]
|
61
|
+
),
|
62
|
+
}
|
63
|
+
|
64
|
+
return pd.DataFrame([data])
|
65
|
+
|
66
|
+
@cached(
|
67
|
+
CACHE_CONFIG["hist_data_cache"],
|
68
|
+
key=lambda self, symbol=None: f"inner_trade_{symbol if symbol else 'all'}",
|
69
|
+
)
|
12
70
|
def get_inner_trade_data(self, symbol: Optional[str] = None) -> pd.DataFrame:
|
13
71
|
"""获取雪球内部交易数据
|
14
72
|
|
@@ -30,9 +88,9 @@ class XueQiuAdapter:
|
|
30
88
|
raw_df = ak.stock_inner_trade_xq()
|
31
89
|
if symbol:
|
32
90
|
raw_df = raw_df[raw_df["股票代码"] == symbol]
|
33
|
-
return self.
|
91
|
+
return self._clean_insider_data(raw_df)
|
34
92
|
|
35
|
-
def
|
93
|
+
def _clean_insider_data(self, raw_df: pd.DataFrame) -> pd.DataFrame:
|
36
94
|
"""清理和标准化内部交易数据
|
37
95
|
|
38
96
|
Args:
|
@@ -104,3 +162,14 @@ class XueQiuAdapter:
|
|
104
162
|
df[col] = pd.to_numeric(df[col], errors="coerce")
|
105
163
|
|
106
164
|
return df
|
165
|
+
|
166
|
+
def _convert_symbol(self, symbol: str) -> str:
|
167
|
+
"""
|
168
|
+
Convert Symbol (600000) to XueQiu Symbol (SH600000)
|
169
|
+
"""
|
170
|
+
if symbol.startswith("6"):
|
171
|
+
return f"SH{symbol}"
|
172
|
+
elif symbol.startswith("0") or symbol.startswith("3"):
|
173
|
+
return f"SZ{symbol}"
|
174
|
+
else: # TODO: add more cases
|
175
|
+
return symbol
|
akshare_one/insider.py
CHANGED
@@ -8,7 +8,9 @@ import pandas as pd
|
|
8
8
|
from .adapters import XueQiuAdapter
|
9
9
|
|
10
10
|
|
11
|
-
def get_inner_trade_data(
|
11
|
+
def get_inner_trade_data(
|
12
|
+
source: str = "xueqiu", symbol: Optional[str] = None
|
13
|
+
) -> "pd.DataFrame":
|
12
14
|
"""获取雪球内部交易数据
|
13
15
|
|
14
16
|
Args:
|
akshare_one/stock.py
CHANGED
@@ -5,6 +5,8 @@
|
|
5
5
|
|
6
6
|
from typing import Optional
|
7
7
|
import pandas as pd
|
8
|
+
|
9
|
+
from akshare_one.adapters.xueqiu import XueQiuAdapter
|
8
10
|
from .adapters import EastMoneyAdapter, SinaAdapter
|
9
11
|
|
10
12
|
|
@@ -59,13 +61,13 @@ def get_hist_data(
|
|
59
61
|
|
60
62
|
|
61
63
|
def get_realtime_data(
|
62
|
-
source: str = "
|
64
|
+
source: str = "xueqiu", symbol: Optional[str] = None
|
63
65
|
) -> "pd.DataFrame":
|
64
66
|
"""Get real-time market quotes
|
65
67
|
|
66
68
|
Args:
|
67
69
|
symbol: 股票代码 (如 "600000")
|
68
|
-
source: 数据源 ('eastmoney')
|
70
|
+
source: 数据源 ('eastmoney', 'xueqiu')
|
69
71
|
|
70
72
|
Returns:
|
71
73
|
pd.DataFrame:
|
@@ -81,6 +83,10 @@ def get_realtime_data(
|
|
81
83
|
- low: 最低
|
82
84
|
- prev_close: 昨收
|
83
85
|
"""
|
84
|
-
if source == "eastmoney":
|
86
|
+
if source == "eastmoney" or symbol is None:
|
85
87
|
return EastMoneyAdapter().get_realtime_data(symbol=symbol)
|
88
|
+
elif source == "xueqiu":
|
89
|
+
if not symbol:
|
90
|
+
raise ValueError("XueQiu source requires a symbol parameter")
|
91
|
+
return XueQiuAdapter().get_realtime_data(symbol=symbol)
|
86
92
|
raise ValueError(f"Unsupported data source: {source}")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: akshare-one
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.3
|
4
4
|
Summary: Standardized interface for Chinese financial market data, built on AKShare with unified data formats and simplified APIs
|
5
5
|
License-Expression: MIT
|
6
6
|
Project-URL: Homepage, https://github.com/zwldarren/akshare-one
|
@@ -9,7 +9,7 @@ Keywords: akshare,financial-data,stock-data,quant
|
|
9
9
|
Requires-Python: >=3.12
|
10
10
|
Description-Content-Type: text/markdown
|
11
11
|
License-File: LICENSE
|
12
|
-
Requires-Dist: akshare>=1.16.
|
12
|
+
Requires-Dist: akshare>=1.16.91
|
13
13
|
Requires-Dist: cachetools>=5.5.2
|
14
14
|
Dynamic: license-file
|
15
15
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
akshare_one/__init__.py,sha256=xWUyTnh1Tv-2mEPxDmk5giUPwhrsoAuZcyoW6mAbX4k,923
|
2
|
+
akshare_one/financial.py,sha256=fCi6FPtPc28id7nQf8b3i2bh5vSCpZTmnPQ9kKr2n8Y,1215
|
3
|
+
akshare_one/insider.py,sha256=Vz1yIvVlk_FVLhqFHdR-CCH5prfO12_CVzyAnrKgH4g,1199
|
4
|
+
akshare_one/news.py,sha256=qUeX_1SnViDXBAb4Gcl28ow1qvMugEEPL75JgJhLbCA,707
|
5
|
+
akshare_one/stock.py,sha256=w2gSjtbtcwyJ-qFpo0BJO7gxVrDur6Sun8en-A6LMb4,2727
|
6
|
+
akshare_one/adapters/__init__.py,sha256=0AVeL7uukxjmkBn4xmq_IGKrZo3LfAWRWYKagSMgD5s,252
|
7
|
+
akshare_one/adapters/eastmoney.py,sha256=nRs61bR_C12gOnqNBpo5-_Vqamt70-lMPr6vlxwPwuo,11780
|
8
|
+
akshare_one/adapters/sina.py,sha256=wD67NLtqDwNzmPuxnqhrRFCyTkhSuiXXuP4a8t1BsBU,16789
|
9
|
+
akshare_one/adapters/xueqiu.py,sha256=u_r3UtlykIZLa86flcqlc4xT8swFN_xLVkRbceNSciA,6073
|
10
|
+
akshare_one/adapters/cache/cache.py,sha256=47A80Xtfr4gkKvEfBQrT8Dz8hNFR769rBa2gU6ew25s,373
|
11
|
+
akshare_one-0.1.3.dist-info/licenses/LICENSE,sha256=Gg6A1GNSJCZWQ73aHJ7TXOa0i8RQ3FejZCTZ6Db07cU,1066
|
12
|
+
akshare_one-0.1.3.dist-info/METADATA,sha256=jEtaMyAF4HllS5DZFdwcYIzT1C6eRkNOvBbfTqvTJX8,1865
|
13
|
+
akshare_one-0.1.3.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
|
14
|
+
akshare_one-0.1.3.dist-info/top_level.txt,sha256=kNiucyLVAGa89wmUSpXbBLWD7pF_RuahuiaOfLHZSyw,12
|
15
|
+
akshare_one-0.1.3.dist-info/RECORD,,
|
@@ -1,15 +0,0 @@
|
|
1
|
-
akshare_one/__init__.py,sha256=xWUyTnh1Tv-2mEPxDmk5giUPwhrsoAuZcyoW6mAbX4k,923
|
2
|
-
akshare_one/financial.py,sha256=fCi6FPtPc28id7nQf8b3i2bh5vSCpZTmnPQ9kKr2n8Y,1215
|
3
|
-
akshare_one/insider.py,sha256=hy1eM0Fa2J4uHU3vl-VDm4uB8zYTSUTbonnxOxbBuGc,1193
|
4
|
-
akshare_one/news.py,sha256=qUeX_1SnViDXBAb4Gcl28ow1qvMugEEPL75JgJhLbCA,707
|
5
|
-
akshare_one/stock.py,sha256=T6AEJlOYpVdAesOEU1lVI5tYrDwcs3Zw8KSwFv44WjQ,2457
|
6
|
-
akshare_one/adapters/__init__.py,sha256=JrpGJ80drrU9Imc3L_gZ5Z90zyMd3PiJ5dG86VAEnmA,252
|
7
|
-
akshare_one/adapters/eastmoney.py,sha256=QN6Tx1IrC7xrQjwm_F4dqpafHGMCy1zHvkMzcVuEWpg,11662
|
8
|
-
akshare_one/adapters/sina.py,sha256=M0KNTE8eE3NhBEZ5NcHsI9teK8DQWgwIYr5hfs2YzSc,16634
|
9
|
-
akshare_one/adapters/xueqiu.py,sha256=bwRNTDnXrXJxp4cFG0Uj5LVLBvCxFyxKOHAJS1nnKaM,3624
|
10
|
-
akshare_one/adapters/cache/cache.py,sha256=GhADIdLuh_IFpPXrkhTLv-joTcuh_vC12kRdqT-cpvI,378
|
11
|
-
akshare_one-0.1.2.dist-info/licenses/LICENSE,sha256=Gg6A1GNSJCZWQ73aHJ7TXOa0i8RQ3FejZCTZ6Db07cU,1066
|
12
|
-
akshare_one-0.1.2.dist-info/METADATA,sha256=K8g-_H6i3YsyEP5J04czM4dtp5cfMScNOm2YmdB2EpQ,1865
|
13
|
-
akshare_one-0.1.2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
14
|
-
akshare_one-0.1.2.dist-info/top_level.txt,sha256=kNiucyLVAGa89wmUSpXbBLWD7pF_RuahuiaOfLHZSyw,12
|
15
|
-
akshare_one-0.1.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|