akshare-one 0.1.3__py3-none-any.whl → 0.2.1__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/__init__.py +2 -3
- akshare_one/financial.py +7 -4
- akshare_one/insider.py +5 -9
- akshare_one/modules/financial/base.py +22 -0
- akshare_one/modules/financial/factory.py +44 -0
- akshare_one/{adapters → modules/financial}/sina.py +19 -203
- akshare_one/modules/historical/base.py +39 -0
- akshare_one/modules/historical/eastmoney.py +241 -0
- akshare_one/modules/historical/factory.py +46 -0
- akshare_one/modules/historical/sina.py +218 -0
- akshare_one/modules/insider/base.py +28 -0
- akshare_one/modules/insider/factory.py +44 -0
- akshare_one/{adapters → modules/insider}/xueqiu.py +16 -76
- akshare_one/modules/news/base.py +22 -0
- akshare_one/modules/news/eastmoney.py +47 -0
- akshare_one/modules/news/factory.py +44 -0
- akshare_one/modules/realtime/base.py +27 -0
- akshare_one/modules/realtime/eastmoney.py +57 -0
- akshare_one/modules/realtime/factory.py +46 -0
- akshare_one/modules/realtime/xueqiu.py +60 -0
- akshare_one/modules/utils.py +10 -0
- akshare_one/news.py +3 -4
- akshare_one/stock.py +17 -31
- {akshare_one-0.1.3.dist-info → akshare_one-0.2.1.dist-info}/METADATA +9 -9
- akshare_one-0.2.1.dist-info/RECORD +29 -0
- {akshare_one-0.1.3.dist-info → akshare_one-0.2.1.dist-info}/WHEEL +1 -1
- akshare_one/adapters/__init__.py +0 -7
- akshare_one/adapters/eastmoney.py +0 -353
- akshare_one-0.1.3.dist-info/RECORD +0 -15
- /akshare_one/{adapters/cache → modules}/cache.py +0 -0
- {akshare_one-0.1.3.dist-info → akshare_one-0.2.1.dist-info}/licenses/LICENSE +0 -0
- {akshare_one-0.1.3.dist-info → akshare_one-0.2.1.dist-info}/top_level.txt +0 -0
@@ -1,73 +1,19 @@
|
|
1
|
-
from
|
1
|
+
from cachetools import cached
|
2
2
|
import pandas as pd
|
3
3
|
import akshare as ak
|
4
|
-
from
|
5
|
-
from
|
4
|
+
from .base import InsiderDataProvider
|
5
|
+
from ..utils import convert_xieqiu_symbol
|
6
|
+
from ..cache import CACHE_CONFIG
|
6
7
|
|
7
8
|
|
8
|
-
class
|
9
|
-
"""
|
9
|
+
class XueQiuInsider(InsiderDataProvider):
|
10
|
+
"""Provider for XueQiu insider trading data"""
|
10
11
|
|
11
12
|
@cached(
|
12
|
-
cache=CACHE_CONFIG,
|
13
|
-
key=lambda self, symbol=None: f"
|
13
|
+
cache=CACHE_CONFIG["financial_cache"],
|
14
|
+
key=lambda self, symbol=None: f"xueqiu_insider_{symbol if symbol else 'all'}",
|
14
15
|
)
|
15
|
-
def
|
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
|
-
)
|
70
|
-
def get_inner_trade_data(self, symbol: Optional[str] = None) -> pd.DataFrame:
|
16
|
+
def get_inner_trade_data(self) -> pd.DataFrame:
|
71
17
|
"""获取雪球内部交易数据
|
72
18
|
|
73
19
|
Args:
|
@@ -86,8 +32,9 @@ class XueQiuAdapter:
|
|
86
32
|
- position: 董监高职务
|
87
33
|
"""
|
88
34
|
raw_df = ak.stock_inner_trade_xq()
|
89
|
-
if symbol:
|
90
|
-
|
35
|
+
if self.symbol:
|
36
|
+
xueqiu_symbol = convert_xieqiu_symbol(self.symbol)
|
37
|
+
raw_df = raw_df[raw_df["股票代码"] == xueqiu_symbol]
|
91
38
|
return self._clean_insider_data(raw_df)
|
92
39
|
|
93
40
|
def _clean_insider_data(self, raw_df: pd.DataFrame) -> pd.DataFrame:
|
@@ -113,6 +60,10 @@ class XueQiuAdapter:
|
|
113
60
|
|
114
61
|
df = raw_df.rename(columns=column_mapping)
|
115
62
|
|
63
|
+
# Convert symbol back to original format (remove SH/SZ prefix)
|
64
|
+
if "symbol" in df.columns:
|
65
|
+
df["symbol"] = df["symbol"].str.replace(r"^[A-Z]{2}", "", regex=True)
|
66
|
+
|
116
67
|
# Add is_board_director column
|
117
68
|
df["is_board_director"] = df["title"].str.contains("董事")
|
118
69
|
|
@@ -162,14 +113,3 @@ class XueQiuAdapter:
|
|
162
113
|
df[col] = pd.to_numeric(df[col], errors="coerce")
|
163
114
|
|
164
115
|
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
|
@@ -0,0 +1,22 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
import pandas as pd
|
3
|
+
|
4
|
+
|
5
|
+
class NewsDataProvider(ABC):
|
6
|
+
def __init__(self, symbol: str) -> None:
|
7
|
+
self.symbol = symbol
|
8
|
+
|
9
|
+
@abstractmethod
|
10
|
+
def get_news_data(self) -> pd.DataFrame:
|
11
|
+
"""Fetches news data for given symbol
|
12
|
+
|
13
|
+
Returns:
|
14
|
+
pd.DataFrame:
|
15
|
+
- keyword: 关键词
|
16
|
+
- title: 新闻标题
|
17
|
+
- content: 新闻内容
|
18
|
+
- publish_time: 发布时间 (UTC)
|
19
|
+
- source: 文章来源
|
20
|
+
- url: 新闻链接
|
21
|
+
"""
|
22
|
+
pass
|
@@ -0,0 +1,47 @@
|
|
1
|
+
from cachetools import cached
|
2
|
+
import pandas as pd
|
3
|
+
import akshare as ak
|
4
|
+
|
5
|
+
from ..cache import CACHE_CONFIG
|
6
|
+
from .base import NewsDataProvider
|
7
|
+
|
8
|
+
|
9
|
+
class EastMoneyNews(NewsDataProvider):
|
10
|
+
@cached(
|
11
|
+
CACHE_CONFIG["news_cache"],
|
12
|
+
key=lambda self: f"eastmoney_news_{self.symbol}",
|
13
|
+
)
|
14
|
+
def get_news_data(self) -> pd.DataFrame:
|
15
|
+
"""获取东方财富个股新闻数据"""
|
16
|
+
raw_df = ak.stock_news_em(symbol=self.symbol)
|
17
|
+
return self._clean_news_data(raw_df)
|
18
|
+
|
19
|
+
def _clean_news_data(self, raw_df: pd.DataFrame) -> pd.DataFrame:
|
20
|
+
"""清理和标准化新闻数据"""
|
21
|
+
column_mapping = {
|
22
|
+
"关键词": "keyword",
|
23
|
+
"新闻标题": "title",
|
24
|
+
"新闻内容": "content",
|
25
|
+
"发布时间": "publish_time",
|
26
|
+
"文章来源": "source",
|
27
|
+
"新闻链接": "url",
|
28
|
+
}
|
29
|
+
|
30
|
+
df = raw_df.rename(columns=column_mapping)
|
31
|
+
|
32
|
+
# Convert time to UTC
|
33
|
+
df["publish_time"] = (
|
34
|
+
pd.to_datetime(df["publish_time"])
|
35
|
+
.dt.tz_localize("Asia/Shanghai")
|
36
|
+
.dt.tz_convert("UTC")
|
37
|
+
)
|
38
|
+
|
39
|
+
required_columns = [
|
40
|
+
"keyword",
|
41
|
+
"title",
|
42
|
+
"content",
|
43
|
+
"publish_time",
|
44
|
+
"source",
|
45
|
+
"url",
|
46
|
+
]
|
47
|
+
return df[required_columns]
|
@@ -0,0 +1,44 @@
|
|
1
|
+
from .eastmoney import EastMoneyNews
|
2
|
+
from .base import NewsDataProvider
|
3
|
+
|
4
|
+
|
5
|
+
class NewsDataFactory:
|
6
|
+
"""
|
7
|
+
Factory class for creating news data providers
|
8
|
+
"""
|
9
|
+
|
10
|
+
_providers = {
|
11
|
+
"eastmoney": EastMoneyNews,
|
12
|
+
}
|
13
|
+
|
14
|
+
@classmethod
|
15
|
+
def get_provider(cls, provider_name: str, **kwargs) -> NewsDataProvider:
|
16
|
+
"""
|
17
|
+
Get a news data provider by name
|
18
|
+
|
19
|
+
Args:
|
20
|
+
provider_name: Name of the provider (e.g., 'eastmoney')
|
21
|
+
**kwargs: Additional arguments to pass to the provider's constructor
|
22
|
+
|
23
|
+
Returns:
|
24
|
+
NewsDataProvider: An instance of the requested provider
|
25
|
+
|
26
|
+
Raises:
|
27
|
+
ValueError: If the requested provider is not found
|
28
|
+
"""
|
29
|
+
provider_class = cls._providers.get(provider_name.lower())
|
30
|
+
if not provider_class:
|
31
|
+
raise ValueError(f"Unknown news data provider: {provider_name}")
|
32
|
+
|
33
|
+
return provider_class(**kwargs)
|
34
|
+
|
35
|
+
@classmethod
|
36
|
+
def register_provider(cls, name: str, provider_class: type):
|
37
|
+
"""
|
38
|
+
Register a new news data provider
|
39
|
+
|
40
|
+
Args:
|
41
|
+
name: Name to associate with this provider
|
42
|
+
provider_class: The provider class to register
|
43
|
+
"""
|
44
|
+
cls._providers[name.lower()] = provider_class
|
@@ -0,0 +1,27 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
import pandas as pd
|
3
|
+
|
4
|
+
|
5
|
+
class RealtimeDataProvider(ABC):
|
6
|
+
def __init__(self, symbol: str) -> None:
|
7
|
+
self.symbol = symbol
|
8
|
+
|
9
|
+
@abstractmethod
|
10
|
+
def get_current_data(self) -> pd.DataFrame:
|
11
|
+
"""Fetches realtime market data
|
12
|
+
|
13
|
+
Returns:
|
14
|
+
pd.DataFrame:
|
15
|
+
- symbol: 股票代码
|
16
|
+
- price: 最新价
|
17
|
+
- change: 涨跌额
|
18
|
+
- pct_change: 涨跌幅(%)
|
19
|
+
- timestamp: 时间戳
|
20
|
+
- volume: 成交量(手)
|
21
|
+
- amount: 成交额(元)
|
22
|
+
- open: 今开
|
23
|
+
- high: 最高
|
24
|
+
- low: 最低
|
25
|
+
- prev_close: 昨收
|
26
|
+
"""
|
27
|
+
pass
|
@@ -0,0 +1,57 @@
|
|
1
|
+
from cachetools import cached
|
2
|
+
import pandas as pd
|
3
|
+
import akshare as ak
|
4
|
+
|
5
|
+
from ..cache import CACHE_CONFIG
|
6
|
+
from .base import RealtimeDataProvider
|
7
|
+
|
8
|
+
|
9
|
+
class EastmoneyRealtime(RealtimeDataProvider):
|
10
|
+
@cached(
|
11
|
+
CACHE_CONFIG["realtime_cache"],
|
12
|
+
key=lambda self, symbol=None: f"eastmoney_{symbol if symbol else 'all'}",
|
13
|
+
)
|
14
|
+
def get_current_data(self) -> pd.DataFrame:
|
15
|
+
"""获取沪深京A股实时行情数据"""
|
16
|
+
raw_df = ak.stock_zh_a_spot_em()
|
17
|
+
df = self._clean_spot_data(raw_df)
|
18
|
+
if self.symbol:
|
19
|
+
df = df[df["symbol"] == self.symbol].reset_index(drop=True)
|
20
|
+
return df
|
21
|
+
|
22
|
+
def _clean_spot_data(self, raw_df: pd.DataFrame) -> pd.DataFrame:
|
23
|
+
"""清理和标准化实时行情数据"""
|
24
|
+
column_mapping = {
|
25
|
+
"代码": "symbol",
|
26
|
+
"最新价": "price",
|
27
|
+
"涨跌额": "change",
|
28
|
+
"涨跌幅": "pct_change",
|
29
|
+
"成交量": "volume",
|
30
|
+
"成交额": "amount",
|
31
|
+
"今开": "open",
|
32
|
+
"最高": "high",
|
33
|
+
"最低": "low",
|
34
|
+
"昨收": "prev_close",
|
35
|
+
}
|
36
|
+
|
37
|
+
df = raw_df.rename(columns=column_mapping)
|
38
|
+
|
39
|
+
# Change time to UTC
|
40
|
+
df = df.assign(
|
41
|
+
timestamp=lambda x: pd.Timestamp.now(tz="Asia/Shanghai").tz_convert("UTC")
|
42
|
+
)
|
43
|
+
|
44
|
+
required_columns = [
|
45
|
+
"symbol",
|
46
|
+
"price",
|
47
|
+
"change",
|
48
|
+
"pct_change",
|
49
|
+
"timestamp",
|
50
|
+
"volume",
|
51
|
+
"amount",
|
52
|
+
"open",
|
53
|
+
"high",
|
54
|
+
"low",
|
55
|
+
"prev_close",
|
56
|
+
]
|
57
|
+
return df[required_columns]
|
@@ -0,0 +1,46 @@
|
|
1
|
+
from .eastmoney import EastmoneyRealtime
|
2
|
+
from .xueqiu import XueQiuRealtime
|
3
|
+
from .base import RealtimeDataProvider
|
4
|
+
|
5
|
+
|
6
|
+
class RealtimeDataFactory:
|
7
|
+
"""
|
8
|
+
Factory class for creating realtime data providers
|
9
|
+
"""
|
10
|
+
|
11
|
+
_providers = {
|
12
|
+
"eastmoney": EastmoneyRealtime,
|
13
|
+
"xueqiu": XueQiuRealtime,
|
14
|
+
}
|
15
|
+
|
16
|
+
@classmethod
|
17
|
+
def get_provider(cls, provider_name: str, **kwargs) -> RealtimeDataProvider:
|
18
|
+
"""
|
19
|
+
Get a realtime data provider by name
|
20
|
+
|
21
|
+
Args:
|
22
|
+
provider_name: Name of the provider (e.g., 'eastmoney')
|
23
|
+
**kwargs: Additional arguments to pass to the provider's constructor
|
24
|
+
|
25
|
+
Returns:
|
26
|
+
RealtimeDataProvider: 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 realtime 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 realtime 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
|
@@ -0,0 +1,60 @@
|
|
1
|
+
from cachetools import cached
|
2
|
+
import pandas as pd
|
3
|
+
import akshare as ak
|
4
|
+
from ..utils import convert_xieqiu_symbol
|
5
|
+
from ..cache import CACHE_CONFIG
|
6
|
+
from .base import RealtimeDataProvider
|
7
|
+
|
8
|
+
|
9
|
+
class XueQiuRealtime(RealtimeDataProvider):
|
10
|
+
@cached(
|
11
|
+
cache=CACHE_CONFIG["realtime_cache"],
|
12
|
+
key=lambda self, symbol=None: f"xueqiu_{symbol}",
|
13
|
+
)
|
14
|
+
def get_current_data(self) -> pd.DataFrame:
|
15
|
+
"""获取雪球实时行情数据
|
16
|
+
|
17
|
+
Args:
|
18
|
+
symbol: 股票代码 ("600000")
|
19
|
+
|
20
|
+
Returns:
|
21
|
+
pd.DataFrame with columns:
|
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
|
+
raw_df = ak.stock_individual_spot_xq(symbol=convert_xieqiu_symbol(self.symbol))
|
35
|
+
|
36
|
+
# Transform to match standard format
|
37
|
+
data = {
|
38
|
+
"symbol": self.symbol,
|
39
|
+
"price": float(raw_df.loc[raw_df["item"] == "现价", "value"].values[0]),
|
40
|
+
"change": float(raw_df.loc[raw_df["item"] == "涨跌", "value"].values[0]),
|
41
|
+
"pct_change": float(
|
42
|
+
raw_df.loc[raw_df["item"] == "涨幅", "value"].values[0]
|
43
|
+
),
|
44
|
+
"timestamp": pd.to_datetime(
|
45
|
+
raw_df.loc[raw_df["item"] == "时间", "value"].values[0]
|
46
|
+
)
|
47
|
+
.tz_localize("Asia/Shanghai")
|
48
|
+
.tz_convert("UTC"),
|
49
|
+
"volume": int(raw_df.loc[raw_df["item"] == "成交量", "value"].values[0])
|
50
|
+
/ 100,
|
51
|
+
"amount": float(raw_df.loc[raw_df["item"] == "成交额", "value"].values[0]),
|
52
|
+
"open": float(raw_df.loc[raw_df["item"] == "今开", "value"].values[0]),
|
53
|
+
"high": float(raw_df.loc[raw_df["item"] == "最高", "value"].values[0]),
|
54
|
+
"low": float(raw_df.loc[raw_df["item"] == "最低", "value"].values[0]),
|
55
|
+
"prev_close": float(
|
56
|
+
raw_df.loc[raw_df["item"] == "昨收", "value"].values[0]
|
57
|
+
),
|
58
|
+
}
|
59
|
+
|
60
|
+
return pd.DataFrame([data])
|
@@ -0,0 +1,10 @@
|
|
1
|
+
def convert_xieqiu_symbol(symbol: str) -> str:
|
2
|
+
"""
|
3
|
+
Convert Symbol (600000) to XueQiu Symbol (SH600000)
|
4
|
+
"""
|
5
|
+
if symbol.startswith("6"):
|
6
|
+
return f"SH{symbol}"
|
7
|
+
elif symbol.startswith("0") or symbol.startswith("3"):
|
8
|
+
return f"SZ{symbol}"
|
9
|
+
else: # TODO: add more cases
|
10
|
+
return symbol
|
akshare_one/news.py
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
"""
|
5
5
|
|
6
6
|
import pandas as pd
|
7
|
-
from .
|
7
|
+
from .modules.news.factory import NewsDataFactory
|
8
8
|
|
9
9
|
|
10
10
|
def get_news_data(symbol: str, source: str = "eastmoney") -> "pd.DataFrame":
|
@@ -23,6 +23,5 @@ def get_news_data(symbol: str, source: str = "eastmoney") -> "pd.DataFrame":
|
|
23
23
|
- source: 文章来源
|
24
24
|
- url: 新闻链接
|
25
25
|
"""
|
26
|
-
|
27
|
-
|
28
|
-
raise ValueError(f"Unsupported data source: {source}")
|
26
|
+
provider = NewsDataFactory.get_provider(source, symbol=symbol)
|
27
|
+
return provider.get_news_data()
|
akshare_one/stock.py
CHANGED
@@ -6,13 +6,13 @@
|
|
6
6
|
from typing import Optional
|
7
7
|
import pandas as pd
|
8
8
|
|
9
|
-
from akshare_one.
|
10
|
-
from .
|
9
|
+
from akshare_one.modules.historical.factory import HistoricalDataFactory
|
10
|
+
from akshare_one.modules.realtime.factory import RealtimeDataFactory
|
11
11
|
|
12
12
|
|
13
13
|
def get_hist_data(
|
14
14
|
symbol: str,
|
15
|
-
interval: str,
|
15
|
+
interval: str = "day",
|
16
16
|
interval_multiplier: int = 1,
|
17
17
|
start_date: str = "1970-01-01",
|
18
18
|
end_date: str = "2030-12-31",
|
@@ -28,7 +28,7 @@ def get_hist_data(
|
|
28
28
|
start_date: 开始日期 (YYYY-MM-DD)
|
29
29
|
end_date: 结束日期 (YYYY-MM-DD)
|
30
30
|
adjust: 复权类型 ('none','qfq','hfq')
|
31
|
-
source: 数据源 ('eastmoney', 'sina')
|
31
|
+
source: 数据源 ('eastmoney', 'sina') (default: 'eastmoney')
|
32
32
|
|
33
33
|
Returns:
|
34
34
|
pd.DataFrame:
|
@@ -39,29 +39,20 @@ def get_hist_data(
|
|
39
39
|
- close: 收盘价
|
40
40
|
- volume: 成交量
|
41
41
|
"""
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
return SinaAdapter().get_hist_data(
|
53
|
-
symbol=symbol,
|
54
|
-
interval=interval,
|
55
|
-
interval_multiplier=interval_multiplier,
|
56
|
-
start_date=start_date,
|
57
|
-
end_date=end_date,
|
58
|
-
adjust=adjust,
|
59
|
-
)
|
60
|
-
raise ValueError(f"Unsupported data source: {source}")
|
42
|
+
kwargs = {
|
43
|
+
"symbol": symbol,
|
44
|
+
"interval": interval,
|
45
|
+
"interval_multiplier": interval_multiplier,
|
46
|
+
"start_date": start_date,
|
47
|
+
"end_date": end_date,
|
48
|
+
"adjust": adjust,
|
49
|
+
}
|
50
|
+
provider = HistoricalDataFactory.get_provider(source, **kwargs)
|
51
|
+
return provider.get_hist_data()
|
61
52
|
|
62
53
|
|
63
54
|
def get_realtime_data(
|
64
|
-
|
55
|
+
symbol: Optional[str] = None, source: str = "xueqiu"
|
65
56
|
) -> "pd.DataFrame":
|
66
57
|
"""Get real-time market quotes
|
67
58
|
|
@@ -83,10 +74,5 @@ def get_realtime_data(
|
|
83
74
|
- low: 最低
|
84
75
|
- prev_close: 昨收
|
85
76
|
"""
|
86
|
-
|
87
|
-
|
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)
|
92
|
-
raise ValueError(f"Unsupported data source: {source}")
|
77
|
+
provider = RealtimeDataFactory.get_provider(source, symbol=symbol)
|
78
|
+
return provider.get_current_data()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: akshare-one
|
3
|
-
Version: 0.1
|
3
|
+
Version: 0.2.1
|
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,35 +9,35 @@ 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.
|
13
|
-
Requires-Dist: cachetools>=
|
12
|
+
Requires-Dist: akshare>=1.16.98
|
13
|
+
Requires-Dist: cachetools>=6.0.0
|
14
14
|
Dynamic: license-file
|
15
15
|
|
16
16
|
<div align="center">
|
17
17
|
<h1>AKShare One</h1>
|
18
18
|
<div>
|
19
|
-
<
|
19
|
+
<a href="README_zh.md">中文</a> | <strong>English</strong>
|
20
20
|
</div>
|
21
21
|
</div>
|
22
22
|
|
23
|
-
**AKShare One** is a
|
23
|
+
**AKShare One** is a data interface for obtaining Chinese A-shares, based on [AKShare](https://github.com/akfamily/akshare). It aims to simplify AKShare's usage and unify input/output formats from different data sources, making it easier to pass data to LLM.
|
24
24
|
|
25
25
|
## ✨ Features
|
26
26
|
|
27
27
|
- 📊 Unified stock code formats across data sources
|
28
28
|
- 🏗️ Standardized return data structures
|
29
|
-
- 🛠️ Simplified API
|
29
|
+
- 🛠️ Simplified API parameter design
|
30
30
|
- ⏱️ Automatic timestamp and adjustment handling
|
31
31
|
|
32
32
|
## 🚀 Core Features
|
33
33
|
|
34
|
-
|
|
35
|
-
|
34
|
+
| Function | Interface |
|
35
|
+
|------|------|
|
36
36
|
| Historical data | `get_hist_data` |
|
37
37
|
| Real-time quotes | `get_realtime_data` |
|
38
38
|
| Stock news | `get_news_data` |
|
39
39
|
| Financial data | `get_balance_sheet`/`get_income_statement`/`get_cash_flow` |
|
40
|
-
|
|
40
|
+
| Internal transactions | `get_inner_trade_data` |
|
41
41
|
|
42
42
|
## 📦 Quick Installation
|
43
43
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
akshare_one/__init__.py,sha256=M4eXCnBzGqa5FihT-q7DHaluTvidnqwVF7AgPgCikKU,878
|
2
|
+
akshare_one/financial.py,sha256=XAsonRzGK8akKtW2Q7LUrew4OFRnRAfZm0nw0JY73Jc,1426
|
3
|
+
akshare_one/insider.py,sha256=fM6wvlLSGm7a2NkQFvxEK2PkhN5WudrO-V0BboVz2Bo,1092
|
4
|
+
akshare_one/news.py,sha256=yrYeCaKTgCGP-TSyOfOou9gMw8185qiWrg380fD9-f8,669
|
5
|
+
akshare_one/stock.py,sha256=7Suh8SWbn9LPO-dylu1oKnb25iFadiTL5lxLYC-uvDs,2226
|
6
|
+
akshare_one/modules/cache.py,sha256=47A80Xtfr4gkKvEfBQrT8Dz8hNFR769rBa2gU6ew25s,373
|
7
|
+
akshare_one/modules/utils.py,sha256=H4nrGf8m4_ezTiW5-OcNPxpV-neTYfffEfaOLDFLY9Y,323
|
8
|
+
akshare_one/modules/financial/base.py,sha256=qj_XeujG7Tn2oO1niuIG4s7lMH3xg5zERDbcj75DUnU,536
|
9
|
+
akshare_one/modules/financial/factory.py,sha256=GqzFp6LoHWj7t5VwtZJkLFxBuaAW_0b__bduBrmlcOg,1301
|
10
|
+
akshare_one/modules/financial/sina.py,sha256=Hf6fVeN0gClS9GU2N9Hg6QJ1f8X4mecpEA6KWVgiwTc,10914
|
11
|
+
akshare_one/modules/historical/base.py,sha256=UeKfMU_k8SgazXn27M1FVNaYJ5vBNgUB0jVBDpgXnz8,980
|
12
|
+
akshare_one/modules/historical/eastmoney.py,sha256=2bYXobIwlrd5vG8pHlUZVE6edjQqn8AEGCVFGcWCCKk,8248
|
13
|
+
akshare_one/modules/historical/factory.py,sha256=adxNNo_-PT180QXRUNwkdiN5x0lDJpPCt6rNFZcJ0ps,1389
|
14
|
+
akshare_one/modules/historical/sina.py,sha256=R-5hBOP5zslDuC0qfzw5zNhQyWmbmkmqB2sI2WhKVgI,7249
|
15
|
+
akshare_one/modules/insider/base.py,sha256=xOhBDzMtZd1DutsHaJWe931P17fgW7dlivo1vz5ZflI,949
|
16
|
+
akshare_one/modules/insider/factory.py,sha256=om51vX-GTXknpptZGvmDD9m10FfgEVmy402xZ3bBsNM,1280
|
17
|
+
akshare_one/modules/insider/xueqiu.py,sha256=2gmSrcer8qw2Jb80kYT3tHNJ3U88hxd0dJSfoh846EY,3971
|
18
|
+
akshare_one/modules/news/base.py,sha256=yrBZf1q1QwJkCXygNmeLIEjvcqm1iti63tjb3s40L_4,559
|
19
|
+
akshare_one/modules/news/eastmoney.py,sha256=efVT4plk03s8TbSfhAhRLWgMLlR5G_2G0xGZTQgSxmY,1333
|
20
|
+
akshare_one/modules/news/factory.py,sha256=Em6c7m46K760iwIX3GZ15HdFu7pXT2w-n4QsjwHezjY,1264
|
21
|
+
akshare_one/modules/realtime/base.py,sha256=XtD-4L1pCrMtfbwtZR7tP_BhWB_eMWtpQr89rAdX7P4,702
|
22
|
+
akshare_one/modules/realtime/eastmoney.py,sha256=7IR35dwPr5xj0ErdBajYwyBivEoi55wd1Q5c0DEjUAI,1650
|
23
|
+
akshare_one/modules/realtime/factory.py,sha256=SxDvJJvp6VutRqLUGYRnrUBtJEOE0N7vVh5Rw-vJ6NY,1373
|
24
|
+
akshare_one/modules/realtime/xueqiu.py,sha256=LKu0fW0EMt3c2m1w2kqBbEt9s2TcHUeBFpbFtueJgbU,2241
|
25
|
+
akshare_one-0.2.1.dist-info/licenses/LICENSE,sha256=Gg6A1GNSJCZWQ73aHJ7TXOa0i8RQ3FejZCTZ6Db07cU,1066
|
26
|
+
akshare_one-0.2.1.dist-info/METADATA,sha256=ofJg4rjif2v6WZJfiO4JjHk_-Q_I3-CDQXp6wPU7Vas,1897
|
27
|
+
akshare_one-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
28
|
+
akshare_one-0.2.1.dist-info/top_level.txt,sha256=kNiucyLVAGa89wmUSpXbBLWD7pF_RuahuiaOfLHZSyw,12
|
29
|
+
akshare_one-0.2.1.dist-info/RECORD,,
|
akshare_one/adapters/__init__.py
DELETED