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.
@@ -4,4 +4,4 @@ from .sina import SinaAdapter
4
4
  from .xueqiu import XueQiuAdapter
5
5
  from .cache.cache import CACHE_CONFIG
6
6
 
7
- __all__ = ['EastMoneyAdapter', 'SinaAdapter', 'XueQiuAdapter', 'CACHE_CONFIG']
7
+ __all__ = ["EastMoneyAdapter", "SinaAdapter", "XueQiuAdapter", "CACHE_CONFIG"]
@@ -2,8 +2,8 @@ from cachetools import TTLCache
2
2
 
3
3
  # 缓存配置
4
4
  CACHE_CONFIG = {
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小时
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: ("eastmoney", symbol, interval, interval_multiplier, start_date, end_date, 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(CACHE_CONFIG["realtime_cache"], key=lambda self, symbol=None: f"eastmoney_{symbol if symbol else 'all'}")
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()
@@ -12,7 +12,10 @@ class SinaAdapter:
12
12
  - Historical market data
13
13
  """
14
14
 
15
- @cached(CACHE_CONFIG["financial_cache"], key=lambda self, symbol: f"sina_balance_{symbol}")
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(CACHE_CONFIG["financial_cache"], key=lambda self, symbol: f"sina_income_{symbol}")
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(CACHE_CONFIG["financial_cache"], key=lambda self, symbol: f"sina_cash_{symbol}")
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: ("sina", symbol, interval, interval_multiplier, start_date, end_date, 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,
@@ -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(CACHE_CONFIG["hist_data_cache"], key=lambda self, symbol=None: f"inner_trade_{symbol if symbol else 'all'}")
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._clean_data(raw_df)
91
+ return self._clean_insider_data(raw_df)
34
92
 
35
- def _clean_data(self, raw_df: pd.DataFrame) -> pd.DataFrame:
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(source: str = "xueqiu", symbol: Optional[str] = None) -> "pd.DataFrame":
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 = "eastmoney", symbol: Optional[str] = None
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.2
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.64
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,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (80.4.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -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,,